Index: /vis_dev/glu-2.1/src/array/array.c
===================================================================
--- /vis_dev/glu-2.1/src/array/array.c	(revision 8)
+++ /vis_dev/glu-2.1/src/array/array.c	(revision 8)
@@ -0,0 +1,270 @@
+/*
+ * $Id: array.c,v 1.6 2002/08/27 06:26:29 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+#include <stdio.h>
+#include "util.h"
+#include "array.h"
+
+#define INIT_SIZE	3
+
+int unsigned array_global_index;
+int array_global_insert;
+
+array_t *
+array_do_alloc(int size, int number)
+{
+    array_t *array;
+
+    array = ALLOC(array_t, 1);
+    if (array == NIL(array_t)) {
+	return NIL(array_t);
+    }
+    array->num = 0;
+    array->n_size = MAX(number, INIT_SIZE);
+    array->obj_size = size;
+    array->index = -size;
+    array->space = ALLOC(char, array->n_size * array->obj_size);
+    if (array->space == NIL(char)) {
+	return NIL(array_t);
+    }
+    (void) memset(array->space, 0, array->n_size * array->obj_size);
+    return array;
+}
+
+
+void
+array_free(array_t *array)
+{
+    if (array == NIL(array_t)) return;
+    if (array->index >= 0) array_abort(array,4);
+    FREE(array->space);
+    FREE(array);
+}
+
+
+array_t *
+array_dup(array_t *old)
+{
+    array_t *newa;
+
+    newa = ALLOC(array_t, 1);
+    if (newa == NIL(array_t)) {
+	return NIL(array_t);
+    }
+    newa->num = old->num;
+    newa->n_size = old->num;
+    newa->obj_size = old->obj_size;
+    newa->index = -newa->obj_size;
+    newa->space = ALLOC(char, newa->n_size * newa->obj_size);
+    if (newa->space == NIL(char)) {
+	FREE(newa);
+	return NIL(array_t);
+    }
+    (void) memcpy(newa->space, old->space, old->num * old->obj_size);
+    return newa;
+}
+
+array_t *
+array_partial_dup(array_t *old, int i)
+{
+    array_t *newa;
+
+    newa = ALLOC(array_t, 1);
+    if (newa == NIL(array_t)) {
+	return NIL(array_t);
+    }
+    newa->num = old->num - 1;
+    newa->n_size = old->num - 1;
+    newa->obj_size = old->obj_size;
+    newa->index = -newa->obj_size;
+    newa->space = ALLOC(char, newa->n_size * newa->obj_size);
+    if (newa->space == NIL(char)) {
+	FREE(newa);
+	return NIL(array_t);
+    }
+    if (i > 0)
+      (void) memcpy(newa->space, old->space, i * old->obj_size);
+    if (i < old->num - 1)
+      (void) memcpy(newa->space + ((i) * old->obj_size), 
+		    old->space + ((i+1) * old->obj_size), (old->num - (i + 1)) * old->obj_size);
+    return newa;
+}
+
+
+/* append the elements of array2 to the end of array1 */
+int
+array_append(array_t *array1, array_t *array2)
+{
+    char *pos;
+
+    if (array1->index >= 0) array_abort(array1,4);
+    if (array1->obj_size != array2->obj_size) {
+	array_abort(array1,2);
+	/* NOTREACHED */
+    }
+
+    /* make sure array1 has enough room */
+    if (array1->n_size < array1->num + array2->num) {
+	if (array_resize(array1, array1->num + array2->num) == ARRAY_OUT_OF_MEM) {
+	    return ARRAY_OUT_OF_MEM;
+	}
+    }
+    pos = array1->space + array1->num * array1->obj_size;
+    (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
+    array1->num += array2->num;
+
+    return 1;
+}
+
+
+/* join array1 and array2, returning a new array */
+array_t *
+array_join(array_t *array1, array_t *array2)
+{
+    array_t *array;
+    char *pos;
+
+    if (array1->obj_size != array2->obj_size) {
+	array_abort(array1,3);
+	fail("array: join not defined for arrays of different sizes\n");
+	/* NOTREACHED */
+    }
+    array = ALLOC(array_t, 1);
+    if (array == NIL(array_t)) {
+	return NIL(array_t);
+    }
+    array->num = array1->num + array2->num;
+    array->n_size = array->num;
+    array->obj_size = array1->obj_size;
+    array->index = -array->obj_size;
+    array->space = ALLOC(char, array->n_size * array->obj_size);
+    if (array->space == NIL(char)) {
+	FREE(array);
+	return NIL(array_t);
+    }
+    (void) memcpy(array->space, array1->space, array1->num * array1->obj_size);
+    pos = array->space + array1->num * array1->obj_size;
+    (void) memcpy(pos, array2->space, array2->num * array2->obj_size);
+    return array;
+}
+
+char *
+array_do_data(array_t *array)
+{
+    char *data;
+
+    data = ALLOC(char, array->num * array->obj_size);
+    if (data == NIL(char)) {
+	return NIL(char);
+    }
+    (void) memcpy(data, array->space, array->num * array->obj_size);
+    return data;
+}
+
+
+int			/* would like to be void, except for macro's */
+array_resize(array_t *array, int new_size)
+{
+    int old_size;
+    char *pos, *newspace;
+
+    /* Note that this is not an exported function, and does not check if
+       the array is locked since that is already done by the caller. */
+    old_size = array->n_size;
+    array->n_size = MAX(array->n_size * 2, new_size);
+    newspace = REALLOC(char, array->space, array->n_size * array->obj_size);
+    if (newspace == NIL(char)) {
+	array->n_size = old_size;
+	return ARRAY_OUT_OF_MEM;
+    } else {
+	array->space = newspace;
+    }
+    pos = array->space + old_size * array->obj_size;
+    (void) memset(pos, 0, (array->n_size - old_size)*array->obj_size);
+    return 1;
+}
+
+void
+array_sort(array_t *array, int (*compare)(const void *, const void *))
+{
+    qsort((void *)array->space, array->num, array->obj_size, compare);
+}
+
+
+void
+array_uniq(array_t *array, int (*compare)(char **, char **), void (*free_func)(char *))
+{
+    int i, last;
+    char *dest, *obj1, *obj2;
+
+    dest = array->space;
+    obj1 = array->space;
+    obj2 = array->space + array->obj_size;
+    last = array->num;
+
+    for(i = 1; i < last; i++) {
+	if ((*compare)((char **) obj1, (char **) obj2) != 0) {
+	    if (dest != obj1) {
+		(void) memcpy(dest, obj1, array->obj_size);
+	    }
+	    dest += array->obj_size;
+	} else {
+	    if (free_func != 0) (*free_func)(obj1);
+	    array->num--;
+	}
+	obj1 += array->obj_size;
+	obj2 += array->obj_size;
+    }
+    if (dest != obj1) {
+	(void) memcpy(dest, obj1, array->obj_size);
+    }
+}
+
+int			/* would like to be void, except for macro's */
+array_abort(array_t *a, int i)
+{
+    fputs("array: ",stderr);
+
+    switch (i) {
+
+      case 0:		/* index error on insert */
+	fprintf(stderr,"insert of %d\n",a->index);
+	break;
+
+      case 1:		/* index error on fetch */
+	fprintf(stderr,"fetch index %d not in [0,%d]\n",
+		array_global_index,a->num-1);
+	break;
+
+      case 2:		/* append with different element sizes */
+	fprintf(stderr,"append undefined for arrays of different sizes\n");
+	break;
+
+      case 3:		/* join with different element sizes */
+	fprintf(stderr,"join not defined for arrays of different sizes\n");
+	break;
+
+      case 4:		/* size error or locked error */
+	if (a->index >= 0) {
+	    /* Since array_insert is a macro, it is not allowed to nest a
+	       call to any routine which might move the array space through
+	       a realloc or free inside an array_insert call. */
+	    fprintf(stderr,"nested insert, append, remove, or free operations\n");
+	} else {
+	    fprintf(stderr,"object size mismatch\n");
+	}
+	break;
+    case 5: /* attempt to remove last item from empty array */
+      fprintf(stderr, "attempt to remove from empty array");
+      break;
+    default:
+	fputs("unknown error\n", stderr);
+	break;
+    }
+
+    fail("array package error");
+    return 0;  /* never reached */
+}
Index: /vis_dev/glu-2.1/src/array/array.h
===================================================================
--- /vis_dev/glu-2.1/src/array/array.h	(revision 8)
+++ /vis_dev/glu-2.1/src/array/array.h	(revision 8)
@@ -0,0 +1,105 @@
+/*
+ * $Id: array.h,v 1.6 2002/12/08 03:37:19 fabio Exp $
+ *
+ */
+#ifndef ARRAY_H
+#define ARRAY_H
+
+/* Return value when memory allocation fails */
+#define ARRAY_OUT_OF_MEM -10000
+
+/*
+ * In between accesses, the "index" field of the array_t structure
+ * holds the negative of the size of the objects stored in the array.
+ * This allows the functions and macros to perform a rudimentary form
+ * of type checking.
+ */
+
+typedef struct array_t {
+    char *space;
+    int	 num;		/* number of array elements.		*/
+    int	 n_size;	/* size of 'data' array (in objects)	*/
+    int	 obj_size;	/* size of each array object.		*/
+    int	 index;		/* combined index and locking flag.	*/
+} array_t;
+
+EXTERN array_t *array_do_alloc ARGS((int, int));
+EXTERN array_t *array_dup ARGS((array_t *));
+EXTERN array_t *array_join ARGS((array_t *, array_t *));
+EXTERN void array_free ARGS((array_t *));
+EXTERN int array_append ARGS((array_t *, array_t *));
+EXTERN void array_sort ARGS((array_t *, int (*)(const void *, const void *)));
+EXTERN void array_uniq ARGS((array_t *, int (*)(char **, char **), void (*)(char *)));
+EXTERN int array_abort ARGS((array_t *, int));
+EXTERN int array_resize ARGS((array_t *, int));
+EXTERN char *array_do_data ARGS((array_t *));
+
+//duplique le tableau old en ignorant la case d'indice i 
+EXTERN array_t *array_partial_dup ARGS((array_t *, int));
+
+extern int unsigned array_global_index;
+extern int array_global_insert;
+
+#define array_alloc(type, number)		\
+    array_do_alloc(sizeof(type), number)
+
+#define array_insert(type, a, i, datum)         \
+    (  -(a)->index != sizeof(type) ? array_abort((a),4) : 0,\
+        (a)->index = (i),\
+        (a)->index < 0 ? array_abort((a),0) : 0,\
+        (a)->index >= (a)->n_size ?\
+	array_global_insert = array_resize(a, (a)->index + 1) : 0,\
+        array_global_insert != ARRAY_OUT_OF_MEM ?\
+        *((type *) ((a)->space + (a)->index * (a)->obj_size)) = datum : datum,\
+        array_global_insert != ARRAY_OUT_OF_MEM ?\
+        ((a)->index >= (a)->num ? (a)->num = (a)->index + 1 : 0) : 0,\
+        array_global_insert != ARRAY_OUT_OF_MEM ?\
+        ((a)->index = -(int)sizeof(type)) : ARRAY_OUT_OF_MEM )
+
+#define array_insert_last(type, array, datum)	\
+    array_insert(type, array, (array)->num, datum)
+
+/* RB, added this without understanding locking */
+#define array_remove_last(a) \
+    (  -(a)->index != (a)->obj_size ? array_abort((a),4) : 0,\
+       (a)->index = -(a)->index,\
+       (a)->num ? (a)->num-- : array_abort((a),5),\
+       (a)->index = -(a)->index )
+
+#define array_fetch(type, a, i)			\
+    (array_global_index = (i),				\
+      (array_global_index >= (unsigned) ((a)->num)) ? array_abort((a),1) : 0,\
+      *((type *) ((a)->space + array_global_index * (a)->obj_size)))
+
+#define array_fetch_p(type, a, i)                       \
+    (array_global_index = (i),                             \
+      (array_global_index >= (unsigned) ((a)->num)) ? array_abort((a),1) : 0,\
+      ((type *) ((a)->space + array_global_index * (a)->obj_size)))
+
+#define array_fetch_last(type, array)		\
+    array_fetch(type, array, ((array)->num)-1)
+
+#define array_n(array)				\
+    (array)->num
+
+#define array_data(type, array)			\
+    (type *) array_do_data(array)
+
+#define arrayForEachItem(                                      \
+  type,  /* type of object stored in array */                  \
+  array, /* array to iterate */                                \
+  i,     /* int, local variable for iterator */                \
+  data   /* object of type */                                  \
+)                                                              \
+  for((i) = 0;                                                 \
+      (((i) < array_n((array)))                                \
+       && (((data) = array_fetch(type, (array), (i))), 1));    \
+      (i)++)
+
+#endif
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/array/array.make
===================================================================
--- /vis_dev/glu-2.1/src/array/array.make	(revision 8)
+++ /vis_dev/glu-2.1/src/array/array.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += array.c
+HEADERS += array.h
+MISC += array.doc
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/avl/avl.c
===================================================================
--- /vis_dev/glu-2.1/src/avl/avl.c	(revision 8)
+++ /vis_dev/glu-2.1/src/avl/avl.c	(revision 8)
@@ -0,0 +1,534 @@
+/*
+ * $Id: avl.c,v 1.11 2005/04/30 03:03:05 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+
+#include <stdio.h>
+
+#ifndef PACKAGE
+#include "util.h"
+#endif
+
+#include "avl.h"
+
+#ifdef PACKAGE
+extern char *malloc();
+#ifdef ultrix
+extern void free();
+#endif
+
+#define MAX(a,b)	((a) > (b) ? (a) : (b))
+
+#define NIL(type)		\
+    ((type *) 0)
+#define ALLOC(type, num)	\
+    ((type *) malloc(sizeof(type) * (num)))
+#define REALLOC(type, obj, num)	\
+    ((type *) realloc((char *) obj, sizeof(type) * (num)))
+#define FREE(obj)		\
+    free((char *) (obj))
+#endif
+
+
+#define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height)
+#define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left))
+
+#define compute_height(node) {				\
+    int x=HEIGHT(node->left), y=HEIGHT(node->right);	\
+    (node)->height = MAX(x,y) + 1;			\
+}
+
+#define COMPARE(key, nodekey, compare)	 		\
+    ((compare == avl_numcmp) ? 				\
+	(long) key - (long) nodekey : 			\
+	(*compare)(key, nodekey))
+
+
+#define STACK_SIZE	50
+
+static avl_node *new_node(char *key, char *value);
+static avl_node *find_rightmost(avl_node **node_p);
+static void do_rebalance(avl_node ***stack_nodep, int stack_n); 
+static int rotate_left(avl_node **node_p);
+static int rotate_right(avl_node **node_p);
+static int do_check_tree(avl_node *node, int (*compar)(const void *, const void *), int *error);
+
+avl_tree *
+avl_init_table(int (*compar)(const void *, const void *))
+{
+    avl_tree *tree;
+
+    tree = ALLOC(avl_tree, 1);
+    tree->root = NIL(avl_node);
+    tree->compar = compar;
+    tree->num_entries = 0;
+    return tree;
+}
+
+
+int
+avl_lookup(avl_tree *tree, const void *key, void *value_p)
+{
+    avl_node *node;
+    int (*compare)(const void *, const void *) = tree->compar, diff;
+
+    node = tree->root;
+    while (node != NIL(avl_node)) {
+	diff = COMPARE(key, node->key, compare);
+	if (diff == 0) {
+	    /* got a match */
+	    if (value_p != NULL) *(char **)value_p = node->value;
+	    return 1;
+	}
+	node = (diff < 0) ? node->left : node->right;
+    }
+    return 0;
+}
+
+int
+avl_first(avl_tree *tree, char **key_p, char **value_p)
+{
+    register avl_node *node;
+
+    if (tree->root == 0) {
+	return 0;		/* no entries */
+    } else {
+	/* walk down the tree; stop at leftmost leaf */
+	for(node = tree->root; node->left != 0; node = node->left) {
+	}
+	if (key_p != NIL(char *)) *key_p = node->key;
+	if (value_p != NIL(char *)) *value_p = node->value;
+	return 1;
+    }
+}
+
+int
+avl_last(avl_tree *tree, char **key_p, char **value_p)
+{
+    register avl_node *node;
+
+    if (tree->root == 0) {
+	return 0;		/* no entries */
+    } else {
+	/* walk down the tree; stop at rightmost leaf */
+	for(node = tree->root; node->right != 0; node = node->right) {
+	}
+	if (key_p != NIL(char *)) *key_p = node->key;
+	if (value_p != NIL(char *)) *value_p = node->value;
+	return 1;
+    }
+}
+
+int
+avl_insert(avl_tree *tree, void *key, void *value)
+{
+    avl_node **node_p, *node;
+    int stack_n = 0;
+    int (*compare)(const void *, const void *) = tree->compar;
+    avl_node **stack_nodep[STACK_SIZE];
+    int diff, status;
+
+    node_p = &tree->root;
+
+    /* walk down the tree (saving the path); stop at insertion point */
+    status = 0;
+    while ((node = *node_p) != NIL(avl_node)) {
+	stack_nodep[stack_n++] = node_p;
+	diff = COMPARE(key, node->key, compare);
+	if (diff == 0) status = 1;
+	node_p = (diff < 0) ? &node->left : &node->right;
+    }
+
+    /* insert the item and re-balance the tree */
+    *node_p = new_node((char *)key, (char *)value);
+    do_rebalance(stack_nodep, stack_n);
+    tree->num_entries++;
+    tree->modified = 1;
+    return status;
+}
+
+
+int
+avl_find_or_add(avl_tree *tree, char *key, char ***slot_p)
+{
+    register avl_node **node_p, *node;
+    register int stack_n = 0;
+    register int (*compare)(const void *, const void *) = tree->compar;
+    avl_node **stack_nodep[STACK_SIZE];
+    int diff;
+
+    node_p = &tree->root;
+
+    /* walk down the tree (saving the path); stop at insertion point */
+    while ((node = *node_p) != NIL(avl_node)) {
+	stack_nodep[stack_n++] = node_p;
+	diff = COMPARE(key, node->key, compare);
+	if (diff == 0) {
+	    if (slot_p != 0) *slot_p = &node->value;
+	    return 1;		/* found */
+	}
+	node_p = (diff < 0) ? &node->left : &node->right;
+    }
+
+    /* insert the item and re-balance the tree */
+    *node_p = new_node(key, NIL(char));
+    if (slot_p != 0) *slot_p = &(*node_p)->value;
+    do_rebalance(stack_nodep, stack_n);
+    tree->num_entries++;
+    tree->modified = 1;
+    return 0;			/* not already in tree */
+}
+
+int
+avl_delete(avl_tree *tree, void *key_p, void *value_p)
+{
+    avl_node **node_p, *node, *rightmost;
+    int stack_n = 0;
+    char *key = *(char **) key_p;
+    int (*compare)(const void *, const void *) = tree->compar, diff;
+    avl_node **stack_nodep[STACK_SIZE];
+
+    node_p = &tree->root;
+
+    /* Walk down the tree saving the path; return if not found */
+    while ((node = *node_p) != NIL(avl_node)) {
+	diff = COMPARE(key, node->key, compare);
+	if (diff == 0) goto delete_item;
+	stack_nodep[stack_n++] = node_p;
+	node_p = (diff < 0) ? &node->left : &node->right;
+    }
+    return 0;		/* not found */
+
+    /* prepare to delete node and replace it with rightmost of left tree */
+delete_item:
+    *(char **) key_p = node->key;
+    if (value_p != NULL) *(char **)value_p = node->value;
+    if (node->left == NIL(avl_node)) {
+	*node_p = node->right;
+    } else {
+	rightmost = find_rightmost(&node->left);
+	rightmost->left = node->left;
+	rightmost->right = node->right;
+	rightmost->height = -2; 	/* mark bogus height for do_rebal */
+	*node_p = rightmost;
+	stack_nodep[stack_n++] = node_p;
+    }
+    FREE(node);
+
+    /* work our way back up, re-balancing the tree */
+    do_rebalance(stack_nodep, stack_n);
+    tree->num_entries--;
+    tree->modified = 1;
+    return 1;
+}
+
+static void 
+avl_record_gen_forward(avl_node *node, avl_generator *gen)
+{
+    if (node != NIL(avl_node)) {
+	avl_record_gen_forward(node->left, gen);
+	gen->nodelist[gen->count++] = node;
+	avl_record_gen_forward(node->right, gen);
+    }
+}
+
+
+static void 
+avl_record_gen_backward(avl_node *node, avl_generator *gen)
+{
+    if (node != NIL(avl_node)) {
+	avl_record_gen_backward(node->right, gen);
+	gen->nodelist[gen->count++] = node;
+	avl_record_gen_backward(node->left, gen);
+    }
+}
+
+
+avl_generator *
+avl_init_gen(avl_tree *tree, int dir)
+{
+    avl_generator *gen;
+
+    /* what a hack */
+    gen = ALLOC(avl_generator, 1);
+    gen->tree = tree;
+    gen->nodelist = ALLOC(avl_node *, avl_count(tree));
+    gen->count = 0;
+    if (dir == AVL_FORWARD) {
+	avl_record_gen_forward(tree->root, gen);
+    } else {
+	avl_record_gen_backward(tree->root, gen);
+    }
+    gen->count = 0;
+
+    /* catch any attempt to modify the tree while we generate */
+    tree->modified = 0;
+    return gen;
+}
+
+
+int
+avl_gen(avl_generator *gen, char **key_p, char **value_p)
+{
+    avl_node *node;
+
+    if (gen->count == gen->tree->num_entries) {
+	return 0;
+    } else {
+	node = gen->nodelist[gen->count++];
+	if (key_p != NIL(char *)) *key_p = node->key;
+	if (value_p != NIL(char *)) *value_p = node->value;
+	return 1;
+    }
+}
+
+
+void
+avl_free_gen(avl_generator *gen)
+{
+    FREE(gen->nodelist);
+    FREE(gen);
+}
+
+
+static avl_node *
+find_rightmost(avl_node **node_p)
+{
+    register avl_node *node;
+    register int stack_n = 0;
+    avl_node **stack_nodep[STACK_SIZE];
+
+    node = *node_p;
+    while (node->right != NIL(avl_node)) {
+	stack_nodep[stack_n++] = node_p;
+	node_p = &node->right;
+	node = *node_p;
+    }
+    *node_p = node->left;
+
+    do_rebalance(stack_nodep, stack_n);
+    return node;
+}
+
+
+static void
+do_rebalance(avl_node ***stack_nodep, int stack_n)
+{
+    register avl_node **node_p, *node;
+    register int hl, hr;
+    int height;
+
+    /* work our way back up, re-balancing the tree */
+    while (--stack_n >= 0) {
+	node_p = stack_nodep[stack_n];
+	node = *node_p;
+	hl = HEIGHT(node->left);		/* watch for NIL */
+	hr = HEIGHT(node->right);		/* watch for NIL */
+	if ((hr - hl) < -1) {
+	    rotate_right(node_p);
+	} else if ((hr - hl) > 1) {
+	    rotate_left(node_p);
+	} else {
+	    height = MAX(hl, hr) + 1;
+	    if (height == node->height) break;
+	    node->height = height;
+	}
+    }
+}
+
+static int
+rotate_left(avl_node **node_p)
+{
+    register avl_node *old_root = *node_p, *new_root, *new_right;
+
+    if (BALANCE(old_root->right) >= 0) {
+	*node_p = new_root = old_root->right;
+	old_root->right = new_root->left;
+	new_root->left = old_root;
+    } else {
+	new_right = old_root->right;
+	*node_p = new_root = new_right->left;
+	old_root->right = new_root->left;
+	new_right->left = new_root->right;
+	new_root->right = new_right;
+	new_root->left = old_root;
+	compute_height(new_right);
+    }
+    compute_height(old_root);
+    compute_height(new_root);
+
+    return 0;
+}
+
+
+static int
+rotate_right(avl_node **node_p)
+{
+    register avl_node *old_root = *node_p, *new_root, *new_left;
+
+    if (BALANCE(old_root->left) <= 0) {
+	*node_p = new_root = old_root->left;
+	old_root->left = new_root->right;
+	new_root->right = old_root;
+    } else {
+	new_left = old_root->left;
+	*node_p = new_root = new_left->right;
+	old_root->left = new_root->right;
+	new_left->right = new_root->left;
+	new_root->left = new_left;
+	new_root->right = old_root;
+	compute_height(new_left);
+    }
+    compute_height(old_root);
+    compute_height(new_root);
+
+    return 0;
+}
+
+static void 
+avl_walk_forward(avl_node *node, void (*func)(const void *, const void *))
+{
+    if (node != NIL(avl_node)) {
+	avl_walk_forward(node->left, func);
+	(*func)(node->key, node->value);
+	avl_walk_forward(node->right, func);
+    }
+}
+
+
+static void 
+avl_walk_backward(avl_node *node, void (*func)(const void *, const void *))
+{
+    if (node != NIL(avl_node)) {
+	avl_walk_backward(node->right, func);
+	(*func)(node->key, node->value);
+	avl_walk_backward(node->left, func);
+    }
+}
+
+
+void
+avl_foreach(
+  avl_tree *tree,
+  void (*func)(const void *, const void *),
+  int direction)
+{
+    if (direction == AVL_FORWARD) {
+	avl_walk_forward(tree->root, func);
+    } else {
+	avl_walk_backward(tree->root, func);
+    }
+}
+
+
+static void
+free_entry(
+  avl_node *node,
+  void (*key_free)(char *),
+  void (*value_free)(char *))
+{
+    if (node != NIL(avl_node)) {
+	free_entry(node->left, key_free, value_free);
+	free_entry(node->right, key_free, value_free);
+	if (key_free != 0) (*key_free)(node->key);
+	if (value_free != 0) (*value_free)(node->value);
+	FREE(node);
+    }
+}
+   
+
+void 
+avl_free_table(
+  avl_tree *tree,
+  void (*key_free)(char *),
+  void (*value_free)(char *))
+{
+    free_entry(tree->root, key_free, value_free);
+    FREE(tree);
+}
+
+
+int 
+avl_count(avl_tree *tree)
+{
+    return tree->num_entries;
+}
+
+
+static avl_node *
+new_node(char *key, char *value)
+{
+    register avl_node *newn;
+
+    newn = ALLOC(avl_node, 1);
+    newn->key = key;
+    newn->value = value;
+    newn->height = 0;
+    newn->left = newn->right = NIL(avl_node);
+    return newn;
+}
+
+
+int 
+avl_numcmp(const void *x, const void *y)
+{
+    return (long) x - (long) y;
+}
+
+int
+avl_check_tree(avl_tree *tree)
+{
+    int error = 0;
+    (void) do_check_tree(tree->root, tree->compar, &error);
+    return error;
+}
+
+
+static int
+do_check_tree(
+  avl_node *node,
+  int (*compar)(const void *, const void *),
+  int *error)
+{
+    int l_height, r_height, comp_height, bal;
+    
+    if (node == NIL(avl_node)) {
+	return -1;
+    }
+
+    r_height = do_check_tree(node->right, compar, error);
+    l_height = do_check_tree(node->left, compar, error);
+
+    comp_height = MAX(l_height, r_height) + 1;
+    bal = r_height - l_height;
+    
+    if (comp_height != node->height) {
+	(void) printf("Bad height for 0x%p: computed=%d stored=%d\n",
+	    (void *) node, comp_height, node->height);
+	++*error;
+    }
+
+    if (bal > 1 || bal < -1) {
+	(void) printf("Out of balance at node 0x%p, balance = %d\n", 
+	    (void *) node, bal);
+	++*error;
+    }
+
+    if (node->left != NIL(avl_node) && 
+		    (*compar)(node->left->key, node->key) > 0) {
+	(void) printf("Bad ordering between 0x%p and 0x%p", 
+	    (void *) node, (void *) node->left);
+	++*error;
+    }
+    
+    if (node->right != NIL(avl_node) && 
+		    (*compar)(node->key, node->right->key) > 0) {
+	(void) printf("Bad ordering between 0x%p and 0x%p", 
+	    (void *) node, (void *) node->right);
+	++*error;
+    }
+
+    return comp_height;
+}
Index: /vis_dev/glu-2.1/src/avl/avl.h
===================================================================
--- /vis_dev/glu-2.1/src/avl/avl.h	(revision 8)
+++ /vis_dev/glu-2.1/src/avl/avl.h	(revision 8)
@@ -0,0 +1,66 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/avl/avl.h,v
+ * rajeev
+ * 1.3
+ * 1995/08/08 22:36:24
+ *
+ */
+#ifndef AVL_INCLUDED
+#define AVL_INCLUDED
+
+
+typedef struct avl_node_struct avl_node;
+struct avl_node_struct {
+    avl_node *left, *right;
+    char *key;
+    char *value;
+    int height;
+};
+
+
+typedef struct avl_tree_struct avl_tree;
+struct avl_tree_struct {
+    avl_node *root;
+    int (*compar)(const void *, const void *);
+    int num_entries;
+    int modified;
+};
+
+
+typedef struct avl_generator_struct avl_generator;
+struct avl_generator_struct {
+    avl_tree *tree;
+    avl_node **nodelist;
+    int count;
+};
+
+
+#define AVL_FORWARD 	0
+#define AVL_BACKWARD 	1
+
+
+EXTERN avl_tree *avl_init_table ARGS((int (*)(const void *, const void *)));
+EXTERN int avl_delete ARGS((avl_tree *, void *, void *));
+EXTERN int avl_insert ARGS((avl_tree *, void *, void *));
+EXTERN int avl_lookup ARGS((avl_tree *, const void *, void *));
+EXTERN int avl_first ARGS((avl_tree *, char **, char **));
+EXTERN int avl_last ARGS((avl_tree *, char **, char **));
+EXTERN int avl_find_or_add ARGS((avl_tree *, char *, char ***));
+EXTERN int avl_count ARGS((avl_tree *));
+EXTERN int avl_numcmp ARGS((const void *, const void *));
+EXTERN int avl_check_tree ARGS((avl_tree *tree));
+EXTERN int avl_gen ARGS((avl_generator *, char **, char **));
+EXTERN void avl_foreach ARGS((avl_tree *, void (*)(const void *, const void *), int));
+EXTERN void avl_free_table ARGS((avl_tree *, void (*)(char *), void (*)(char *)));
+EXTERN void avl_free_gen ARGS((avl_generator *));
+EXTERN avl_generator *avl_init_gen ARGS((avl_tree *, int));
+
+#define avl_is_member(tree, key)	avl_lookup(tree, key, (char **) 0)
+
+#define avl_foreach_item(table, gen, dir, key_p, value_p) 	\
+    for(gen = avl_init_gen(table, dir); 			\
+	    avl_gen(gen, key_p, value_p) || (avl_free_gen(gen),0);)
+
+#endif
Index: /vis_dev/glu-2.1/src/avl/avl.make
===================================================================
--- /vis_dev/glu-2.1/src/avl/avl.make	(revision 8)
+++ /vis_dev/glu-2.1/src/avl/avl.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += avl.c
+HEADERS += avl.h
+MISC += avl.doc avl_bench1.c
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/avl/avl_bench1.c
===================================================================
--- /vis_dev/glu-2.1/src/avl/avl_bench1.c	(revision 8)
+++ /vis_dev/glu-2.1/src/avl/avl_bench1.c	(revision 8)
@@ -0,0 +1,72 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/avl/avl_bench1.c,v
+ * rajeev
+ * 1.3
+ * 1995/08/08 22:36:26
+ *
+ */
+#include <stdio.h>
+#include "array.h"
+#include "avl.h"
+#include "util.h"
+
+#define MAX_WORD	1024
+
+extern long random();
+
+/* ARGSUSED */
+main(argc, argv)
+char *argv;
+{
+    array_t *words;
+    avl_tree *table;
+    char word[MAX_WORD], *tempi, *tempj;
+    register int i, j;
+    long time;
+#ifdef TEST
+    avl_generator *gen;
+    char *key;
+#endif
+
+    /* read the words */
+    words = array_alloc(char *, 1000);
+    while (gets(word) != NIL(char)) {
+	array_insert_last(char *, words, util_strsav(word));
+	if (array_n(words) == 100000) break;
+    }
+
+    /* scramble them */
+    for(i = array_n(words)-1; i >= 1; i--) {
+	j = random() % i;
+	tempi = array_fetch(char *, words, i);
+	tempj = array_fetch(char *, words, j);
+	array_insert(char *, words, i, tempj);
+	array_insert(char *, words, j, tempi);
+    }
+
+#ifdef TEST
+    (void) printf("Initial data is\n");
+    for(i = array_n(words)-1; i >= 0; i--) {
+	(void) printf("%s\n", array_fetch(char *, words, i));
+    }
+#endif
+
+    /* time putting them into an avl tree */
+    time = util_cpu_time();
+    table = avl_init_table(strcmp);
+    for(i = array_n(words)-1; i >= 0; i--) {
+	(void) avl_insert(table, array_fetch(char *, words, i), NIL(char));
+    }
+    (void) printf("Elapsed time for insert of %d objects was %s\n",
+	array_n(words), util_print_time(util_cpu_time() - time));
+
+#ifdef TEST
+    (void) printf("Sorted data is\n");
+    avl_foreach_item(table, gen, AVL_FORWARD, &key, NIL(char *)) {
+	(void) printf("%s\n", key);
+    }
+#endif
+    return 0;
+}
Index: /vis_dev/glu-2.1/src/bdd/bdd.h
===================================================================
--- /vis_dev/glu-2.1/src/bdd/bdd.h	(revision 8)
+++ /vis_dev/glu-2.1/src/bdd/bdd.h	(revision 8)
@@ -0,0 +1,546 @@
+/******************************************************************************
+
+  PackageName [bdd]
+
+  Synopsis    [Package-independent BDD interface functions.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Thomas R. Shiple. Modified by Rajeev K. Ranjan.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: bdd.h,v 1.78 2004/02/06 22:21:55 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _BDD_H
+#define _BDD_H
+#include "util.h"  
+#include "array.h"
+#include "st.h"
+#include "var_set.h"
+#include "avl.h"
+#ifndef	EPD_MAX_BIN
+#include "epd.h"
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef int boolean;
+typedef void bdd_manager;
+typedef unsigned int bdd_variableId; /* the id of the variable in a bdd node */
+typedef void bdd_mgr_init; /* Typecasting to void to avoid error messages */
+typedef int bdd_literal;	        /* integers in the set { 0, 1, 2 } */
+typedef struct bdd_t bdd_t;
+typedef void bdd_node;
+typedef void bdd_gen;
+typedef struct bdd_external_hooks_struct bdd_external_hooks;
+typedef void bdd_block;
+typedef double BDD_VALUE_TYPE;
+
+/*---------------------------------------------------------------------------*/
+/* Enumerated type declarations                                              */
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Dynamic reordering.
+ */
+typedef enum {
+  BDD_REORDER_SIFT,
+  BDD_REORDER_WINDOW,
+  BDD_REORDER_SAME,
+  BDD_REORDER_RANDOM,
+  BDD_REORDER_RANDOM_PIVOT,
+  BDD_REORDER_SIFT_CONVERGE,
+  BDD_REORDER_SYMM_SIFT,
+  BDD_REORDER_SYMM_SIFT_CONV,
+  BDD_REORDER_LINEAR,
+  BDD_REORDER_LINEAR_CONVERGE,
+  BDD_REORDER_EXACT,
+  BDD_REORDER_WINDOW2,
+  BDD_REORDER_WINDOW3,
+  BDD_REORDER_WINDOW4,
+  BDD_REORDER_WINDOW2_CONV,
+  BDD_REORDER_WINDOW3_CONV,
+  BDD_REORDER_WINDOW4_CONV,
+  BDD_REORDER_GROUP_SIFT,
+  BDD_REORDER_GROUP_SIFT_CONV,
+  BDD_REORDER_ANNEALING,
+  BDD_REORDER_GENETIC,
+  BDD_REORDER_LAZY_SIFT,
+  BDD_REORDER_NONE
+} bdd_reorder_type_t;
+
+typedef enum {
+  CMU,
+  CAL,
+  CUDD
+} bdd_package_type_t;
+
+typedef enum {
+    bdd_EMPTY,
+    bdd_NONEMPTY
+} bdd_gen_status;
+
+typedef enum {
+    BDD_PRE_GC_HOOK,
+    BDD_POST_GC_HOOK,
+    BDD_PRE_REORDERING_HOOK,
+    BDD_POST_REORDERING_HOOK
+} bdd_hook_type_t;
+
+typedef enum {
+    BDD_OVER_APPROX,
+    BDD_UNDER_APPROX
+} bdd_approx_dir_t;
+
+typedef enum {
+    BDD_CONJUNCTS,
+    BDD_DISJUNCTS
+} bdd_partition_type_t;
+
+typedef enum {
+  BDD_REORDER_VERBOSITY_DEFAULT,
+  BDD_REORDER_NO_VERBOSITY,
+  BDD_REORDER_VERBOSITY
+}bdd_reorder_verbosity_t;
+
+typedef enum {
+  BDD_APPROX_HB,
+  BDD_APPROX_SP,
+  BDD_APPROX_COMP,
+  BDD_APPROX_UA,
+  BDD_APPROX_RUA,
+  BDD_APPROX_BIASED_RUA
+} bdd_approx_type_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+struct bdd_external_hooks_struct {
+    char *network;
+    char *mdd;
+    char *undef1;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+/*
+** It is assumed that dynamic reordering will not occur while there are open
+** generators.  It is the user's responsibility to make sure dynamic
+** reordering doesn't occur. As long as new nodes are not created during
+** generation, and you don't explicitly call dynamic reordering, you should be
+** okay. 
+*/
+
+/*
+ *    foreach_bdd_cube(fn, gen, cube)
+ *    bdd_t *fn;
+ *    bdd_gen *gen;
+ *    array_t *cube;	- return
+ *
+ *    foreach_bdd_cube(fn, gen, cube) {
+ *        ...
+ *    }
+ */
+#define foreach_bdd_cube(fn, gen, cube)\
+  for((gen) = bdd_first_cube(fn, &cube);\
+      (bdd_gen_read_status(gen) != bdd_EMPTY) ? TRUE: bdd_gen_free(gen);\
+      (void) bdd_next_cube(gen, &cube))
+
+/*
+ *    foreach_bdd_disjoint_cube(fn, gen, cube)
+ *    bdd_t *fn;
+ *    bdd_gen *gen;
+ *    array_t *cube;	- return
+ *
+ *    foreach_bdd_disjoint_cube(fn, gen, cube) {
+ *        ...
+ *    }
+ */
+#define foreach_bdd_disjoint_cube(fn, gen, cube)\
+  for((gen) = bdd_first_disjoint_cube(fn, &cube);\
+      (bdd_gen_read_status(gen) != bdd_EMPTY) ? TRUE: bdd_gen_free(gen);\
+      (void) bdd_next_disjoint_cube(gen, &cube))
+
+/*
+ *    foreach_bdd_node(fn, gen, node)
+ *    bdd_t *fn;
+ *    bdd_gen *gen;
+ *    bdd_node *node;	- return
+ */
+#define foreach_bdd_node(fn, gen, node)\
+  for((gen) = bdd_first_node(fn, &node);\
+      (bdd_gen_read_status(gen) != bdd_EMPTY) ? TRUE: bdd_gen_free(gen);\
+      (void) bdd_next_node(gen, &node))
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+EXTERN bdd_package_type_t bdd_get_package_name ARGS((void));
+
+/*
+ * BDD Manager Allocation And Destruction
+ */
+EXTERN bdd_manager *bdd_start ARGS((int));
+EXTERN void bdd_end ARGS((bdd_manager *));
+
+/*
+ * BDD variable management
+ */
+EXTERN bdd_t *bdd_create_variable ARGS((bdd_manager *));		
+EXTERN bdd_t *bdd_create_variable_after ARGS((bdd_manager *, bdd_variableId));
+EXTERN bdd_t *bdd_get_variable ARGS((bdd_manager *, bdd_variableId));	
+EXTERN bdd_t *bdd_create_variable_after ARGS((bdd_manager *, bdd_variableId));
+EXTERN bdd_t * bdd_var_with_index ARGS((bdd_manager *manager, int index));
+EXTERN bdd_node *bdd_add_ith_var ARGS((bdd_manager *mgr, int i));
+
+
+/*
+ * BDD Formula Management
+ */
+EXTERN bdd_t *bdd_dup ARGS((bdd_t *));
+EXTERN void bdd_free ARGS((bdd_t *));
+
+/* 
+ * Operations on BDD Formulas
+ */
+EXTERN bdd_t *bdd_and ARGS((bdd_t *, bdd_t *, boolean, boolean));
+EXTERN bdd_t *bdd_and_with_limit ARGS((bdd_t *, bdd_t *, boolean, boolean, unsigned int));
+EXTERN bdd_t *bdd_and_array ARGS((bdd_t *, array_t *, boolean, boolean));
+EXTERN bdd_t *bdd_and_smooth ARGS((bdd_t *, bdd_t *, array_t *));
+EXTERN bdd_t *bdd_and_smooth_with_limit ARGS((bdd_t *, bdd_t *, array_t *, unsigned int));
+EXTERN bdd_t *bdd_and_smooth_with_cube ARGS((bdd_t *, bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_clipping_and_smooth ARGS((bdd_t *, bdd_t *, array_t *, int , int ));
+EXTERN bdd_t *bdd_xor_smooth ARGS((bdd_t *, bdd_t *, array_t *));
+EXTERN bdd_t *bdd_between ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_cofactor ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_cofactor_array ARGS((bdd_t *, array_t *));
+EXTERN bdd_t *bdd_var_cofactor ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_compose ARGS((bdd_t *, bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_vector_compose ARGS((bdd_t *, array_t *, array_t *));
+EXTERN bdd_t *bdd_consensus ARGS((bdd_t *, array_t *));
+EXTERN bdd_t *bdd_consensus_with_cube ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_cproject ARGS((bdd_t *, array_t *));
+EXTERN bdd_t *bdd_else ARGS((bdd_t *));
+EXTERN bdd_t *bdd_ite ARGS((bdd_t *, bdd_t *, bdd_t *, boolean, boolean, boolean));
+EXTERN bdd_t *bdd_minimize ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_minimize_array ARGS((bdd_t *, array_t *));
+EXTERN bdd_t *bdd_compact ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_squeeze ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_not ARGS((bdd_t *));
+EXTERN bdd_t *bdd_one ARGS((bdd_manager *));
+EXTERN bdd_t *bdd_or ARGS((bdd_t *, bdd_t *, boolean, boolean));
+EXTERN bdd_t *bdd_smooth ARGS((bdd_t *, array_t *));
+EXTERN bdd_t *bdd_smooth_with_cube ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_substitute ARGS((bdd_t *, array_t *, array_t *));
+EXTERN bdd_t *bdd_substitute_with_permut ARGS((bdd_t *, int *));
+EXTERN array_t *bdd_substitute_array ARGS((array_t *, array_t *, array_t *));
+EXTERN array_t *bdd_substitute_array_with_permut ARGS((array_t *, int *));
+EXTERN void *bdd_pointer ARGS((bdd_t *));
+EXTERN bdd_t *bdd_then ARGS((bdd_t *));
+EXTERN bdd_t *bdd_top_var ARGS((bdd_t *));
+EXTERN bdd_t *bdd_xnor ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_xor ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_zero ARGS((bdd_manager *));
+EXTERN bdd_t *bdd_multiway_and ARGS((bdd_manager *, array_t *));
+EXTERN bdd_t *bdd_multiway_or ARGS((bdd_manager *, array_t *));
+EXTERN bdd_t *bdd_multiway_xor ARGS((bdd_manager *, array_t *));
+EXTERN array_t * bdd_pairwise_or ARGS((bdd_manager *manager, array_t *bddArray1, array_t *bddArray2));
+EXTERN array_t * bdd_pairwise_and ARGS((bdd_manager *manager, array_t *bddArray1, array_t *bddArray2));
+EXTERN array_t * bdd_pairwise_xor ARGS((bdd_manager *manager, array_t *bddArray1, array_t *bddArray2));
+EXTERN bdd_t *bdd_approx_hb ARGS((bdd_t *, bdd_approx_dir_t , int , int ));
+EXTERN bdd_t *bdd_approx_sp ARGS((bdd_t *, bdd_approx_dir_t , int , int , int ));
+EXTERN bdd_t *bdd_approx_ua ARGS((bdd_t *, bdd_approx_dir_t , int , int , int , double ));
+EXTERN bdd_t *bdd_approx_remap_ua ARGS((bdd_t *, bdd_approx_dir_t , int , int , double ));
+EXTERN bdd_t *bdd_approx_biased_rua ARGS((bdd_t *, bdd_approx_dir_t , bdd_t *, int , int , double, double ));
+EXTERN bdd_t *bdd_approx_compress ARGS((bdd_t *, bdd_approx_dir_t , int , int ));
+EXTERN int bdd_var_decomp ARGS((bdd_t *, bdd_partition_type_t , bdd_t ***));
+EXTERN int bdd_gen_decomp ARGS((bdd_t *, bdd_partition_type_t , bdd_t ***));
+EXTERN int bdd_approx_decomp ARGS((bdd_t *, bdd_partition_type_t , bdd_t ***));
+EXTERN int bdd_iter_decomp ARGS((bdd_t *, bdd_partition_type_t , bdd_t ***));
+EXTERN bdd_t *bdd_shortest_path ARGS((bdd_t *f, int *weight, int *support, int *length));
+
+EXTERN bdd_t *bdd_compute_cube ARGS((bdd_manager *mgr, array_t *vars));
+EXTERN bdd_t *bdd_compute_cube_with_phase ARGS((bdd_manager *mgr, array_t *vars, array_t *phase));
+EXTERN bdd_node *bdd_add_compose ARGS((bdd_manager *mgr, bdd_node *fn1, bdd_node *fn2, int var));
+EXTERN bdd_node *bdd_add_xnor ARGS((bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2 ));
+EXTERN bdd_node *bdd_add_times ARGS((bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2));
+EXTERN bdd_node *bdd_add_vector_compose ARGS((bdd_manager *mgr, bdd_node *fn, bdd_node **vector));
+EXTERN bdd_node *bdd_add_residue ARGS((bdd_manager *mgr, int n, int m, int options, int top));
+EXTERN bdd_node *bdd_add_nonsim_compose ARGS((bdd_manager *mgr, bdd_node *fn, bdd_node **vector));
+EXTERN bdd_node *bdd_add_apply ARGS((bdd_manager *mgr, bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **), bdd_node *fn1, bdd_node *fn2));
+EXTERN bdd_node *bdd_add_exist_abstract ARGS((bdd_manager *mgr, bdd_node *fn, bdd_node *vars));
+EXTERN void bdd_recursive_deref ARGS((bdd_manager *mgr, bdd_node *f));
+EXTERN void bdd_ref ARGS((bdd_node *fn));
+EXTERN bdd_node *bdd_bdd_to_add ARGS((bdd_manager *mgr, bdd_node *fn));
+EXTERN bdd_node *bdd_add_permute ARGS((bdd_manager *mgr, bdd_node *fn, int *permut));
+EXTERN bdd_node *bdd_bdd_permute ARGS((bdd_manager *mgr, bdd_node *fn, int *permut));
+EXTERN bdd_node * bdd_bdd_exist_abstract ARGS((bdd_manager *mgr, bdd_node *fn, bdd_node *cube));
+/* Added by Balakrishna Kumthekar. There are potential duplicates. */
+
+EXTERN int  bdd_equal_sup_norm  ARGS((bdd_manager *mgr, bdd_node *fn, bdd_node *gn, BDD_VALUE_TYPE tolerance, int pr));
+EXTERN bdd_node * bdd_read_logic_zero ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_bdd_ith_var ARGS((bdd_manager *mgr, int i));
+EXTERN bdd_node * bdd_add_divide ARGS((bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2));
+EXTERN bdd_node * bdd_bdd_constrain ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *c));
+EXTERN bdd_node * bdd_bdd_restrict ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *c));
+EXTERN bdd_node * bdd_add_hamming ARGS((bdd_manager *mgr, bdd_node **xVars, bdd_node **yVars, int nVars));
+EXTERN bdd_node * bdd_add_ite ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g, bdd_node *h));
+EXTERN bdd_node * bdd_add_find_max ARGS((bdd_manager *mgr, bdd_node *f));
+EXTERN int bdd_bdd_pick_one_cube ARGS((bdd_manager *mgr, bdd_node *node, char *string));
+EXTERN bdd_node * bdd_add_swap_variables ARGS((bdd_manager *mgr, bdd_node *f, bdd_node **x, bdd_node **y, int n));
+EXTERN bdd_node * bdd_bdd_or ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_bdd_compute_cube ARGS((bdd_manager *mgr, bdd_node **vars, int *phase, int n));
+EXTERN bdd_node * bdd_indices_to_cube ARGS((bdd_manager *mgr, int *idArray, int n));
+EXTERN bdd_node * bdd_bdd_and ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_add_matrix_multiply ARGS((bdd_manager *mgr, bdd_node *A, bdd_node *B, bdd_node **z, int nz));
+EXTERN bdd_node * bdd_add_compute_cube ARGS((bdd_manager *mgr, bdd_node **vars, int *phase, int n));
+EXTERN bdd_node * bdd_add_const ARGS((bdd_manager *mgr, BDD_VALUE_TYPE c));
+EXTERN bdd_node * bdd_bdd_swap_variables ARGS((bdd_manager *mgr, bdd_node *f, bdd_node **x, bdd_node **y, int n));
+EXTERN double bdd_count_minterm ARGS((bdd_manager *mgr, bdd_node *f, int n));
+EXTERN bdd_node * bdd_add_bdd_threshold ARGS((bdd_manager *mgr, bdd_node *f, BDD_VALUE_TYPE value));
+EXTERN bdd_node * bdd_add_bdd_strict_threshold ARGS((bdd_manager *mgr,bdd_node *f,BDD_VALUE_TYPE value));
+EXTERN BDD_VALUE_TYPE bdd_read_epsilon ARGS((bdd_manager *mgr)); 
+EXTERN bdd_node * bdd_read_one ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_bdd_pick_one_minterm ARGS((bdd_manager *mgr, bdd_node *f, bdd_node **vars, int n));
+EXTERN bdd_t * bdd_pick_one_minterm ARGS((bdd_t *f, array_t *varsArray));
+EXTERN array_t * bdd_bdd_pick_arbitrary_minterms ARGS((bdd_t *f, array_t *varsArray, int n, int k));
+EXTERN bdd_t * bdd_subset_with_mask_vars ARGS((bdd_t *f, array_t *varsArray, array_t *maskVarsArray));
+EXTERN bdd_node * bdd_read_zero ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_bdd_new_var ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_bdd_and_abstract ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g, bdd_node *cube));
+
+EXTERN int bdd_test_unate ARGS((bdd_t *f, int varId, int phase));
+EXTERN array_t * bdd_find_essential ARGS((bdd_t *));
+EXTERN bdd_t * bdd_find_essential_cube ARGS((bdd_t *));
+EXTERN void bdd_deref ARGS((bdd_node *f));
+EXTERN bdd_node * bdd_add_plus ARGS((bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2));
+EXTERN int bdd_read_reorderings ARGS((bdd_manager *mgr));
+EXTERN int bdd_read_next_reordering ARGS((bdd_manager *mgr));
+EXTERN void bdd_set_next_reordering ARGS((bdd_manager *mgr, int next));
+EXTERN bdd_node * bdd_bdd_xnor ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_bdd_xor ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_bdd_vector_compose ARGS((bdd_manager *mgr, bdd_node *f, bdd_node **vector));
+
+EXTERN bdd_node * bdd_zdd_get_node ARGS((bdd_manager *mgr, int id, bdd_node *g, bdd_node *h));
+EXTERN bdd_node * bdd_zdd_product ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_product_recur ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_union ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_union_recur ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_weak_div ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_weak_div_recur ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_isop_recur ARGS((bdd_manager *mgr, bdd_node *L, bdd_node *U, bdd_node **zdd_I));
+EXTERN bdd_node * bdd_zdd_isop ARGS((bdd_manager *mgr, bdd_node *L, bdd_node *U, bdd_node **zdd_I));
+EXTERN int bdd_zdd_get_cofactors3 ARGS((bdd_manager *mgr, bdd_node *f, int v, bdd_node **f1, bdd_node **f0, bdd_node **fd));
+EXTERN bdd_node * bdd_bdd_and_recur ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_unique_inter ARGS((bdd_manager *mgr, int v, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_unique_inter_ivo ARGS((bdd_manager *mgr, int v, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_diff ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_zdd_diff_recur ARGS((bdd_manager *mgr, bdd_node *f, bdd_node *g));
+EXTERN int bdd_num_zdd_vars ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_regular ARGS((bdd_node *f));
+EXTERN int bdd_is_constant ARGS((bdd_node *f));
+EXTERN int bdd_is_complement ARGS((bdd_node *f));
+EXTERN bdd_node * bdd_bdd_T ARGS((bdd_node *f));
+EXTERN bdd_node * bdd_bdd_E ARGS((bdd_node *f));
+EXTERN bdd_node * bdd_not_bdd_node ARGS((bdd_node *f));
+EXTERN void bdd_recursive_deref_zdd ARGS((bdd_manager *mgr, bdd_node *f));
+EXTERN int bdd_zdd_count ARGS((bdd_manager *mgr, bdd_node *f));
+EXTERN int bdd_read_zdd_level ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_zdd_vars_from_bdd_vars ARGS((bdd_manager *mgr, int multiplicity));
+EXTERN void bdd_zdd_realign_enable ARGS((bdd_manager *mgr));
+EXTERN void bdd_zdd_realign_disable ARGS((bdd_manager *mgr));
+EXTERN int bdd_zdd_realignment_enabled ARGS((bdd_manager *mgr));
+EXTERN void bdd_realign_enable ARGS((bdd_manager *mgr));
+EXTERN void bdd_realign_disable ARGS((bdd_manager *mgr));
+EXTERN int bdd_realignment_enabled ARGS((bdd_manager *mgr));
+EXTERN int bdd_node_read_index ARGS((bdd_node *f));
+EXTERN bdd_node * bdd_read_next ARGS((bdd_node *f));
+/* This function should not be used by an external user. This will not be a
+ * part of any future releases.
+ */
+EXTERN void bdd_set_next ARGS((bdd_node *f, bdd_node *g));
+EXTERN bdd_node * bdd_add_apply_recur ARGS((bdd_manager *mgr, bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **), bdd_node *fn1, bdd_node *fn2));
+EXTERN BDD_VALUE_TYPE bdd_add_value ARGS((bdd_node *f));
+
+EXTERN bdd_node * bdd_read_plus_infinity ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_priority_select ARGS((bdd_manager *mgr,bdd_node *R,bdd_node **x,bdd_node **y,bdd_node **z,bdd_node *Pi,int n, bdd_node *(*Pifunc)(bdd_manager *, int, bdd_node **, bdd_node **, bdd_node **)));
+EXTERN void bdd_set_background ARGS((bdd_manager *mgr,bdd_node *f));
+EXTERN bdd_node * bdd_read_background ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_bdd_cofactor ARGS((bdd_manager *mgr,bdd_node *f,bdd_node *g));
+EXTERN bdd_node * bdd_bdd_ite ARGS((bdd_manager *mgr,bdd_node *f,bdd_node *g,bdd_node *h));
+EXTERN bdd_node * bdd_add_minus ARGS((bdd_manager *mgr,bdd_node **fn1,bdd_node **fn2));
+EXTERN bdd_node * bdd_dxygtdxz ARGS((bdd_manager *mgr,int N,bdd_node **x, bdd_node **y, bdd_node **z));
+EXTERN bdd_node * bdd_bdd_univ_abstract ARGS((bdd_manager *mgr,bdd_node *fn,bdd_node *vars));
+EXTERN bdd_node * bdd_bdd_cprojection ARGS((bdd_manager *mgr,bdd_node *R,bdd_node *Y));
+EXTERN double *bdd_cof_minterm ARGS((bdd_t *));
+EXTERN int bdd_var_is_dependent ARGS((bdd_t *, bdd_t *));
+EXTERN int bdd_debug_check ARGS((bdd_manager *mgr));
+EXTERN bdd_node * bdd_xeqy ARGS((bdd_manager *mgr, int N, bdd_node **x, bdd_node **y));
+EXTERN bdd_node * bdd_add_roundoff ARGS((bdd_manager *mgr, bdd_node *f, int N));
+EXTERN bdd_node * bdd_xgty ARGS((bdd_manager *mgr, int N, bdd_node **x, bdd_node **y));
+EXTERN bdd_node * bdd_add_cmpl ARGS((bdd_manager *mgr, bdd_node *f));
+EXTERN bdd_node * bdd_split_set ARGS((bdd_manager *mgr, bdd_node *f, bdd_node ** x, int n, double m));
+
+/*
+ * Queries about BDD Formulas
+ */
+EXTERN boolean bdd_equal ARGS((bdd_t *, bdd_t *));
+EXTERN boolean bdd_equal_mod_care_set ARGS((bdd_t *, bdd_t *, bdd_t *));
+EXTERN boolean bdd_equal_mod_care_set_array ARGS((bdd_t *, bdd_t *, array_t *));
+EXTERN bdd_t *bdd_intersects ARGS((bdd_t *, bdd_t *));
+EXTERN bdd_t *bdd_closest_cube ARGS((bdd_t *, bdd_t *, int *));
+EXTERN boolean bdd_is_tautology ARGS((bdd_t *, boolean));
+EXTERN boolean bdd_leq ARGS((bdd_t *, bdd_t *, boolean, boolean));
+EXTERN boolean bdd_lequal_mod_care_set ARGS((bdd_t *, bdd_t *, boolean, boolean, bdd_t *));
+EXTERN boolean bdd_lequal_mod_care_set_array ARGS((bdd_t *, bdd_t *, boolean, boolean, array_t *));
+EXTERN boolean bdd_leq_array ARGS((bdd_t *, array_t *, boolean, boolean));
+EXTERN double bdd_count_onset ARGS((bdd_t *, array_t *));
+EXTERN int bdd_epd_count_onset ARGS((bdd_t *, array_t *, EpDouble *epd));
+EXTERN int bdd_print_apa_minterm ARGS((FILE *, bdd_t *, int, int));
+EXTERN int bdd_apa_compare_ratios ARGS((int, bdd_t *, bdd_t *, int, int));
+
+EXTERN double bdd_correlation ARGS((bdd_t *, bdd_t *));
+EXTERN int bdd_get_free ARGS((bdd_t *));
+EXTERN bdd_manager *bdd_get_manager ARGS((bdd_t *));
+EXTERN bdd_node *bdd_get_node ARGS((bdd_t *, boolean *));
+EXTERN bdd_node *bdd_extract_node_as_is ARGS((bdd_t *));
+EXTERN var_set_t *bdd_get_support ARGS((bdd_t *));
+EXTERN int bdd_is_support_var ARGS((bdd_t *, bdd_t *));
+EXTERN int bdd_is_support_var_id ARGS((bdd_t *, int));
+EXTERN array_t *bdd_get_varids ARGS((array_t *));
+EXTERN unsigned int bdd_num_vars ARGS((bdd_manager *));
+EXTERN int bdd_read_node_count ARGS((bdd_manager *mgr));
+EXTERN void bdd_print ARGS((bdd_t *));
+EXTERN int bdd_print_minterm ARGS((bdd_t *));
+EXTERN void bdd_print_stats ARGS((bdd_manager *, FILE *));
+EXTERN int bdd_set_parameters ARGS((bdd_manager *, avl_tree *valueTable, FILE *));
+EXTERN int bdd_size ARGS((bdd_t *));
+EXTERN int bdd_node_size ARGS((bdd_node *));
+EXTERN long bdd_size_multiple ARGS((array_t *));
+EXTERN boolean bdd_is_cube ARGS((bdd_t*));
+EXTERN bdd_block * bdd_new_var_block(bdd_t *f, long length);
+EXTERN long bdd_top_var_level ARGS((bdd_manager *manager, bdd_t *fn));
+EXTERN bdd_variableId bdd_get_id_from_level ARGS((bdd_manager *, long));
+EXTERN bdd_variableId bdd_top_var_id ARGS((bdd_t *));
+EXTERN int bdd_get_level_from_id ARGS((bdd_manager *mgr, int id));
+EXTERN int bdd_check_zero_ref ARGS((bdd_manager *mgr));
+EXTERN int bdd_estimate_cofactor ARGS((bdd_t *, bdd_t *, int ));
+/* Reordering related stuff */
+EXTERN void bdd_dynamic_reordering ARGS((bdd_manager *, bdd_reorder_type_t, bdd_reorder_verbosity_t));
+EXTERN void bdd_dynamic_reordering_zdd ARGS((bdd_manager *, bdd_reorder_type_t, bdd_reorder_verbosity_t));
+EXTERN int bdd_reordering_status ARGS((bdd_manager *mgr, bdd_reorder_type_t *method));
+EXTERN int bdd_reordering_zdd_status ARGS((bdd_manager *mgr, bdd_reorder_type_t *method));
+EXTERN void bdd_reorder ARGS((bdd_manager *));
+EXTERN int bdd_shuffle_heap ARGS((bdd_manager *mgr, int *permut));
+EXTERN void bdd_dynamic_reordering_disable ARGS((bdd_manager *mgr));
+EXTERN void bdd_dynamic_reordering_zdd_disable ARGS((bdd_manager *mgr));
+EXTERN int bdd_read_reordered_field ARGS((bdd_manager *mgr));
+EXTERN int bdd_add_hook ARGS((bdd_manager *, int (*procedure)(bdd_manager *, char *, void *), bdd_hook_type_t ));
+EXTERN int bdd_remove_hook ARGS((bdd_manager *, int (*procedure)(bdd_manager *, char *, void *), bdd_hook_type_t ));
+EXTERN int bdd_enable_reordering_reporting ARGS((bdd_manager *));
+EXTERN int bdd_disable_reordering_reporting ARGS((bdd_manager *));
+EXTERN bdd_reorder_verbosity_t bdd_reordering_reporting ARGS((bdd_manager *));
+/* This function should not be used by an external user. It will
+ * not be a part of any future release.
+ */
+EXTERN void bdd_set_reordered_field ARGS((bdd_manager *mgr, int n));
+EXTERN bdd_node *bdd_bdd_vector_support ARGS((bdd_manager *mgr,bdd_node **F,int n));
+EXTERN int bdd_bdd_vector_support_size ARGS((bdd_manager *mgr,bdd_node **F, int n));
+EXTERN int bdd_bdd_support_size ARGS((bdd_manager *mgr,bdd_node *F));
+EXTERN bdd_node *bdd_bdd_support ARGS((bdd_manager *mgr,bdd_node *F));
+EXTERN bdd_node *bdd_add_general_vector_compose ARGS((bdd_manager *mgr,bdd_node *f,bdd_node **vectorOn,bdd_node **vectorOff));
+EXTERN int bdd_bdd_leq ARGS((bdd_manager *mgr,bdd_node *f,bdd_node *g));
+EXTERN bdd_node *bdd_bdd_boolean_diff ARGS((bdd_manager *mgr,bdd_node *f,int x));
+
+/*
+** Generator related functions.
+** These are NOT to be used directly; only indirectly in the macros.
+*/
+EXTERN bdd_gen_status bdd_gen_read_status ARGS((bdd_gen *gen));
+EXTERN bdd_gen *bdd_first_cube ARGS((bdd_t *, array_t **));
+EXTERN boolean bdd_next_cube ARGS((bdd_gen *, array_t **));
+EXTERN bdd_gen *bdd_first_disjoint_cube ARGS((bdd_t *, array_t **));
+EXTERN boolean bdd_next_disjoint_cube ARGS((bdd_gen *, array_t **));
+EXTERN bdd_gen *bdd_first_node ARGS((bdd_t *, bdd_node **));
+EXTERN boolean bdd_next_node ARGS((bdd_gen *, bdd_node **));
+EXTERN int bdd_gen_free ARGS((bdd_gen *));
+
+/* 
+ * Miscellaneous
+ */
+EXTERN void bdd_set_gc_mode ARGS((bdd_manager *, boolean));
+EXTERN bdd_external_hooks *bdd_get_external_hooks ARGS((bdd_manager *));
+EXTERN bdd_t *bdd_construct_bdd_t ARGS((bdd_manager *mgr, bdd_node * fn));
+EXTERN void bdd_dump_blif ARGS((bdd_manager *mgr, int nBdds, bdd_node **bdds, char **inames, char **onames, char *model, FILE *fp));
+EXTERN void bdd_dump_blif_body ARGS((bdd_manager *mgr, int nBdds, bdd_node **bdds, char **inames, char **onames, FILE *fp));
+EXTERN void bdd_dump_dot ARGS((bdd_manager *mgr, int nBdds, bdd_node **bdds, char **inames, char **onames, FILE *fp));
+EXTERN bdd_node *bdd_make_bdd_from_zdd_cover ARGS((bdd_manager *mgr, bdd_node *node));
+EXTERN bdd_node *bdd_zdd_complement ARGS((bdd_manager *mgr, bdd_node *node));
+EXTERN int bdd_ptrcmp ARGS((bdd_t *f, bdd_t *g));
+EXTERN int bdd_ptrhash ARGS((bdd_t *f,int size));
+EXTERN long bdd_read_peak_memory ARGS (( bdd_manager *mgr));
+EXTERN int bdd_read_peak_live_node ARGS (( bdd_manager *mgr));
+EXTERN int bdd_set_pi_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_set_ps_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_set_ns_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_is_pi_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_is_ps_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_is_ns_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_set_pair_index ARGS((bdd_manager *mgr, int index, int pairIndex));
+EXTERN int bdd_read_pair_index ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_set_var_to_be_grouped ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_set_var_hard_group ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_reset_var_to_be_grouped ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_is_var_to_be_grouped ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_is_var_hard_group ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_is_var_to_be_ungrouped ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_set_var_to_be_ungrouped ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_bind_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_unbind_var ARGS((bdd_manager *mgr, int index));
+EXTERN int bdd_is_lazy_sift ARGS((bdd_manager *mgr));
+EXTERN void bdd_discard_all_var_groups ARGS((bdd_manager *mgr));
+#endif 
+
Index: /vis_dev/glu-2.1/src/bdd/bdd.make
===================================================================
--- /vis_dev/glu-2.1/src/bdd/bdd.make	(revision 8)
+++ /vis_dev/glu-2.1/src/bdd/bdd.make	(revision 8)
@@ -0,0 +1,1 @@
+HEADERS += bdd.h
Index: /vis_dev/glu-2.1/src/calBdd/cal.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/cal.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/cal.c	(revision 8)
@@ -0,0 +1,1034 @@
+/**CFile***********************************************************************
+
+  FileName    [cal.c]
+
+  PackageName [cal]
+
+  Synopsis    [Miscellaneous collection of exported BDD functions]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [
+               Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu
+              ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: cal.c,v 1.1.1.5 1998/05/04 00:58:48 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Cal_Bdd_t BddIntersectsStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t g);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if argument BDDs are equal, 0 otherwise.]
+
+  Description [Returns 1 if argument BDDs are equal, 0 otherwise.]
+
+  SideEffects [None.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cal_BddIsEqual(Cal_BddManager bddManager, Cal_Bdd userBdd1, Cal_Bdd userBdd2)
+{
+  return (userBdd1 == userBdd2);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the argument BDD is constant one, 0 otherwise.]
+
+  Description [Returns 1 if the argument BDD is constant one, 0 otherwise.]
+
+  SideEffects [None.]
+
+  SeeAlso     [Cal_BddIsBddZero]
+
+******************************************************************************/
+int
+Cal_BddIsBddOne(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  return (userBdd == bddManager->userOneBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the argument BDD is constant zero, 0 otherwise.]
+
+  Description [Returns 1 if the argument BDD is constant zero, 0 otherwise.]
+
+  SideEffects [None.]
+
+  SeeAlso     [Cal_BddIsBddOne]
+
+******************************************************************************/
+int
+Cal_BddIsBddZero(
+  Cal_BddManager bddManager,
+  Cal_Bdd userBdd)
+{
+  return (userBdd == bddManager->userZeroBdd);
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the argument BDD is NULL, 0 otherwise.]
+
+  Description [Returns 1 if the argument BDD is NULL, 0 otherwise.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+int
+Cal_BddIsBddNull(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  return (userBdd == 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the argument BDD is a constant, 0 otherwise.]
+
+  Description [Returns 1 if the argument BDD is either constant one or
+  constant zero, otherwise returns 0.]
+
+  SideEffects [None.]
+
+  SeeAlso     [Cal_BddIsBddOne, Cal_BddIsBddZero]
+
+******************************************************************************/
+int
+Cal_BddIsBddConst(
+  Cal_BddManager bddManager,
+  Cal_Bdd userBdd)
+{
+  return ((userBdd == bddManager->userOneBdd) ||
+          (userBdd == bddManager->userZeroBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the duplicate BDD of the argument BDD.]
+
+  Description [Returns the duplicate BDD of the argument BDD.]
+
+  SideEffects [The reference count of the BDD is increased by 1.]
+
+  SeeAlso     [Cal_BddNot]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddIdentity(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  /* Interface BDD reference count */
+  CalBddNode_t *bddNode = CAL_BDD_POINTER(userBdd);
+  CalBddNodeIcrRefCount(bddNode);
+  return userBdd;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for the constant one]
+
+  Description [Returns the BDD for the constant one]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddZero]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddOne(Cal_BddManager bddManager)
+{
+  return bddManager->userOneBdd;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for the constant zero]
+
+  Description [Returns the BDD for the constant zero]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddOne]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddZero(Cal_BddManager bddManager)
+{
+  return bddManager->userZeroBdd;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the complement of the argument BDD.]
+
+  Description [Returns the complement of the argument BDD.]
+
+  SideEffects [The reference count of the argument BDD is increased by 1.]
+
+  SeeAlso     [Cal_BddIdentity]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddNot(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  /* Interface BDD reference count */
+  CalBddNode_t *bddNode = CAL_BDD_POINTER(userBdd);
+  CalBddNodeIcrRefCount(bddNode);
+  return CalBddNodeNot(userBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the top variable of the argument BDD.]
+
+  Description [Returns the index of the top variable of the argument BDD.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddGetIfId]
+
+******************************************************************************/
+Cal_BddId_t
+Cal_BddGetIfIndex(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  Cal_Bdd_t F;
+  if (CalBddPreProcessing(bddManager, 1, userBdd) == 1){
+    F = CalBddGetInternalBdd(bddManager, userBdd);
+    if (CalBddIsBddConst(F)){
+      return -1;
+    }
+    return CalBddGetBddIndex(bddManager, F);
+  }
+  return -1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the id of the top variable of the argument BDD.]
+
+  Description [Returns the id of the top variable of the argument BDD.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddGetIfIndex]
+
+******************************************************************************/
+Cal_BddId_t
+Cal_BddGetIfId(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  Cal_Bdd_t F;
+  if (CalBddPreProcessing(bddManager, 1, userBdd) == 1){
+    F = CalBddGetInternalBdd(bddManager, userBdd);
+    if (CalBddIsBddConst(F)){
+      return 0;
+    }
+    return CalBddGetBddId(F);
+  }
+  return -1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD corresponding to the top variable of
+  the argument BDD.]
+
+  Description [Returns the BDD corresponding to the top variable of
+  the argument BDD.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddIf(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  Cal_Bdd_t F;
+  if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+    return (Cal_Bdd)0;
+  }
+  F = CalBddGetInternalBdd(bddManager, userBdd);
+  if (CalBddIsBddConst(F)){
+    CalBddWarningMessage("Cal_BddIf: argument is constant");
+  }
+  return CalBddGetExternalBdd(bddManager, bddManager->varBdds[CalBddGetBddId(F)]);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the positive cofactor of the argument BDD with
+  respect to the top variable of the BDD.]
+
+  Description [Returns the positive cofactor of the argument BDD with
+  respect to the top variable of the BDD.]
+
+  SideEffects [The reference count of the returned BDD is increased by 1.]
+
+  SeeAlso     [Cal_BddElse]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddThen(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  Cal_Bdd_t thenBdd;
+  Cal_Bdd_t F;
+  if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+    return (Cal_Bdd)0;
+  }
+  F = CalBddGetInternalBdd(bddManager, userBdd);
+  CalBddGetThenBdd(F, thenBdd);
+  return CalBddGetExternalBdd(bddManager, thenBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the negative cofactor of the argument BDD with
+  respect to the top variable of the BDD.]
+
+  Description [Returns the negative cofactor of the argument BDD with
+  respect to the top variable of the BDD.]
+
+  SideEffects [The reference count of the returned BDD is increased by 1.]
+
+  SeeAlso     [Cal_BddThen]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddElse(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  Cal_Bdd_t elseBdd;
+  Cal_Bdd_t F;
+  if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+    return (Cal_Bdd) 0;
+  }
+  F = CalBddGetInternalBdd(bddManager, userBdd);
+  CalBddGetElseBdd(F, elseBdd);
+  return CalBddGetExternalBdd(bddManager, elseBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the argument BDD.]
+
+  Description [Frees the argument BDD. It is an error to free a BDD
+  more than once.]
+
+  SideEffects [The reference count of the argument BDD is decreased by 1.]
+
+  SeeAlso     [Cal_BddUnFree]
+
+******************************************************************************/
+void
+Cal_BddFree(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  /* Interface BDD reference count */
+  CalBddNodeDcrRefCount(CAL_BDD_POINTER(userBdd));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Unfrees the argument BDD.]
+
+  Description [Unfrees the argument BDD. It is an error to pass a BDD
+  with reference count of zero to be unfreed.]
+
+  SideEffects [The reference count of the argument BDD is increased by 1.]
+
+  SeeAlso     [Cal_BddFree]
+
+******************************************************************************/
+void
+Cal_BddUnFree(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  /* Interface BDD reference count */
+  CalBddNode_t *bddNode = CAL_BDD_POINTER(userBdd);
+  CalBddNodeIcrRefCount(bddNode);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a BDD with positive from a given BDD with arbitrary phase]
+
+  Description [Returns a BDD with positive from a given BDD with arbitrary phase]
+
+  SideEffects [None.]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddGetRegular(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  return CAL_BDD_POINTER(userBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a BDD that implies conjunction of f and g.]
+
+  Description [Computes a BDD that implies conjunction of f and g.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddImplies]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddIntersects(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd
+                  gUserBdd) 
+{
+  Cal_Bdd_t result;
+  Cal_Bdd_t f, g;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd) == 0){
+    return (Cal_Bdd) 0;
+  }
+  f = CalBddGetInternalBdd(bddManager, fUserBdd);
+  g = CalBddGetInternalBdd(bddManager, gUserBdd);
+  result = BddIntersectsStep(bddManager,f,g);
+  return CalBddGetExternalBdd(bddManager, result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a BDD that implies conjunction of f and Cal_BddNot(g)]
+
+  Description [Computes a BDD that implies conjunction of f and Cal_BddNot(g)]
+
+  SideEffects [none]
+
+  SeeAlso     [Cal_BddIntersects]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddImplies(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd_t f, g;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    Cal_Bdd_t gNot;
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    g = CalBddGetInternalBdd(bddManager, gUserBdd);
+    CalBddNot(g, gNot);
+    result = BddIntersectsStep(bddManager,f, gNot);
+  }
+  else{
+    return (Cal_Bdd) 0;
+  }
+  return CalBddGetExternalBdd(bddManager, result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes in the Unique table]
+
+  Description [Returns the number of nodes in the Unique table]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddManagerGetNumNodes]
+
+******************************************************************************/
+unsigned long
+Cal_BddTotalSize(Cal_BddManager bddManager)
+{
+  return Cal_BddManagerGetNumNodes(bddManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints miscellaneous BDD statistics]
+
+  Description [Prints miscellaneous BDD statistics]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cal_BddStats(Cal_BddManager bddManager, FILE * fp)
+{
+  unsigned long cacheInsertions = 0;
+  unsigned long cacheEntries = 0;
+  unsigned long cacheSize = 0;
+  unsigned long cacheHits = 0;
+  unsigned long cacheLookups = 0;
+  unsigned long cacheCollisions = 0;
+  unsigned long numLockedNodes = 0;
+  int i, id, depth;
+  long numPages;
+  unsigned long totalBytes;
+  
+  
+  fprintf(fp, "**** CAL modifiable parameters ****\n");
+  fprintf(fp, "Node limit: %ld\n", bddManager->nodeLimit);
+  fprintf(fp, "Garbage collection enabled: %s\n",
+          ((bddManager->gcMode) ? "yes" : "no"));
+  fprintf(fp, "Maximum number of variables sifted per reordering: %ld\n", 
+          bddManager->maxNumVarsSiftedPerReordering);
+  fprintf(fp, "Maximum number of variable swaps per reordering: %ld\n",
+          bddManager->maxNumSwapsPerReordering);
+  fprintf(fp, "Maximum growth while sifting a variable: %2.2f\n",
+          bddManager->maxSiftingGrowth);
+  fprintf(fp, "Dynamic reordering of BDDs enabled: %s\n", 
+          ((bddManager->dynamicReorderingEnableFlag) ? "yes" : "no"));
+  fprintf(fp, "Repacking after GC Threshold: %f\n", 
+          bddManager->repackAfterGCThreshold);
+  fprintf(fp, "**** CAL statistics ****\n");
+  fprintf(fp, "Total BDD Node Usage : %ld nodes, %ld Bytes\n",
+          bddManager->numNodes, bddManager->numNodes*sizeof(CalBddNode_t));
+  fprintf(fp, "Peak BDD Node Usage : %ld nodes, %ld Bytes\n",
+          bddManager->numPeakNodes,
+          bddManager->numPeakNodes*sizeof(CalBddNode_t)); 
+  for (i=1; i<=bddManager->numVars; i++){
+    numLockedNodes += CalBddUniqueTableNumLockedNodes(bddManager,
+                                                      bddManager->uniqueTable[i]);
+  }
+  fprintf(fp, "Number of nodes locked: %ld\n", numLockedNodes);
+  fprintf(fp, "Total Number of variables: %d\n", bddManager->numVars);
+  numPages =
+      bddManager->pageManager1->totalNumPages+
+      bddManager->pageManager2->totalNumPages;
+  fprintf(fp, "Total memory allocated for BDD nodes: %ld pages (%ld Bytes)\n",
+          numPages, PAGE_SIZE*numPages);
+  /* Calculate the memory consumed */
+  totalBytes =
+      /* Over all bdd manager */
+      sizeof(Cal_BddManager_t)+
+      bddManager->maxNumVars*(sizeof(Cal_Bdd_t)+sizeof(CalNodeManager_t *)+
+                              sizeof(CalHashTable_t *) +
+                              sizeof(CalHashTable_t *) + sizeof(CalRequestNode_t*)*2)+
+      sizeof(CalPageManager_t)*2+
+      /* Page manager */
+      bddManager->pageManager1->maxNumSegments*(sizeof(CalAddress_t *)+sizeof(int))+
+      bddManager->pageManager2->maxNumSegments*
+      (sizeof(CalAddress_t *)+sizeof(int)); 
+
+  for (id=0; id <= bddManager->numVars; id++){
+    totalBytes += bddManager->nodeManagerArray[id]->maxNumPages*sizeof(int);;
+  }
+  /* IndexToId and IdToIndex */
+  totalBytes += 2*bddManager->maxNumVars*(sizeof(Cal_BddIndex_t));
+  for (id=0; id <= bddManager->numVars; id++){
+    totalBytes += bddManager->uniqueTable[id]->numBins*sizeof(int);;
+  }
+  /* Cache Table */
+  totalBytes += CalCacheTableMemoryConsumption(bddManager->cacheTable);
+  
+  /* Req que */
+  totalBytes += bddManager->maxDepth*sizeof(CalHashTable_t **);
+  for (depth = 0; depth < bddManager->depth; depth++){
+    for (id=0; id <= bddManager->numVars; id++){
+      if (bddManager->reqQue[depth][id]){
+        totalBytes +=
+            bddManager->reqQue[depth][id]->numBins*
+            sizeof(CalBddNode_t*);
+      }
+    }
+  }
+  /* Association */
+  totalBytes += sizeof(CalAssociation_t)*2;
+  /* Block */
+  totalBytes += CalBlockMemoryConsumption(bddManager->superBlock);
+
+  fprintf(fp, "Total memory consumed: %ld Pages (%ld Bytes)\n",
+          numPages+totalBytes/PAGE_SIZE,
+          PAGE_SIZE*numPages+totalBytes);  
+
+  CalBddManagerGetCacheTableData(bddManager, &cacheSize,
+                                 &cacheEntries, &cacheInsertions, 
+                                 &cacheLookups, &cacheHits, &cacheCollisions);
+  fprintf(fp, "Cache Size: %ld\n", cacheSize);
+  fprintf(fp, "Cache Entries: %ld\n", cacheEntries);
+  fprintf(fp, "Cache Insertions: %ld\n", cacheInsertions);
+  fprintf(fp, "Cache Collisions: %ld\n", cacheCollisions);
+  fprintf(fp, "Cache Hits: %ld\n", cacheHits);
+  if (cacheLookups){
+    fprintf(fp, "Cache Lookup: %ld\n", cacheLookups);
+    fprintf(fp, "Cache hit ratio: %-.2f\n", ((double)cacheHits)/cacheLookups);
+  }
+  fprintf(fp, "Number of nodes garbage collected: %ld\n",
+          bddManager->numNodesFreed);
+  fprintf(fp,"number of garbage collections: %d\n", bddManager->numGC);
+  fprintf(fp,"number of dynamic reorderings: %d\n",
+          bddManager->numReorderings); 
+  fprintf(fp,"number of trivial swaps: %ld\n", bddManager->numTrivialSwaps); 
+  fprintf(fp,"number of swaps in last reordering: %ld\n", bddManager->numSwaps); 
+  fprintf(fp,"garbage collection limit: %ld\n", bddManager->uniqueTableGCLimit);
+  fflush(fp);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Specify dynamic reordering technique.]
+
+  Description [Selects the method for dynamic reordering.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddReorder]
+
+******************************************************************************/
+void
+Cal_BddDynamicReordering(Cal_BddManager bddManager, int technique)
+{
+  bddManager->reorderTechnique = technique;
+  bddManager->dynamicReorderingEnableFlag = 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Invoke the current dynamic reodering method.]
+
+  Description [Invoke the current dynamic reodering method.]
+
+  SideEffects [Index of a variable may change due to reodering]
+
+  SeeAlso     [Cal_BddDynamicReordering]
+
+******************************************************************************/
+void
+Cal_BddReorder(Cal_BddManager bddManager)
+{
+  if ((bddManager->dynamicReorderingEnableFlag == 0) ||
+      (bddManager->reorderTechnique == CAL_REORDER_NONE)){
+    return;
+  }
+  CalCacheTableTwoFlush(bddManager->cacheTable);
+  if (bddManager->reorderMethod == CAL_REORDER_METHOD_DF){
+    CalBddReorderAuxDF(bddManager);
+  }
+  else if (bddManager->reorderMethod == CAL_REORDER_METHOD_BF){ 
+    Cal_BddManagerGC(bddManager);
+    CalBddReorderAuxBF(bddManager);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns type of a BDD ( 0, 1, +var, -var, ovrflow, nonterminal)]
+
+  Description [Returns BDD_TYPE_ZERO if f is false, BDD_TYPE_ONE 
+  if f is true, BDD_TYPE_POSVAR is f is an unnegated variable,
+  BDD_TYPE_NEGVAR if f is a negated variable, BDD_TYPE_OVERFLOW if f
+  is null, and BDD_TYPE_NONTERMINAL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+Cal_BddType(Cal_BddManager bddManager, Cal_Bdd fUserBdd)
+{
+  Cal_Bdd_t f;
+  if (CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    return (CalBddTypeAux(bddManager, f));
+  }
+  return (CAL_BDD_TYPE_OVERFLOW);
+}
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of BDD variables]
+
+  Description [Returns the number of BDD variables]
+
+  SideEffects [None]
+
+******************************************************************************/
+long
+Cal_BddVars(Cal_BddManager bddManager)
+{
+  return (bddManager->numVars);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the node limit to new_limit and returns the old limit.]
+
+  Description [Sets the node limit to new_limit and returns the old limit.]
+
+  SideEffects [Threshold for garbage collection may change]
+
+  SeeAlso     [Cal_BddManagerGC]
+
+******************************************************************************/
+long
+Cal_BddNodeLimit(
+  Cal_BddManager bddManager,
+  long  newLimit)
+{
+  long oldLimit;
+
+  oldLimit = bddManager->nodeLimit;
+  if (newLimit < 0){
+    newLimit=0;
+  }
+  bddManager->nodeLimit = newLimit;
+  if (newLimit && (bddManager->uniqueTableGCLimit > newLimit)){
+    bddManager->uniqueTableGCLimit = newLimit;
+  }
+  return (oldLimit);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the node limit has been exceeded, 0 otherwise. The
+  overflow flag is cleared.]
+
+  Description [Returns 1 if the node limit has been exceeded, 0 otherwise. The
+  overflow flag is cleared.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddNodeLimit]
+
+******************************************************************************/
+int
+Cal_BddOverflow(Cal_BddManager bddManager)
+{
+  int result;
+  result = bddManager->overflow;
+  bddManager->overflow = 0;
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Returns 1 if the argument BDD is a cube, 0 otherwise]
+
+  Description        [Returns 1 if the argument BDD is a cube, 0 otherwise]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+Cal_BddIsCube(
+  Cal_BddManager bddManager,
+  Cal_Bdd fUserBdd)
+{
+  Cal_Bdd_t f0, f1;
+  Cal_Bdd_t f;
+  f = CalBddGetInternalBdd(bddManager, fUserBdd);
+  if (CalBddIsBddConst(f)){
+    if (CalBddIsBddZero(bddManager, f)){
+      CalBddFatalMessage("Cal_BddIsCube called with 0");
+    }
+    else return 1;
+  }
+
+  CalBddGetThenBdd(f, f1);
+  CalBddGetElseBdd(f, f0);
+  /*
+   * Exactly one branch of f must point to ZERO to be a cube.
+   */
+  if (CalBddIsBddZero(bddManager, f1)){
+	return (CalBddIsCubeStep(bddManager, f0));
+  } else if (CalBddIsBddZero(bddManager, f0)){
+	return (CalBddIsCubeStep(bddManager, f1));
+  } else { /* not a cube, because neither branch is zero */
+	return 0;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Returns the hooks field of the manager.]
+
+  Description        [Returns the hooks field of the manager.]
+
+  SideEffects        [None]
+
+  SeeAlso            []
+
+******************************************************************************/
+void *
+Cal_BddManagerGetHooks(Cal_BddManager bddManager)
+{
+  return bddManager->hooks;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Sets the hooks field of the manager.]
+
+  Description        [Sets the hooks field of the manager.]
+
+  SideEffects        [Hooks field changes. ]
+
+  SeeAlso            []
+
+******************************************************************************/
+void 
+Cal_BddManagerSetHooks(Cal_BddManager bddManager, void *hooks)
+{
+  bddManager->hooks = hooks;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD corresponding to the top variable of
+  the argument BDD.]
+
+  Description [Returns the BDD corresponding to the top variable of
+  the argument BDD.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+Cal_Bdd_t
+CalBddIf(Cal_BddManager bddManager, Cal_Bdd_t F)
+{
+  if (CalBddIsBddConst(F)){
+    CalBddWarningMessage("CalBddIf: argument is constant");
+  }
+  return bddManager->varBdds[CalBddGetBddId(F)];
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Returns 1 if the argument BDD is a cube, 0 otherwise]
+
+  Description        [Returns 1 if the argument BDD is a cube, 0 otherwise]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+CalBddIsCubeStep(Cal_BddManager bddManager, Cal_Bdd_t f)
+{
+  Cal_Bdd_t f0, f1;
+  if (CalBddIsBddConst(f)){
+    if (CalBddIsBddZero(bddManager, f)){
+      CalBddFatalMessage("Cal_BddIsCube called with 0");
+    }
+    else return 1;
+  }
+
+  CalBddGetThenBdd(f, f1);
+  CalBddGetElseBdd(f, f0);
+  /*
+   * Exactly one branch of f must point to ZERO to be a cube.
+   */
+  if (CalBddIsBddZero(bddManager, f1)){
+	return (CalBddIsCubeStep(bddManager, f0));
+  } else if (CalBddIsBddZero(bddManager, f0)){
+	return (CalBddIsCubeStep(bddManager, f1));
+  } else { /* not a cube, because neither branch is zero */
+	return 0;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD type by recursively traversing the argument BDD]
+
+  Description [Returns the BDD type by recursively traversing the argument BDD]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+CalBddTypeAux(Cal_BddManager_t * bddManager, Cal_Bdd_t f)
+{
+  Cal_Bdd_t thenBdd, elseBdd;
+  
+  if (CalBddIsBddConst(f)){
+    if (CalBddIsBddZero(bddManager, f)) return (CAL_BDD_TYPE_ZERO);
+    if (CalBddIsBddOne(bddManager, f)) return (CAL_BDD_TYPE_ONE);
+  }
+  CalBddGetThenBdd(f, thenBdd);
+  CalBddGetElseBdd(f, elseBdd);
+  if (CalBddIsBddOne(bddManager, thenBdd) &&
+      CalBddIsBddZero(bddManager, elseBdd))
+    return CAL_BDD_TYPE_POSVAR;
+  if (CalBddIsBddZero(bddManager, thenBdd) &&
+      CalBddIsBddOne(bddManager, elseBdd))
+    return (CAL_BDD_TYPE_NEGVAR);
+  return (CAL_BDD_TYPE_NONTERMINAL);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the duplicate BDD of the argument BDD.]
+
+  Description [Returns the duplicate BDD of the argument BDD.]
+
+  SideEffects [The reference count of the BDD is increased by 1.]
+
+  SeeAlso     [Cal_BddNot]
+
+******************************************************************************/
+Cal_Bdd_t
+CalBddIdentity(Cal_BddManager_t *bddManager, Cal_Bdd_t calBdd)
+{
+  CalBddIcrRefCount(calBdd);
+  return calBdd;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Recursive routine to returns a BDD that implies conjunction of
+  argument BDDs]
+
+  Description [Recursive routine to returns a BDD that implies conjunction of
+  argument BDDs]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddIntersectsStep(Cal_BddManager_t * bddManager, Cal_Bdd_t  f, Cal_Bdd_t  g)
+{
+  Cal_Bdd_t f1, f2, g1, g2, result, temp;
+  Cal_BddId_t topId;
+  
+  
+  if (CalBddIsBddConst(f)){
+    if (CalBddIsBddZero(bddManager, f)){
+      return f;
+    }
+    else {
+      return g;
+    }
+  }
+  if (CalBddIsBddConst(g)){
+    if (CalBddIsBddZero(bddManager, g)){
+      return g;
+    }
+    else {
+      return f;
+    }
+  }
+  if (CalBddSameOrNegation(f, g)){
+    if (CalBddIsEqual(f, g)){
+      return f;
+    }
+    else
+      return bddManager->bddZero;
+  }
+  if (CAL_BDD_OUT_OF_ORDER(f, g)) CAL_BDD_SWAP(f, g);
+  CalBddGetMinId2(bddManager, f, g, topId);
+  CalBddGetCofactors(f, topId, f1, f2);
+  CalBddGetCofactors(g, topId, g1, g2);
+  temp = BddIntersectsStep(bddManager, f1, g1);
+  if (CalBddIsBddZero(bddManager, temp)){
+    temp = BddIntersectsStep(bddManager, f2, g2);
+    if (CalBddIsBddZero(bddManager, temp)){
+      return bddManager->bddZero;
+    }
+    else{
+      if(CalUniqueTableForIdFindOrAdd(bddManager,
+                                      bddManager->uniqueTable[topId],  
+                                      bddManager->bddZero, temp,
+                                      &result) == 0){
+        CalBddIcrRefCount(temp);
+      }
+    }
+  }
+  else {
+    if(CalUniqueTableForIdFindOrAdd(bddManager, bddManager->uniqueTable[topId],
+                          temp, bddManager->bddZero,&result) == 0){
+      CalBddIcrRefCount(temp);
+    }
+  }
+  return result;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/cal.h
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/cal.h	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/cal.h	(revision 8)
@@ -0,0 +1,251 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cal.h]
+
+  PackageName [cal]
+
+  Synopsis    [Header CAL file for exported data structures and functions.]
+
+  Description []
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu)] 
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: cal.h,v 1.8 2002/09/08 21:22:16 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CAL
+#define _CAL
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+#endif
+#if HAVE_SYS_RESOURCE_H
+#  include <sys/resource.h>
+#endif
+#if HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+#if HAVE_TIME_H
+#  include <time.h>
+#endif
+
+#include <assert.h>
+#include <math.h>
+
+#include "calMem.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef EXTERN
+#  ifdef __cplusplus
+#    define EXTERN	extern "C"
+#  else
+#    define EXTERN	extern
+#  endif
+#endif
+
+#define CAL_BDD_TYPE_NONTERMINAL 0
+#define CAL_BDD_TYPE_ZERO 1
+#define CAL_BDD_TYPE_ONE 2
+#define CAL_BDD_TYPE_POSVAR 3
+#define CAL_BDD_TYPE_NEGVAR 4
+#define CAL_BDD_TYPE_OVERFLOW 5
+#define CAL_BDD_TYPE_CONSTANT 6
+
+#define CAL_BDD_UNDUMP_FORMAT 1
+#define CAL_BDD_UNDUMP_OVERFLOW 2
+#define CAL_BDD_UNDUMP_IOERROR 3
+#define CAL_BDD_UNDUMP_EOF 4
+
+#define CAL_REORDER_NONE 0
+#define CAL_REORDER_SIFT 1
+#define CAL_REORDER_WINDOW 2
+#define CAL_REORDER_METHOD_BF 0
+#define CAL_REORDER_METHOD_DF 1
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct Cal_BddManagerStruct *Cal_BddManager;
+typedef struct Cal_BddManagerStruct Cal_BddManager_t;
+typedef struct CalBddNodeStruct *Cal_Bdd;
+typedef unsigned short int Cal_BddId_t;
+typedef unsigned short int Cal_BddIndex_t;
+typedef char * (*Cal_VarNamingFn_t)(Cal_BddManager, Cal_Bdd, Cal_Pointer_t); 
+typedef char * (*Cal_TerminalIdFn_t)(Cal_BddManager, Cal_Address_t, Cal_Address_t, Cal_Pointer_t);      
+typedef struct Cal_BlockStruct *Cal_Block;
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+enum Cal_BddOpEnum {CAL_AND, CAL_OR, CAL_XOR};
+typedef enum Cal_BddOpEnum Cal_BddOp_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#define Cal_BddNamingFnNone ((char *(*)(Cal_BddManager, Cal_Bdd, Cal_Pointer_t))0)
+#define Cal_BddTerminalIdFnNone ((char *(*)(Cal_BddManager, Cal_Address_t, Cal_Address_t, Cal_Pointer_t))0)
+#ifdef _CAL_DEBUG_
+#define Cal_Assert(valid) assert(valid)
+#else
+#define Cal_Assert(ignore) ((void)0)
+#endif
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int Cal_BddIsEqual(Cal_BddManager bddManager, Cal_Bdd userBdd1, Cal_Bdd userBdd2);
+EXTERN int Cal_BddIsBddOne(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN int Cal_BddIsBddZero(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN int Cal_BddIsBddNull(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN int Cal_BddIsBddConst(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddIdentity(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddOne(Cal_BddManager bddManager);
+EXTERN Cal_Bdd Cal_BddZero(Cal_BddManager bddManager);
+EXTERN Cal_Bdd Cal_BddNot(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_BddId_t Cal_BddGetIfIndex(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_BddId_t Cal_BddGetIfId(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddIf(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddThen(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddElse(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN void Cal_BddFree(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN void Cal_BddUnFree(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddGetRegular(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddIntersects(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd Cal_BddImplies(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN unsigned long Cal_BddTotalSize(Cal_BddManager bddManager);
+EXTERN void Cal_BddStats(Cal_BddManager bddManager, FILE * fp);
+EXTERN void Cal_BddDynamicReordering(Cal_BddManager bddManager, int technique);
+EXTERN void Cal_BddReorder(Cal_BddManager bddManager);
+EXTERN int Cal_BddType(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN long Cal_BddVars(Cal_BddManager bddManager);
+EXTERN long Cal_BddNodeLimit(Cal_BddManager bddManager, long newLimit);
+EXTERN int Cal_BddOverflow(Cal_BddManager bddManager);
+EXTERN int Cal_BddIsCube(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN void * Cal_BddManagerGetHooks(Cal_BddManager bddManager);
+EXTERN void Cal_BddManagerSetHooks(Cal_BddManager bddManager, void *hooks);
+EXTERN int Cal_AssociationInit(Cal_BddManager bddManager, Cal_Bdd *associationInfoUserBdds, int pairs);
+EXTERN void Cal_AssociationQuit(Cal_BddManager bddManager, int associationId);
+EXTERN int Cal_AssociationSetCurrent(Cal_BddManager bddManager, int associationId);
+EXTERN void Cal_TempAssociationAugment(Cal_BddManager bddManager, Cal_Bdd *associationInfoUserBdds, int pairs);
+EXTERN void Cal_TempAssociationInit(Cal_BddManager bddManager, Cal_Bdd *associationInfoUserBdds, int pairs);
+EXTERN void Cal_TempAssociationQuit(Cal_BddManager bddManager);
+EXTERN Cal_Bdd Cal_BddCompose(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd, Cal_Bdd hUserBdd);
+EXTERN Cal_Bdd Cal_BddITE(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd, Cal_Bdd hUserBdd);
+EXTERN Cal_BddManager Cal_BddManagerInit(void);
+EXTERN int Cal_BddManagerQuit(Cal_BddManager bddManager);
+EXTERN void Cal_BddManagerSetParameters(Cal_BddManager bddManager, long reorderingThreshold, long maxForwardedNodes, double repackAfterGCThreshold, double tableRepackThreshold);
+EXTERN unsigned long Cal_BddManagerGetNumNodes(Cal_BddManager bddManager);
+EXTERN Cal_Bdd Cal_BddManagerCreateNewVarFirst(Cal_BddManager bddManager);
+EXTERN Cal_Bdd Cal_BddManagerCreateNewVarLast(Cal_BddManager bddManager);
+EXTERN Cal_Bdd Cal_BddManagerCreateNewVarBefore(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddManagerCreateNewVarAfter(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd Cal_BddManagerGetVarWithIndex(Cal_BddManager bddManager, Cal_BddIndex_t index);
+EXTERN Cal_Bdd Cal_BddManagerGetVarWithId(Cal_BddManager bddManager, Cal_BddId_t id);
+EXTERN Cal_Bdd Cal_BddAnd(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd Cal_BddNand(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd Cal_BddOr(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd Cal_BddNor(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd Cal_BddXor(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd Cal_BddXnor(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd * Cal_BddPairwiseAnd(Cal_BddManager bddManager, Cal_Bdd *userBddArray);
+EXTERN Cal_Bdd * Cal_BddPairwiseOr(Cal_BddManager bddManager, Cal_Bdd *userBddArray);
+EXTERN Cal_Bdd * Cal_BddPairwiseXor(Cal_BddManager bddManager, Cal_Bdd *userBddArray);
+EXTERN Cal_Bdd Cal_BddMultiwayAnd(Cal_BddManager bddManager, Cal_Bdd *userBddArray);
+EXTERN Cal_Bdd Cal_BddMultiwayOr(Cal_BddManager bddManager, Cal_Bdd *userBddArray);
+EXTERN Cal_Bdd Cal_BddMultiwayXor(Cal_BddManager bddManager, Cal_Bdd *userBddArray);
+EXTERN Cal_Bdd Cal_BddSatisfy(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN Cal_Bdd Cal_BddSatisfySupport(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN double Cal_BddSatisfyingFraction(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN long Cal_BddSize(Cal_BddManager bddManager, Cal_Bdd fUserBdd, int negout);
+EXTERN long Cal_BddSizeMultiple(Cal_BddManager bddManager, Cal_Bdd *fUserBddArray, int negout);
+EXTERN void Cal_BddProfile(Cal_BddManager bddManager, Cal_Bdd fUserBdd, long * levelCounts, int negout);
+EXTERN void Cal_BddProfileMultiple(Cal_BddManager bddManager, Cal_Bdd *fUserBddArray, long * levelCounts, int negout);
+EXTERN void Cal_BddFunctionProfile(Cal_BddManager bddManager, Cal_Bdd fUserBdd, long * funcCounts);
+EXTERN void Cal_BddFunctionProfileMultiple(Cal_BddManager bddManager, Cal_Bdd *fUserBddArray, long * funcCounts);
+EXTERN Cal_Bdd Cal_BddSubstitute(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN void Cal_BddSupport(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd *support);
+EXTERN int Cal_BddDependsOn(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd varUserBdd);
+EXTERN Cal_Bdd Cal_BddSwapVars(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd, Cal_Bdd hUserBdd);
+EXTERN Cal_Bdd Cal_BddVarSubstitute(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN Cal_Block Cal_BddNewVarBlock(Cal_BddManager bddManager, Cal_Bdd variable, long length);
+EXTERN void Cal_BddVarBlockReorderable(Cal_BddManager bddManager, Cal_Block block, int reorderable);
+EXTERN Cal_Bdd Cal_BddUndumpBdd(Cal_BddManager bddManager, Cal_Bdd * userVars, FILE * fp, int * error);
+EXTERN int Cal_BddDumpBdd(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd * userVars, FILE * fp);
+EXTERN void Cal_BddSetGCMode(Cal_BddManager bddManager, int gcMode);
+EXTERN int Cal_BddManagerGC(Cal_BddManager bddManager);
+EXTERN void Cal_BddManagerSetGCLimit(Cal_BddManager manager);
+EXTERN void Cal_MemFatal(char *message);
+EXTERN Cal_Address_t Cal_MemAllocation(void);
+EXTERN Cal_Pointer_t Cal_MemGetBlock(Cal_Address_t size);
+EXTERN void Cal_MemFreeBlock(Cal_Pointer_t p);
+EXTERN Cal_Pointer_t Cal_MemResizeBlock(Cal_Pointer_t p, Cal_Address_t newSize);
+EXTERN Cal_Pointer_t Cal_MemNewRec(Cal_RecMgr mgr);
+EXTERN void Cal_MemFreeRec(Cal_RecMgr mgr, Cal_Pointer_t rec);
+EXTERN Cal_RecMgr Cal_MemNewRecMgr(int size);
+EXTERN void Cal_MemFreeRecMgr(Cal_RecMgr mgr);
+EXTERN int Cal_PerformanceTest(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions, int iteration, int seed, int andPerformanceFlag, int multiwayPerformanceFlag, int onewayPerformanceFlag, int quantifyPerformanceFlag, int composePerformanceFlag, int relprodPerformanceFlag, int swapPerformanceFlag, int substitutePerformanceFlag, int sanityCheckFlag, int computeMemoryOverheadFlag, int superscalarFlag);
+EXTERN void Cal_PipelineSetDepth(Cal_BddManager bddManager, int depth);
+EXTERN int Cal_PipelineInit(Cal_BddManager bddManager, Cal_BddOp_t bddOp);
+EXTERN Cal_Bdd Cal_PipelineCreateProvisionalBdd(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN int Cal_PipelineExecute(Cal_BddManager bddManager);
+EXTERN Cal_Bdd Cal_PipelineUpdateProvisionalBdd(Cal_BddManager bddManager, Cal_Bdd provisionalBdd);
+EXTERN int Cal_BddIsProvisional(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN void Cal_PipelineQuit(Cal_BddManager bddManager);
+EXTERN void Cal_BddPrintBdd(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_VarNamingFn_t VarNamingFn, Cal_TerminalIdFn_t TerminalIdFn, Cal_Pointer_t env, FILE *fp);
+EXTERN void Cal_BddPrintProfile(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_VarNamingFn_t varNamingProc, char * env, int lineLength, FILE * fp);
+EXTERN void Cal_BddPrintProfileMultiple(Cal_BddManager bddManager, Cal_Bdd *userBdds, Cal_VarNamingFn_t varNamingProc, char * env, int lineLength, FILE * fp);
+EXTERN void Cal_BddPrintFunctionProfile(Cal_BddManager bddManager, Cal_Bdd f, Cal_VarNamingFn_t varNamingProc, char * env, int lineLength, FILE * fp);
+EXTERN void Cal_BddPrintFunctionProfileMultiple(Cal_BddManager bddManager, Cal_Bdd *userBdds, Cal_VarNamingFn_t varNamingProc, char * env, int lineLength, FILE * fp);
+EXTERN Cal_Bdd Cal_BddExists(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN Cal_Bdd Cal_BddRelProd(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd);
+EXTERN Cal_Bdd Cal_BddForAll(Cal_BddManager bddManager, Cal_Bdd fUserBdd);
+EXTERN Cal_Bdd Cal_BddCofactor(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd cUserBdd);
+EXTERN Cal_Bdd Cal_BddReduce(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd cUserBdd);
+EXTERN Cal_Bdd Cal_BddBetween(Cal_BddManager bddManager, Cal_Bdd fMinUserBdd, Cal_Bdd fMaxUserBdd);
+EXTERN void Cal_ImageDump(Cal_BddManager_t *bddManager, FILE *fp);
+EXTERN void Cal_BddFunctionPrint(Cal_BddManager bddManager, Cal_Bdd userBdd, char *name);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CAL */
Index: /vis_dev/glu-2.1/src/calBdd/calAllAbs.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calAllAbs.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calAllAbs.html	(revision 8)
@@ -0,0 +1,1293 @@
+<HTML>
+<HEAD><TITLE>cal package abstract</TITLE></HEAD>
+<BODY>
+
+
+<!-- Function Abstracts -->
+
+<dl>
+<DT> <A HREF="calAllDet.html#AddBlock" TARGET="MAIN"><CODE>AddBlock()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#AddToFreeList" TARGET="MAIN"><CODE>AddToFreeList()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#AssociationIsEqual" TARGET="MAIN"><CODE>AssociationIsEqual()</CODE></A>
+<DD> Checks for equality of two associations
+
+<DT> <A HREF="calAllDet.html#BddAddInternalReferences" TARGET="MAIN"><CODE>BddAddInternalReferences()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddArrayOpBF" TARGET="MAIN"><CODE>BddArrayOpBF()</CODE></A>
+<DD> Internal common routine for Cal_BddPairwiseAnd and Cal_BddPairwiseOr
+
+<DT> <A HREF="calAllDet.html#BddArrayToRequestNodeListArray" TARGET="MAIN"><CODE>BddArrayToRequestNodeListArray()</CODE></A>
+<DD> Converts an array of BDDs to a list of requests representing BDD
+  pairs
+
+<DT> <A HREF="calAllDet.html#BddCofactorBF" TARGET="MAIN"><CODE>BddCofactorBF()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddConvertDataStructBack" TARGET="MAIN"><CODE>BddConvertDataStructBack()</CODE></A>
+<DD> Changes the data structure of the bdd nodes to
+  the original one.
+
+<DT> <A HREF="calAllDet.html#BddConvertDataStruct" TARGET="MAIN"><CODE>BddConvertDataStruct()</CODE></A>
+<DD> Changes the data structure of the bdd nodes.
+
+<DT> <A HREF="calAllDet.html#BddCountNoNodes" TARGET="MAIN"><CODE>BddCountNoNodes()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddCountNodes" TARGET="MAIN"><CODE>BddCountNodes()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddDFStep" TARGET="MAIN"><CODE>BddDFStep()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddDefaultTransformFn" TARGET="MAIN"><CODE>BddDefaultTransformFn()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddDominatedStep" TARGET="MAIN"><CODE>BddDominatedStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddDumpBddStep" TARGET="MAIN"><CODE>BddDumpBddStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddExchangeAux" TARGET="MAIN"><CODE>BddExchangeAux()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddExchangeVarBlocks" TARGET="MAIN"><CODE>BddExchangeVarBlocks()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddExchange" TARGET="MAIN"><CODE>BddExchange()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddExistsApply" TARGET="MAIN"><CODE>BddExistsApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddExistsBFAux" TARGET="MAIN"><CODE>BddExistsBFAux()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddExistsBFPlusDF" TARGET="MAIN"><CODE>BddExistsBFPlusDF()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddExistsReduce" TARGET="MAIN"><CODE>BddExistsReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddExistsStep" TARGET="MAIN"><CODE>BddExistsStep()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddHighestRefStep" TARGET="MAIN"><CODE>BddHighestRefStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddIntersectsStep" TARGET="MAIN"><CODE>BddIntersectsStep()</CODE></A>
+<DD> Recursive routine to returns a BDD that implies conjunction of
+  argument BDDs
+
+<DT> <A HREF="calAllDet.html#BddMarkBdd" TARGET="MAIN"><CODE>BddMarkBdd()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddMultiwayOp" TARGET="MAIN"><CODE>BddMultiwayOp()</CODE></A>
+<DD> Internal routine for multiway operations
+
+<DT> <A HREF="calAllDet.html#BddNukeInternalReferences" TARGET="MAIN"><CODE>BddNukeInternalReferences()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddPrintBddStep" TARGET="MAIN"><CODE>BddPrintBddStep()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddPrintTopVar" TARGET="MAIN"><CODE>BddPrintTopVar()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddProfileStep" TARGET="MAIN"><CODE>BddProfileStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddReallocateNodesInPlace" TARGET="MAIN"><CODE>BddReallocateNodesInPlace()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReallocateNodes" TARGET="MAIN"><CODE>BddReallocateNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReduceBF" TARGET="MAIN"><CODE>BddReduceBF()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddRelProdApply" TARGET="MAIN"><CODE>BddRelProdApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddRelProdBFAux" TARGET="MAIN"><CODE>BddRelProdBFAux()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddRelProdBFPlusDF" TARGET="MAIN"><CODE>BddRelProdBFPlusDF()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddRelProdReduce" TARGET="MAIN"><CODE>BddRelProdReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddRelProdStep" TARGET="MAIN"><CODE>BddRelProdStep()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderFixAndFreeForwardingNodes" TARGET="MAIN"><CODE>BddReorderFixAndFreeForwardingNodes()</CODE></A>
+<DD> Traverses the forwarding node lists of index,
+  index+1 .. up to index+level. Frees the intermediate forwarding nodes.
+
+<DT> <A HREF="calAllDet.html#BddReorderFixForwardingNodes" TARGET="MAIN"><CODE>BddReorderFixForwardingNodes()</CODE></A>
+<DD> Fixes the forwarding nodes in a unique table.
+
+<DT> <A HREF="calAllDet.html#BddReorderFreeNodes" TARGET="MAIN"><CODE>BddReorderFreeNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderSiftAux" TARGET="MAIN"><CODE>BddReorderSiftAux()</CODE></A>
+<DD> Reorder variables using "sift" algorithm.
+
+<DT> <A HREF="calAllDet.html#BddReorderSiftToBestPos" TARGET="MAIN"><CODE>BddReorderSiftToBestPos()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderSift" TARGET="MAIN"><CODE>BddReorderSift()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderStableWindow3Aux" TARGET="MAIN"><CODE>BddReorderStableWindow3Aux()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderStableWindow3" TARGET="MAIN"><CODE>BddReorderStableWindow3()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderSwapVarIndex" TARGET="MAIN"><CODE>BddReorderSwapVarIndex()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderVarSift" TARGET="MAIN"><CODE>BddReorderVarSift()</CODE></A>
+<DD> Reorder variables using "sift" algorithm.
+
+<DT> <A HREF="calAllDet.html#BddReorderVarWindow" TARGET="MAIN"><CODE>BddReorderVarWindow()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderWindow2" TARGET="MAIN"><CODE>BddReorderWindow2()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderWindow2" TARGET="MAIN"><CODE>BddReorderWindow2()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderWindow3" TARGET="MAIN"><CODE>BddReorderWindow3()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddReorderWindow3" TARGET="MAIN"><CODE>BddReorderWindow3()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddSatisfyStep" TARGET="MAIN"><CODE>BddSatisfyStep()</CODE></A>
+<DD> Returns a BDD which implies f, is true for some valuation
+  on which f is true, and which has at most one node at each level
+
+<DT> <A HREF="calAllDet.html#BddSatisfySupportStep" TARGET="MAIN"><CODE>BddSatisfySupportStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddSatisfyingFractionStep" TARGET="MAIN"><CODE>BddSatisfyingFractionStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddSiftBlock" TARGET="MAIN"><CODE>BddSiftBlock()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddSiftPerfromPhaseIV" TARGET="MAIN"><CODE>BddSiftPerfromPhaseIV()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddSizeStep" TARGET="MAIN"><CODE>BddSizeStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BddTerminalId" TARGET="MAIN"><CODE>BddTerminalId()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddTerminalValueAux" TARGET="MAIN"><CODE>BddTerminalValueAux()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BddUndumpBddStep" TARGET="MAIN"><CODE>BddUndumpBddStep()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#BlockSizeIndex" TARGET="MAIN"><CODE>BlockSizeIndex()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#Buddy" TARGET="MAIN"><CODE>Buddy()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#BytesNeeded" TARGET="MAIN"><CODE>BytesNeeded()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#CacheTablePrint" TARGET="MAIN"><CODE>CacheTablePrint()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CacheTableTwoRehash" TARGET="MAIN"><CODE>CacheTableTwoRehash()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalAlignCollisionChains" TARGET="MAIN"><CODE>CalAlignCollisionChains()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalAssociationListFree" TARGET="MAIN"><CODE>CalAssociationListFree()</CODE></A>
+<DD> Frees the variable associations
+
+<DT> <A HREF="calAllDet.html#CalBddArrayPreProcessing" TARGET="MAIN"><CODE>CalBddArrayPreProcessing()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddBlockDelta" TARGET="MAIN"><CODE>CalBddBlockDelta()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddDependsOnStep" TARGET="MAIN"><CODE>CalBddDependsOnStep()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddFatalMessage" TARGET="MAIN"><CODE>CalBddFatalMessage()</CODE></A>
+<DD> Prints fatal message and exits.
+
+<DT> <A HREF="calAllDet.html#CalBddFindBlock" TARGET="MAIN"><CODE>CalBddFindBlock()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddFunctionPrint" TARGET="MAIN"><CODE>CalBddFunctionPrint()</CODE></A>
+<DD> Prints the function implemented by the argument BDD
+
+<DT> <A HREF="calAllDet.html#CalBddGetExternalBdd" TARGET="MAIN"><CODE>CalBddGetExternalBdd()</CODE></A>
+<DD> Prints fatal message and exits.
+
+<DT> <A HREF="calAllDet.html#CalBddGetInternalBdd" TARGET="MAIN"><CODE>CalBddGetInternalBdd()</CODE></A>
+<DD> Prints fatal message and exits.
+
+<DT> <A HREF="calAllDet.html#CalBddITE" TARGET="MAIN"><CODE>CalBddITE()</CODE></A>
+<DD> Returns the BDD for logical If-Then-Else
+ 
+   Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+   - f g + f' h
+
+<DT> <A HREF="calAllDet.html#CalBddIdentity" TARGET="MAIN"><CODE>CalBddIdentity()</CODE></A>
+<DD> Returns the duplicate BDD of the argument BDD.
+
+<DT> <A HREF="calAllDet.html#CalBddIf" TARGET="MAIN"><CODE>CalBddIf()</CODE></A>
+<DD> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+
+<DT> <A HREF="calAllDet.html#CalBddIsCubeStep" TARGET="MAIN"><CODE>CalBddIsCubeStep()</CODE></A>
+<DD> Returns 1 if the argument BDD is a cube, 0 otherwise
+
+<DT> <A HREF="calAllDet.html#CalBddManagerCreateNewVar" TARGET="MAIN"><CODE>CalBddManagerCreateNewVar()</CODE></A>
+<DD> This function creates and returns a new variable with given
+  index value.
+
+<DT> <A HREF="calAllDet.html#CalBddManagerGCCheck" TARGET="MAIN"><CODE>CalBddManagerGCCheck()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddManagerGetCacheTableData" TARGET="MAIN"><CODE>CalBddManagerGetCacheTableData()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddManagerPrint" TARGET="MAIN"><CODE>CalBddManagerPrint()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddMarkSharedNodes" TARGET="MAIN"><CODE>CalBddMarkSharedNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddNodePrint" TARGET="MAIN"><CODE>CalBddNodePrint()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddNumberSharedNodes" TARGET="MAIN"><CODE>CalBddNumberSharedNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddOpBF" TARGET="MAIN"><CODE>CalBddOpBF()</CODE></A>
+<DD> Internal routine to compute a logical operation on a pair of BDDs
+
+<DT> <A HREF="calAllDet.html#CalBddOpITEBF" TARGET="MAIN"><CODE>CalBddOpITEBF()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddPackNodesAfterReorderForSingleId" TARGET="MAIN"><CODE>CalBddPackNodesAfterReorderForSingleId()</CODE></A>
+<DD> Packs the nodes if the variables which has just
+  been sifted.
+
+<DT> <A HREF="calAllDet.html#CalBddPackNodesForMultipleIds" TARGET="MAIN"><CODE>CalBddPackNodesForMultipleIds()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddPackNodesForSingleId" TARGET="MAIN"><CODE>CalBddPackNodesForSingleId()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddPostProcessing" TARGET="MAIN"><CODE>CalBddPostProcessing()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddPreProcessing" TARGET="MAIN"><CODE>CalBddPreProcessing()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddPrintProfileAux" TARGET="MAIN"><CODE>CalBddPrintProfileAux()</CODE></A>
+<DD> Prints a profile to the file given by fp.  The varNamingProc
+               is as in Cal_BddPrintBdd. lineLength gives the line width to scale
+               the profile to.
+
+<DT> <A HREF="calAllDet.html#CalBddPrint" TARGET="MAIN"><CODE>CalBddPrint()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddReorderAuxBF" TARGET="MAIN"><CODE>CalBddReorderAuxBF()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddReorderAuxDF" TARGET="MAIN"><CODE>CalBddReorderAuxDF()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddReorderFixCofactors" TARGET="MAIN"><CODE>CalBddReorderFixCofactors()</CODE></A>
+<DD> Fixes the cofactors of the nodes belonging to
+  the given index.
+
+<DT> <A HREF="calAllDet.html#CalBddReorderFixProvisionalNodes" TARGET="MAIN"><CODE>CalBddReorderFixProvisionalNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddReorderFixUserBddPtrs" TARGET="MAIN"><CODE>CalBddReorderFixUserBddPtrs()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddReorderReclaimForwardedNodes" TARGET="MAIN"><CODE>CalBddReorderReclaimForwardedNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddShiftBlock" TARGET="MAIN"><CODE>CalBddShiftBlock()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddSupportStep" TARGET="MAIN"><CODE>CalBddSupportStep()</CODE></A>
+<DD> returns the support of f as a null-terminated array of variables
+
+<DT> <A HREF="calAllDet.html#CalBddTypeAux" TARGET="MAIN"><CODE>CalBddTypeAux()</CODE></A>
+<DD> Returns the BDD type by recursively traversing the argument BDD
+
+<DT> <A HREF="calAllDet.html#CalBddUniqueTableNumLockedNodes" TARGET="MAIN"><CODE>CalBddUniqueTableNumLockedNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddUnmarkNodes" TARGET="MAIN"><CODE>CalBddUnmarkNodes()</CODE></A>
+<DD> recursively unmarks the nodes
+
+<DT> <A HREF="calAllDet.html#CalBddVarName" TARGET="MAIN"><CODE>CalBddVarName()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalBddVarSubstitute" TARGET="MAIN"><CODE>CalBddVarSubstitute()</CODE></A>
+<DD> Substitute a set of variables by functions
+
+<DT> <A HREF="calAllDet.html#CalBddWarningMessage" TARGET="MAIN"><CODE>CalBddWarningMessage()</CODE></A>
+<DD> Prints warning message.
+
+<DT> <A HREF="calAllDet.html#CalBlockMemoryConsumption" TARGET="MAIN"><CODE>CalBlockMemoryConsumption()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCacheTableMemoryConsumption" TARGET="MAIN"><CODE>CalCacheTableMemoryConsumption()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCacheTablePrint" TARGET="MAIN"><CODE>CalCacheTablePrint()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCacheTableRehash" TARGET="MAIN"><CODE>CalCacheTableRehash()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoFixResultPointers" TARGET="MAIN"><CODE>CalCacheTableTwoFixResultPointers()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoFlushAll" TARGET="MAIN"><CODE>CalCacheTableTwoFlushAll()</CODE></A>
+<DD> Free a Cache table along with the associated storage.
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoFlushAssociationId" TARGET="MAIN"><CODE>CalCacheTableTwoFlushAssociationId()</CODE></A>
+<DD> Flushes the entries from the cache which
+                      correspond to the given associationId.
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoFlush" TARGET="MAIN"><CODE>CalCacheTableTwoFlush()</CODE></A>
+<DD> Free a Cache table along with the associated storage.
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoGCFlush" TARGET="MAIN"><CODE>CalCacheTableTwoGCFlush()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoInit" TARGET="MAIN"><CODE>CalCacheTableTwoInit()</CODE></A>
+<DD> Initialize a Cache table using default parameters.
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoInsert" TARGET="MAIN"><CODE>CalCacheTableTwoInsert()</CODE></A>
+<DD> Directly insert a BDD node in the Cache table.
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoLookup" TARGET="MAIN"><CODE>CalCacheTableTwoLookup()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoQuit" TARGET="MAIN"><CODE>CalCacheTableTwoQuit()</CODE></A>
+<DD> Free a Cache table along with the associated storage.
+
+<DT> <A HREF="calAllDet.html#CalCacheTableTwoRepackUpdate" TARGET="MAIN"><CODE>CalCacheTableTwoRepackUpdate()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckAllValidity" TARGET="MAIN"><CODE>CalCheckAllValidity()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckAssociationValidity" TARGET="MAIN"><CODE>CalCheckAssociationValidity()</CODE></A>
+<DD> Checks the validity of association.
+
+<DT> <A HREF="calAllDet.html#CalCheckAssoc" TARGET="MAIN"><CODE>CalCheckAssoc()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckCacheTableValidity" TARGET="MAIN"><CODE>CalCheckCacheTableValidity()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckPipelineValidity" TARGET="MAIN"><CODE>CalCheckPipelineValidity()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckRefCountValidity" TARGET="MAIN"><CODE>CalCheckRefCountValidity()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckValidityOfANode" TARGET="MAIN"><CODE>CalCheckValidityOfANode()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckValidityOfNodesForId" TARGET="MAIN"><CODE>CalCheckValidityOfNodesForId()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalCheckValidityOfNodesForWindow" TARGET="MAIN"><CODE>CalCheckValidityOfNodesForWindow()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalComposeRequestCreate" TARGET="MAIN"><CODE>CalComposeRequestCreate()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalDecreasingOrderCompare" TARGET="MAIN"><CODE>CalDecreasingOrderCompare()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalFixupAssoc" TARGET="MAIN"><CODE>CalFixupAssoc()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalFreeBlockRecursively" TARGET="MAIN"><CODE>CalFreeBlockRecursively()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableAddDirectAux" TARGET="MAIN"><CODE>CalHashTableAddDirectAux()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableAddDirect" TARGET="MAIN"><CODE>CalHashTableAddDirect()</CODE></A>
+<DD> Directly insert a BDD node in the hash table.
+
+<DT> <A HREF="calAllDet.html#CalHashTableApply" TARGET="MAIN"><CODE>CalHashTableApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableCleanUp" TARGET="MAIN"><CODE>CalHashTableCleanUp()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableComposeApply" TARGET="MAIN"><CODE>CalHashTableComposeApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableDelete" TARGET="MAIN"><CODE>CalHashTableDelete()</CODE></A>
+<DD> Deletes a BDD node in the hash table.
+
+<DT> <A HREF="calAllDet.html#CalHashTableFindOrAdd" TARGET="MAIN"><CODE>CalHashTableFindOrAdd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableGC" TARGET="MAIN"><CODE>CalHashTableGC()</CODE></A>
+<DD> This function performs the garbage collection operation
+  for a particular index.
+
+<DT> <A HREF="calAllDet.html#CalHashTableITEApply" TARGET="MAIN"><CODE>CalHashTableITEApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableInit" TARGET="MAIN"><CODE>CalHashTableInit()</CODE></A>
+<DD> Initialize a hash table using default parameters.
+
+<DT> <A HREF="calAllDet.html#CalHashTableLookup" TARGET="MAIN"><CODE>CalHashTableLookup()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableOneInit" TARGET="MAIN"><CODE>CalHashTableOneInit()</CODE></A>
+<DD> Initialize a hash table using default parameters.
+
+<DT> <A HREF="calAllDet.html#CalHashTableOneInsert" TARGET="MAIN"><CODE>CalHashTableOneInsert()</CODE></A>
+<DD> Directly insert a BDD node in the hash table.
+
+<DT> <A HREF="calAllDet.html#CalHashTableOneLookup" TARGET="MAIN"><CODE>CalHashTableOneLookup()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableOnePrint" TARGET="MAIN"><CODE>CalHashTableOnePrint()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableOneQuit" TARGET="MAIN"><CODE>CalHashTableOneQuit()</CODE></A>
+<DD> Free a hash table along with the associated storage.
+
+<DT> <A HREF="calAllDet.html#CalHashTablePrint" TARGET="MAIN"><CODE>CalHashTablePrint()</CODE></A>
+<DD> Prints a hash table.
+
+<DT> <A HREF="calAllDet.html#CalHashTableQuit" TARGET="MAIN"><CODE>CalHashTableQuit()</CODE></A>
+<DD> Free a hash table along with the associated storage.
+
+<DT> <A HREF="calAllDet.html#CalHashTableReduce" TARGET="MAIN"><CODE>CalHashTableReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableRehash" TARGET="MAIN"><CODE>CalHashTableRehash()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableSubstituteApply" TARGET="MAIN"><CODE>CalHashTableSubstituteApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableSubstituteApply" TARGET="MAIN"><CODE>CalHashTableSubstituteApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableSubstituteReduce" TARGET="MAIN"><CODE>CalHashTableSubstituteReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableSubstituteReduce" TARGET="MAIN"><CODE>CalHashTableSubstituteReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableSwapVarsApply" TARGET="MAIN"><CODE>CalHashTableSwapVarsApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableSwapVarsMinusApply" TARGET="MAIN"><CODE>CalHashTableSwapVarsMinusApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableSwapVarsPlusApply" TARGET="MAIN"><CODE>CalHashTableSwapVarsPlusApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableThreeFindOrAdd" TARGET="MAIN"><CODE>CalHashTableThreeFindOrAdd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalHashTableThreeRehash" TARGET="MAIN"><CODE>CalHashTableThreeRehash()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalIncreasingOrderCompare" TARGET="MAIN"><CODE>CalIncreasingOrderCompare()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalInitInteract" TARGET="MAIN"><CODE>CalInitInteract()</CODE></A>
+<DD> Initializes the interaction matrix.
+
+<DT> <A HREF="calAllDet.html#CalNodeManagerInit" TARGET="MAIN"><CODE>CalNodeManagerInit()</CODE></A>
+<DD> Initializes a node manager.
+
+<DT> <A HREF="calAllDet.html#CalNodeManagerPrint" TARGET="MAIN"><CODE>CalNodeManagerPrint()</CODE></A>
+<DD> Prints address of each free node.
+
+<DT> <A HREF="calAllDet.html#CalNodeManagerQuit" TARGET="MAIN"><CODE>CalNodeManagerQuit()</CODE></A>
+<DD> Frees a node manager.
+
+<DT> <A HREF="calAllDet.html#CalOpAnd" TARGET="MAIN"><CODE>CalOpAnd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpBddVarSubstitute" TARGET="MAIN"><CODE>CalOpBddVarSubstitute()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpCofactor" TARGET="MAIN"><CODE>CalOpCofactor()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpExists" TARGET="MAIN"><CODE>CalOpExists()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpITE" TARGET="MAIN"><CODE>CalOpITE()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpNand" TARGET="MAIN"><CODE>CalOpNand()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpOr" TARGET="MAIN"><CODE>CalOpOr()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpRelProd" TARGET="MAIN"><CODE>CalOpRelProd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalOpXor" TARGET="MAIN"><CODE>CalOpXor()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalPackNodes" TARGET="MAIN"><CODE>CalPackNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalPageManagerAllocPage" TARGET="MAIN"><CODE>CalPageManagerAllocPage()</CODE></A>
+<DD> Allocs a new page.
+
+<DT> <A HREF="calAllDet.html#CalPageManagerFreePage" TARGET="MAIN"><CODE>CalPageManagerFreePage()</CODE></A>
+<DD> Free a page.
+
+<DT> <A HREF="calAllDet.html#CalPageManagerInit" TARGET="MAIN"><CODE>CalPageManagerInit()</CODE></A>
+<DD> Initializes a pageManager.
+
+<DT> <A HREF="calAllDet.html#CalPageManagerPrint" TARGET="MAIN"><CODE>CalPageManagerPrint()</CODE></A>
+<DD> Prints address of each memory segment and address of each page.
+
+<DT> <A HREF="calAllDet.html#CalPageManagerQuit" TARGET="MAIN"><CODE>CalPageManagerQuit()</CODE></A>
+<DD> Frees pageManager and associated pages.
+
+<DT> <A HREF="calAllDet.html#CalPerformaceTestSuperscalar" TARGET="MAIN"><CODE>CalPerformaceTestSuperscalar()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceMemoryOverhead" TARGET="MAIN"><CODE>CalPerformanceMemoryOverhead()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestAnd" TARGET="MAIN"><CODE>CalPerformanceTestAnd()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestCompose" TARGET="MAIN"><CODE>CalPerformanceTestCompose()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestMultiway" TARGET="MAIN"><CODE>CalPerformanceTestMultiway()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestNonSuperscalar" TARGET="MAIN"><CODE>CalPerformanceTestNonSuperscalar()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestOneway" TARGET="MAIN"><CODE>CalPerformanceTestOneway()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestQuantifyAllTogether" TARGET="MAIN"><CODE>CalPerformanceTestQuantifyAllTogether()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestRelProd" TARGET="MAIN"><CODE>CalPerformanceTestRelProd()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestSubstitute" TARGET="MAIN"><CODE>CalPerformanceTestSubstitute()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalPerformanceTestSwapVars" TARGET="MAIN"><CODE>CalPerformanceTestSwapVars()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalQuantifySanityCheck" TARGET="MAIN"><CODE>CalQuantifySanityCheck()</CODE></A>
+<DD> Performance test routine for quantify (all variables at the same
+  time).
+
+<DT> <A HREF="calAllDet.html#CalReorderAssociationFix" TARGET="MAIN"><CODE>CalReorderAssociationFix()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalRepackNodesAfterGC" TARGET="MAIN"><CODE>CalRepackNodesAfterGC()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalRequestNodeListArrayITE" TARGET="MAIN"><CODE>CalRequestNodeListArrayITE()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalRequestNodeListArrayOp" TARGET="MAIN"><CODE>CalRequestNodeListArrayOp()</CODE></A>
+<DD> Computes result BDDs for an array of lists, each entry of which 
+  is pair of pointers, each of which points to a operand BDD or an entry in
+  another list with a smaller array index
+
+<DT> <A HREF="calAllDet.html#CalRequestNodeListCompose" TARGET="MAIN"><CODE>CalRequestNodeListCompose()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalSetInteract" TARGET="MAIN"><CODE>CalSetInteract()</CODE></A>
+<DD> Set interaction matrix entries.
+
+<DT> <A HREF="calAllDet.html#CalTestInteract" TARGET="MAIN"><CODE>CalTestInteract()</CODE></A>
+<DD> Test interaction matrix entries.
+
+<DT> <A HREF="calAllDet.html#CalUniqueTableForIdFindOrAdd" TARGET="MAIN"><CODE>CalUniqueTableForIdFindOrAdd()</CODE></A>
+<DD> find or add in the unique table for id.
+
+<DT> <A HREF="calAllDet.html#CalUniqueTableForIdLookup" TARGET="MAIN"><CODE>CalUniqueTableForIdLookup()</CODE></A>
+<DD> Lookup unique table for id.
+
+<DT> <A HREF="calAllDet.html#CalUniqueTableForIdRehashNode" TARGET="MAIN"><CODE>CalUniqueTableForIdRehashNode()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalUniqueTablePrint" TARGET="MAIN"><CODE>CalUniqueTablePrint()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CalVarAssociationRepackUpdate" TARGET="MAIN"><CODE>CalVarAssociationRepackUpdate()</CODE></A>
+<DD> Need to be called after repacking.
+
+<DT> <A HREF="calAllDet.html#Cal_AssociationInit" TARGET="MAIN"><CODE>Cal_AssociationInit()</CODE></A>
+<DD> Creates or finds a variable association.
+
+<DT> <A HREF="calAllDet.html#Cal_AssociationQuit" TARGET="MAIN"><CODE>Cal_AssociationQuit()</CODE></A>
+<DD> Deletes the variable association given by id
+
+<DT> <A HREF="calAllDet.html#Cal_AssociationSetCurrent" TARGET="MAIN"><CODE>Cal_AssociationSetCurrent()</CODE></A>
+<DD> Sets the current variable association to the one given by id and
+  returns the ID of the old association.
+
+<DT> <A HREF="calAllDet.html#Cal_BddAnd" TARGET="MAIN"><CODE>Cal_BddAnd()</CODE></A>
+<DD> Returns the BDD for logical AND of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddBetween" TARGET="MAIN"><CODE>Cal_BddBetween()</CODE></A>
+<DD> Returns a minimal BDD whose function contains fMin and is
+  contained in fMax.
+
+<DT> <A HREF="calAllDet.html#Cal_BddCofactor" TARGET="MAIN"><CODE>Cal_BddCofactor()</CODE></A>
+<DD> Returns the generalized cofactor of BDD f with respect
+  to BDD c.
+
+<DT> <A HREF="calAllDet.html#Cal_BddCompose" TARGET="MAIN"><CODE>Cal_BddCompose()</CODE></A>
+<DD> composition - substitute a BDD variable by a function
+
+<DT> <A HREF="calAllDet.html#Cal_BddDependsOn" TARGET="MAIN"><CODE>Cal_BddDependsOn()</CODE></A>
+<DD> Returns 1 if f depends on var and returns 0 otherwise.
+
+<DT> <A HREF="calAllDet.html#Cal_BddDumpBdd" TARGET="MAIN"><CODE>Cal_BddDumpBdd()</CODE></A>
+<DD> Write a BDD to a file
+
+<DT> <A HREF="calAllDet.html#Cal_BddDynamicReordering" TARGET="MAIN"><CODE>Cal_BddDynamicReordering()</CODE></A>
+<DD> Specify dynamic reordering technique.
+
+<DT> <A HREF="calAllDet.html#Cal_BddElse" TARGET="MAIN"><CODE>Cal_BddElse()</CODE></A>
+<DD> Returns the negative cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddExists" TARGET="MAIN"><CODE>Cal_BddExists()</CODE></A>
+<DD> Returns the result of existentially quantifying some
+  variables from the given BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddForAll" TARGET="MAIN"><CODE>Cal_BddForAll()</CODE></A>
+<DD> Returns the result of universally quantifying some
+  variables from the given BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddFree" TARGET="MAIN"><CODE>Cal_BddFree()</CODE></A>
+<DD> Frees the argument BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddFunctionPrint" TARGET="MAIN"><CODE>Cal_BddFunctionPrint()</CODE></A>
+<DD> Prints the function implemented by the argument BDD
+
+<DT> <A HREF="calAllDet.html#Cal_BddFunctionProfileMultiple" TARGET="MAIN"><CODE>Cal_BddFunctionProfileMultiple()</CODE></A>
+<DD> Returns a "function profile" for fArray.
+
+<DT> <A HREF="calAllDet.html#Cal_BddFunctionProfile" TARGET="MAIN"><CODE>Cal_BddFunctionProfile()</CODE></A>
+<DD> Returns a "function profile" for f.
+
+<DT> <A HREF="calAllDet.html#Cal_BddGetIfId" TARGET="MAIN"><CODE>Cal_BddGetIfId()</CODE></A>
+<DD> Returns the id of the top variable of the argument BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddGetIfIndex" TARGET="MAIN"><CODE>Cal_BddGetIfIndex()</CODE></A>
+<DD> Returns the index of the top variable of the argument BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddGetRegular" TARGET="MAIN"><CODE>Cal_BddGetRegular()</CODE></A>
+<DD> Returns a BDD with positive from a given BDD with arbitrary phase
+
+<DT> <A HREF="calAllDet.html#Cal_BddITE" TARGET="MAIN"><CODE>Cal_BddITE()</CODE></A>
+<DD> Returns the BDD for logical If-Then-Else
+
+  Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+  - f g + f' h
+
+<DT> <A HREF="calAllDet.html#Cal_BddIdentity" TARGET="MAIN"><CODE>Cal_BddIdentity()</CODE></A>
+<DD> Returns the duplicate BDD of the argument BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddIf" TARGET="MAIN"><CODE>Cal_BddIf()</CODE></A>
+<DD> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddImplies" TARGET="MAIN"><CODE>Cal_BddImplies()</CODE></A>
+<DD> Computes a BDD that implies conjunction of f and Cal_BddNot(g)
+
+<DT> <A HREF="calAllDet.html#Cal_BddIntersects" TARGET="MAIN"><CODE>Cal_BddIntersects()</CODE></A>
+<DD> Computes a BDD that implies conjunction of f and g.
+
+<DT> <A HREF="calAllDet.html#Cal_BddIsBddConst" TARGET="MAIN"><CODE>Cal_BddIsBddConst()</CODE></A>
+<DD> Returns 1 if the argument BDD is a constant, 0 otherwise.
+
+<DT> <A HREF="calAllDet.html#Cal_BddIsBddNull" TARGET="MAIN"><CODE>Cal_BddIsBddNull()</CODE></A>
+<DD> Returns 1 if the argument BDD is NULL, 0 otherwise.
+
+<DT> <A HREF="calAllDet.html#Cal_BddIsBddOne" TARGET="MAIN"><CODE>Cal_BddIsBddOne()</CODE></A>
+<DD> Returns 1 if the argument BDD is constant one, 0 otherwise.
+
+<DT> <A HREF="calAllDet.html#Cal_BddIsBddZero" TARGET="MAIN"><CODE>Cal_BddIsBddZero()</CODE></A>
+<DD> Returns 1 if the argument BDD is constant zero, 0 otherwise.
+
+<DT> <A HREF="calAllDet.html#Cal_BddIsCube" TARGET="MAIN"><CODE>Cal_BddIsCube()</CODE></A>
+<DD> Returns 1 if the argument BDD is a cube, 0 otherwise
+
+<DT> <A HREF="calAllDet.html#Cal_BddIsEqual" TARGET="MAIN"><CODE>Cal_BddIsEqual()</CODE></A>
+<DD> Returns 1 if argument BDDs are equal, 0 otherwise.
+
+<DT> <A HREF="calAllDet.html#Cal_BddIsProvisional" TARGET="MAIN"><CODE>Cal_BddIsProvisional()</CODE></A>
+<DD> Returns 1, if the given user BDD contains
+  provisional BDD node.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarAfter" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarAfter()</CODE></A>
+<DD> Creates and returns a new variable after the specified one in
+  the variable  order.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarBefore" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarBefore()</CODE></A>
+<DD> Creates and returns a new variable before the specified one in
+  the variable order.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarFirst" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarFirst()</CODE></A>
+<DD> Creates and returns a new variable at the start of the variable
+  order.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarLast" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarLast()</CODE></A>
+<DD> Creates and returns a new variable at the end of the variable
+  order.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerGC" TARGET="MAIN"><CODE>Cal_BddManagerGC()</CODE></A>
+<DD> Invokes the garbage collection at the manager level.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerGetHooks" TARGET="MAIN"><CODE>Cal_BddManagerGetHooks()</CODE></A>
+<DD> Returns the hooks field of the manager.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerGetNumNodes" TARGET="MAIN"><CODE>Cal_BddManagerGetNumNodes()</CODE></A>
+<DD> Returns the number of BDD nodes
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerGetVarWithId" TARGET="MAIN"><CODE>Cal_BddManagerGetVarWithId()</CODE></A>
+<DD> Returns the variable with the specified id, null if no
+  such variable exists
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerGetVarWithIndex" TARGET="MAIN"><CODE>Cal_BddManagerGetVarWithIndex()</CODE></A>
+<DD> Returns the variable with the specified index, null if no
+  such variable exists
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerInit" TARGET="MAIN"><CODE>Cal_BddManagerInit()</CODE></A>
+<DD> Creates and initializes a new BDD manager.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerQuit" TARGET="MAIN"><CODE>Cal_BddManagerQuit()</CODE></A>
+<DD> Frees the BDD manager and all the associated allocations
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerSetGCLimit" TARGET="MAIN"><CODE>Cal_BddManagerSetGCLimit()</CODE></A>
+<DD> Sets the limit of the garbage collection.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerSetHooks" TARGET="MAIN"><CODE>Cal_BddManagerSetHooks()</CODE></A>
+<DD> Sets the hooks field of the manager.
+
+<DT> <A HREF="calAllDet.html#Cal_BddManagerSetParameters" TARGET="MAIN"><CODE>Cal_BddManagerSetParameters()</CODE></A>
+<DD> Sets appropriate fields of BDD Manager.
+
+<DT> <A HREF="calAllDet.html#Cal_BddMultiwayAnd" TARGET="MAIN"><CODE>Cal_BddMultiwayAnd()</CODE></A>
+<DD> Returns the BDD for logical AND of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddMultiwayOr" TARGET="MAIN"><CODE>Cal_BddMultiwayOr()</CODE></A>
+<DD> Returns the BDD for logical OR of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddMultiwayXor" TARGET="MAIN"><CODE>Cal_BddMultiwayXor()</CODE></A>
+<DD> Returns the BDD for logical XOR of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddNand" TARGET="MAIN"><CODE>Cal_BddNand()</CODE></A>
+<DD> Returns the BDD for logical NAND of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddNewVarBlock" TARGET="MAIN"><CODE>Cal_BddNewVarBlock()</CODE></A>
+<DD> Creates and returns a variable block used for
+  controlling dynamic reordering.
+
+<DT> <A HREF="calAllDet.html#Cal_BddNodeLimit" TARGET="MAIN"><CODE>Cal_BddNodeLimit()</CODE></A>
+<DD> Sets the node limit to new_limit and returns the old limit.
+
+<DT> <A HREF="calAllDet.html#Cal_BddNor" TARGET="MAIN"><CODE>Cal_BddNor()</CODE></A>
+<DD> Returns the BDD for logical NOR of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddNot" TARGET="MAIN"><CODE>Cal_BddNot()</CODE></A>
+<DD> Returns the complement of the argument BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddOne" TARGET="MAIN"><CODE>Cal_BddOne()</CODE></A>
+<DD> Returns the BDD for the constant one
+
+<DT> <A HREF="calAllDet.html#Cal_BddOr" TARGET="MAIN"><CODE>Cal_BddOr()</CODE></A>
+<DD> Returns the BDD for logical OR of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddOverflow" TARGET="MAIN"><CODE>Cal_BddOverflow()</CODE></A>
+<DD> Returns 1 if the node limit has been exceeded, 0 otherwise. The
+  overflow flag is cleared.
+
+<DT> <A HREF="calAllDet.html#Cal_BddPairwiseAnd" TARGET="MAIN"><CODE>Cal_BddPairwiseAnd()</CODE></A>
+<DD> Returns an array of BDDs obtained by logical AND of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+<DT> <A HREF="calAllDet.html#Cal_BddPairwiseOr" TARGET="MAIN"><CODE>Cal_BddPairwiseOr()</CODE></A>
+<DD> Returns an array of BDDs obtained by logical OR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+<DT> <A HREF="calAllDet.html#Cal_BddPairwiseXor" TARGET="MAIN"><CODE>Cal_BddPairwiseXor()</CODE></A>
+<DD> Returns an array of BDDs obtained by logical XOR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+<DT> <A HREF="calAllDet.html#Cal_BddPrintBdd" TARGET="MAIN"><CODE>Cal_BddPrintBdd()</CODE></A>
+<DD> Prints a BDD in the human readable form.
+
+<DT> <A HREF="calAllDet.html#Cal_BddPrintFunctionProfileMultiple" TARGET="MAIN"><CODE>Cal_BddPrintFunctionProfileMultiple()</CODE></A>
+<DD> Cal_BddPrintFunctionProfileMultiple is like
+               Cal_BddPrintFunctionProfile except for multiple BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddPrintFunctionProfile" TARGET="MAIN"><CODE>Cal_BddPrintFunctionProfile()</CODE></A>
+<DD> Cal_BddPrintFunctionProfile is like Cal_BddPrintProfile except
+               it displays a function profile for f
+
+<DT> <A HREF="calAllDet.html#Cal_BddPrintProfileMultiple" TARGET="MAIN"><CODE>Cal_BddPrintProfileMultiple()</CODE></A>
+<DD> Cal_BddPrintProfileMultiple is like Cal_BddPrintProfile except
+               it displays the profile for a set of BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddPrintProfile" TARGET="MAIN"><CODE>Cal_BddPrintProfile()</CODE></A>
+<DD> Displays the node profile for f on fp. lineLength specifies 
+               the maximum line length.  varNamingFn is as in
+               Cal_BddPrintBdd.
+
+<DT> <A HREF="calAllDet.html#Cal_BddProfileMultiple" TARGET="MAIN"><CODE>Cal_BddProfileMultiple()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#Cal_BddProfile" TARGET="MAIN"><CODE>Cal_BddProfile()</CODE></A>
+<DD> Returns a "node profile" of f, i.e., the number of nodes at each
+  level in f.
+
+<DT> <A HREF="calAllDet.html#Cal_BddReduce" TARGET="MAIN"><CODE>Cal_BddReduce()</CODE></A>
+<DD> Returns a BDD which agrees with f for all valuations
+  which satisfy c.
+
+<DT> <A HREF="calAllDet.html#Cal_BddRelProd" TARGET="MAIN"><CODE>Cal_BddRelProd()</CODE></A>
+<DD> Returns the result of taking the logical AND of the
+  argument BDDs and existentially quantifying some variables from the
+  product.
+
+<DT> <A HREF="calAllDet.html#Cal_BddReorder" TARGET="MAIN"><CODE>Cal_BddReorder()</CODE></A>
+<DD> Invoke the current dynamic reodering method.
+
+<DT> <A HREF="calAllDet.html#Cal_BddSatisfySupport" TARGET="MAIN"><CODE>Cal_BddSatisfySupport()</CODE></A>
+<DD> Returns a special cube contained in f.
+
+<DT> <A HREF="calAllDet.html#Cal_BddSatisfyingFraction" TARGET="MAIN"><CODE>Cal_BddSatisfyingFraction()</CODE></A>
+<DD> Returns the fraction of valuations which make f true. (Note that
+  this fraction is independent of whatever set of variables f is supposed to be
+  a function of)
+
+<DT> <A HREF="calAllDet.html#Cal_BddSatisfy" TARGET="MAIN"><CODE>Cal_BddSatisfy()</CODE></A>
+<DD> Returns a BDD which implies f, true for
+               some valuation on which f is true, and which has at most
+               one node at each level
+
+<DT> <A HREF="calAllDet.html#Cal_BddSetGCMode" TARGET="MAIN"><CODE>Cal_BddSetGCMode()</CODE></A>
+<DD> Sets the garbage collection mode, 0 means the garbage
+  collection should be turned off, 1 means garbage collection should
+  be on.
+
+<DT> <A HREF="calAllDet.html#Cal_BddSizeMultiple" TARGET="MAIN"><CODE>Cal_BddSizeMultiple()</CODE></A>
+<DD> The routine is like Cal_BddSize, but takes a null-terminated
+               array of BDDs and accounts for sharing of nodes.
+
+<DT> <A HREF="calAllDet.html#Cal_BddSize" TARGET="MAIN"><CODE>Cal_BddSize()</CODE></A>
+<DD> Returns the number of nodes in f when negout is nonzero. If
+  negout is zero, we pretend that the BDDs don't have negative-output pointers.
+
+<DT> <A HREF="calAllDet.html#Cal_BddStats" TARGET="MAIN"><CODE>Cal_BddStats()</CODE></A>
+<DD> Prints miscellaneous BDD statistics
+
+<DT> <A HREF="calAllDet.html#Cal_BddSubstitute" TARGET="MAIN"><CODE>Cal_BddSubstitute()</CODE></A>
+<DD> Substitute a set of variables by functions
+
+<DT> <A HREF="calAllDet.html#Cal_BddSupport" TARGET="MAIN"><CODE>Cal_BddSupport()</CODE></A>
+<DD> returns the support of f as a null-terminated array of variables
+
+<DT> <A HREF="calAllDet.html#Cal_BddSwapVars" TARGET="MAIN"><CODE>Cal_BddSwapVars()</CODE></A>
+<DD> Return a function obtained by swapping two variables
+
+<DT> <A HREF="calAllDet.html#Cal_BddThen" TARGET="MAIN"><CODE>Cal_BddThen()</CODE></A>
+<DD> Returns the positive cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddTotalSize" TARGET="MAIN"><CODE>Cal_BddTotalSize()</CODE></A>
+<DD> Returns the number of nodes in the Unique table
+
+<DT> <A HREF="calAllDet.html#Cal_BddType" TARGET="MAIN"><CODE>Cal_BddType()</CODE></A>
+<DD> Returns type of a BDD ( 0, 1, +var, -var, ovrflow, nonterminal)
+
+<DT> <A HREF="calAllDet.html#Cal_BddUnFree" TARGET="MAIN"><CODE>Cal_BddUnFree()</CODE></A>
+<DD> Unfrees the argument BDD.
+
+<DT> <A HREF="calAllDet.html#Cal_BddUndumpBdd" TARGET="MAIN"><CODE>Cal_BddUndumpBdd()</CODE></A>
+<DD> Reads a BDD from a file
+
+<DT> <A HREF="calAllDet.html#Cal_BddVarBlockReorderable" TARGET="MAIN"><CODE>Cal_BddVarBlockReorderable()</CODE></A>
+<DD> Sets the reoderability of a particular block.
+
+<DT> <A HREF="calAllDet.html#Cal_BddVarSubstitute" TARGET="MAIN"><CODE>Cal_BddVarSubstitute()</CODE></A>
+<DD> Substitute a set of variables by set of another variables.
+
+<DT> <A HREF="calAllDet.html#Cal_BddVars" TARGET="MAIN"><CODE>Cal_BddVars()</CODE></A>
+<DD> Returns the number of BDD variables
+
+<DT> <A HREF="calAllDet.html#Cal_BddXnor" TARGET="MAIN"><CODE>Cal_BddXnor()</CODE></A>
+<DD> Returns the BDD for logical exclusive NOR of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddXor" TARGET="MAIN"><CODE>Cal_BddXor()</CODE></A>
+<DD> Returns the BDD for logical exclusive OR of argument BDDs
+
+<DT> <A HREF="calAllDet.html#Cal_BddZero" TARGET="MAIN"><CODE>Cal_BddZero()</CODE></A>
+<DD> Returns the BDD for the constant zero
+
+<DT> <A HREF="calAllDet.html#Cal_MemAllocation" TARGET="MAIN"><CODE>Cal_MemAllocation()</CODE></A>
+<DD> Returns the memory allocated.
+
+<DT> <A HREF="calAllDet.html#Cal_MemFatal" TARGET="MAIN"><CODE>Cal_MemFatal()</CODE></A>
+<DD> Prints an error message and exits.
+
+<DT> <A HREF="calAllDet.html#Cal_MemFreeBlock" TARGET="MAIN"><CODE>Cal_MemFreeBlock()</CODE></A>
+<DD> Frees the block.
+
+<DT> <A HREF="calAllDet.html#Cal_MemFreeRecMgr" TARGET="MAIN"><CODE>Cal_MemFreeRecMgr()</CODE></A>
+<DD> Frees all the storage associated with the specified record manager.
+
+<DT> <A HREF="calAllDet.html#Cal_MemFreeRec" TARGET="MAIN"><CODE>Cal_MemFreeRec()</CODE></A>
+<DD> Frees a record managed by the indicated record manager.
+
+<DT> <A HREF="calAllDet.html#Cal_MemGetBlock" TARGET="MAIN"><CODE>Cal_MemGetBlock()</CODE></A>
+<DD> Allocates a new block of the specified size.
+
+<DT> <A HREF="calAllDet.html#Cal_MemNewRecMgr" TARGET="MAIN"><CODE>Cal_MemNewRecMgr()</CODE></A>
+<DD> Creates a new record manager with the given  record size.
+
+<DT> <A HREF="calAllDet.html#Cal_MemNewRec" TARGET="MAIN"><CODE>Cal_MemNewRec()</CODE></A>
+<DD> Allocates a record from the specified record manager.
+
+<DT> <A HREF="calAllDet.html#Cal_MemResizeBlock" TARGET="MAIN"><CODE>Cal_MemResizeBlock()</CODE></A>
+<DD> Expands or contracts the block to a new size.
+  We try to avoid moving the block if possible.
+
+<DT> <A HREF="calAllDet.html#Cal_PerformanceTest" TARGET="MAIN"><CODE>Cal_PerformanceTest()</CODE></A>
+<DD> Main routine for testing performances of various routines.
+
+<DT> <A HREF="calAllDet.html#Cal_PipelineCreateProvisionalBdd" TARGET="MAIN"><CODE>Cal_PipelineCreateProvisionalBdd()</CODE></A>
+<DD> Create a provisional BDD in the pipeline.
+
+<DT> <A HREF="calAllDet.html#Cal_PipelineExecute" TARGET="MAIN"><CODE>Cal_PipelineExecute()</CODE></A>
+<DD> Executes a pipeline.
+
+<DT> <A HREF="calAllDet.html#Cal_PipelineInit" TARGET="MAIN"><CODE>Cal_PipelineInit()</CODE></A>
+<DD> Initialize a BDD pipeline.
+
+<DT> <A HREF="calAllDet.html#Cal_PipelineQuit" TARGET="MAIN"><CODE>Cal_PipelineQuit()</CODE></A>
+<DD> Resets the pipeline freeing all resources.
+
+<DT> <A HREF="calAllDet.html#Cal_PipelineSetDepth" TARGET="MAIN"><CODE>Cal_PipelineSetDepth()</CODE></A>
+<DD> Set depth of a BDD pipeline.
+
+<DT> <A HREF="calAllDet.html#Cal_PipelineUpdateProvisionalBdd" TARGET="MAIN"><CODE>Cal_PipelineUpdateProvisionalBdd()</CODE></A>
+<DD> Update a provisional Bdd obtained during pipelining.
+
+<DT> <A HREF="calAllDet.html#Cal_TempAssociationAugment" TARGET="MAIN"><CODE>Cal_TempAssociationAugment()</CODE></A>
+<DD> Adds to the temporary variable association.
+
+<DT> <A HREF="calAllDet.html#Cal_TempAssociationInit" TARGET="MAIN"><CODE>Cal_TempAssociationInit()</CODE></A>
+<DD> Sets the temporary variable association.
+
+<DT> <A HREF="calAllDet.html#Cal_TempAssociationQuit" TARGET="MAIN"><CODE>Cal_TempAssociationQuit()</CODE></A>
+<DD> Cleans up temporary association
+
+<DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+<DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+<DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+<DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+<DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+<DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+<DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+<DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+<DT> <A HREF="calAllDet.html#CeilingLog2" TARGET="MAIN"><CODE>CeilingLog2()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#Chars" TARGET="MAIN"><CODE>Chars()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CheckAssoc" TARGET="MAIN"><CODE>CheckAssoc()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CheckValidityOfNodes" TARGET="MAIN"><CODE>CheckValidityOfNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#CofactorFixAndReclaimForwardedNodes" TARGET="MAIN"><CODE>CofactorFixAndReclaimForwardedNodes()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#Cofactor" TARGET="MAIN"><CODE>Cofactor()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#Decode" TARGET="MAIN"><CODE>Decode()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#Error" TARGET="MAIN"><CODE>Error()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#GetRandomNumbers" TARGET="MAIN"><CODE>GetRandomNumbers()</CODE></A>
+<DD> Generates "count" many random numbers ranging between
+  "lowerBound" and "upperBound".
+
+<DT> <A HREF="calAllDet.html#HashTableAddDirect" TARGET="MAIN"><CODE>HashTableAddDirect()</CODE></A>
+<DD> Directly insert a BDD node in the hash table.
+
+<DT> <A HREF="calAllDet.html#HashTableApply" TARGET="MAIN"><CODE>HashTableApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#HashTableCofactorApply" TARGET="MAIN"><CODE>HashTableCofactorApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#HashTableCofactorReduce" TARGET="MAIN"><CODE>HashTableCofactorReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#HashTableFindOrAdd" TARGET="MAIN"><CODE>HashTableFindOrAdd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#HashTableOneRehash" TARGET="MAIN"><CODE>HashTableOneRehash()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#HashTableReduceApply" TARGET="MAIN"><CODE>HashTableReduceApply()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#HashTableReduce" TARGET="MAIN"><CODE>HashTableReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#IndexCmp" TARGET="MAIN"><CODE>IndexCmp()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#MergeAndFree" TARGET="MAIN"><CODE>MergeAndFree()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#PageAlign" TARGET="MAIN"><CODE>PageAlign()</CODE></A>
+<DD> Return page aligned address greater than or equal to
+  the pointer.
+
+<DT> <A HREF="calAllDet.html#PageManagerExpandStorage" TARGET="MAIN"><CODE>PageManagerExpandStorage()</CODE></A>
+<DD> Allocates a segment of memory to expand the storage managed by
+              pageManager. The allocated segment is divided into free pages
+              which are linked as a freePageList.
+
+<DT> <A HREF="calAllDet.html#PrintBddProfileAfterReorder" TARGET="MAIN"><CODE>PrintBddProfileAfterReorder()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#PrintBdd" TARGET="MAIN"><CODE>PrintBdd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#RandomTests" TARGET="MAIN"><CODE>RandomTests()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#Read" TARGET="MAIN"><CODE>Read()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#RemoveFromFreeList" TARGET="MAIN"><CODE>RemoveFromFreeList()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#SegmentToPageList" TARGET="MAIN"><CODE>SegmentToPageList()</CODE></A>
+<DD> Converts a memory segment into a linked list of pages.
+              if p is a pointer to a page, *p contains address of the next page
+              if p is a pointer to the last page, *p contains lastPointer.
+
+<DT> <A HREF="calAllDet.html#SweepVarTable" TARGET="MAIN"><CODE>SweepVarTable()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestAnd" TARGET="MAIN"><CODE>TestAnd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestArrayOp" TARGET="MAIN"><CODE>TestArrayOp()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestAssoc" TARGET="MAIN"><CODE>TestAssoc()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestCompose" TARGET="MAIN"><CODE>TestCompose()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestDump" TARGET="MAIN"><CODE>TestDump()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestGenCof" TARGET="MAIN"><CODE>TestGenCof()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestITE" TARGET="MAIN"><CODE>TestITE()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestIdNot" TARGET="MAIN"><CODE>TestIdNot()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestInterImpl" TARGET="MAIN"><CODE>TestInterImpl()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestMultiwayAnd" TARGET="MAIN"><CODE>TestMultiwayAnd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestMultiwayLarge" TARGET="MAIN"><CODE>TestMultiwayLarge()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestMultiwayOr" TARGET="MAIN"><CODE>TestMultiwayOr()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestNand" TARGET="MAIN"><CODE>TestNand()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestOr" TARGET="MAIN"><CODE>TestOr()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestPipeline" TARGET="MAIN"><CODE>TestPipeline()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestQnt" TARGET="MAIN"><CODE>TestQnt()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestReduce" TARGET="MAIN"><CODE>TestReduce()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestRelProd" TARGET="MAIN"><CODE>TestRelProd()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestReorderBlock" TARGET="MAIN"><CODE>TestReorderBlock()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestReorder" TARGET="MAIN"><CODE>TestReorder()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestSatisfy" TARGET="MAIN"><CODE>TestSatisfy()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestSize" TARGET="MAIN"><CODE>TestSize()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestSubstitute" TARGET="MAIN"><CODE>TestSubstitute()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestSwapVars" TARGET="MAIN"><CODE>TestSwapVars()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestVarSubstitute" TARGET="MAIN"><CODE>TestVarSubstitute()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TestXor" TARGET="MAIN"><CODE>TestXor()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#TrimToSize" TARGET="MAIN"><CODE>TrimToSize()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#UniqueTableForIdFindOrAdd" TARGET="MAIN"><CODE>UniqueTableForIdFindOrAdd()</CODE></A>
+<DD> find or add in the unique table for id.
+
+<DT> <A HREF="calAllDet.html#Write" TARGET="MAIN"><CODE>Write()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#asAddress" TARGET="MAIN"><CODE>asAddress()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#asDouble" TARGET="MAIN"><CODE>asDouble()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#chars" TARGET="MAIN"><CODE>chars()</CODE></A>
+<DD> 
+
+<DT> <A HREF="calAllDet.html#cpuTime" TARGET="MAIN"><CODE>cpuTime()</CODE></A>
+<DD> Computes the number of page faults.
+
+<DT> <A HREF="calAllDet.html#cpuTime" TARGET="MAIN"><CODE>cpuTime()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#ddClearLocal" TARGET="MAIN"><CODE>ddClearLocal()</CODE></A>
+<DD> Performs a DFS from f, clearing the LSB of the then pointers.
+
+<DT> <A HREF="calAllDet.html#ddSuppInteract" TARGET="MAIN"><CODE>ddSuppInteract()</CODE></A>
+<DD> Find the support of f.
+
+<DT> <A HREF="calAllDet.html#ddUpdateInteract" TARGET="MAIN"><CODE>ddUpdateInteract()</CODE></A>
+<DD> Marks as interacting all pairs of variables that appear in
+  support.
+
+<DT> <A HREF="calAllDet.html#elapsedTime" TARGET="MAIN"><CODE>elapsedTime()</CODE></A>
+<DD> Computes the time.
+
+<DT> <A HREF="calAllDet.html#elapsedTime" TARGET="MAIN"><CODE>elapsedTime()</CODE></A>
+<DD> Computes the time.
+
+<DT> <A HREF="calAllDet.html#handler" TARGET="MAIN"><CODE>handler()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#main" TARGET="MAIN"><CODE>main()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#main" TARGET="MAIN"><CODE>main()</CODE></A>
+<DD> required
+
+<DT> <A HREF="calAllDet.html#pageFaults" TARGET="MAIN"><CODE>pageFaults()</CODE></A>
+<DD> Computes the number of page faults.
+
+<DT> <A HREF="calAllDet.html#terminalIdFn" TARGET="MAIN"><CODE>terminalIdFn()</CODE></A>
+<DD> required
+
+</DL>
+
+<HR>
+
+Last updated on 970711 20h11
+</BODY></HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calAllByFile.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calAllByFile.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calAllByFile.html	(revision 8)
@@ -0,0 +1,13 @@
+<HTML>
+<HEAD><TITLE>The cal package for maintainers</TITLE></HEAD>
+
+<FRAMESET ROWS="5%,90%,5%">
+  <FRAME SRC="calTitle.html">
+  <FRAMESET COLS="40%,60%">
+    <FRAME SRC="calAllFile.html" NAME="ABSTRACT">
+    <FRAME SRC="calAllDet.html" NAME="MAIN">
+  </FRAMESET>
+  <FRAME SRC="credit.html">
+</FRAMESET>
+
+</HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calAllByFunc.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calAllByFunc.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calAllByFunc.html	(revision 8)
@@ -0,0 +1,13 @@
+<HTML>
+<HEAD><TITLE>The cal package for maintainers</TITLE></HEAD>
+
+<FRAMESET ROWS="5%,90%,5%">
+  <FRAME SRC="calTitle.html">
+  <FRAMESET COLS="40%,60%">
+    <FRAME SRC="calAllAbs.html" NAME="ABSTRACT">
+    <FRAME SRC="calAllDet.html" NAME="MAIN">
+  </FRAMESET>
+  <FRAME SRC="credit.html">
+</FRAMESET>
+
+</HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calAllDet.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calAllDet.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calAllDet.html	(revision 8)
@@ -0,0 +1,7870 @@
+<html>
+<head><title>The cal package: all functions </title></head>
+<body>
+
+
+<HR>
+<DL>
+<dt><pre>
+<A NAME="AddBlock"></A>
+static void <I></I>
+<B>AddBlock</B>(
+  Cal_Block  <b>b1</b>, <i></i>
+  Cal_Block  <b>b2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="AddToFreeList"></A>
+static void <I></I>
+<B>AddToFreeList</B>(
+  Block  <b>b</b> <i></i>
+)
+</pre>
+<dd> AddToFreeList(b) adds b to the appropriate free list.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="AssociationIsEqual"></A>
+static int <I></I>
+<B>AssociationIsEqual</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t * <b>p</b>, <i></i>
+  Cal_Bdd_t * <b>q</b> <i></i>
+)
+</pre>
+<dd> Checks for equality of two associations
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddAddInternalReferences"></A>
+static void <I></I>
+<B>BddAddInternalReferences</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddArrayOpBF"></A>
+static Cal_Bdd_t * <I></I>
+<B>BddArrayOpBF</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t* <b>bddArray</b>, <i></i>
+  int  <b>numFunction</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b> <i></i>
+)
+</pre>
+<dd> Internal common routine for Cal_BddPairwiseAnd and Cal_BddPairwiseOr
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddArrayToRequestNodeListArray"></A>
+static void <I></I>
+<B>BddArrayToRequestNodeListArray</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t * <b>calBddArray</b>, <i></i>
+  int  <b>numBdds</b> <i></i>
+)
+</pre>
+<dd> Converts an array of BDDs to a list of requests representing BDD
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddCofactorBF"></A>
+static Cal_Bdd_t <I></I>
+<B>BddCofactorBF</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>c</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddConvertDataStructBack"></A>
+static void <I></I>
+<B>BddConvertDataStructBack</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Data structure conversion: thenBddId -> id 
+  elseBddId -> ref count
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddConvertDataStruct"></A>
+static void <I></I>
+<B>BddConvertDataStruct</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> New data structure: thenBddId -> id 
+                                          elseBddId -> ref count
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddCountNoNodes"></A>
+static int <I></I>
+<B>BddCountNoNodes</B>(
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddCountNodes"></A>
+static int <I></I>
+<B>BddCountNodes</B>(
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddDFStep"></A>
+static Cal_Bdd_t <I></I>
+<B>BddDFStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b>, <i></i>
+  unsigned short  <b>opCode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddDefaultTransformFn"></A>
+static void <I></I>
+<B>BddDefaultTransformFn</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalAddress_t  <b>value1</b>, <i></i>
+  CalAddress_t  <b>value2</b>, <i></i>
+  CalAddress_t * <b>result1</b>, <i></i>
+  CalAddress_t * <b>result2</b>, <i></i>
+  Cal_Pointer_t  <b>pointer</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddDominatedStep"></A>
+static void <I></I>
+<B>BddDominatedStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  long * <b>funcCounts</b>, <i></i>
+  CalHashTable_t * <b>h</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddDumpBddStep"></A>
+static void <I></I>
+<B>BddDumpBddStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  FILE * <b>fp</b>, <i></i>
+  CalHashTable_t * <b>h</b>, <i></i>
+  Cal_BddIndex_t * <b>normalizedIndexes</b>, <i></i>
+  int  <b>indexSize</b>, <i></i>
+  int  <b>nodeNumberSize</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calDump.c"TARGET="ABSTRACT"><CODE>calDump.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExchangeAux"></A>
+static void <I></I>
+<B>BddExchangeAux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalBddNode_t * <b>f</b>, <i></i>
+  int  <b>id</b>, <i></i>
+  int  <b>nextId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExchangeVarBlocks"></A>
+static void <I></I>
+<B>BddExchangeVarBlocks</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Block  <b>parent</b>, <i></i>
+  long  <b>blockIndex</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExchange"></A>
+static void <I></I>
+<B>BddExchange</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  long  <b>id</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExistsApply"></A>
+static void <I></I>
+<B>BddExistsApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>quantifying</b>, <i></i>
+  CalHashTable_t * <b>existHashTable</b>, <i></i>
+  CalHashTable_t ** <b>existHashTableArray</b>, <i></i>
+  CalOpProc1_t  <b>calOpProc</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExistsBFAux"></A>
+static void <I></I>
+<B>BddExistsBFAux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>minIndex</b>, <i></i>
+  CalHashTable_t ** <b>existHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>orHashTableArray</b>, <i></i>
+  CalOpProc1_t  <b>calOpProc</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExistsBFPlusDF"></A>
+static Cal_Bdd_t <I></I>
+<B>BddExistsBFPlusDF</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>association</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExistsReduce"></A>
+static void <I></I>
+<B>BddExistsReduce</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>existHashTable</b>, <i></i>
+  CalHashTable_t ** <b>existHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>orHashTableArray</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>association</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddExistsStep"></A>
+static Cal_Bdd_t <I></I>
+<B>BddExistsStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>association</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddHighestRefStep"></A>
+static void <I></I>
+<B>BddHighestRefStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  CalHashTable_t * <b>h</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddIntersectsStep"></A>
+static Cal_Bdd_t <I></I>
+<B>BddIntersectsStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b> <i></i>
+)
+</pre>
+<dd> Recursive routine to returns a BDD that implies conjunction of
+  argument BDDs
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddMarkBdd"></A>
+static void <I></I>
+<B>BddMarkBdd</B>(
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddMultiwayOp"></A>
+static Cal_Bdd_t <I></I>
+<B>BddMultiwayOp</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t * <b>calBddArray</b>, <i></i>
+  int  <b>numBdds</b>, <i></i>
+  CalOpProc_t  <b>op</b> <i></i>
+)
+</pre>
+<dd> Internal routine for multiway operations
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddNukeInternalReferences"></A>
+static void <I></I>
+<B>BddNukeInternalReferences</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddPrintBddStep"></A>
+static void <I></I>
+<B>BddPrintBddStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_VarNamingFn_t  <b>VarNamingFn</b>, <i></i>
+  Cal_TerminalIdFn_t  <b>TerminalIdFn</b>, <i></i>
+  Cal_Pointer_t  <b>env</b>, <i></i>
+  FILE * <b>fp</b>, <i></i>
+  CalHashTable_t* <b>hashTable</b>, <i></i>
+  int  <b>indentation</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddPrintTopVar"></A>
+static void <I></I>
+<B>BddPrintTopVar</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_VarNamingFn_t  <b>VarNamingFn</b>, <i></i>
+  Cal_Pointer_t  <b>env</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddProfileStep"></A>
+static void <I></I>
+<B>BddProfileStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  long * <b>levelCounts</b>, <i></i>
+  CountFn_t  <b>countFn</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReallocateNodesInPlace"></A>
+static void <I></I>
+<B>BddReallocateNodesInPlace</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReallocateNodes"></A>
+static void <I></I>
+<B>BddReallocateNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReduceBF"></A>
+static Cal_Bdd_t <I></I>
+<B>BddReduceBF</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>c</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddRelProdApply"></A>
+static void <I></I>
+<B>BddRelProdApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>quantifying</b>, <i></i>
+  CalHashTable_t * <b>relProdHashTable</b>, <i></i>
+  CalHashTable_t ** <b>relProdHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>andHashTableArray</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddRelProdBFAux"></A>
+static void <I></I>
+<B>BddRelProdBFAux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>minIndex</b>, <i></i>
+  CalHashTable_t ** <b>relProdHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>andHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>orHashTableArray</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddRelProdBFPlusDF"></A>
+static Cal_Bdd_t <I></I>
+<B>BddRelProdBFPlusDF</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>association</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddRelProdReduce"></A>
+static void <I></I>
+<B>BddRelProdReduce</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>relProdHashTable</b>, <i></i>
+  CalHashTable_t ** <b>relProdHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>andHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>orHashTableArray</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddRelProdStep"></A>
+static Cal_Bdd_t <I></I>
+<B>BddRelProdStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderFixAndFreeForwardingNodes"></A>
+static void <I></I>
+<B>BddReorderFixAndFreeForwardingNodes</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>id</b>, <i></i>
+  int  <b>numLevels</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderFixForwardingNodes"></A>
+static void <I></I>
+<B>BddReorderFixForwardingNodes</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>id</b> <i></i>
+)
+</pre>
+<dd> As opposed to CalBddReorderFixCofactors, which fixes
+  the cofactors of the non-forwarding nodes, this routine traverses
+  the list of forwarding nodes and removes the intermediate level of
+  forwarding. Number of levels should be 1 or 2.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderFreeNodes"></A>
+static void <I></I>
+<B>BddReorderFreeNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>varId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderSiftAux"></A>
+static void <I></I>
+<B>BddReorderSiftAux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Block  <b>block</b>, <i></i>
+  Cal_Block * <b>toSift</b>, <i></i>
+  double  <b>maxSizeFactor</b> <i></i>
+)
+</pre>
+<dd> Reorder variables using "sift" algorithm.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderSiftToBestPos"></A>
+static int <I></I>
+<B>BddReorderSiftToBestPos</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>varStartIndex</b>, <i></i>
+  double  <b>maxSizeFactor</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderSift"></A>
+static void <I></I>
+<B>BddReorderSift</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  double  <b>maxSizeFactor</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderStableWindow3Aux"></A>
+static void <I></I>
+<B>BddReorderStableWindow3Aux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Block  <b>block</b>, <i></i>
+  char * <b>levels</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderStableWindow3"></A>
+static void <I></I>
+<B>BddReorderStableWindow3</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderSwapVarIndex"></A>
+static void <I></I>
+<B>BddReorderSwapVarIndex</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>varIndex</b>, <i></i>
+  int  <b>forwardCheckFlag</b> <i></i>
+)
+</pre>
+<dd> Traversesoptional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderVarSift"></A>
+static void <I></I>
+<B>BddReorderVarSift</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  double  <b>maxSizeFactor</b> <i></i>
+)
+</pre>
+<dd> Reorder variables using "sift" algorithm.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderVarWindow"></A>
+static void <I></I>
+<B>BddReorderVarWindow</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  char * <b>levels</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderWindow2"></A>
+static int <I></I>
+<B>BddReorderWindow2</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  long  <b>index</b>, <i></i>
+  int  <b>directionFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderWindow2"></A>
+static int <I></I>
+<B>BddReorderWindow2</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Block  <b>block</b>, <i></i>
+  long  <b>i</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderWindow3"></A>
+static int <I></I>
+<B>BddReorderWindow3</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  long  <b>index</b>, <i></i>
+  int  <b>directionFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddReorderWindow3"></A>
+static int <I></I>
+<B>BddReorderWindow3</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Block  <b>block</b>, <i></i>
+  long  <b>i</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddSatisfyStep"></A>
+static Cal_Bdd_t <I></I>
+<B>BddSatisfyStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSatisfy.c"TARGET="ABSTRACT"><CODE>calBddSatisfy.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddSatisfySupportStep"></A>
+static Cal_Bdd_t <I></I>
+<B>BddSatisfySupportStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_BddId_t * <b>support</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSatisfy.c"TARGET="ABSTRACT"><CODE>calBddSatisfy.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddSatisfyingFractionStep"></A>
+static double <I></I>
+<B>BddSatisfyingFractionStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSatisfy.c"TARGET="ABSTRACT"><CODE>calBddSatisfy.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddSiftBlock"></A>
+static void <I></I>
+<B>BddSiftBlock</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Block  <b>block</b>, <i></i>
+  long  <b>startPosition</b>, <i></i>
+  double  <b>maxSizeFactor</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddSiftPerfromPhaseIV"></A>
+static void <I></I>
+<B>BddSiftPerfromPhaseIV</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>varStartIndex</b>, <i></i>
+  int  <b>bestIndex</b>, <i></i>
+  int  <b>bottomMostSwapIndex</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddSizeStep"></A>
+static long <I></I>
+<B>BddSizeStep</B>(
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  CountFn_t  <b>countFn</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddTerminalId"></A>
+static char * <I></I>
+<B>BddTerminalId</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_TerminalIdFn_t  <b>TerminalIdFn</b>, <i></i>
+  Cal_Pointer_t  <b>env</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddTerminalValueAux"></A>
+static void <I></I>
+<B>BddTerminalValueAux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  CalAddress_t * <b>value1</b>, <i></i>
+  CalAddress_t * <b>value2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="BddUndumpBddStep"></A>
+static Cal_Bdd_t <I></I>
+<B>BddUndumpBddStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t * <b>vars</b>, <i></i>
+  FILE * <b>fp</b>, <i></i>
+  Cal_BddIndex_t  <b>numberVars</b>, <i></i>
+  Cal_Bdd_t * <b>shared</b>, <i></i>
+  long  <b>numberShared</b>, <i></i>
+  long * <b>sharedSoFar</b>, <i></i>
+  int  <b>indexSize</b>, <i></i>
+  int  <b>nodeNumberSize</b>, <i></i>
+  int * <b>error</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calDump.c"TARGET="ABSTRACT"><CODE>calDump.c</CODE></A>
+
+<dt><pre>
+<A NAME="BlockSizeIndex"></A>
+static int <I></I>
+<B>BlockSizeIndex</B>(
+  Cal_Address_t  <b>size</b> <i></i>
+)
+</pre>
+<dd> BlockSizeIndex(size) return the coded size for a block.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Buddy"></A>
+static Block <I></I>
+<B>Buddy</B>(
+  Block  <b>b</b> <i></i>
+)
+</pre>
+<dd> Buddy(b) returns the Buddy block of b, or null if there is no  Buddy.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="BytesNeeded"></A>
+static int <I></I>
+<B>BytesNeeded</B>(
+  long  <b>n</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calDump.c"TARGET="ABSTRACT"><CODE>calDump.c</CODE></A>
+
+<dt><pre>
+<A NAME="CacheTablePrint"></A>
+static void <I></I>
+<B>CacheTablePrint</B>(
+  CalCacheTable_t * <b>cacheTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CacheTableTwoRehash"></A>
+static void <I></I>
+<B>CacheTableTwoRehash</B>(
+  CalCacheTable_t * <b>cacheTable</b>, <i></i>
+  int  <b>grow</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalAlignCollisionChains"></A>
+void <I></I>
+<B>CalAlignCollisionChains</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalAssociationListFree"></A>
+void <I></I>
+<B>CalAssociationListFree</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddArrayPreProcessing"></A>
+int <I></I>
+<B>CalBddArrayPreProcessing</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddBlockDelta"></A>
+void <I></I>
+<B>CalBddBlockDelta</B>(
+  Cal_Block  <b>b</b>, <i></i>
+  long  <b>delta</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddDependsOnStep"></A>
+static int <I></I>
+<B>CalBddDependsOnStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_BddIndex_t  <b>varIndex</b>, <i></i>
+  int  <b>mark</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSupport.c"TARGET="ABSTRACT"><CODE>calBddSupport.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddFatalMessage"></A>
+void <I></I>
+<B>CalBddFatalMessage</B>(
+  char * <b>string</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddFindBlock"></A>
+long <I></I>
+<B>CalBddFindBlock</B>(
+  Cal_Block  <b>block</b>, <i></i>
+  long  <b>index</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddFunctionPrint"></A>
+void <I></I>
+<B>CalBddFunctionPrint</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>calBdd</b>, <i></i>
+  char * <b>name</b> <i></i>
+)
+</pre>
+<dd> Prints the function implemented by the argument BDD
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddGetExternalBdd"></A>
+Cal_Bdd <I></I>
+<B>CalBddGetExternalBdd</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>internalBdd</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddGetInternalBdd"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddGetInternalBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddITE"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddITE</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>F</b>, <i></i>
+  Cal_Bdd_t  <b>G</b>, <i></i>
+  Cal_Bdd_t  <b>H</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical If-Then-Else
+ 
+   Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+   - f g + f' h
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddAnd">Cal_BddAnd</a>
+<a href="#Cal_BddNand">Cal_BddNand</a>
+<a href="#Cal_BddOr">Cal_BddOr</a>
+<a href="#Cal_BddNor">Cal_BddNor</a>
+<a href="#Cal_BddXor">Cal_BddXor</a>
+<a href="#Cal_BddXnor">Cal_BddXnor</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddITE.c"TARGET="ABSTRACT"><CODE>calBddITE.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddIdentity"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddIdentity</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>calBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the duplicate BDD of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddNot">Cal_BddNot</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddIf"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddIf</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>F</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddIsCubeStep"></A>
+int <I></I>
+<B>CalBddIsCubeStep</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is a cube, 0 otherwise
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddManagerCreateNewVar"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddManagerCreateNewVar</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_BddIndex_t  <b>index</b> <i></i>
+)
+</pre>
+<dd> Right now this function does not handle the case when the
+  package is working in multiprocessor mode. We need to put in the necessary
+  code later.
+<p>
+
+<dd> <b>Side Effects</b> If the number of variables in the manager exceeds that of value
+  of numMaxVars, then we need to reallocate various fields of the manager. Also
+  depending upon the value of "index", idToIndex and indexToId tables would
+  change.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddManagerGCCheck"></A>
+void <I></I>
+<B>CalBddManagerGCCheck</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calGC.c"TARGET="ABSTRACT"><CODE>calGC.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddManagerGetCacheTableData"></A>
+void <I></I>
+<B>CalBddManagerGetCacheTableData</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  unsigned long * <b>cacheSize</b>, <i></i>
+  unsigned long * <b>cacheEntries</b>, <i></i>
+  unsigned long * <b>cacheInsertions</b>, <i></i>
+  unsigned long * <b>cacheLookups</b>, <i></i>
+  unsigned long * <b>cacheHits</b>, <i></i>
+  unsigned long * <b>cacheCollisions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddManagerPrint"></A>
+static int <I></I>
+<B>CalBddManagerPrint</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddMarkSharedNodes"></A>
+void <I></I>
+<B>CalBddMarkSharedNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddNodePrint"></A>
+void <I></I>
+<B>CalBddNodePrint</B>(
+  CalBddNode_t * <b>bddNode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddNumberSharedNodes"></A>
+void <I></I>
+<B>CalBddNumberSharedNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  long * <b>next</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddOpBF"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddOpBF</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b>, <i></i>
+  Cal_Bdd_t  <b>F</b>, <i></i>
+  Cal_Bdd_t  <b>G</b> <i></i>
+)
+</pre>
+<dd> Internal routine to compute a logical operation on a pair of BDDs
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddOpITEBF"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddOpITEBF</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  Cal_Bdd_t  <b>h</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddITE.c"TARGET="ABSTRACT"><CODE>calBddITE.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddPackNodesAfterReorderForSingleId"></A>
+void <I></I>
+<B>CalBddPackNodesAfterReorderForSingleId</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>fixForwardedNodesFlag</b>, <i></i>
+  int  <b>bestIndex</b>, <i></i>
+  int  <b>bottomIndex</b> <i></i>
+)
+</pre>
+<dd> fixForwardedNodesFlag: Whether we need to fix
+  the forwarded nodes of variables corresponding to bestIndex through
+  bottomIndex. If this flag is set, then the forwarded nodes of these
+  variables are traversed and updated after the nodes of the bestIndex
+  have been copied. At the end the forwarded nodes are freed. If this
+  flag is not set, it is assumed that the cleanup pass has already
+  been performed.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddPackNodesForMultipleIds"></A>
+void <I></I>
+<B>CalBddPackNodesForMultipleIds</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>beginId</b>, <i></i>
+  int  <b>numLevels</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddPackNodesForSingleId"></A>
+void <I></I>
+<B>CalBddPackNodesForSingleId</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>id</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddPostProcessing"></A>
+int <I></I>
+<B>CalBddPostProcessing</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddPreProcessing"></A>
+int <I></I>
+<B>CalBddPreProcessing</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>count</b>, <i></i>
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddPrintProfileAux"></A>
+static void <I></I>
+<B>CalBddPrintProfileAux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  long * <b>levelCounts</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrintProfile.c"TARGET="ABSTRACT"><CODE>calPrintProfile.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddPrint"></A>
+void <I></I>
+<B>CalBddPrint</B>(
+  Cal_Bdd_t  <b>calBdd</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddReorderAuxBF"></A>
+void <I></I>
+<B>CalBddReorderAuxBF</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddReorderAuxDF"></A>
+void <I></I>
+<B>CalBddReorderAuxDF</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddReorderFixCofactors"></A>
+void <I></I>
+<B>CalBddReorderFixCofactors</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>id</b> <i></i>
+)
+</pre>
+<dd> This routine traverses the unique table and for
+  each node, looks at the then and else cofactors. If needed fixes the
+  cofactors.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddReorderFixProvisionalNodes"></A>
+void <I></I>
+<B>CalBddReorderFixProvisionalNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddReorderFixUserBddPtrs"></A>
+void <I></I>
+<B>CalBddReorderFixUserBddPtrs</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddReorderReclaimForwardedNodes"></A>
+void <I></I>
+<B>CalBddReorderReclaimForwardedNodes</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>startIndex</b>, <i></i>
+  int  <b>endIndex</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddShiftBlock"></A>
+Cal_Block <I></I>
+<B>CalBddShiftBlock</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Block  <b>b</b>, <i></i>
+  long  <b>index</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddSupportStep"></A>
+static Cal_Bdd_t * <I></I>
+<B>CalBddSupportStep</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t * <b>support</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSupport.c"TARGET="ABSTRACT"><CODE>calBddSupport.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddTypeAux"></A>
+int <I></I>
+<B>CalBddTypeAux</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD type by recursively traversing the argument BDD
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddUniqueTableNumLockedNodes"></A>
+unsigned long <I></I>
+<B>CalBddUniqueTableNumLockedNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>uniqueTableForId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddUnmarkNodes"></A>
+static void <I></I>
+<B>CalBddUnmarkNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSupport.c"TARGET="ABSTRACT"><CODE>calBddSupport.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddVarName"></A>
+char * <I></I>
+<B>CalBddVarName</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>v</b>, <i></i>
+  Cal_VarNamingFn_t  <b>VarNamingFn</b>, <i></i>
+  Cal_Pointer_t  <b>env</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddVarSubstitute"></A>
+Cal_Bdd_t <I></I>
+<B>CalBddVarSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  unsigned short  <b>opCode</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD for f using the substitution defined by current
+  variable association. Each variable is replaced by its associated BDDs. The 
+  substitution is effective simultaneously
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddCompose">Cal_BddCompose</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddVarSubstitute.c"TARGET="ABSTRACT"><CODE>calBddVarSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBddWarningMessage"></A>
+void <I></I>
+<B>CalBddWarningMessage</B>(
+  char * <b>string</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalBlockMemoryConsumption"></A>
+unsigned long <I></I>
+<B>CalBlockMemoryConsumption</B>(
+  Cal_Block  <b>block</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableMemoryConsumption"></A>
+unsigned long <I></I>
+<B>CalCacheTableMemoryConsumption</B>(
+  CalCacheTable_t * <b>cacheTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTablePrint"></A>
+void <I></I>
+<B>CalCacheTablePrint</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableRehash"></A>
+void <I></I>
+<B>CalCacheTableRehash</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoFixResultPointers"></A>
+void <I></I>
+<B>CalCacheTableTwoFixResultPointers</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoFlushAll"></A>
+int <I></I>
+<B>CalCacheTableTwoFlushAll</B>(
+  CalCacheTable_t * <b>cacheTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoFlushAssociationId"></A>
+void <I></I>
+<B>CalCacheTableTwoFlushAssociationId</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>associationId</b> <i></i>
+)
+</pre>
+<dd> Flushes the entries from the cache which
+                      correspond to the given associationId.
+<p>
+
+<dd> <b>Side Effects</b> Cache entries are affected.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoFlush"></A>
+void <I></I>
+<B>CalCacheTableTwoFlush</B>(
+  CalCacheTable_t * <b>cacheTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoGCFlush"></A>
+void <I></I>
+<B>CalCacheTableTwoGCFlush</B>(
+  CalCacheTable_t * <b>cacheTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoInit"></A>
+CalCacheTable_t * <I></I>
+<B>CalCacheTableTwoInit</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoInsert"></A>
+void <I></I>
+<B>CalCacheTableTwoInsert</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  Cal_Bdd_t  <b>result</b>, <i></i>
+  unsigned long  <b>opCode</b>, <i></i>
+  int  <b>cacheLevel</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoLookup"></A>
+int <I></I>
+<B>CalCacheTableTwoLookup</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  unsigned long  <b>opCode</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoQuit"></A>
+int <I></I>
+<B>CalCacheTableTwoQuit</B>(
+  CalCacheTable_t * <b>cacheTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCacheTableTwoRepackUpdate"></A>
+void <I></I>
+<B>CalCacheTableTwoRepackUpdate</B>(
+  CalCacheTable_t * <b>cacheTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckAllValidity"></A>
+int <I></I>
+<B>CalCheckAllValidity</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckAssociationValidity"></A>
+void <I></I>
+<B>CalCheckAssociationValidity</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckAssoc"></A>
+int <I></I>
+<B>CalCheckAssoc</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckCacheTableValidity"></A>
+void <I></I>
+<B>CalCheckCacheTableValidity</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calCacheTableTwo.c"TARGET="ABSTRACT"><CODE>calCacheTableTwo.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckPipelineValidity"></A>
+void <I></I>
+<B>CalCheckPipelineValidity</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckRefCountValidity"></A>
+void <I></I>
+<B>CalCheckRefCountValidity</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckValidityOfANode"></A>
+int <I></I>
+<B>CalCheckValidityOfANode</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalBddNode_t * <b>bddNode</b>, <i></i>
+  int  <b>id</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckValidityOfNodesForId"></A>
+int <I></I>
+<B>CalCheckValidityOfNodesForId</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>id</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalCheckValidityOfNodesForWindow"></A>
+int <I></I>
+<B>CalCheckValidityOfNodesForWindow</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddIndex_t  <b>index</b>, <i></i>
+  int  <b>numLevels</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalComposeRequestCreate"></A>
+void <I></I>
+<B>CalComposeRequestCreate</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>h</b>, <i></i>
+  Cal_BddIndex_t  <b>composeIndex</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForCompose</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForITE</b>, <i></i>
+  Cal_Bdd_t * <b>resultPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddCompose.c"TARGET="ABSTRACT"><CODE>calBddCompose.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalDecreasingOrderCompare"></A>
+int <I></I>
+<B>CalDecreasingOrderCompare</B>(
+  const void * <b>a</b>, <i></i>
+  const void * <b>b</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalFixupAssoc"></A>
+void <I></I>
+<B>CalFixupAssoc</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  long  <b>id1</b>, <i></i>
+  long  <b>id2</b>, <i></i>
+  CalAssociation_t * <b>assoc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderUtil.c"TARGET="ABSTRACT"><CODE>calReorderUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalFreeBlockRecursively"></A>
+void <I></I>
+<B>CalFreeBlockRecursively</B>(
+  Cal_Block  <b>block</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableAddDirectAux"></A>
+int <I></I>
+<B>CalHashTableAddDirectAux</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>thenBdd</b>, <i></i>
+  Cal_Bdd_t  <b>elseBdd</b>, <i></i>
+  Cal_Bdd_t * <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableAddDirect"></A>
+void <I></I>
+<B>CalHashTableAddDirect</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalBddNode_t * <b>bddNode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableApply"></A>
+void <I></I>
+<B>CalHashTableApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t ** <b>reqQueAtPipeDepth</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calApplyReduce.c"TARGET="ABSTRACT"><CODE>calApplyReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableCleanUp"></A>
+void <I></I>
+<B>CalHashTableCleanUp</B>(
+  CalHashTable_t * <b>hashTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableComposeApply"></A>
+void <I></I>
+<B>CalHashTableComposeApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_BddIndex_t  <b>gIndex</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForCompose</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForITE</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddCompose.c"TARGET="ABSTRACT"><CODE>calBddCompose.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableDelete"></A>
+void <I></I>
+<B>CalHashTableDelete</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalBddNode_t * <b>bddNode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableFindOrAdd"></A>
+int <I></I>
+<B>CalHashTableFindOrAdd</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>thenBdd</b>, <i></i>
+  Cal_Bdd_t  <b>elseBdd</b>, <i></i>
+  Cal_Bdd_t * <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableGC"></A>
+int <I></I>
+<B>CalHashTableGC</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b> <i></i>
+)
+</pre>
+<dd> The input is the hash table containing the nodes
+  belonging to that level. Each bin of the hash table is traversed and
+  the Bdd nodes with 0 reference count are put at the appropriate
+  level in the processing que of the manager.
+<p>
+
+<dd> <b>Side Effects</b> The number of nodes in the hash table can possibly decrease.
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calGC.c"TARGET="ABSTRACT"><CODE>calGC.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableITEApply"></A>
+void <I></I>
+<B>CalHashTableITEApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t ** <b>reqQueAtPipeDepth</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddITE.c"TARGET="ABSTRACT"><CODE>calBddITE.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableInit"></A>
+CalHashTable_t * <I></I>
+<B>CalHashTableInit</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>bddId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableLookup"></A>
+int <I></I>
+<B>CalHashTableLookup</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>thenBdd</b>, <i></i>
+  Cal_Bdd_t  <b>elseBdd</b>, <i></i>
+  Cal_Bdd_t * <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableOneInit"></A>
+CalHashTable_t * <I></I>
+<B>CalHashTableOneInit</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>itemSize</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTableOne.c"TARGET="ABSTRACT"><CODE>calHashTableOne.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableOneInsert"></A>
+void <I></I>
+<B>CalHashTableOneInsert</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>keyBdd</b>, <i></i>
+  char * <b>valuePtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTableOne.c"TARGET="ABSTRACT"><CODE>calHashTableOne.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableOneLookup"></A>
+int <I></I>
+<B>CalHashTableOneLookup</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>keyBdd</b>, <i></i>
+  char ** <b>valuePtrPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTableOne.c"TARGET="ABSTRACT"><CODE>calHashTableOne.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableOnePrint"></A>
+void <I></I>
+<B>CalHashTableOnePrint</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  int  <b>flag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableOneQuit"></A>
+void <I></I>
+<B>CalHashTableOneQuit</B>(
+  CalHashTable_t * <b>hashTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTableOne.c"TARGET="ABSTRACT"><CODE>calHashTableOne.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTablePrint"></A>
+void <I></I>
+<B>CalHashTablePrint</B>(
+  CalHashTable_t * <b>hashTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableQuit"></A>
+int <I></I>
+<B>CalHashTableQuit</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableReduce"></A>
+void <I></I>
+<B>CalHashTableReduce</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t * <b>uniqueTableForId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calApplyReduce.c"TARGET="ABSTRACT"><CODE>calApplyReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableRehash"></A>
+void <I></I>
+<B>CalHashTableRehash</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  int  <b>grow</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableSubstituteApply"></A>
+static void <I></I>
+<B>CalHashTableSubstituteApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  int  <b>lastIndex</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSubstitute</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSubstitute.c"TARGET="ABSTRACT"><CODE>calBddSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableSubstituteApply"></A>
+static void <I></I>
+<B>CalHashTableSubstituteApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  int  <b>lastIndex</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSubstitute</b>, <i></i>
+  unsigned short  <b>opCode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddVarSubstitute.c"TARGET="ABSTRACT"><CODE>calBddVarSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableSubstituteReduce"></A>
+static void <I></I>
+<B>CalHashTableSubstituteReduce</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForITE</b>, <i></i>
+  CalHashTable_t * <b>uniqueTableForId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSubstitute.c"TARGET="ABSTRACT"><CODE>calBddSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableSubstituteReduce"></A>
+static void <I></I>
+<B>CalHashTableSubstituteReduce</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForITE</b>, <i></i>
+  CalHashTable_t * <b>uniqueTableForId</b>, <i></i>
+  unsigned short  <b>opCode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddVarSubstitute.c"TARGET="ABSTRACT"><CODE>calBddVarSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableSwapVarsApply"></A>
+static void <I></I>
+<B>CalHashTableSwapVarsApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_BddIndex_t  <b>gIndex</b>, <i></i>
+  Cal_BddIndex_t  <b>hIndex</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVars</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVarsPlus</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVarsMinus</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForCompose</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForITE</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSwapVars.c"TARGET="ABSTRACT"><CODE>calBddSwapVars.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableSwapVarsMinusApply"></A>
+static void <I></I>
+<B>CalHashTableSwapVarsMinusApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_BddIndex_t  <b>hIndex</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVars</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVarsPlus</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVarsMinus</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForCompose</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSwapVars.c"TARGET="ABSTRACT"><CODE>calBddSwapVars.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableSwapVarsPlusApply"></A>
+static void <I></I>
+<B>CalHashTableSwapVarsPlusApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_BddIndex_t  <b>hIndex</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVars</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVarsPlus</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForSwapVarsMinus</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForCompose</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSwapVars.c"TARGET="ABSTRACT"><CODE>calBddSwapVars.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableThreeFindOrAdd"></A>
+int <I></I>
+<B>CalHashTableThreeFindOrAdd</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  Cal_Bdd_t  <b>h</b>, <i></i>
+  Cal_Bdd_t * <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTableThree.c"TARGET="ABSTRACT"><CODE>calHashTableThree.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalHashTableThreeRehash"></A>
+static void <I></I>
+<B>CalHashTableThreeRehash</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  int  <b>grow</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTableThree.c"TARGET="ABSTRACT"><CODE>calHashTableThree.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalIncreasingOrderCompare"></A>
+int <I></I>
+<B>CalIncreasingOrderCompare</B>(
+  const void * <b>a</b>, <i></i>
+  const void * <b>b</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalInitInteract"></A>
+int <I></I>
+<B>CalInitInteract</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Initializes the interaction matrix. The interaction
+  matrix is implemented as a bit vector storing the upper triangle of
+  the symmetric interaction matrix. The bit vector is kept in an array
+  of long integers. The computation is based on a series of depth-first
+  searches, one for each root of the DAG. A local flag (the mark bits)
+  is used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calInteract.c"TARGET="ABSTRACT"><CODE>calInteract.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalNodeManagerInit"></A>
+CalNodeManager_t * <I></I>
+<B>CalNodeManagerInit</B>(
+  CalPageManager_t * <b>pageManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalNodeManagerPrint"></A>
+void <I></I>
+<B>CalNodeManagerPrint</B>(
+  CalNodeManager_t * <b>nodeManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalNodeManagerQuit"></A>
+int <I></I>
+<B>CalNodeManagerQuit</B>(
+  CalNodeManager_t * <b>nodeManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> The associated nodes are lost.
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpAnd"></A>
+int <I></I>
+<B>CalOpAnd</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>F</b>, <i></i>
+  Cal_Bdd_t  <b>G</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTerminal.c"TARGET="ABSTRACT"><CODE>calTerminal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpBddVarSubstitute"></A>
+int <I></I>
+<B>CalOpBddVarSubstitute</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddVarSubstitute.c"TARGET="ABSTRACT"><CODE>calBddVarSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpCofactor"></A>
+int <I></I>
+<B>CalOpCofactor</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>c</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpExists"></A>
+int <I></I>
+<B>CalOpExists</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpITE"></A>
+Cal_Bdd_t <I></I>
+<B>CalOpITE</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  Cal_Bdd_t  <b>h</b>, <i></i>
+  CalHashTable_t ** <b>reqQueForITE</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTerminal.c"TARGET="ABSTRACT"><CODE>calTerminal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpNand"></A>
+int <I></I>
+<B>CalOpNand</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>F</b>, <i></i>
+  Cal_Bdd_t  <b>G</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTerminal.c"TARGET="ABSTRACT"><CODE>calTerminal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpOr"></A>
+int <I></I>
+<B>CalOpOr</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>F</b>, <i></i>
+  Cal_Bdd_t  <b>G</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTerminal.c"TARGET="ABSTRACT"><CODE>calTerminal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpRelProd"></A>
+int <I></I>
+<B>CalOpRelProd</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  Cal_Bdd_t  <b>g</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalOpXor"></A>
+int <I></I>
+<B>CalOpXor</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>F</b>, <i></i>
+  Cal_Bdd_t  <b>G</b>, <i></i>
+  Cal_Bdd_t * <b>resultBddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTerminal.c"TARGET="ABSTRACT"><CODE>calTerminal.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPackNodes"></A>
+void <I></I>
+<B>CalPackNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPageManagerAllocPage"></A>
+CalAddress_t * <I></I>
+<B>CalPageManagerAllocPage</B>(
+  CalPageManager_t * <b>pageManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPageManagerFreePage"></A>
+void <I></I>
+<B>CalPageManagerFreePage</B>(
+  CalPageManager_t * <b>pageManager</b>, <i></i>
+  CalAddress_t * <b>page</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPageManagerInit"></A>
+CalPageManager_t * <I></I>
+<B>CalPageManagerInit</B>(
+  int  <b>numPagesPerSegment</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPageManagerPrint"></A>
+void <I></I>
+<B>CalPageManagerPrint</B>(
+  CalPageManager_t * <b>pageManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPageManagerQuit"></A>
+int <I></I>
+<B>CalPageManagerQuit</B>(
+  CalPageManager_t * <b>pageManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformaceTestSuperscalar"></A>
+static void <I></I>
+<B>CalPerformaceTestSuperscalar</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceMemoryOverhead"></A>
+static void <I></I>
+<B>CalPerformanceMemoryOverhead</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestAnd"></A>
+static void <I></I>
+<B>CalPerformanceTestAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestCompose"></A>
+static void <I></I>
+<B>CalPerformanceTestCompose</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestMultiway"></A>
+static void <I></I>
+<B>CalPerformanceTestMultiway</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestNonSuperscalar"></A>
+static void <I></I>
+<B>CalPerformanceTestNonSuperscalar</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestOneway"></A>
+static void <I></I>
+<B>CalPerformanceTestOneway</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestQuantifyAllTogether"></A>
+static void <I></I>
+<B>CalPerformanceTestQuantifyAllTogether</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b>, <i></i>
+  int  <b>bfZeroBFPlusDFOne</b>, <i></i>
+  int  <b>cacheExistsResultsFlag</b>, <i></i>
+  int  <b>cacheOrResultsFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestRelProd"></A>
+static void <I></I>
+<B>CalPerformanceTestRelProd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b>, <i></i>
+  int  <b>bfZeroBFPlusDFOne</b>, <i></i>
+  int  <b>cacheRelProdResultsFlag</b>, <i></i>
+  int  <b>cacheAndResultsFlag</b>, <i></i>
+  int  <b>cacheOrResultsFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestSubstitute"></A>
+static void <I></I>
+<B>CalPerformanceTestSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalPerformanceTestSwapVars"></A>
+static void <I></I>
+<B>CalPerformanceTestSwapVars</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalQuantifySanityCheck"></A>
+static void <I></I>
+<B>CalQuantifySanityCheck</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalReorderAssociationFix"></A>
+void <I></I>
+<B>CalReorderAssociationFix</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalRepackNodesAfterGC"></A>
+static void <I></I>
+<B>CalRepackNodesAfterGC</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calGC.c"TARGET="ABSTRACT"><CODE>calGC.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalRequestNodeListArrayITE"></A>
+void <I></I>
+<B>CalRequestNodeListArrayITE</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalRequestNode_t ** <b>requestNodeListArray</b> <i></i>
+)
+</pre>
+<dd> This routine is to be used for pipelined and
+  superscalar ITE operations. Currently there is no user interface
+  provided to this routine.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddITE.c"TARGET="ABSTRACT"><CODE>calBddITE.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalRequestNodeListArrayOp"></A>
+void <I></I>
+<B>CalRequestNodeListArrayOp</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalRequestNode_t ** <b>requestNodeListArray</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b> <i></i>
+)
+</pre>
+<dd> Computes result BDDs for an array of lists, each entry of which
+  is pair of pointers, each of which points to a operand BDD or an entry in
+  another list with a smaller array index
+<p>
+
+<dd> <b>Side Effects</b> ThenBDD pointer of an entry is over written by the result BDD
+  and ElseBDD pointer is marked using FORWARD_FLAG
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalRequestNodeListCompose"></A>
+void <I></I>
+<B>CalRequestNodeListCompose</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalRequestNode_t * <b>requestNodeList</b>, <i></i>
+  Cal_BddIndex_t  <b>composeIndex</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddCompose.c"TARGET="ABSTRACT"><CODE>calBddCompose.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalSetInteract"></A>
+void <I></I>
+<B>CalSetInteract</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Given a pair of variables 0 <= x < y < table->size,
+  sets the corresponding bit of the interaction matrix to 1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calInteract.c"TARGET="ABSTRACT"><CODE>calInteract.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalTestInteract"></A>
+int <I></I>
+<B>CalTestInteract</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Given a pair of variables 0 <= x < y < bddManager->numVars,
+  tests whether the corresponding bit of the interaction matrix is 1.
+  Returns the value of the bit.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calInteract.c"TARGET="ABSTRACT"><CODE>calInteract.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalUniqueTableForIdFindOrAdd"></A>
+int <I></I>
+<B>CalUniqueTableForIdFindOrAdd</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>thenBdd</b>, <i></i>
+  Cal_Bdd_t  <b>elseBdd</b>, <i></i>
+  Cal_Bdd_t * <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> If a new BDD node is created (found == false), then the
+  numNodes field of the manager needs to be incremented.
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalUniqueTableForIdLookup"></A>
+int <I></I>
+<B>CalUniqueTableForIdLookup</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  Cal_Bdd_t  <b>thenBdd</b>, <i></i>
+  Cal_Bdd_t  <b>elseBdd</b>, <i></i>
+  Cal_Bdd_t * <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalUniqueTableForIdRehashNode"></A>
+void <I></I>
+<B>CalUniqueTableForIdRehashNode</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalBddNode_t * <b>bddNode</b>, <i></i>
+  CalBddNode_t * <b>thenBddNode</b>, <i></i>
+  CalBddNode_t * <b>elseBddNode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalUniqueTablePrint"></A>
+void <I></I>
+<B>CalUniqueTablePrint</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="CalVarAssociationRepackUpdate"></A>
+void <I></I>
+<B>CalVarAssociationRepackUpdate</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>id</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_AssociationInit"></A>
+int <I></I>
+<B>Cal_AssociationInit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>associationInfoUserBdds</b>, <i></i>
+  int  <b>pairs</b> <i></i>
+)
+</pre>
+<dd> Creates or finds a variable association. The association is
+  specified by associationInfo, which is a an array of BDD with 
+  Cal_BddNull(bddManager) as the end marker. If pairs is 0, the array is
+  assumed to be an array of variables. In this case, each variable is paired
+  with constant BDD one. Such an association may viewed as specifying a set
+  of variables for use with routines such as Cal_BddExists. If pair is not 0,
+  then the even numbered array elements should be variables and the odd numbered
+  elements should be the BDDs which they are mapped to. In both cases, the 
+  return value is an integer identifier for this association. If the given
+  association is equivalent to one which already exists, the same identifier
+  is used for both, and the reference count of the association is increased by
+  one.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_AssociationQuit">Cal_AssociationQuit</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_AssociationQuit"></A>
+void <I></I>
+<B>Cal_AssociationQuit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>associationId</b> <i></i>
+)
+</pre>
+<dd> Decrements the reference count of the variable association with
+  identifier id, and frees it if the reference count becomes zero.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_AssociationInit">Cal_AssociationInit</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_AssociationSetCurrent"></A>
+int <I></I>
+<B>Cal_AssociationSetCurrent</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>associationId</b> <i></i>
+)
+</pre>
+<dd> Sets the current variable association to the one given by id and
+  returns the ID of the old association.  An id of -1 indicates the temporary
+  association
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddAnd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical AND of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddBetween"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddBetween</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fMinUserBdd</b>, <i></i>
+  Cal_Bdd  <b>fMaxUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a minimal BDD f which is contains fMin and is
+  contained in fMax ( fMin <= f <= fMax).
+  This operation is typically used in state space searches to simplify
+  the representation for the set of states wich will be expanded at
+  each step (Rk Rk-1' <= f <= Rk).
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddReduce">Cal_BddReduce</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddCofactor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddCofactor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>cUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the generalized cofactor of BDD f with respect
+  to BDD c. The constrain operator given by Coudert et al (ICCAD90) is
+  used to find the generalized cofactor.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddReduce">Cal_BddReduce</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddCompose"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddCompose</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b>, <i></i>
+  Cal_Bdd  <b>hUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD obtained by substituting a variable by a function
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddCompose.c"TARGET="ABSTRACT"><CODE>calBddCompose.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddDependsOn"></A>
+int <I></I>
+<B>Cal_BddDependsOn</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>varUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f depends on var and returns 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSupport.c"TARGET="ABSTRACT"><CODE>calBddSupport.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddDumpBdd"></A>
+int <I></I>
+<B>Cal_BddDumpBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd * <b>userVars</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Writes an encoded description of the BDD to the file given by fp.
+  The argument vars should be a null-terminated array of variables that include
+  the support of f .  These variables need not be in order of increasing index.
+  The function returns a nonzero value if f was written to the file successfully.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calDump.c"TARGET="ABSTRACT"><CODE>calDump.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddDynamicReordering"></A>
+void <I></I>
+<B>Cal_BddDynamicReordering</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>technique</b> <i></i>
+)
+</pre>
+<dd> Selects the method for dynamic reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddReorder">Cal_BddReorder</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddElse"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddElse</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the negative cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the returned BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddThen">Cal_BddThen</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddExists"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddExists</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for f with all the variables that are
+  paired with something in the current variable association
+  existentially quantified out.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddRelProd">Cal_BddRelProd</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddForAll"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddForAll</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for f with all the variables that are
+  paired with something in the current variable association
+  universally quantified out.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddFree"></A>
+void <I></I>
+<B>Cal_BddFree</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Frees the argument BDD. It is an error to free a BDD
+  more than once.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the argument BDD is decreased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddUnFree">Cal_BddUnFree</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddFunctionPrint"></A>
+void <I></I>
+<B>Cal_BddFunctionPrint</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b>, <i></i>
+  char * <b>name</b> <i></i>
+)
+</pre>
+<dd> Prints the function implemented by the argument BDD
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calUtil.c"TARGET="ABSTRACT"><CODE>calUtil.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddFunctionProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddFunctionProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>fUserBddArray</b>, <i></i>
+  long * <b>funcCounts</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddFunctionProfile"></A>
+void <I></I>
+<B>Cal_BddFunctionProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  long * <b>funcCounts</b> <i></i>
+)
+</pre>
+<dd> The nth entry of the function
+  profile array is the number of subfunctions of f which may be obtained by 
+  restricting the variables whose index is less than n.  An entry of zero 
+  indicates that f is independent of the variable with the corresponding index.
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddGetIfId"></A>
+Cal_BddId_t <I></I>
+<B>Cal_BddGetIfId</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the id of the top variable of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddGetIfIndex">Cal_BddGetIfIndex</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddGetIfIndex"></A>
+Cal_BddId_t <I></I>
+<B>Cal_BddGetIfIndex</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the top variable of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddGetIfId">Cal_BddGetIfId</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddGetRegular"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddGetRegular</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD with positive from a given BDD with arbitrary phase
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddITE"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddITE</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b>, <i></i>
+  Cal_Bdd  <b>hUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical If-Then-Else
+
+  Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+  - f g + f' h
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddAnd">Cal_BddAnd</a>
+<a href="#Cal_BddNand">Cal_BddNand</a>
+<a href="#Cal_BddOr">Cal_BddOr</a>
+<a href="#Cal_BddNor">Cal_BddNor</a>
+<a href="#Cal_BddXor">Cal_BddXor</a>
+<a href="#Cal_BddXnor">Cal_BddXnor</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddITE.c"TARGET="ABSTRACT"><CODE>calBddITE.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIdentity"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddIdentity</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the duplicate BDD of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddNot">Cal_BddNot</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIf"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddIf</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddImplies"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddImplies</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Computes a BDD that implies conjunction of f and Cal_BddNot(g)
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIntersects">Cal_BddIntersects</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIntersects"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddIntersects</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Computes a BDD that implies conjunction of f and g.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddImplies">Cal_BddImplies</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddConst"></A>
+int <I></I>
+<B>Cal_BddIsBddConst</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is either constant one or
+  constant zero, otherwise returns 0.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIsBddOne">Cal_BddIsBddOne</a>
+<a href="#Cal_BddIsBddZero">Cal_BddIsBddZero</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddNull"></A>
+int <I></I>
+<B>Cal_BddIsBddNull</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is NULL, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddOne"></A>
+int <I></I>
+<B>Cal_BddIsBddOne</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is constant one, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIsBddZero">Cal_BddIsBddZero</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddZero"></A>
+int <I></I>
+<B>Cal_BddIsBddZero</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is constant zero, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIsBddOne">Cal_BddIsBddOne</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIsCube"></A>
+int <I></I>
+<B>Cal_BddIsCube</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is a cube, 0 otherwise
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIsEqual"></A>
+int <I></I>
+<B>Cal_BddIsEqual</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd1</b>, <i></i>
+  Cal_Bdd  <b>userBdd2</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if argument BDDs are equal, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddIsProvisional"></A>
+int <I></I>
+<B>Cal_BddIsProvisional</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1, if the given user BDD contains
+  provisional BDD node.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarAfter"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarAfter</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable after the specified one in
+  the variable  order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarBefore"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarBefore</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable before the specified one in
+  the variable order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarFirst"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarFirst</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable at the start of the
+  variable order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarLast"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarLast</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable at the end of the variable
+  order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGC"></A>
+int <I></I>
+<B>Cal_BddManagerGC</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> For each variable in the increasing id free nodes with reference
+  count equal to zero freeing a node results in decrementing reference count of
+  then and else nodes by one.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calGC.c"TARGET="ABSTRACT"><CODE>calGC.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetHooks"></A>
+void * <I></I>
+<B>Cal_BddManagerGetHooks</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the hooks field of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetNumNodes"></A>
+unsigned long <I></I>
+<B>Cal_BddManagerGetNumNodes</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the number of BDD nodes
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddTotalSize">Cal_BddTotalSize</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetVarWithId"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerGetVarWithId</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>id</b> <i></i>
+)
+</pre>
+<dd> Returns the variable with the specified id, null if no
+  such variable exists
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetVarWithIndex"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerGetVarWithIndex</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddIndex_t  <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the variable with the specified index, null if no
+  such variable exists
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerInit"></A>
+Cal_BddManager <I></I>
+<B>Cal_BddManagerInit</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> Initializes and allocates fields of the BDD manager. Some of the
+  fields are initialized for maxNumVars+1 or numVars+1, whereas some of them are
+  initialized for maxNumVars or numVars. The first kind of fields are associated
+  with the id of a variable and the second ones are with the index of the
+  variable.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerQuit">Cal_BddManagerQuit</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerQuit"></A>
+int <I></I>
+<B>Cal_BddManagerQuit</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Frees the BDD manager and all the associated allocations
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerInit">Cal_BddManagerInit</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerSetGCLimit"></A>
+void <I></I>
+<B>Cal_BddManagerSetGCLimit</B>(
+  Cal_BddManager  <b>manager</b> <i></i>
+)
+</pre>
+<dd> It tries to set the limit at twice the number of nodes
+  in the manager at the current point. However, the limit is not
+  allowed to fall below the MIN_GC_LIMIT or to exceed the value of
+  node limit (if one exists).
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calGC.c"TARGET="ABSTRACT"><CODE>calGC.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerSetHooks"></A>
+void <I></I>
+<B>Cal_BddManagerSetHooks</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  void * <b>hooks</b> <i></i>
+)
+</pre>
+<dd> Sets the hooks field of the manager.
+<p>
+
+<dd> <b>Side Effects</b> Hooks field changes.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddManagerSetParameters"></A>
+void <I></I>
+<B>Cal_BddManagerSetParameters</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  long  <b>reorderingThreshold</b>, <i></i>
+  long  <b>maxForwardedNodes</b>, <i></i>
+  double  <b>repackAfterGCThreshold</b>, <i></i>
+  double  <b>tableRepackThreshold</b> <i></i>
+)
+</pre>
+<dd> This function is used to set the parameters which are
+  used to control the reordering process. "reorderingThreshold"
+  determines the number of nodes below which reordering will NOT be
+  invoked, "maxForwardedNodes" determines the maximum number of
+  forwarded nodes which are allowed (at that point the cleanup must be
+  done), and "repackingThreshold" determines the fraction of the page
+  utilized below which repacking has to be invoked. These parameters
+  have different affect on the computational and memory usage aspects
+  of reordeing. For instance, higher value of "maxForwardedNodes" will
+  result in process consuming more memory, and a lower value on the
+  other hand would invoke the cleanup process repeatedly resulting in
+  increased computation.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddManager.c"TARGET="ABSTRACT"><CODE>calBddManager.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddMultiwayAnd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddMultiwayAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical AND of set of BDDs in the bddArray
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddMultiwayOr"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddMultiwayOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical OR of set of BDDs in the bddArray
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddMultiwayXor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddMultiwayXor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical XOR of set of BDDs in the bddArray
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddNand"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddNand</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical NAND of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddNewVarBlock"></A>
+Cal_Block <I></I>
+<B>Cal_BddNewVarBlock</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>variable</b>, <i></i>
+  long  <b>length</b> <i></i>
+)
+</pre>
+<dd> The block is specified by passing the first
+  variable and the length of the block. The "length" number of
+  consecutive variables starting from "variable" are put in the
+  block.
+<p>
+
+<dd> <b>Side Effects</b> A new block is created.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddNodeLimit"></A>
+long <I></I>
+<B>Cal_BddNodeLimit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  long  <b>newLimit</b> <i></i>
+)
+</pre>
+<dd> Sets the node limit to new_limit and returns the old limit.
+<p>
+
+<dd> <b>Side Effects</b> Threshold for garbage collection may change
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerGC">Cal_BddManagerGC</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddNor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddNor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical NOR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddNot"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddNot</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the complement of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the argument BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIdentity">Cal_BddIdentity</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddOne"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddOne</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for the constant one
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddZero">Cal_BddZero</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddOr"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical OR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddOverflow"></A>
+int <I></I>
+<B>Cal_BddOverflow</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the node limit has been exceeded, 0 otherwise. The
+  overflow flag is cleared.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddNodeLimit">Cal_BddNodeLimit</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPairwiseAnd"></A>
+Cal_Bdd * <I></I>
+<B>Cal_BddPairwiseAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns an array of BDDs obtained by logical AND of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddPairwiseOr">Cal_BddPairwiseOr</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPairwiseOr"></A>
+Cal_Bdd * <I></I>
+<B>Cal_BddPairwiseOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns an array of BDDs obtained by logical OR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddPairwiseAnd">Cal_BddPairwiseAnd</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPairwiseXor"></A>
+Cal_Bdd * <I></I>
+<B>Cal_BddPairwiseXor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns an array of BDDs obtained by logical XOR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddPairwiseAnd">Cal_BddPairwiseAnd</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPrintBdd"></A>
+void <I></I>
+<B>Cal_BddPrintBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_VarNamingFn_t  <b>VarNamingFn</b>, <i></i>
+  Cal_TerminalIdFn_t  <b>TerminalIdFn</b>, <i></i>
+  Cal_Pointer_t  <b>env</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints a human-readable representation of the BDD f to
+  the file given by fp. The namingFn should be a pointer to a function
+  taking a bddManager, a BDD and the pointer given by env. This
+  function should return either a null pointer or a srting that is the
+  name of the supplied variable. If it returns a null pointer, a
+  default name is generated based on the index of the variable. It is
+  also legal for naminFN to e null; in this case, default names are
+  generated for all variables. The macro bddNamingFnNone is a null
+  pointer of suitable type. terminalIdFn should be apointer to a
+  function taking a bddManager and two longs. plus the pointer given
+  by the env. It should return either a null pointer. If it returns a
+  null pointer, or if terminalIdFn is null, then default names are
+  generated for the terminals. The macro bddTerminalIdFnNone is a null
+  pointer of suitable type.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPrintFunctionProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddPrintFunctionProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBdds</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrintProfile.c"TARGET="ABSTRACT"><CODE>calPrintProfile.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPrintFunctionProfile"></A>
+void <I></I>
+<B>Cal_BddPrintFunctionProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrintProfile.c"TARGET="ABSTRACT"><CODE>calPrintProfile.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPrintProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddPrintProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBdds</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrintProfile.c"TARGET="ABSTRACT"><CODE>calPrintProfile.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddPrintProfile"></A>
+void <I></I>
+<B>Cal_BddPrintProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrintProfile.c"TARGET="ABSTRACT"><CODE>calPrintProfile.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>fUserBddArray</b>, <i></i>
+  long * <b>levelCounts</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddProfile"></A>
+void <I></I>
+<B>Cal_BddProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  long * <b>levelCounts</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> negout is as in Cal_BddSize. levelCounts should be an array of
+  size Cal_BddVars(bddManager)+1 to hold the profile.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddReduce"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddReduce</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>cUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD which agrees with f for all valuations
+  which satisfy c. The result is usually smaller in terms of number of
+  BDD nodes than f. This operation is typically used in state space
+  searches to simplify the representation for the set of states wich
+  will be expanded at each step.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddCofactor">Cal_BddCofactor</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddRelProd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddRelProd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for the logical AND of f and g with all
+  the variables that are paired with something in the current variable
+  association existentially quantified out.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddReorder"></A>
+void <I></I>
+<B>Cal_BddReorder</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Invoke the current dynamic reodering method.
+<p>
+
+<dd> <b>Side Effects</b> Index of a variable may change due to reodering
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddDynamicReordering">Cal_BddDynamicReordering</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSatisfySupport"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSatisfySupport</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> The returned BDD which implies f, is true for some valuation on
+               which f is true, which has at most one node at each level,
+               and which has exactly one node corresponding to each variable
+               which is associated with something in the current variable
+               association.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSatisfy.c"TARGET="ABSTRACT"><CODE>calBddSatisfy.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSatisfyingFraction"></A>
+double <I></I>
+<B>Cal_BddSatisfyingFraction</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSatisfy.c"TARGET="ABSTRACT"><CODE>calBddSatisfy.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSatisfy"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSatisfy</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSatisfy.c"TARGET="ABSTRACT"><CODE>calBddSatisfy.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSetGCMode"></A>
+void <I></I>
+<B>Cal_BddSetGCMode</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>gcMode</b> <i></i>
+)
+</pre>
+<dd> Sets the garbage collection mode, 0 means the garbage
+  collection should be turned off, 1 means garbage collection should
+  be on.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calGC.c"TARGET="ABSTRACT"><CODE>calGC.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSizeMultiple"></A>
+long <I></I>
+<B>Cal_BddSizeMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>fUserBddArray</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSize"></A>
+long <I></I>
+<B>Cal_BddSize</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSize.c"TARGET="ABSTRACT"><CODE>calBddSize.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddStats"></A>
+void <I></I>
+<B>Cal_BddStats</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints miscellaneous BDD statistics
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSubstitute"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD for f using the substitution defined by current
+  variable association. Each variable is replaced by its associated BDDs. The 
+  substitution is effective simultaneously
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddCompose">Cal_BddCompose</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSubstitute.c"TARGET="ABSTRACT"><CODE>calBddSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSupport"></A>
+void <I></I>
+<B>Cal_BddSupport</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd * <b>support</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSupport.c"TARGET="ABSTRACT"><CODE>calBddSupport.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddSwapVars"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSwapVars</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b>, <i></i>
+  Cal_Bdd  <b>hUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD obtained by simultaneously substituting variable
+  g by variable h and variable h and variable g in the BDD f
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddSubstitute">Cal_BddSubstitute</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSwapVars.c"TARGET="ABSTRACT"><CODE>calBddSwapVars.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddThen"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddThen</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the positive cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the returned BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddElse">Cal_BddElse</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddTotalSize"></A>
+unsigned long <I></I>
+<B>Cal_BddTotalSize</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the number of nodes in the Unique table
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerGetNumNodes">Cal_BddManagerGetNumNodes</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddType"></A>
+int <I></I>
+<B>Cal_BddType</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns BDD_TYPE_ZERO if f is false, BDD_TYPE_ONE 
+  if f is true, BDD_TYPE_POSVAR is f is an unnegated variable,
+  BDD_TYPE_NEGVAR if f is a negated variable, BDD_TYPE_OVERFLOW if f
+  is null, and BDD_TYPE_NONTERMINAL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddUnFree"></A>
+void <I></I>
+<B>Cal_BddUnFree</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Unfrees the argument BDD. It is an error to pass a BDD
+  with reference count of zero to be unfreed.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the argument BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddFree">Cal_BddFree</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddUndumpBdd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddUndumpBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userVars</b>, <i></i>
+  FILE * <b>fp</b>, <i></i>
+  int * <b>error</b> <i></i>
+)
+</pre>
+<dd> Loads an encoded description of a BDD from the file given by
+  fp. The argument vars should be a null terminated array of variables that will
+  become the support of the BDD. As in Cal_BddDumpBdd, these need not be in
+  the order of increasing index. If the same array of variables in used in 
+  dumping and undumping, the BDD returned will be equal to the one that was 
+  dumped. More generally, if array v1 is used when dumping, and the array v2
+  is used when undumping, the BDD returned will be equal to the original BDD
+  with the ith variable in v2 substituted for the ith variable in v1 for all i.
+  Null BDD is returned in the operation fails for reason (node limit reached,
+  I/O error, invalid file format, etc.). In this case, an error code is stored
+  in error. the code will be one of the following. 
+  CAL_BDD_UNDUMP_FORMAT Invalid file format
+  CAL_BDD_UNDUMP_OVERFLOW Node limit exceeded
+  CAL_BDD_UNDUMP_IOERROR File I/O error
+  CAL_BDD_UNDUMP_EOF Unexpected EOF
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calDump.c"TARGET="ABSTRACT"><CODE>calDump.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddVarBlockReorderable"></A>
+void <I></I>
+<B>Cal_BddVarBlockReorderable</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Block  <b>block</b>, <i></i>
+  int  <b>reorderable</b> <i></i>
+)
+</pre>
+<dd> If a block is reorderable, the child blocks are
+  recursively involved in swapping.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBlk.c"TARGET="ABSTRACT"><CODE>calBlk.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddVarSubstitute"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddVarSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD for f using the substitution defined by current
+  variable association. It is assumed that each variable is replaced
+  by another variable. For the substitution of a variable by a
+  function, use Cal_BddSubstitute instead.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddSubstitute">Cal_BddSubstitute</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddVarSubstitute.c"TARGET="ABSTRACT"><CODE>calBddVarSubstitute.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddVars"></A>
+long <I></I>
+<B>Cal_BddVars</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the number of BDD variables
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddXnor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddXnor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical exclusive NOR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddXor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddXor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical exclusive OR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_BddZero"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddZero</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for the constant zero
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddOne">Cal_BddOne</a>
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#cal.c"TARGET="ABSTRACT"><CODE>cal.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemAllocation"></A>
+Cal_Address_t <I></I>
+<B>Cal_MemAllocation</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> Returns the memory allocated.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemFatal"></A>
+void <I></I>
+<B>Cal_MemFatal</B>(
+  char * <b>message</b> <i></i>
+)
+</pre>
+<dd> Prints an error message and exits.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemFreeBlock"></A>
+void <I></I>
+<B>Cal_MemFreeBlock</B>(
+  Cal_Pointer_t  <b>p</b> <i></i>
+)
+</pre>
+<dd> Frees the block.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemFreeRecMgr"></A>
+void <I></I>
+<B>Cal_MemFreeRecMgr</B>(
+  Cal_RecMgr  <b>mgr</b> <i></i>
+)
+</pre>
+<dd> Frees all the storage associated with the specified record manager.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemFreeRec"></A>
+void <I></I>
+<B>Cal_MemFreeRec</B>(
+  Cal_RecMgr  <b>mgr</b>, <i></i>
+  Cal_Pointer_t  <b>rec</b> <i></i>
+)
+</pre>
+<dd> Frees a record managed by the indicated record manager.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemGetBlock"></A>
+Cal_Pointer_t <I></I>
+<B>Cal_MemGetBlock</B>(
+  Cal_Address_t  <b>size</b> <i></i>
+)
+</pre>
+<dd> Allocates a new block of the specified size.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemNewRecMgr"></A>
+Cal_RecMgr <I></I>
+<B>Cal_MemNewRecMgr</B>(
+  int  <b>size</b> <i></i>
+)
+</pre>
+<dd> Creates a new record manager with the given  record size.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemNewRec"></A>
+Cal_Pointer_t <I></I>
+<B>Cal_MemNewRec</B>(
+  Cal_RecMgr  <b>mgr</b> <i></i>
+)
+</pre>
+<dd> Allocates a record from the specified record manager.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_MemResizeBlock"></A>
+Cal_Pointer_t <I></I>
+<B>Cal_MemResizeBlock</B>(
+  Cal_Pointer_t  <b>p</b>, <i></i>
+  Cal_Address_t  <b>newSize</b> <i></i>
+)
+</pre>
+<dd> Expands or contracts the block to a new size.
+  We try to avoid moving the block if possible.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_PerformanceTest"></A>
+int <I></I>
+<B>Cal_PerformanceTest</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b>, <i></i>
+  int  <b>iteration</b>, <i></i>
+  int  <b>seed</b>, <i></i>
+  int  <b>andPerformanceFlag</b>, <i></i>
+  int  <b>multiwayPerformanceFlag</b>, <i></i>
+  int  <b>onewayPerformanceFlag</b>, <i></i>
+  int  <b>quantifyPerformanceFlag</b>, <i></i>
+  int  <b>composePerformanceFlag</b>, <i></i>
+  int  <b>relprodPerformanceFlag</b>, <i></i>
+  int  <b>swapPerformanceFlag</b>, <i></i>
+  int  <b>substitutePerformanceFlag</b>, <i></i>
+  int  <b>sanityCheckFlag</b>, <i></i>
+  int  <b>computeMemoryOverheadFlag</b>, <i></i>
+  int  <b>superscalarFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_PipelineCreateProvisionalBdd"></A>
+Cal_Bdd <I></I>
+<B>Cal_PipelineCreateProvisionalBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> The provisional BDD is automatically freed once the
+  pipeline is quitted.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_PipelineExecute"></A>
+int <I></I>
+<B>Cal_PipelineExecute</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> All the results are computed. User should update the
+  BDDs of interest. Eventually this feature would become transparent.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_PipelineInit"></A>
+int <I></I>
+<B>Cal_PipelineInit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddOp_t  <b>bddOp</b> <i></i>
+)
+</pre>
+<dd> All the operations for this pipeline must be of the
+  same kind.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_PipelineQuit"></A>
+void <I></I>
+<B>Cal_PipelineQuit</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> The user must make sure to update all provisional BDDs
+  of interest before calling this routine.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_PipelineSetDepth"></A>
+void <I></I>
+<B>Cal_PipelineSetDepth</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>depth</b> <i></i>
+)
+</pre>
+<dd> The "depth" determines the amount of dependency we
+  would allow in pipelined computation.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_PipelineUpdateProvisionalBdd"></A>
+Cal_Bdd <I></I>
+<B>Cal_PipelineUpdateProvisionalBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>provisionalBdd</b> <i></i>
+)
+</pre>
+<dd> The provisional BDD is automatically freed after
+  quitting pipeline.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPipeline.c"TARGET="ABSTRACT"><CODE>calPipeline.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_TempAssociationAugment"></A>
+void <I></I>
+<B>Cal_TempAssociationAugment</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>associationInfoUserBdds</b>, <i></i>
+  int  <b>pairs</b> <i></i>
+)
+</pre>
+<dd> Pairs is 0 if the information represents only a list of
+  variables rather than a full association.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_TempAssociationInit"></A>
+void <I></I>
+<B>Cal_TempAssociationInit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>associationInfoUserBdds</b>, <i></i>
+  int  <b>pairs</b> <i></i>
+)
+</pre>
+<dd> Pairs is 0 if the information represents only a list of
+  variables rather than a full association.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cal_TempAssociationQuit"></A>
+void <I></I>
+<B>Cal_TempAssociationQuit</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Cleans up temporary associationoptional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="CeilLog2"></A>
+static int <I></I>
+<B>CeilLog2</B>(
+  int  <b>number</b> <i></i>
+)
+</pre>
+<dd> Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddOp.c"TARGET="ABSTRACT"><CODE>calBddOp.c</CODE></A>
+
+<dt><pre>
+<A NAME="CeilLog2"></A>
+static int <I></I>
+<B>CeilLog2</B>(
+  int  <b>number</b> <i></i>
+)
+</pre>
+<dd> Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calGC.c"TARGET="ABSTRACT"><CODE>calGC.c</CODE></A>
+
+<dt><pre>
+<A NAME="CeilLog2"></A>
+static int <I></I>
+<B>CeilLog2</B>(
+  int  <b>number</b> <i></i>
+)
+</pre>
+<dd> Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTable.c"TARGET="ABSTRACT"><CODE>calHashTable.c</CODE></A>
+
+<dt><pre>
+<A NAME="CeilLog2"></A>
+static int <I></I>
+<B>CeilLog2</B>(
+  int  <b>number</b> <i></i>
+)
+</pre>
+<dd> Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="CeilingLog2"></A>
+static int <I></I>
+<B>CeilingLog2</B>(
+  Cal_Address_t  <b>i</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="Chars"></A>
+static void <I></I>
+<B>Chars</B>(
+  char  <b>c</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrint.c"TARGET="ABSTRACT"><CODE>calPrint.c</CODE></A>
+
+<dt><pre>
+<A NAME="CheckAssoc"></A>
+static int <I></I>
+<B>CheckAssoc</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>assocInfo</b>, <i></i>
+  int  <b>pairs</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calAssociation.c"TARGET="ABSTRACT"><CODE>calAssociation.c</CODE></A>
+
+<dt><pre>
+<A NAME="CheckValidityOfNodes"></A>
+static int <I></I>
+<B>CheckValidityOfNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  long  <b>id</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="CofactorFixAndReclaimForwardedNodes"></A>
+static int <I></I>
+<B>CofactorFixAndReclaimForwardedNodes</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int  <b>cofactorCheckStartIndex</b>, <i></i>
+  int  <b>cofactorCheckEndIndex</b>, <i></i>
+  int  <b>reclaimStartIndex</b>, <i></i>
+  int  <b>reclaimEndIndex</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="Cofactor"></A>
+static TruthTable_t <I></I>
+<B>Cofactor</B>(
+  TruthTable_t  <b>table</b>, <i></i>
+  int  <b>var</b>, <i></i>
+  int  <b>value</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="Decode"></A>
+static Cal_Bdd <I></I>
+<B>Decode</B>(
+  int  <b>var</b>, <i></i>
+  TruthTable_t  <b>table</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="Error"></A>
+static void <I></I>
+<B>Error</B>(
+  char * <b>op</b>, <i></i>
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>result</b>, <i></i>
+  Cal_Bdd  <b>expected</b>, <i></i>
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="GetRandomNumbers"></A>
+static void <I></I>
+<B>GetRandomNumbers</B>(
+  int  <b>lowerBound</b>, <i></i>
+  int  <b>upperBound</b>, <i></i>
+  int  <b>count</b>, <i></i>
+  int * <b>resultVector</b> <i></i>
+)
+</pre>
+<dd> The restriction is that count <= upperBound-lowerBound+1. The
+  size of the resultVector should be >= count.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableAddDirect"></A>
+static void <I></I>
+<B>HashTableAddDirect</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalBddNode_t * <b>bddNode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableApply"></A>
+static void <I></I>
+<B>HashTableApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t ** <b>reqQueAtPipeDepth</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b>, <i></i>
+  unsigned long  <b>opCode</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableCofactorApply"></A>
+static void <I></I>
+<B>HashTableCofactorApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t ** <b>cofactorHashTableArray</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableCofactorReduce"></A>
+static void <I></I>
+<B>HashTableCofactorReduce</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t * <b>uniqueTableForId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableFindOrAdd"></A>
+static int <I></I>
+<B>HashTableFindOrAdd</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalBddNode_t * <b>thenBdd</b>, <i></i>
+  CalBddNode_t * <b>elseBdd</b>, <i></i>
+  CalBddNode_t ** <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableOneRehash"></A>
+static void <I></I>
+<B>HashTableOneRehash</B>(
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  int  <b>grow</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calHashTableOne.c"TARGET="ABSTRACT"><CODE>calHashTableOne.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableReduceApply"></A>
+static void <I></I>
+<B>HashTableReduceApply</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t ** <b>reduceHashTableArray</b>, <i></i>
+  CalHashTable_t ** <b>orHashTableArray</b>, <i></i>
+  CalOpProc_t  <b>calOpProc</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReduce.c"TARGET="ABSTRACT"><CODE>calReduce.c</CODE></A>
+
+<dt><pre>
+<A NAME="HashTableReduce"></A>
+static void <I></I>
+<B>HashTableReduce</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalHashTable_t * <b>uniqueTableForId</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calQuant.c"TARGET="ABSTRACT"><CODE>calQuant.c</CODE></A>
+
+<dt><pre>
+<A NAME="IndexCmp"></A>
+static int <I></I>
+<B>IndexCmp</B>(
+  const void * <b>p1</b>, <i></i>
+  const void * <b>p2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddSatisfy.c"TARGET="ABSTRACT"><CODE>calBddSatisfy.c</CODE></A>
+
+<dt><pre>
+<A NAME="MergeAndFree"></A>
+static void <I></I>
+<B>MergeAndFree</B>(
+  Block  <b>b</b> <i></i>
+)
+</pre>
+<dd> MergeAndFree(b) repeatedly merges b its Buddy until b has no Buddy or the Buddy isn't free, then adds the result to the  appropriate free list.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="PageAlign"></A>
+static CalAddress_t * <I></I>
+<B>PageAlign</B>(
+  CalAddress_t * <b>p</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="PageManagerExpandStorage"></A>
+static int <I></I>
+<B>PageManagerExpandStorage</B>(
+  CalPageManager_t * <b>pageManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> The size of the segment is stored in one of the fields
+              of page manager - numPagesPerSegment. If a memory
+              segment of a specific size cannot be allocated, the
+              routine calls itself recursively by reducing
+              numPagesPerSegment by a factor of 2.
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="PrintBddProfileAfterReorder"></A>
+static void <I></I>
+<B>PrintBddProfileAfterReorder</B>(
+  Cal_BddManager_t * <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderBF.c"TARGET="ABSTRACT"><CODE>calReorderBF.c</CODE></A>
+
+<dt><pre>
+<A NAME="PrintBdd"></A>
+static void <I></I>
+<B>PrintBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="RandomTests"></A>
+static void <I></I>
+<B>RandomTests</B>(
+  int  <b>numVars</b>, <i></i>
+  int  <b>iterations</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="Read"></A>
+static unsigned long <I></I>
+<B>Read</B>(
+  int * <b>error</b>, <i></i>
+  int  <b>bytes</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calDump.c"TARGET="ABSTRACT"><CODE>calDump.c</CODE></A>
+
+<dt><pre>
+<A NAME="RemoveFromFreeList"></A>
+static Block <I></I>
+<B>RemoveFromFreeList</B>(
+  Block  <b>b</b> <i></i>
+)
+</pre>
+<dd> RemoveFromFreeList(b) removes b from the free list which it is on.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="SegmentToPageList"></A>
+static int <I></I>
+<B>SegmentToPageList</B>(
+  CalAddress_t * <b>segment</b>, <i></i>
+  int  <b>numPages</b>, <i></i>
+  CalAddress_t * <b>lastPointer</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMemoryManagement.c"TARGET="ABSTRACT"><CODE>calMemoryManagement.c</CODE></A>
+
+<dt><pre>
+<A NAME="SweepVarTable"></A>
+static void <I></I>
+<B>SweepVarTable</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  long  <b>id</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestAnd"></A>
+static void <I></I>
+<B>TestAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestArrayOp"></A>
+static void <I></I>
+<B>TestArrayOp</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>numBdds</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestAssoc"></A>
+static void <I></I>
+<B>TestAssoc</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b>, <i></i>
+  TruthTable_t  <b>table</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestCompose"></A>
+static void <I></I>
+<B>TestCompose</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestDump"></A>
+static void <I></I>
+<B>TestDump</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestGenCof"></A>
+static void <I></I>
+<B>TestGenCof</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestITE"></A>
+static void <I></I>
+<B>TestITE</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b>, <i></i>
+  Cal_Bdd  <b>f3</b>, <i></i>
+  TruthTable_t  <b>table3</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestIdNot"></A>
+static void <I></I>
+<B>TestIdNot</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b>, <i></i>
+  TruthTable_t  <b>table</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestInterImpl"></A>
+static void <I></I>
+<B>TestInterImpl</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestMultiwayAnd"></A>
+static void <I></I>
+<B>TestMultiwayAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b>, <i></i>
+  Cal_Bdd  <b>f3</b>, <i></i>
+  TruthTable_t  <b>table3</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestMultiwayLarge"></A>
+static void <I></I>
+<B>TestMultiwayLarge</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>numBdds</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestMultiwayOr"></A>
+static void <I></I>
+<B>TestMultiwayOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b>, <i></i>
+  Cal_Bdd  <b>f3</b>, <i></i>
+  TruthTable_t  <b>table3</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestNand"></A>
+static void <I></I>
+<B>TestNand</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestOr"></A>
+static void <I></I>
+<B>TestOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestPipeline"></A>
+static void <I></I>
+<B>TestPipeline</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b>, <i></i>
+  Cal_Bdd  <b>f3</b>, <i></i>
+  TruthTable_t  <b>table3</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestQnt"></A>
+static void <I></I>
+<B>TestQnt</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b>, <i></i>
+  TruthTable_t  <b>table</b>, <i></i>
+  int  <b>bfZeroBFPlusDFOne</b>, <i></i>
+  int  <b>cacheExistsResultsFlag</b>, <i></i>
+  int  <b>cacheOrResultsFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestReduce"></A>
+static void <I></I>
+<B>TestReduce</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestRelProd"></A>
+static void <I></I>
+<B>TestRelProd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b>, <i></i>
+  int  <b>bfZeroBFPlusDFOne</b>, <i></i>
+  int  <b>cacheRelProdResultsFlag</b>, <i></i>
+  int  <b>cacheAndResultsFlag</b>, <i></i>
+  int  <b>cacheOrResultsFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestReorderBlock"></A>
+static void <I></I>
+<B>TestReorderBlock</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  TruthTable_t  <b>table</b>, <i></i>
+  Cal_Bdd  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestReorder"></A>
+static void <I></I>
+<B>TestReorder</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  TruthTable_t  <b>table</b>, <i></i>
+  Cal_Bdd  <b>f</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestSatisfy"></A>
+static void <I></I>
+<B>TestSatisfy</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b>, <i></i>
+  TruthTable_t  <b>table</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestSize"></A>
+static void <I></I>
+<B>TestSize</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestSubstitute"></A>
+static void <I></I>
+<B>TestSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b>, <i></i>
+  Cal_Bdd  <b>f3</b>, <i></i>
+  TruthTable_t  <b>table3</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestSwapVars"></A>
+static void <I></I>
+<B>TestSwapVars</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b>, <i></i>
+  TruthTable_t  <b>table</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestVarSubstitute"></A>
+static void <I></I>
+<B>TestVarSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b>, <i></i>
+  Cal_Bdd  <b>f3</b>, <i></i>
+  TruthTable_t  <b>table3</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TestXor"></A>
+static void <I></I>
+<B>TestXor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f1</b>, <i></i>
+  TruthTable_t  <b>table1</b>, <i></i>
+  Cal_Bdd  <b>f2</b>, <i></i>
+  TruthTable_t  <b>table2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="TrimToSize"></A>
+static void <I></I>
+<B>TrimToSize</B>(
+  Block  <b>b</b>, <i></i>
+  int  <b>sizeIndex</b> <i></i>
+)
+</pre>
+<dd> TrimToSize(b, sizeIndex) repeatedly splits b until it has  the indicated size.  Blocks which are split off are added to the appropriate free list.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calMem.c"TARGET="ABSTRACT"><CODE>calMem.c</CODE></A>
+
+<dt><pre>
+<A NAME="UniqueTableForIdFindOrAdd"></A>
+static int <I></I>
+<B>UniqueTableForIdFindOrAdd</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  CalHashTable_t * <b>hashTable</b>, <i></i>
+  CalBddNode_t * <b>thenBdd</b>, <i></i>
+  CalBddNode_t * <b>elseBdd</b>, <i></i>
+  CalBddNode_t ** <b>bddPtr</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> If a new BDD node is created (found == false), then the
+  numNodes field of the manager needs to be incremented.
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calReorderDF.c"TARGET="ABSTRACT"><CODE>calReorderDF.c</CODE></A>
+
+<dt><pre>
+<A NAME="Write"></A>
+static void <I></I>
+<B>Write</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  unsigned long  <b>n</b>, <i></i>
+  int  <b>bytes</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calDump.c"TARGET="ABSTRACT"><CODE>calDump.c</CODE></A>
+
+<dt><pre>
+<A NAME="asAddress"></A>
+static void <I></I>
+<B>asAddress</B>(
+  double  <b>n</b>, <i></i>
+  CalAddress_t * <b>r1</b>, <i></i>
+  CalAddress_t * <b>r2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="asDouble"></A>
+static double <I></I>
+<B>asDouble</B>(
+  CalAddress_t  <b>v1</b>, <i></i>
+  CalAddress_t  <b>v2</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="chars"></A>
+static void <I></I>
+<B>chars</B>(
+  char  <b>c</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPrintProfile.c"TARGET="ABSTRACT"><CODE>calPrintProfile.c</CODE></A>
+
+<dt><pre>
+<A NAME="cpuTime"></A>
+static double <I></I>
+<B>cpuTime</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="cpuTime"></A>
+static double <I></I>
+<B>cpuTime</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddReorderTest.c"TARGET="ABSTRACT"><CODE>calBddReorderTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="ddClearLocal"></A>
+static void <I></I>
+<B>ddClearLocal</B>(
+  Cal_Bdd_t  <b>f</b> <i></i>
+)
+</pre>
+<dd> Performs a DFS from f, clearing the LSB of the then pointers.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calInteract.c"TARGET="ABSTRACT"><CODE>calInteract.c</CODE></A>
+
+<dt><pre>
+<A NAME="ddSuppInteract"></A>
+static void <I></I>
+<B>ddSuppInteract</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  Cal_Bdd_t  <b>f</b>, <i></i>
+  int * <b>support</b> <i></i>
+)
+</pre>
+<dd> Performs a DFS from f. Uses the LSB of the then pointer
+  as visited flag.
+<p>
+
+<dd> <b>Side Effects</b> Accumulates in support the variables on which f depends.
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calInteract.c"TARGET="ABSTRACT"><CODE>calInteract.c</CODE></A>
+
+<dt><pre>
+<A NAME="ddUpdateInteract"></A>
+static void <I></I>
+<B>ddUpdateInteract</B>(
+  Cal_BddManager_t * <b>bddManager</b>, <i></i>
+  int * <b>support</b> <i></i>
+)
+</pre>
+<dd> If support[i
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calInteract.c"TARGET="ABSTRACT"><CODE>calInteract.c</CODE></A>
+
+<dt><pre>
+<A NAME="elapsedTime"></A>
+static long <I></I>
+<B>elapsedTime</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddReorderTest.c"TARGET="ABSTRACT"><CODE>calBddReorderTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="elapsedTime"></A>
+static long <I></I>
+<B>elapsedTime</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="handler"></A>
+static void <I></I>
+<B>handler</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="main"></A>
+int <I></I>
+<B>main</B>(
+  int  <b>argc</b>, <i></i>
+  char ** <b>argv</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calBddReorderTest.c"TARGET="ABSTRACT"><CODE>calBddReorderTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="main"></A>
+int <I></I>
+<B>main</B>(
+  int  <b>argc</b>, <i></i>
+  char ** <b>argv</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="pageFaults"></A>
+static long <I></I>
+<B>pageFaults</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calPerformanceTest.c"TARGET="ABSTRACT"><CODE>calPerformanceTest.c</CODE></A>
+
+<dt><pre>
+<A NAME="terminalIdFn"></A>
+static char * <I></I>
+<B>terminalIdFn</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  CalAddress_t  <b>v1</b>, <i></i>
+  CalAddress_t  <b>v2</b>, <i></i>
+  Cal_Pointer_t  <b>pointer</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<DD> <B>Defined in </B> <A HREF="calAllFile.html#calTest.c"TARGET="ABSTRACT"><CODE>calTest.c</CODE></A>
+
+
+</DL>
+<HR>
+Last updated on 970711 20h11
+</BODY></HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calAllFile.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calAllFile.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calAllFile.html	(revision 8)
@@ -0,0 +1,1756 @@
+<HTML>
+<HEAD><TITLE>The cal package: files</TITLE></HEAD>
+<BODY>
+
+<DL>
+ <DT> <A HREF="#cal.h"><CODE>cal.h</CODE></A>
+ <DD> External header file
+ <DT> <A HREF="#calInt.h"><CODE>calInt.h</CODE></A>
+ <DD> Internal header file
+ <DT> <A HREF="#cal.c"><CODE>cal.c</CODE></A>
+ <DD> Miscellaneous collection of exported BDD functions
+ <DT> <A HREF="#calApplyReduce.c"><CODE>calApplyReduce.c</CODE></A>
+ <DD> Generic routines for processing temporary nodes during
+  "apply" and "reduce" phases.
+ <DT> <A HREF="#calAssociation.c"><CODE>calAssociation.c</CODE></A>
+ <DD> Contains the routines related to the variable association.
+ <DT> <A HREF="#calBddCompose.c"><CODE>calBddCompose.c</CODE></A>
+ <DD> Routine for composing one BDD into another.
+ <DT> <A HREF="#calBddITE.c"><CODE>calBddITE.c</CODE></A>
+ <DD> Routine for computing ITE of 3 BDD operands.
+ <DT> <A HREF="#calBddManager.c"><CODE>calBddManager.c</CODE></A>
+ <DD> Routines for maintaing the manager and creating
+  variables etc.
+ <DT> <A HREF="#calBddOp.c"><CODE>calBddOp.c</CODE></A>
+ <DD> Routines for performing simple boolean operations on a
+  pair of BDDs or on an array of pair of BDDs or on an array of BDDs.
+ <DT> <A HREF="#calBddReorderTest.c"><CODE>calBddReorderTest.c</CODE></A>
+ <DD> A test routine for checking the functionality of
+  dynamic reordering.
+ <DT> <A HREF="#calBddSatisfy.c"><CODE>calBddSatisfy.c</CODE></A>
+ <DD> Routines for BDD satisfying valuation.
+ <DT> <A HREF="#calBddSize.c"><CODE>calBddSize.c</CODE></A>
+ <DD> BDD size and profile routines
+ <DT> <A HREF="#calBddSubstitute.c"><CODE>calBddSubstitute.c</CODE></A>
+ <DD> Routine for simultaneous substitution of an array of
+  variables with an array of functions.
+ <DT> <A HREF="#calBddSupport.c"><CODE>calBddSupport.c</CODE></A>
+ <DD> Routines related to the support of a BDD.
+ <DT> <A HREF="#calBddSwapVars.c"><CODE>calBddSwapVars.c</CODE></A>
+ <DD> Routine for swapping two variables.
+ <DT> <A HREF="#calBddVarSubstitute.c"><CODE>calBddVarSubstitute.c</CODE></A>
+ <DD> Routine for simultaneous substitution of an array of
+  variables with another array of variables.
+ <DT> <A HREF="#calBlk.c"><CODE>calBlk.c</CODE></A>
+ <DD> Routines for manipulating blocks of variables.
+ <DT> <A HREF="#calCacheTableTwo.c"><CODE>calCacheTableTwo.c</CODE></A>
+ <DD> Functions to manage the Cache tables.
+ <DT> <A HREF="#calDump.c"><CODE>calDump.c</CODE></A>
+ <DD> BDD library dump/undump routines
+ <DT> <A HREF="#calGC.c"><CODE>calGC.c</CODE></A>
+ <DD> Garbage collection routines
+ <DT> <A HREF="#calHashTable.c"><CODE>calHashTable.c</CODE></A>
+ <DD> Functions to manage the hash tables that are a part of
+                  1. unique table
+                  2. request queue
+ <DT> <A HREF="#calHashTableOne.c"><CODE>calHashTableOne.c</CODE></A>
+ <DD> Routines for managing hash table with Bdd is a key and
+               int, long, or double as a value
+ <DT> <A HREF="#calHashTableThree.c"><CODE>calHashTableThree.c</CODE></A>
+ <DD> Functions to manage the hash tables that are a part of
+                  ITE operation
+ <DT> <A HREF="#calInteract.c"><CODE>calInteract.c</CODE></A>
+ <DD> Functions to manipulate the variable interaction matrix.
+ <DT> <A HREF="#calMem.c"><CODE>calMem.c</CODE></A>
+ <DD> Routines for memory management.
+ <DT> <A HREF="#calMemoryManagement.c"><CODE>calMemoryManagement.c</CODE></A>
+ <DD> Special memory management routines specific to CAL.
+ <DT> <A HREF="#calPerformanceTest.c"><CODE>calPerformanceTest.c</CODE></A>
+ <DD> This file contains the performance test routines for
+  the CAL package.
+ <DT> <A HREF="#calPipeline.c"><CODE>calPipeline.c</CODE></A>
+ <DD> Routines for creating and managing the pipelined BDD
+  operations.
+ <DT> <A HREF="#calPrint.c"><CODE>calPrint.c</CODE></A>
+ <DD> Routine for printing a BDD.
+ <DT> <A HREF="#calPrintProfile.c"><CODE>calPrintProfile.c</CODE></A>
+ <DD> Routines for printing various profiles for a BDD.
+ <DT> <A HREF="#calQuant.c"><CODE>calQuant.c</CODE></A>
+ <DD> Routines for existential/universal quantification and
+  relational product.
+ <DT> <A HREF="#calReduce.c"><CODE>calReduce.c</CODE></A>
+ <DD> Routines for optimizing a BDD with respect to a don't
+  care set (cofactor and restrict).
+ <DT> <A HREF="#calReorderBF.c"><CODE>calReorderBF.c</CODE></A>
+ <DD> Routines for dynamic reordering of variables.
+ <DT> <A HREF="#calReorderDF.c"><CODE>calReorderDF.c</CODE></A>
+ <DD> Routines for dynamic reordering of variables.
+ <DT> <A HREF="#calReorderUtil.c"><CODE>calReorderUtil.c</CODE></A>
+ <DD> Some utility routines used by both breadth-first and
+  depth-first reordering techniques.
+ <DT> <A HREF="#calTerminal.c"><CODE>calTerminal.c</CODE></A>
+ <DD> Contains the terminal function for various BDD operations.
+ <DT> <A HREF="#calTest.c"><CODE>calTest.c</CODE></A>
+ <DD> This file contains the test routines for the CAL package.
+ <DT> <A HREF="#calUtil.c"><CODE>calUtil.c</CODE></A>
+ <DD> Utility functions for the Cal package.
+</DL><HR>
+<A NAME="cal.h"><H1>cal.h</H1></A>
+External header file <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+</DL>
+<HR>
+<A NAME="calInt.h"><H1>calInt.h</H1></A>
+Internal header file <P>
+<B>By: Rajeev K. Ranjan (rajeev@ic.eecs.berkeley.edu
+               Jagesh Sanghavi  (sanghavi@ic.eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#cal.h"><CODE>cal.h</CODE></A>
+<DL>
+</DL>
+<HR>
+<A NAME="cal.c"><H1>cal.c</H1></A>
+Miscellaneous collection of exported BDD functions <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu</B><P>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddIsEqual" TARGET="MAIN"><CODE>Cal_BddIsEqual()</CODE></A>
+ <DD> Returns 1 if argument BDDs are equal, 0 otherwise.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIsBddOne" TARGET="MAIN"><CODE>Cal_BddIsBddOne()</CODE></A>
+ <DD> Returns 1 if the argument BDD is constant one, 0 otherwise.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIsBddZero" TARGET="MAIN"><CODE>Cal_BddIsBddZero()</CODE></A>
+ <DD> Returns 1 if the argument BDD is constant zero, 0 otherwise.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIsBddNull" TARGET="MAIN"><CODE>Cal_BddIsBddNull()</CODE></A>
+ <DD> Returns 1 if the argument BDD is NULL, 0 otherwise.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIsBddConst" TARGET="MAIN"><CODE>Cal_BddIsBddConst()</CODE></A>
+ <DD> Returns 1 if the argument BDD is a constant, 0 otherwise.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIdentity" TARGET="MAIN"><CODE>Cal_BddIdentity()</CODE></A>
+ <DD> Returns the duplicate BDD of the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddOne" TARGET="MAIN"><CODE>Cal_BddOne()</CODE></A>
+ <DD> Returns the BDD for the constant one
+
+ <DT> <A HREF="calAllDet.html#Cal_BddZero" TARGET="MAIN"><CODE>Cal_BddZero()</CODE></A>
+ <DD> Returns the BDD for the constant zero
+
+ <DT> <A HREF="calAllDet.html#Cal_BddNot" TARGET="MAIN"><CODE>Cal_BddNot()</CODE></A>
+ <DD> Returns the complement of the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddGetIfIndex" TARGET="MAIN"><CODE>Cal_BddGetIfIndex()</CODE></A>
+ <DD> Returns the index of the top variable of the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddGetIfId" TARGET="MAIN"><CODE>Cal_BddGetIfId()</CODE></A>
+ <DD> Returns the id of the top variable of the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIf" TARGET="MAIN"><CODE>Cal_BddIf()</CODE></A>
+ <DD> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddThen" TARGET="MAIN"><CODE>Cal_BddThen()</CODE></A>
+ <DD> Returns the positive cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddElse" TARGET="MAIN"><CODE>Cal_BddElse()</CODE></A>
+ <DD> Returns the negative cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddFree" TARGET="MAIN"><CODE>Cal_BddFree()</CODE></A>
+ <DD> Frees the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddUnFree" TARGET="MAIN"><CODE>Cal_BddUnFree()</CODE></A>
+ <DD> Unfrees the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddGetRegular" TARGET="MAIN"><CODE>Cal_BddGetRegular()</CODE></A>
+ <DD> Returns a BDD with positive from a given BDD with arbitrary phase
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIntersects" TARGET="MAIN"><CODE>Cal_BddIntersects()</CODE></A>
+ <DD> Computes a BDD that implies conjunction of f and g.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddImplies" TARGET="MAIN"><CODE>Cal_BddImplies()</CODE></A>
+ <DD> Computes a BDD that implies conjunction of f and Cal_BddNot(g)
+
+ <DT> <A HREF="calAllDet.html#Cal_BddTotalSize" TARGET="MAIN"><CODE>Cal_BddTotalSize()</CODE></A>
+ <DD> Returns the number of nodes in the Unique table
+
+ <DT> <A HREF="calAllDet.html#Cal_BddStats" TARGET="MAIN"><CODE>Cal_BddStats()</CODE></A>
+ <DD> Prints miscellaneous BDD statistics
+
+ <DT> <A HREF="calAllDet.html#Cal_BddDynamicReordering" TARGET="MAIN"><CODE>Cal_BddDynamicReordering()</CODE></A>
+ <DD> Specify dynamic reordering technique.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddReorder" TARGET="MAIN"><CODE>Cal_BddReorder()</CODE></A>
+ <DD> Invoke the current dynamic reodering method.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddType" TARGET="MAIN"><CODE>Cal_BddType()</CODE></A>
+ <DD> Returns type of a BDD ( 0, 1, +var, -var, ovrflow, nonterminal)
+
+ <DT> <A HREF="calAllDet.html#Cal_BddVars" TARGET="MAIN"><CODE>Cal_BddVars()</CODE></A>
+ <DD> Returns the number of BDD variables
+
+ <DT> <A HREF="calAllDet.html#Cal_BddNodeLimit" TARGET="MAIN"><CODE>Cal_BddNodeLimit()</CODE></A>
+ <DD> Sets the node limit to new_limit and returns the old limit.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddOverflow" TARGET="MAIN"><CODE>Cal_BddOverflow()</CODE></A>
+ <DD> Returns 1 if the node limit has been exceeded, 0 otherwise. The
+  overflow flag is cleared.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIsCube" TARGET="MAIN"><CODE>Cal_BddIsCube()</CODE></A>
+ <DD> Returns 1 if the argument BDD is a cube, 0 otherwise
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerGetHooks" TARGET="MAIN"><CODE>Cal_BddManagerGetHooks()</CODE></A>
+ <DD> Returns the hooks field of the manager.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerSetHooks" TARGET="MAIN"><CODE>Cal_BddManagerSetHooks()</CODE></A>
+ <DD> Sets the hooks field of the manager.
+
+ <DT> <A HREF="calAllDet.html#CalBddIf" TARGET="MAIN"><CODE>CalBddIf()</CODE></A>
+ <DD> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#CalBddIsCubeStep" TARGET="MAIN"><CODE>CalBddIsCubeStep()</CODE></A>
+ <DD> Returns 1 if the argument BDD is a cube, 0 otherwise
+
+ <DT> <A HREF="calAllDet.html#CalBddTypeAux" TARGET="MAIN"><CODE>CalBddTypeAux()</CODE></A>
+ <DD> Returns the BDD type by recursively traversing the argument BDD
+
+ <DT> <A HREF="calAllDet.html#CalBddIdentity" TARGET="MAIN"><CODE>CalBddIdentity()</CODE></A>
+ <DD> Returns the duplicate BDD of the argument BDD.
+
+ <DT> <A HREF="calAllDet.html#BddIntersectsStep" TARGET="MAIN"><CODE>BddIntersectsStep()</CODE></A>
+ <DD> Recursive routine to returns a BDD that implies conjunction of
+  argument BDDs
+
+</DL>
+<HR>
+<A NAME="calApplyReduce.c"><H1>calApplyReduce.c</H1></A>
+Generic routines for processing temporary nodes during
+  "apply" and "reduce" phases. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalHashTableApply" TARGET="MAIN"><CODE>CalHashTableApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableReduce" TARGET="MAIN"><CODE>CalHashTableReduce()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calAssociation.c"><H1>calAssociation.c</H1></A>
+Contains the routines related to the variable association. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi  (sanghavi@eecs.berkeley.edu)</B><P>
+optional <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_AssociationInit" TARGET="MAIN"><CODE>Cal_AssociationInit()</CODE></A>
+ <DD> Creates or finds a variable association.
+
+ <DT> <A HREF="calAllDet.html#Cal_AssociationQuit" TARGET="MAIN"><CODE>Cal_AssociationQuit()</CODE></A>
+ <DD> Deletes the variable association given by id
+
+ <DT> <A HREF="calAllDet.html#Cal_AssociationSetCurrent" TARGET="MAIN"><CODE>Cal_AssociationSetCurrent()</CODE></A>
+ <DD> Sets the current variable association to the one given by id and
+  returns the ID of the old association.
+
+ <DT> <A HREF="calAllDet.html#Cal_TempAssociationAugment" TARGET="MAIN"><CODE>Cal_TempAssociationAugment()</CODE></A>
+ <DD> Adds to the temporary variable association.
+
+ <DT> <A HREF="calAllDet.html#Cal_TempAssociationInit" TARGET="MAIN"><CODE>Cal_TempAssociationInit()</CODE></A>
+ <DD> Sets the temporary variable association.
+
+ <DT> <A HREF="calAllDet.html#Cal_TempAssociationQuit" TARGET="MAIN"><CODE>Cal_TempAssociationQuit()</CODE></A>
+ <DD> Cleans up temporary association
+
+ <DT> <A HREF="calAllDet.html#CalAssociationListFree" TARGET="MAIN"><CODE>CalAssociationListFree()</CODE></A>
+ <DD> Frees the variable associations
+
+ <DT> <A HREF="calAllDet.html#CalVarAssociationRepackUpdate" TARGET="MAIN"><CODE>CalVarAssociationRepackUpdate()</CODE></A>
+ <DD> Need to be called after repacking.
+
+ <DT> <A HREF="calAllDet.html#CalCheckAssociationValidity" TARGET="MAIN"><CODE>CalCheckAssociationValidity()</CODE></A>
+ <DD> Checks the validity of association.
+
+ <DT> <A HREF="calAllDet.html#CalReorderAssociationFix" TARGET="MAIN"><CODE>CalReorderAssociationFix()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#AssociationIsEqual" TARGET="MAIN"><CODE>AssociationIsEqual()</CODE></A>
+ <DD> Checks for equality of two associations
+
+ <DT> <A HREF="calAllDet.html#CheckAssoc" TARGET="MAIN"><CODE>CheckAssoc()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calBddCompose.c"><H1>calBddCompose.c</H1></A>
+Routine for composing one BDD into another. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddCompose" TARGET="MAIN"><CODE>Cal_BddCompose()</CODE></A>
+ <DD> composition - substitute a BDD variable by a function
+
+ <DT> <A HREF="calAllDet.html#CalRequestNodeListCompose" TARGET="MAIN"><CODE>CalRequestNodeListCompose()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableComposeApply" TARGET="MAIN"><CODE>CalHashTableComposeApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalComposeRequestCreate" TARGET="MAIN"><CODE>CalComposeRequestCreate()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calBddITE.c"><H1>calBddITE.c</H1></A>
+Routine for computing ITE of 3 BDD operands. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddITE" TARGET="MAIN"><CODE>Cal_BddITE()</CODE></A>
+ <DD> Returns the BDD for logical If-Then-Else
+
+  Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+  - f g + f' h
+
+ <DT> <A HREF="calAllDet.html#CalRequestNodeListArrayITE" TARGET="MAIN"><CODE>CalRequestNodeListArrayITE()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddOpITEBF" TARGET="MAIN"><CODE>CalBddOpITEBF()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableITEApply" TARGET="MAIN"><CODE>CalHashTableITEApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddITE" TARGET="MAIN"><CODE>CalBddITE()</CODE></A>
+ <DD> Returns the BDD for logical If-Then-Else
+ 
+   Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+   - f g + f' h
+
+</DL>
+<HR>
+<A NAME="calBddManager.c"><H1>calBddManager.c</H1></A>
+Routines for maintaing the manager and creating
+  variables etc. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerInit" TARGET="MAIN"><CODE>Cal_BddManagerInit()</CODE></A>
+ <DD> Creates and initializes a new BDD manager.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerQuit" TARGET="MAIN"><CODE>Cal_BddManagerQuit()</CODE></A>
+ <DD> Frees the BDD manager and all the associated allocations
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerSetParameters" TARGET="MAIN"><CODE>Cal_BddManagerSetParameters()</CODE></A>
+ <DD> Sets appropriate fields of BDD Manager.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerGetNumNodes" TARGET="MAIN"><CODE>Cal_BddManagerGetNumNodes()</CODE></A>
+ <DD> Returns the number of BDD nodes
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarFirst" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarFirst()</CODE></A>
+ <DD> Creates and returns a new variable at the start of the variable
+  order.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarLast" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarLast()</CODE></A>
+ <DD> Creates and returns a new variable at the end of the variable
+  order.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarBefore" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarBefore()</CODE></A>
+ <DD> Creates and returns a new variable before the specified one in
+  the variable order.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerCreateNewVarAfter" TARGET="MAIN"><CODE>Cal_BddManagerCreateNewVarAfter()</CODE></A>
+ <DD> Creates and returns a new variable after the specified one in
+  the variable  order.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerGetVarWithIndex" TARGET="MAIN"><CODE>Cal_BddManagerGetVarWithIndex()</CODE></A>
+ <DD> Returns the variable with the specified index, null if no
+  such variable exists
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerGetVarWithId" TARGET="MAIN"><CODE>Cal_BddManagerGetVarWithId()</CODE></A>
+ <DD> Returns the variable with the specified id, null if no
+  such variable exists
+
+ <DT> <A HREF="calAllDet.html#CalBddManagerCreateNewVar" TARGET="MAIN"><CODE>CalBddManagerCreateNewVar()</CODE></A>
+ <DD> This function creates and returns a new variable with given
+  index value.
+
+ <DT> <A HREF="calAllDet.html#BddDefaultTransformFn" TARGET="MAIN"><CODE>BddDefaultTransformFn()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddManagerPrint" TARGET="MAIN"><CODE>CalBddManagerPrint()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calBddOp.c"><H1>calBddOp.c</H1></A>
+Routines for performing simple boolean operations on a
+  pair of BDDs or on an array of pair of BDDs or on an array of BDDs. <P>
+<B>By: Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+The "cal" specific routines are "Cal_BddPairwiseAnd/Or",
+  "Cal_BddMultiwayAnd/Or". <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddAnd" TARGET="MAIN"><CODE>Cal_BddAnd()</CODE></A>
+ <DD> Returns the BDD for logical AND of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddNand" TARGET="MAIN"><CODE>Cal_BddNand()</CODE></A>
+ <DD> Returns the BDD for logical NAND of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddOr" TARGET="MAIN"><CODE>Cal_BddOr()</CODE></A>
+ <DD> Returns the BDD for logical OR of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddNor" TARGET="MAIN"><CODE>Cal_BddNor()</CODE></A>
+ <DD> Returns the BDD for logical NOR of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddXor" TARGET="MAIN"><CODE>Cal_BddXor()</CODE></A>
+ <DD> Returns the BDD for logical exclusive OR of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddXnor" TARGET="MAIN"><CODE>Cal_BddXnor()</CODE></A>
+ <DD> Returns the BDD for logical exclusive NOR of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddPairwiseAnd" TARGET="MAIN"><CODE>Cal_BddPairwiseAnd()</CODE></A>
+ <DD> Returns an array of BDDs obtained by logical AND of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+ <DT> <A HREF="calAllDet.html#Cal_BddPairwiseOr" TARGET="MAIN"><CODE>Cal_BddPairwiseOr()</CODE></A>
+ <DD> Returns an array of BDDs obtained by logical OR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+ <DT> <A HREF="calAllDet.html#Cal_BddPairwiseXor" TARGET="MAIN"><CODE>Cal_BddPairwiseXor()</CODE></A>
+ <DD> Returns an array of BDDs obtained by logical XOR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+ <DT> <A HREF="calAllDet.html#Cal_BddMultiwayAnd" TARGET="MAIN"><CODE>Cal_BddMultiwayAnd()</CODE></A>
+ <DD> Returns the BDD for logical AND of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddMultiwayOr" TARGET="MAIN"><CODE>Cal_BddMultiwayOr()</CODE></A>
+ <DD> Returns the BDD for logical OR of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddMultiwayXor" TARGET="MAIN"><CODE>Cal_BddMultiwayXor()</CODE></A>
+ <DD> Returns the BDD for logical XOR of argument BDDs
+
+ <DT> <A HREF="calAllDet.html#CalRequestNodeListArrayOp" TARGET="MAIN"><CODE>CalRequestNodeListArrayOp()</CODE></A>
+ <DD> Computes result BDDs for an array of lists, each entry of which 
+  is pair of pointers, each of which points to a operand BDD or an entry in
+  another list with a smaller array index
+
+ <DT> <A HREF="calAllDet.html#CalBddOpBF" TARGET="MAIN"><CODE>CalBddOpBF()</CODE></A>
+ <DD> Internal routine to compute a logical operation on a pair of BDDs
+
+ <DT> <A HREF="calAllDet.html#BddArrayOpBF" TARGET="MAIN"><CODE>BddArrayOpBF()</CODE></A>
+ <DD> Internal common routine for Cal_BddPairwiseAnd and Cal_BddPairwiseOr
+
+ <DT> <A HREF="calAllDet.html#BddMultiwayOp" TARGET="MAIN"><CODE>BddMultiwayOp()</CODE></A>
+ <DD> Internal routine for multiway operations
+
+ <DT> <A HREF="calAllDet.html#BddArrayToRequestNodeListArray" TARGET="MAIN"><CODE>BddArrayToRequestNodeListArray()</CODE></A>
+ <DD> Converts an array of BDDs to a list of requests representing BDD
+  pairs
+
+ <DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+ <DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+</DL>
+<HR>
+<A NAME="calBddReorderTest.c"><H1>calBddReorderTest.c</H1></A>
+A test routine for checking the functionality of
+  dynamic reordering. <P>
+<B>By: Wilsin Gosti    (wilsin@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#main" TARGET="MAIN"><CODE>main()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#cpuTime" TARGET="MAIN"><CODE>cpuTime()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#elapsedTime" TARGET="MAIN"><CODE>elapsedTime()</CODE></A>
+ <DD> Computes the time.
+
+</DL>
+<HR>
+<A NAME="calBddSatisfy.c"><H1>calBddSatisfy.c</H1></A>
+Routines for BDD satisfying valuation. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddSatisfy" TARGET="MAIN"><CODE>Cal_BddSatisfy()</CODE></A>
+ <DD> Returns a BDD which implies f, true for
+               some valuation on which f is true, and which has at most
+               one node at each level
+
+ <DT> <A HREF="calAllDet.html#Cal_BddSatisfySupport" TARGET="MAIN"><CODE>Cal_BddSatisfySupport()</CODE></A>
+ <DD> Returns a special cube contained in f.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddSatisfyingFraction" TARGET="MAIN"><CODE>Cal_BddSatisfyingFraction()</CODE></A>
+ <DD> Returns the fraction of valuations which make f true. (Note that
+  this fraction is independent of whatever set of variables f is supposed to be
+  a function of)
+
+ <DT> <A HREF="calAllDet.html#BddSatisfyStep" TARGET="MAIN"><CODE>BddSatisfyStep()</CODE></A>
+ <DD> Returns a BDD which implies f, is true for some valuation
+  on which f is true, and which has at most one node at each level
+
+ <DT> <A HREF="calAllDet.html#BddSatisfySupportStep" TARGET="MAIN"><CODE>BddSatisfySupportStep()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#IndexCmp" TARGET="MAIN"><CODE>IndexCmp()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddSatisfyingFractionStep" TARGET="MAIN"><CODE>BddSatisfyingFractionStep()</CODE></A>
+ <DD> 
+
+</DL>
+<HR>
+<A NAME="calBddSize.c"><H1>calBddSize.c</H1></A>
+BDD size and profile routines <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddSize" TARGET="MAIN"><CODE>Cal_BddSize()</CODE></A>
+ <DD> Returns the number of nodes in f when negout is nonzero. If
+  negout is zero, we pretend that the BDDs don't have negative-output pointers.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddSizeMultiple" TARGET="MAIN"><CODE>Cal_BddSizeMultiple()</CODE></A>
+ <DD> The routine is like Cal_BddSize, but takes a null-terminated
+               array of BDDs and accounts for sharing of nodes.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddProfile" TARGET="MAIN"><CODE>Cal_BddProfile()</CODE></A>
+ <DD> Returns a "node profile" of f, i.e., the number of nodes at each
+  level in f.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddProfileMultiple" TARGET="MAIN"><CODE>Cal_BddProfileMultiple()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#Cal_BddFunctionProfile" TARGET="MAIN"><CODE>Cal_BddFunctionProfile()</CODE></A>
+ <DD> Returns a "function profile" for f.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddFunctionProfileMultiple" TARGET="MAIN"><CODE>Cal_BddFunctionProfileMultiple()</CODE></A>
+ <DD> Returns a "function profile" for fArray.
+
+ <DT> <A HREF="calAllDet.html#BddMarkBdd" TARGET="MAIN"><CODE>BddMarkBdd()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddCountNoNodes" TARGET="MAIN"><CODE>BddCountNoNodes()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddCountNodes" TARGET="MAIN"><CODE>BddCountNodes()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddSizeStep" TARGET="MAIN"><CODE>BddSizeStep()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddProfileStep" TARGET="MAIN"><CODE>BddProfileStep()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddHighestRefStep" TARGET="MAIN"><CODE>BddHighestRefStep()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddDominatedStep" TARGET="MAIN"><CODE>BddDominatedStep()</CODE></A>
+ <DD> 
+
+</DL>
+<HR>
+<A NAME="calBddSubstitute.c"><H1>calBddSubstitute.c</H1></A>
+Routine for simultaneous substitution of an array of
+  variables with an array of functions. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+Routine for simultaneous substitution of an array of
+  variables with an array of functions. <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddSubstitute" TARGET="MAIN"><CODE>Cal_BddSubstitute()</CODE></A>
+ <DD> Substitute a set of variables by functions
+
+ <DT> <A HREF="calAllDet.html#CalHashTableSubstituteApply" TARGET="MAIN"><CODE>CalHashTableSubstituteApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableSubstituteReduce" TARGET="MAIN"><CODE>CalHashTableSubstituteReduce()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calBddSupport.c"><H1>calBddSupport.c</H1></A>
+Routines related to the support of a BDD. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddSupport" TARGET="MAIN"><CODE>Cal_BddSupport()</CODE></A>
+ <DD> returns the support of f as a null-terminated array of variables
+
+ <DT> <A HREF="calAllDet.html#Cal_BddDependsOn" TARGET="MAIN"><CODE>Cal_BddDependsOn()</CODE></A>
+ <DD> Returns 1 if f depends on var and returns 0 otherwise.
+
+ <DT> <A HREF="calAllDet.html#CalBddSupportStep" TARGET="MAIN"><CODE>CalBddSupportStep()</CODE></A>
+ <DD> returns the support of f as a null-terminated array of variables
+
+ <DT> <A HREF="calAllDet.html#CalBddUnmarkNodes" TARGET="MAIN"><CODE>CalBddUnmarkNodes()</CODE></A>
+ <DD> recursively unmarks the nodes
+
+ <DT> <A HREF="calAllDet.html#CalBddDependsOnStep" TARGET="MAIN"><CODE>CalBddDependsOnStep()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calBddSwapVars.c"><H1>calBddSwapVars.c</H1></A>
+Routine for swapping two variables. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+Routine for swapping two variables. <P>
+<P><B>See Also</B><A HREF="#None"><CODE>None</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddSwapVars" TARGET="MAIN"><CODE>Cal_BddSwapVars()</CODE></A>
+ <DD> Return a function obtained by swapping two variables
+
+ <DT> <A HREF="calAllDet.html#CalHashTableSwapVarsApply" TARGET="MAIN"><CODE>CalHashTableSwapVarsApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableSwapVarsPlusApply" TARGET="MAIN"><CODE>CalHashTableSwapVarsPlusApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableSwapVarsMinusApply" TARGET="MAIN"><CODE>CalHashTableSwapVarsMinusApply()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calBddVarSubstitute.c"><H1>calBddVarSubstitute.c</H1></A>
+Routine for simultaneous substitution of an array of
+  variables with another array of variables. <P>
+<B>By: Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddVarSubstitute" TARGET="MAIN"><CODE>Cal_BddVarSubstitute()</CODE></A>
+ <DD> Substitute a set of variables by set of another variables.
+
+ <DT> <A HREF="calAllDet.html#CalBddVarSubstitute" TARGET="MAIN"><CODE>CalBddVarSubstitute()</CODE></A>
+ <DD> Substitute a set of variables by functions
+
+ <DT> <A HREF="calAllDet.html#CalOpBddVarSubstitute" TARGET="MAIN"><CODE>CalOpBddVarSubstitute()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableSubstituteApply" TARGET="MAIN"><CODE>CalHashTableSubstituteApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableSubstituteReduce" TARGET="MAIN"><CODE>CalHashTableSubstituteReduce()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calBlk.c"><H1>calBlk.c</H1></A>
+Routines for manipulating blocks of variables. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu). Modelled on the BDD package
+  developed by David Long.</B><P>
+Routines for manipulating blocks of variables. <P>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddNewVarBlock" TARGET="MAIN"><CODE>Cal_BddNewVarBlock()</CODE></A>
+ <DD> Creates and returns a variable block used for
+  controlling dynamic reordering.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddVarBlockReorderable" TARGET="MAIN"><CODE>Cal_BddVarBlockReorderable()</CODE></A>
+ <DD> Sets the reoderability of a particular block.
+
+ <DT> <A HREF="calAllDet.html#CalBddFindBlock" TARGET="MAIN"><CODE>CalBddFindBlock()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddBlockDelta" TARGET="MAIN"><CODE>CalBddBlockDelta()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddShiftBlock" TARGET="MAIN"><CODE>CalBddShiftBlock()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBlockMemoryConsumption" TARGET="MAIN"><CODE>CalBlockMemoryConsumption()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalFreeBlockRecursively" TARGET="MAIN"><CODE>CalFreeBlockRecursively()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#AddBlock" TARGET="MAIN"><CODE>AddBlock()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calCacheTableTwo.c"><H1>calCacheTableTwo.c</H1></A>
+Functions to manage the Cache tables. <P>
+<B>By: Rajeev K. Ranjan   (rajeev@eecs.berkeley.edu)
+                Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoInit" TARGET="MAIN"><CODE>CalCacheTableTwoInit()</CODE></A>
+ <DD> Initialize a Cache table using default parameters.
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoQuit" TARGET="MAIN"><CODE>CalCacheTableTwoQuit()</CODE></A>
+ <DD> Free a Cache table along with the associated storage.
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoInsert" TARGET="MAIN"><CODE>CalCacheTableTwoInsert()</CODE></A>
+ <DD> Directly insert a BDD node in the Cache table.
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoLookup" TARGET="MAIN"><CODE>CalCacheTableTwoLookup()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoFlush" TARGET="MAIN"><CODE>CalCacheTableTwoFlush()</CODE></A>
+ <DD> Free a Cache table along with the associated storage.
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoFlushAll" TARGET="MAIN"><CODE>CalCacheTableTwoFlushAll()</CODE></A>
+ <DD> Free a Cache table along with the associated storage.
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoGCFlush" TARGET="MAIN"><CODE>CalCacheTableTwoGCFlush()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoRepackUpdate" TARGET="MAIN"><CODE>CalCacheTableTwoRepackUpdate()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckCacheTableValidity" TARGET="MAIN"><CODE>CalCheckCacheTableValidity()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoFixResultPointers" TARGET="MAIN"><CODE>CalCacheTableTwoFixResultPointers()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCacheTablePrint" TARGET="MAIN"><CODE>CalCacheTablePrint()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddManagerGetCacheTableData" TARGET="MAIN"><CODE>CalBddManagerGetCacheTableData()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableRehash" TARGET="MAIN"><CODE>CalCacheTableRehash()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableTwoFlushAssociationId" TARGET="MAIN"><CODE>CalCacheTableTwoFlushAssociationId()</CODE></A>
+ <DD> Flushes the entries from the cache which
+                      correspond to the given associationId.
+
+ <DT> <A HREF="calAllDet.html#CalCacheTableMemoryConsumption" TARGET="MAIN"><CODE>CalCacheTableMemoryConsumption()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CacheTableTwoRehash" TARGET="MAIN"><CODE>CacheTableTwoRehash()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CacheTablePrint" TARGET="MAIN"><CODE>CacheTablePrint()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calDump.c"><H1>calDump.c</H1></A>
+BDD library dump/undump routines <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddUndumpBdd" TARGET="MAIN"><CODE>Cal_BddUndumpBdd()</CODE></A>
+ <DD> Reads a BDD from a file
+
+ <DT> <A HREF="calAllDet.html#Cal_BddDumpBdd" TARGET="MAIN"><CODE>Cal_BddDumpBdd()</CODE></A>
+ <DD> Write a BDD to a file
+
+ <DT> <A HREF="calAllDet.html#Write" TARGET="MAIN"><CODE>Write()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddDumpBddStep" TARGET="MAIN"><CODE>BddDumpBddStep()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#Read" TARGET="MAIN"><CODE>Read()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BddUndumpBddStep" TARGET="MAIN"><CODE>BddUndumpBddStep()</CODE></A>
+ <DD> 
+
+ <DT> <A HREF="calAllDet.html#BytesNeeded" TARGET="MAIN"><CODE>BytesNeeded()</CODE></A>
+ <DD> 
+
+</DL>
+<HR>
+<A NAME="calGC.c"><H1>calGC.c</H1></A>
+Garbage collection routines <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan (rajeev@eecs.berkeley.edu)</B><P>
+optional <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddSetGCMode" TARGET="MAIN"><CODE>Cal_BddSetGCMode()</CODE></A>
+ <DD> Sets the garbage collection mode, 0 means the garbage
+  collection should be turned off, 1 means garbage collection should
+  be on.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerGC" TARGET="MAIN"><CODE>Cal_BddManagerGC()</CODE></A>
+ <DD> Invokes the garbage collection at the manager level.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddManagerSetGCLimit" TARGET="MAIN"><CODE>Cal_BddManagerSetGCLimit()</CODE></A>
+ <DD> Sets the limit of the garbage collection.
+
+ <DT> <A HREF="calAllDet.html#CalBddManagerGCCheck" TARGET="MAIN"><CODE>CalBddManagerGCCheck()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableGC" TARGET="MAIN"><CODE>CalHashTableGC()</CODE></A>
+ <DD> This function performs the garbage collection operation
+  for a particular index.
+
+ <DT> <A HREF="calAllDet.html#CalRepackNodesAfterGC" TARGET="MAIN"><CODE>CalRepackNodesAfterGC()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+ <DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+</DL>
+<HR>
+<A NAME="calHashTable.c"><H1>calHashTable.c</H1></A>
+Functions to manage the hash tables that are a part of
+                  1. unique table
+                  2. request queue <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+                Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalHashTableInit" TARGET="MAIN"><CODE>CalHashTableInit()</CODE></A>
+ <DD> Initialize a hash table using default parameters.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableQuit" TARGET="MAIN"><CODE>CalHashTableQuit()</CODE></A>
+ <DD> Free a hash table along with the associated storage.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableAddDirect" TARGET="MAIN"><CODE>CalHashTableAddDirect()</CODE></A>
+ <DD> Directly insert a BDD node in the hash table.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableFindOrAdd" TARGET="MAIN"><CODE>CalHashTableFindOrAdd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableAddDirectAux" TARGET="MAIN"><CODE>CalHashTableAddDirectAux()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableCleanUp" TARGET="MAIN"><CODE>CalHashTableCleanUp()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableLookup" TARGET="MAIN"><CODE>CalHashTableLookup()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableDelete" TARGET="MAIN"><CODE>CalHashTableDelete()</CODE></A>
+ <DD> Deletes a BDD node in the hash table.
+
+ <DT> <A HREF="calAllDet.html#CalUniqueTableForIdLookup" TARGET="MAIN"><CODE>CalUniqueTableForIdLookup()</CODE></A>
+ <DD> Lookup unique table for id.
+
+ <DT> <A HREF="calAllDet.html#CalUniqueTableForIdFindOrAdd" TARGET="MAIN"><CODE>CalUniqueTableForIdFindOrAdd()</CODE></A>
+ <DD> find or add in the unique table for id.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableRehash" TARGET="MAIN"><CODE>CalHashTableRehash()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalUniqueTableForIdRehashNode" TARGET="MAIN"><CODE>CalUniqueTableForIdRehashNode()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddUniqueTableNumLockedNodes" TARGET="MAIN"><CODE>CalBddUniqueTableNumLockedNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalPackNodes" TARGET="MAIN"><CODE>CalPackNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddPackNodesForSingleId" TARGET="MAIN"><CODE>CalBddPackNodesForSingleId()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddPackNodesAfterReorderForSingleId" TARGET="MAIN"><CODE>CalBddPackNodesAfterReorderForSingleId()</CODE></A>
+ <DD> Packs the nodes if the variables which has just
+  been sifted.
+
+ <DT> <A HREF="calAllDet.html#CalBddPackNodesForMultipleIds" TARGET="MAIN"><CODE>CalBddPackNodesForMultipleIds()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+ <DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+</DL>
+<HR>
+<A NAME="calHashTableOne.c"><H1>calHashTableOne.c</H1></A>
+Routines for managing hash table with Bdd is a key and
+               int, long, or double as a value <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalHashTableOneInit" TARGET="MAIN"><CODE>CalHashTableOneInit()</CODE></A>
+ <DD> Initialize a hash table using default parameters.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableOneQuit" TARGET="MAIN"><CODE>CalHashTableOneQuit()</CODE></A>
+ <DD> Free a hash table along with the associated storage.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableOneInsert" TARGET="MAIN"><CODE>CalHashTableOneInsert()</CODE></A>
+ <DD> Directly insert a BDD node in the hash table.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableOneLookup" TARGET="MAIN"><CODE>CalHashTableOneLookup()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#HashTableOneRehash" TARGET="MAIN"><CODE>HashTableOneRehash()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calHashTableThree.c"><H1>calHashTableThree.c</H1></A>
+Functions to manage the hash tables that are a part of
+                  ITE operation <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+                Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+CalHashTableThreeFindOrAdd <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalHashTableThreeFindOrAdd" TARGET="MAIN"><CODE>CalHashTableThreeFindOrAdd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTableThreeRehash" TARGET="MAIN"><CODE>CalHashTableThreeRehash()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calInteract.c"><H1>calInteract.c</H1></A>
+Functions to manipulate the variable interaction matrix. <P>
+<B>By: Original author:Fabio Somenzi. Modified for CAL package
+  by Rajeev K. Ranjan</B><P>
+The interaction matrix tells whether two variables are
+  both in the support of some function of the DD. The main use of the
+  interaction matrix is in the in-place swapping. Indeed, if two
+  variables do not interact, there is no arc connecting the two layers;
+  therefore, the swap can be performed in constant time, without
+  scanning the subtables. Another use of the interaction matrix is in
+  the computation of the lower bounds for sifting. Finally, the
+  interaction matrix can be used to speed up aggregation checks in
+  symmetric and group sifting.<p>
+  The computation of the interaction matrix is done with a series of
+  depth-first searches. The searches start from those nodes that have
+  only external references. The matrix is stored as a packed array of bits;
+  since it is symmetric, only the upper triangle is kept in memory.
+  As a final remark, we note that there may be variables that do
+  intercat, but that for a given variable order have no arc connecting
+  their layers when they are adjacent. <P>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalSetInteract" TARGET="MAIN"><CODE>CalSetInteract()</CODE></A>
+ <DD> Set interaction matrix entries.
+
+ <DT> <A HREF="calAllDet.html#CalTestInteract" TARGET="MAIN"><CODE>CalTestInteract()</CODE></A>
+ <DD> Test interaction matrix entries.
+
+ <DT> <A HREF="calAllDet.html#CalInitInteract" TARGET="MAIN"><CODE>CalInitInteract()</CODE></A>
+ <DD> Initializes the interaction matrix.
+
+ <DT> <A HREF="calAllDet.html#ddSuppInteract" TARGET="MAIN"><CODE>ddSuppInteract()</CODE></A>
+ <DD> Find the support of f.
+
+ <DT> <A HREF="calAllDet.html#ddClearLocal" TARGET="MAIN"><CODE>ddClearLocal()</CODE></A>
+ <DD> Performs a DFS from f, clearing the LSB of the then pointers.
+
+ <DT> <A HREF="calAllDet.html#ddUpdateInteract" TARGET="MAIN"><CODE>ddUpdateInteract()</CODE></A>
+ <DD> Marks as interacting all pairs of variables that appear in
+  support.
+
+</DL>
+<HR>
+<A NAME="calMem.c"><H1>calMem.c</H1></A>
+Routines for memory management. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu). Originally
+  written by David Long.</B><P>
+Contains allocation, free, resize routines. Also has
+  routines for managing records of fixed size. <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_MemFatal" TARGET="MAIN"><CODE>Cal_MemFatal()</CODE></A>
+ <DD> Prints an error message and exits.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemAllocation" TARGET="MAIN"><CODE>Cal_MemAllocation()</CODE></A>
+ <DD> Returns the memory allocated.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemGetBlock" TARGET="MAIN"><CODE>Cal_MemGetBlock()</CODE></A>
+ <DD> Allocates a new block of the specified size.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemFreeBlock" TARGET="MAIN"><CODE>Cal_MemFreeBlock()</CODE></A>
+ <DD> Frees the block.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemResizeBlock" TARGET="MAIN"><CODE>Cal_MemResizeBlock()</CODE></A>
+ <DD> Expands or contracts the block to a new size.
+  We try to avoid moving the block if possible.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemNewRec" TARGET="MAIN"><CODE>Cal_MemNewRec()</CODE></A>
+ <DD> Allocates a record from the specified record manager.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemFreeRec" TARGET="MAIN"><CODE>Cal_MemFreeRec()</CODE></A>
+ <DD> Frees a record managed by the indicated record manager.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemNewRecMgr" TARGET="MAIN"><CODE>Cal_MemNewRecMgr()</CODE></A>
+ <DD> Creates a new record manager with the given  record size.
+
+ <DT> <A HREF="calAllDet.html#Cal_MemFreeRecMgr" TARGET="MAIN"><CODE>Cal_MemFreeRecMgr()</CODE></A>
+ <DD> Frees all the storage associated with the specified record manager.
+
+ <DT> <A HREF="calAllDet.html#CeilingLog2" TARGET="MAIN"><CODE>CeilingLog2()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BlockSizeIndex" TARGET="MAIN"><CODE>BlockSizeIndex()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#AddToFreeList" TARGET="MAIN"><CODE>AddToFreeList()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#RemoveFromFreeList" TARGET="MAIN"><CODE>RemoveFromFreeList()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#Buddy" TARGET="MAIN"><CODE>Buddy()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TrimToSize" TARGET="MAIN"><CODE>TrimToSize()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#MergeAndFree" TARGET="MAIN"><CODE>MergeAndFree()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calMemoryManagement.c"><H1>calMemoryManagement.c</H1></A>
+Special memory management routines specific to CAL. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+Functions for managing the system memory using a set of 
+              nodeManagers. Each nodeManager manages a set of fixed size
+              nodes obtained from a set of pages. When additional memory
+              is required, nodeManager obtains a new page from the pageManager.
+              The new page is divided into ( PAGE_SIZE/NODE_SIZE ) number of
+              nodes. <P>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalPageManagerInit" TARGET="MAIN"><CODE>CalPageManagerInit()</CODE></A>
+ <DD> Initializes a pageManager.
+
+ <DT> <A HREF="calAllDet.html#CalPageManagerQuit" TARGET="MAIN"><CODE>CalPageManagerQuit()</CODE></A>
+ <DD> Frees pageManager and associated pages.
+
+ <DT> <A HREF="calAllDet.html#CalPageManagerPrint" TARGET="MAIN"><CODE>CalPageManagerPrint()</CODE></A>
+ <DD> Prints address of each memory segment and address of each page.
+
+ <DT> <A HREF="calAllDet.html#CalNodeManagerInit" TARGET="MAIN"><CODE>CalNodeManagerInit()</CODE></A>
+ <DD> Initializes a node manager.
+
+ <DT> <A HREF="calAllDet.html#CalNodeManagerQuit" TARGET="MAIN"><CODE>CalNodeManagerQuit()</CODE></A>
+ <DD> Frees a node manager.
+
+ <DT> <A HREF="calAllDet.html#CalNodeManagerPrint" TARGET="MAIN"><CODE>CalNodeManagerPrint()</CODE></A>
+ <DD> Prints address of each free node.
+
+ <DT> <A HREF="calAllDet.html#CalPageManagerAllocPage" TARGET="MAIN"><CODE>CalPageManagerAllocPage()</CODE></A>
+ <DD> Allocs a new page.
+
+ <DT> <A HREF="calAllDet.html#CalPageManagerFreePage" TARGET="MAIN"><CODE>CalPageManagerFreePage()</CODE></A>
+ <DD> Free a page.
+
+ <DT> <A HREF="calAllDet.html#PageManagerExpandStorage" TARGET="MAIN"><CODE>PageManagerExpandStorage()</CODE></A>
+ <DD> Allocates a segment of memory to expand the storage managed by
+              pageManager. The allocated segment is divided into free pages
+              which are linked as a freePageList.
+
+ <DT> <A HREF="calAllDet.html#PageAlign" TARGET="MAIN"><CODE>PageAlign()</CODE></A>
+ <DD> Return page aligned address greater than or equal to
+  the pointer.
+
+ <DT> <A HREF="calAllDet.html#SegmentToPageList" TARGET="MAIN"><CODE>SegmentToPageList()</CODE></A>
+ <DD> Converts a memory segment into a linked list of pages.
+              if p is a pointer to a page, *p contains address of the next page
+              if p is a pointer to the last page, *p contains lastPointer.
+
+</DL>
+<HR>
+<A NAME="calPerformanceTest.c"><H1>calPerformanceTest.c</H1></A>
+This file contains the performance test routines for
+  the CAL package. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi  (sanghavi@eecs.berkeley.edu)</B><P>
+optional <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_PerformanceTest" TARGET="MAIN"><CODE>Cal_PerformanceTest()</CODE></A>
+ <DD> Main routine for testing performances of various routines.
+
+ <DT> <A HREF="calAllDet.html#CalIncreasingOrderCompare" TARGET="MAIN"><CODE>CalIncreasingOrderCompare()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalDecreasingOrderCompare" TARGET="MAIN"><CODE>CalDecreasingOrderCompare()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestAnd" TARGET="MAIN"><CODE>CalPerformanceTestAnd()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceMemoryOverhead" TARGET="MAIN"><CODE>CalPerformanceMemoryOverhead()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformaceTestSuperscalar" TARGET="MAIN"><CODE>CalPerformaceTestSuperscalar()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestNonSuperscalar" TARGET="MAIN"><CODE>CalPerformanceTestNonSuperscalar()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestMultiway" TARGET="MAIN"><CODE>CalPerformanceTestMultiway()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestOneway" TARGET="MAIN"><CODE>CalPerformanceTestOneway()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestCompose" TARGET="MAIN"><CODE>CalPerformanceTestCompose()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestQuantifyAllTogether" TARGET="MAIN"><CODE>CalPerformanceTestQuantifyAllTogether()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalQuantifySanityCheck" TARGET="MAIN"><CODE>CalQuantifySanityCheck()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestRelProd" TARGET="MAIN"><CODE>CalPerformanceTestRelProd()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestSubstitute" TARGET="MAIN"><CODE>CalPerformanceTestSubstitute()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#CalPerformanceTestSwapVars" TARGET="MAIN"><CODE>CalPerformanceTestSwapVars()</CODE></A>
+ <DD> Performance test routine for quantify (all variables at the same
+  time).
+
+ <DT> <A HREF="calAllDet.html#elapsedTime" TARGET="MAIN"><CODE>elapsedTime()</CODE></A>
+ <DD> Computes the time.
+
+ <DT> <A HREF="calAllDet.html#cpuTime" TARGET="MAIN"><CODE>cpuTime()</CODE></A>
+ <DD> Computes the number of page faults.
+
+ <DT> <A HREF="calAllDet.html#pageFaults" TARGET="MAIN"><CODE>pageFaults()</CODE></A>
+ <DD> Computes the number of page faults.
+
+ <DT> <A HREF="calAllDet.html#GetRandomNumbers" TARGET="MAIN"><CODE>GetRandomNumbers()</CODE></A>
+ <DD> Generates "count" many random numbers ranging between
+  "lowerBound" and "upperBound".
+
+</DL>
+<HR>
+<A NAME="calPipeline.c"><H1>calPipeline.c</H1></A>
+Routines for creating and managing the pipelined BDD
+  operations. <P>
+<B>By: Rajeev K. Ranjan   (rajeev@eecs.berkeley.edu)
+                Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+Eventually we would like to have this feature
+  transparent to the user. <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_PipelineSetDepth" TARGET="MAIN"><CODE>Cal_PipelineSetDepth()</CODE></A>
+ <DD> Set depth of a BDD pipeline.
+
+ <DT> <A HREF="calAllDet.html#Cal_PipelineInit" TARGET="MAIN"><CODE>Cal_PipelineInit()</CODE></A>
+ <DD> Initialize a BDD pipeline.
+
+ <DT> <A HREF="calAllDet.html#Cal_PipelineCreateProvisionalBdd" TARGET="MAIN"><CODE>Cal_PipelineCreateProvisionalBdd()</CODE></A>
+ <DD> Create a provisional BDD in the pipeline.
+
+ <DT> <A HREF="calAllDet.html#Cal_PipelineExecute" TARGET="MAIN"><CODE>Cal_PipelineExecute()</CODE></A>
+ <DD> Executes a pipeline.
+
+ <DT> <A HREF="calAllDet.html#Cal_PipelineUpdateProvisionalBdd" TARGET="MAIN"><CODE>Cal_PipelineUpdateProvisionalBdd()</CODE></A>
+ <DD> Update a provisional Bdd obtained during pipelining.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddIsProvisional" TARGET="MAIN"><CODE>Cal_BddIsProvisional()</CODE></A>
+ <DD> Returns 1, if the given user BDD contains
+  provisional BDD node.
+
+ <DT> <A HREF="calAllDet.html#Cal_PipelineQuit" TARGET="MAIN"><CODE>Cal_PipelineQuit()</CODE></A>
+ <DD> Resets the pipeline freeing all resources.
+
+ <DT> <A HREF="calAllDet.html#CalBddReorderFixProvisionalNodes" TARGET="MAIN"><CODE>CalBddReorderFixProvisionalNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckPipelineValidity" TARGET="MAIN"><CODE>CalCheckPipelineValidity()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calPrint.c"><H1>calPrint.c</H1></A>
+Routine for printing a BDD. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu)
+               Originally written by David Long.</B><P>
+<P><B>See Also</B><A HREF="#None"><CODE>None</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddPrintBdd" TARGET="MAIN"><CODE>Cal_BddPrintBdd()</CODE></A>
+ <DD> Prints a BDD in the human readable form.
+
+ <DT> <A HREF="calAllDet.html#CalBddVarName" TARGET="MAIN"><CODE>CalBddVarName()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddNumberSharedNodes" TARGET="MAIN"><CODE>CalBddNumberSharedNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddMarkSharedNodes" TARGET="MAIN"><CODE>CalBddMarkSharedNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#Chars" TARGET="MAIN"><CODE>Chars()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddPrintTopVar" TARGET="MAIN"><CODE>BddPrintTopVar()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddPrintBddStep" TARGET="MAIN"><CODE>BddPrintBddStep()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddTerminalId" TARGET="MAIN"><CODE>BddTerminalId()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddTerminalValueAux" TARGET="MAIN"><CODE>BddTerminalValueAux()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calPrintProfile.c"><H1>calPrintProfile.c</H1></A>
+Routines for printing various profiles for a BDD. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddPrintProfile" TARGET="MAIN"><CODE>Cal_BddPrintProfile()</CODE></A>
+ <DD> Displays the node profile for f on fp. lineLength specifies 
+               the maximum line length.  varNamingFn is as in
+               Cal_BddPrintBdd.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddPrintProfileMultiple" TARGET="MAIN"><CODE>Cal_BddPrintProfileMultiple()</CODE></A>
+ <DD> Cal_BddPrintProfileMultiple is like Cal_BddPrintProfile except
+               it displays the profile for a set of BDDs
+
+ <DT> <A HREF="calAllDet.html#Cal_BddPrintFunctionProfile" TARGET="MAIN"><CODE>Cal_BddPrintFunctionProfile()</CODE></A>
+ <DD> Cal_BddPrintFunctionProfile is like Cal_BddPrintProfile except
+               it displays a function profile for f
+
+ <DT> <A HREF="calAllDet.html#Cal_BddPrintFunctionProfileMultiple" TARGET="MAIN"><CODE>Cal_BddPrintFunctionProfileMultiple()</CODE></A>
+ <DD> Cal_BddPrintFunctionProfileMultiple is like
+               Cal_BddPrintFunctionProfile except for multiple BDDs
+
+ <DT> <A HREF="calAllDet.html#CalBddPrintProfileAux" TARGET="MAIN"><CODE>CalBddPrintProfileAux()</CODE></A>
+ <DD> Prints a profile to the file given by fp.  The varNamingProc
+               is as in Cal_BddPrintBdd. lineLength gives the line width to scale
+               the profile to.
+
+ <DT> <A HREF="calAllDet.html#chars" TARGET="MAIN"><CODE>chars()</CODE></A>
+ <DD> 
+
+</DL>
+<HR>
+<A NAME="calQuant.c"><H1>calQuant.c</H1></A>
+Routines for existential/universal quantification and
+  relational product. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#None"><CODE>None</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddExists" TARGET="MAIN"><CODE>Cal_BddExists()</CODE></A>
+ <DD> Returns the result of existentially quantifying some
+  variables from the given BDD.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddRelProd" TARGET="MAIN"><CODE>Cal_BddRelProd()</CODE></A>
+ <DD> Returns the result of taking the logical AND of the
+  argument BDDs and existentially quantifying some variables from the
+  product.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddForAll" TARGET="MAIN"><CODE>Cal_BddForAll()</CODE></A>
+ <DD> Returns the result of universally quantifying some
+  variables from the given BDD.
+
+ <DT> <A HREF="calAllDet.html#CalOpExists" TARGET="MAIN"><CODE>CalOpExists()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalOpRelProd" TARGET="MAIN"><CODE>CalOpRelProd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExistsStep" TARGET="MAIN"><CODE>BddExistsStep()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddRelProdStep" TARGET="MAIN"><CODE>BddRelProdStep()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddDFStep" TARGET="MAIN"><CODE>BddDFStep()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#HashTableApply" TARGET="MAIN"><CODE>HashTableApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#HashTableReduce" TARGET="MAIN"><CODE>HashTableReduce()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExistsApply" TARGET="MAIN"><CODE>BddExistsApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExistsBFAux" TARGET="MAIN"><CODE>BddExistsBFAux()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExistsReduce" TARGET="MAIN"><CODE>BddExistsReduce()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExistsBFPlusDF" TARGET="MAIN"><CODE>BddExistsBFPlusDF()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddRelProdApply" TARGET="MAIN"><CODE>BddRelProdApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddRelProdReduce" TARGET="MAIN"><CODE>BddRelProdReduce()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddRelProdBFAux" TARGET="MAIN"><CODE>BddRelProdBFAux()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddRelProdBFPlusDF" TARGET="MAIN"><CODE>BddRelProdBFPlusDF()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calReduce.c"><H1>calReduce.c</H1></A>
+Routines for optimizing a BDD with respect to a don't
+  care set (cofactor and restrict). <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu</B><P>
+<P><B>See Also</B><A HREF="#None"><CODE>None</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddCofactor" TARGET="MAIN"><CODE>Cal_BddCofactor()</CODE></A>
+ <DD> Returns the generalized cofactor of BDD f with respect
+  to BDD c.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddReduce" TARGET="MAIN"><CODE>Cal_BddReduce()</CODE></A>
+ <DD> Returns a BDD which agrees with f for all valuations
+  which satisfy c.
+
+ <DT> <A HREF="calAllDet.html#Cal_BddBetween" TARGET="MAIN"><CODE>Cal_BddBetween()</CODE></A>
+ <DD> Returns a minimal BDD whose function contains fMin and is
+  contained in fMax.
+
+ <DT> <A HREF="calAllDet.html#CalOpCofactor" TARGET="MAIN"><CODE>CalOpCofactor()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReduceBF" TARGET="MAIN"><CODE>BddReduceBF()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddCofactorBF" TARGET="MAIN"><CODE>BddCofactorBF()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#HashTableReduceApply" TARGET="MAIN"><CODE>HashTableReduceApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#HashTableCofactorApply" TARGET="MAIN"><CODE>HashTableCofactorApply()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#HashTableCofactorReduce" TARGET="MAIN"><CODE>HashTableCofactorReduce()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calReorderBF.c"><H1>calReorderBF.c</H1></A>
+Routines for dynamic reordering of variables. <P>
+<B>By: Rajeev K. Ranjan   (rajeev@ic.eecs.berkeley.edu)
+               Wilsin Gosti (wilsin@ic.eecs.berkeley.edu)</B><P>
+This method dynamically reorders variables while
+  preserving their locality. This entails both memory and
+  computational overheads.  Conceptually and experimentally it has
+  been observed that these overheads lead to poorer performance
+  compared to the traditional reordering methods. For details, please
+  refer to the work by Rajeev K. Ranjan et al - "Dynamic variable
+  reordering in a breadth-first manipulation based package: Challenges
+  and Solutions"- Proceedings of ICCD'97. <P>
+<P><B>See Also</B><A HREF="#calReorderDF.c"><CODE>calReorderDF.c</CODE></A>
+<A HREF="#calReorderUtil.c"><CODE>calReorderUtil.c</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalBddReorderAuxBF" TARGET="MAIN"><CODE>CalBddReorderAuxBF()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderFixForwardingNodes" TARGET="MAIN"><CODE>BddReorderFixForwardingNodes()</CODE></A>
+ <DD> Fixes the forwarding nodes in a unique table.
+
+ <DT> <A HREF="calAllDet.html#BddReorderFixAndFreeForwardingNodes" TARGET="MAIN"><CODE>BddReorderFixAndFreeForwardingNodes()</CODE></A>
+ <DD> Traverses the forwarding node lists of index,
+  index+1 .. up to index+level. Frees the intermediate forwarding nodes.
+
+ <DT> <A HREF="calAllDet.html#BddReorderSwapVarIndex" TARGET="MAIN"><CODE>BddReorderSwapVarIndex()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CofactorFixAndReclaimForwardedNodes" TARGET="MAIN"><CODE>CofactorFixAndReclaimForwardedNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderFreeNodes" TARGET="MAIN"><CODE>BddReorderFreeNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#PrintBddProfileAfterReorder" TARGET="MAIN"><CODE>PrintBddProfileAfterReorder()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderVarSift" TARGET="MAIN"><CODE>BddReorderVarSift()</CODE></A>
+ <DD> Reorder variables using "sift" algorithm.
+
+ <DT> <A HREF="calAllDet.html#BddReorderSiftToBestPos" TARGET="MAIN"><CODE>BddReorderSiftToBestPos()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddSiftPerfromPhaseIV" TARGET="MAIN"><CODE>BddSiftPerfromPhaseIV()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderVarWindow" TARGET="MAIN"><CODE>BddReorderVarWindow()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderWindow2" TARGET="MAIN"><CODE>BddReorderWindow2()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderWindow3" TARGET="MAIN"><CODE>BddReorderWindow3()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calReorderDF.c"><H1>calReorderDF.c</H1></A>
+Routines for dynamic reordering of variables. <P>
+<B>By: Rajeev K. Ranjan   (rajeev@@ic. eecs.berkeley.edu)</B><P>
+This method is based on traditional dynamic reordering
+  technique found in depth-first based packages. The data structure is
+  first converted to conform to traditional one and then reordering is
+  performed. At the end the nodes are arranged back on the pages. The
+  computational overheads are in terms of converting the data
+  structure back and forth and the memory overhead due to the extra
+  space needed to arrange the nodes. This overhead can be eliminated
+  by proper implementation. For details, please refer to the work by
+  Rajeev K. Ranjan et al - "Dynamic variable reordering in a
+  breadth-first manipulation based package: Challenges and Solutions"-
+  Proceedings of ICCD'97. <P>
+<P><B>See Also</B><A HREF="#calReorderBF.c"><CODE>calReorderBF.c</CODE></A>
+<A HREF="#calReorderUtil.c"><CODE>calReorderUtil.c</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalBddReorderAuxDF" TARGET="MAIN"><CODE>CalBddReorderAuxDF()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#UniqueTableForIdFindOrAdd" TARGET="MAIN"><CODE>UniqueTableForIdFindOrAdd()</CODE></A>
+ <DD> find or add in the unique table for id.
+
+ <DT> <A HREF="calAllDet.html#HashTableAddDirect" TARGET="MAIN"><CODE>HashTableAddDirect()</CODE></A>
+ <DD> Directly insert a BDD node in the hash table.
+
+ <DT> <A HREF="calAllDet.html#HashTableFindOrAdd" TARGET="MAIN"><CODE>HashTableFindOrAdd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddConvertDataStruct" TARGET="MAIN"><CODE>BddConvertDataStruct()</CODE></A>
+ <DD> Changes the data structure of the bdd nodes.
+
+ <DT> <A HREF="calAllDet.html#BddConvertDataStructBack" TARGET="MAIN"><CODE>BddConvertDataStructBack()</CODE></A>
+ <DD> Changes the data structure of the bdd nodes to
+  the original one.
+
+ <DT> <A HREF="calAllDet.html#BddReallocateNodesInPlace" TARGET="MAIN"><CODE>BddReallocateNodesInPlace()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalAlignCollisionChains" TARGET="MAIN"><CODE>CalAlignCollisionChains()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReallocateNodes" TARGET="MAIN"><CODE>BddReallocateNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExchangeAux" TARGET="MAIN"><CODE>BddExchangeAux()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CheckValidityOfNodes" TARGET="MAIN"><CODE>CheckValidityOfNodes()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#SweepVarTable" TARGET="MAIN"><CODE>SweepVarTable()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExchange" TARGET="MAIN"><CODE>BddExchange()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddExchangeVarBlocks" TARGET="MAIN"><CODE>BddExchangeVarBlocks()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderWindow2" TARGET="MAIN"><CODE>BddReorderWindow2()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderWindow3" TARGET="MAIN"><CODE>BddReorderWindow3()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderStableWindow3Aux" TARGET="MAIN"><CODE>BddReorderStableWindow3Aux()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderStableWindow3" TARGET="MAIN"><CODE>BddReorderStableWindow3()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddSiftBlock" TARGET="MAIN"><CODE>BddSiftBlock()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddReorderSiftAux" TARGET="MAIN"><CODE>BddReorderSiftAux()</CODE></A>
+ <DD> Reorder variables using "sift" algorithm.
+
+ <DT> <A HREF="calAllDet.html#BddReorderSift" TARGET="MAIN"><CODE>BddReorderSift()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddAddInternalReferences" TARGET="MAIN"><CODE>BddAddInternalReferences()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#BddNukeInternalReferences" TARGET="MAIN"><CODE>BddNukeInternalReferences()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CeilLog2" TARGET="MAIN"><CODE>CeilLog2()</CODE></A>
+ <DD> Returns the smallest integer greater than or equal to log2 of a
+  number
+
+</DL>
+<HR>
+<A NAME="calReorderUtil.c"><H1>calReorderUtil.c</H1></A>
+Some utility routines used by both breadth-first and
+  depth-first reordering techniques. <P>
+<B>By: Rajeev K. Ranjan   (rajeev@ic.eecs.berkeley.edu)
+               Wilsin Gosti (wilsin@ic.eecs.berkeley.edu)</B><P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalBddReorderFixUserBddPtrs" TARGET="MAIN"><CODE>CalBddReorderFixUserBddPtrs()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckAllValidity" TARGET="MAIN"><CODE>CalCheckAllValidity()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckValidityOfNodesForId" TARGET="MAIN"><CODE>CalCheckValidityOfNodesForId()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckValidityOfNodesForWindow" TARGET="MAIN"><CODE>CalCheckValidityOfNodesForWindow()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckValidityOfANode" TARGET="MAIN"><CODE>CalCheckValidityOfANode()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckRefCountValidity" TARGET="MAIN"><CODE>CalCheckRefCountValidity()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalCheckAssoc" TARGET="MAIN"><CODE>CalCheckAssoc()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalFixupAssoc" TARGET="MAIN"><CODE>CalFixupAssoc()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddReorderFixCofactors" TARGET="MAIN"><CODE>CalBddReorderFixCofactors()</CODE></A>
+ <DD> Fixes the cofactors of the nodes belonging to
+  the given index.
+
+ <DT> <A HREF="calAllDet.html#CalBddReorderReclaimForwardedNodes" TARGET="MAIN"><CODE>CalBddReorderReclaimForwardedNodes()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calTerminal.c"><H1>calTerminal.c</H1></A>
+Contains the terminal function for various BDD operations. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu</B><P>
+<DL>
+ <DT> <A HREF="calAllDet.html#CalOpAnd" TARGET="MAIN"><CODE>CalOpAnd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalOpNand" TARGET="MAIN"><CODE>CalOpNand()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalOpOr" TARGET="MAIN"><CODE>CalOpOr()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalOpXor" TARGET="MAIN"><CODE>CalOpXor()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalOpITE" TARGET="MAIN"><CODE>CalOpITE()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calTest.c"><H1>calTest.c</H1></A>
+This file contains the test routines for the CAL package. <P>
+<B>By: Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi  (sanghavi@eecs.berkeley.edu)
+               Modified and extended from the original version written
+               by David Long.</B><P>
+optional <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#main" TARGET="MAIN"><CODE>main()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#asDouble" TARGET="MAIN"><CODE>asDouble()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#asAddress" TARGET="MAIN"><CODE>asAddress()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#terminalIdFn" TARGET="MAIN"><CODE>terminalIdFn()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#PrintBdd" TARGET="MAIN"><CODE>PrintBdd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#Error" TARGET="MAIN"><CODE>Error()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#Cofactor" TARGET="MAIN"><CODE>Cofactor()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#Decode" TARGET="MAIN"><CODE>Decode()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestAnd" TARGET="MAIN"><CODE>TestAnd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestNand" TARGET="MAIN"><CODE>TestNand()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestOr" TARGET="MAIN"><CODE>TestOr()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestITE" TARGET="MAIN"><CODE>TestITE()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestXor" TARGET="MAIN"><CODE>TestXor()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestIdNot" TARGET="MAIN"><CODE>TestIdNot()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestCompose" TARGET="MAIN"><CODE>TestCompose()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestSubstitute" TARGET="MAIN"><CODE>TestSubstitute()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestVarSubstitute" TARGET="MAIN"><CODE>TestVarSubstitute()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestSwapVars" TARGET="MAIN"><CODE>TestSwapVars()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestMultiwayAnd" TARGET="MAIN"><CODE>TestMultiwayAnd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestMultiwayOr" TARGET="MAIN"><CODE>TestMultiwayOr()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestMultiwayLarge" TARGET="MAIN"><CODE>TestMultiwayLarge()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestArrayOp" TARGET="MAIN"><CODE>TestArrayOp()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestInterImpl" TARGET="MAIN"><CODE>TestInterImpl()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestQnt" TARGET="MAIN"><CODE>TestQnt()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestAssoc" TARGET="MAIN"><CODE>TestAssoc()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestRelProd" TARGET="MAIN"><CODE>TestRelProd()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestReduce" TARGET="MAIN"><CODE>TestReduce()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestGenCof" TARGET="MAIN"><CODE>TestGenCof()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestSize" TARGET="MAIN"><CODE>TestSize()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestSatisfy" TARGET="MAIN"><CODE>TestSatisfy()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestPipeline" TARGET="MAIN"><CODE>TestPipeline()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestDump" TARGET="MAIN"><CODE>TestDump()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestReorderBlock" TARGET="MAIN"><CODE>TestReorderBlock()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#TestReorder" TARGET="MAIN"><CODE>TestReorder()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#handler" TARGET="MAIN"><CODE>handler()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#RandomTests" TARGET="MAIN"><CODE>RandomTests()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+<A NAME="calUtil.c"><H1>calUtil.c</H1></A>
+Utility functions for the Cal package. <P>
+<B>By: Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev K. Ranjan   (rajeev@eecs.berkeley.edu)</B><P>
+Utility functions used in the Cal package. <P>
+<P><B>See Also</B><A HREF="#optional"><CODE>optional</CODE></A>
+<DL>
+ <DT> <A HREF="calAllDet.html#Cal_BddFunctionPrint" TARGET="MAIN"><CODE>Cal_BddFunctionPrint()</CODE></A>
+ <DD> Prints the function implemented by the argument BDD
+
+ <DT> <A HREF="calAllDet.html#CalUniqueTablePrint" TARGET="MAIN"><CODE>CalUniqueTablePrint()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddFunctionPrint" TARGET="MAIN"><CODE>CalBddFunctionPrint()</CODE></A>
+ <DD> Prints the function implemented by the argument BDD
+
+ <DT> <A HREF="calAllDet.html#CalBddPreProcessing" TARGET="MAIN"><CODE>CalBddPreProcessing()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddPostProcessing" TARGET="MAIN"><CODE>CalBddPostProcessing()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddArrayPreProcessing" TARGET="MAIN"><CODE>CalBddArrayPreProcessing()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddGetInternalBdd" TARGET="MAIN"><CODE>CalBddGetInternalBdd()</CODE></A>
+ <DD> Prints fatal message and exits.
+
+ <DT> <A HREF="calAllDet.html#CalBddGetExternalBdd" TARGET="MAIN"><CODE>CalBddGetExternalBdd()</CODE></A>
+ <DD> Prints fatal message and exits.
+
+ <DT> <A HREF="calAllDet.html#CalBddFatalMessage" TARGET="MAIN"><CODE>CalBddFatalMessage()</CODE></A>
+ <DD> Prints fatal message and exits.
+
+ <DT> <A HREF="calAllDet.html#CalBddWarningMessage" TARGET="MAIN"><CODE>CalBddWarningMessage()</CODE></A>
+ <DD> Prints warning message.
+
+ <DT> <A HREF="calAllDet.html#CalBddNodePrint" TARGET="MAIN"><CODE>CalBddNodePrint()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalBddPrint" TARGET="MAIN"><CODE>CalBddPrint()</CODE></A>
+ <DD> required
+
+ <DT> <A HREF="calAllDet.html#CalHashTablePrint" TARGET="MAIN"><CODE>CalHashTablePrint()</CODE></A>
+ <DD> Prints a hash table.
+
+ <DT> <A HREF="calAllDet.html#CalHashTableOnePrint" TARGET="MAIN"><CODE>CalHashTableOnePrint()</CODE></A>
+ <DD> required
+
+</DL>
+<HR>
+Last updated on 970711 20h11
+</BODY></HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calApplyReduce.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calApplyReduce.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calApplyReduce.c	(revision 8)
@@ -0,0 +1,224 @@
+/**CFile***********************************************************************
+
+  FileName    [calApplyReduce.c]
+
+  PackageName [cal]
+
+  Synopsis    [Generic routines for processing temporary nodes during
+  "apply" and "reduce" phases.]
+
+  Description []
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calApplyReduce.c,v 1.1.1.3 1998/05/04 00:58:49 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableApply(Cal_BddManager_t * bddManager, CalHashTable_t *
+                  hashTable, CalHashTable_t ** reqQueAtPipeDepth, CalOpProc_t
+                  calOpProc) 
+{
+  int i, numBins;
+  CalBddNode_t **bins = 0;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t fx, gx, fxbar, gxbar, result;
+  Cal_BddId_t bddId;
+
+  numBins = hashTable->numBins;
+  bins = hashTable->bins;
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      /* Process the requestNode */
+      CalRequestNodeGetCofactors(bddManager, requestNode, fx, fxbar, gx, gxbar);
+      Cal_Assert(((CalAddress_t)(fx.bddNode)) & ~0xf);
+      Cal_Assert(((CalAddress_t)(gx.bddNode)) & ~0xf);
+      Cal_Assert(((CalAddress_t)(fxbar.bddNode)) & ~0xf);
+      Cal_Assert(((CalAddress_t)(gxbar.bddNode)) & ~0xf);
+      if((*calOpProc)(bddManager, fx, gx, &result) == 0){
+        CalBddNormalize(fx, gx);
+        CalBddGetMinId2(bddManager, fx, gx, bddId);
+        CalHashTableFindOrAdd(reqQueAtPipeDepth[bddId], fx, gx, &result);
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutThenRequest(requestNode, result);
+      if((*calOpProc)(bddManager, fxbar, gxbar, &result) == 0){
+        CalBddNormalize(fxbar, gxbar);
+        CalBddGetMinId2(bddManager, fxbar, gxbar, bddId);
+        CalHashTableFindOrAdd(reqQueAtPipeDepth[bddId], fxbar, gxbar, &result);
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableReduce(Cal_BddManager_t * bddManager,
+                   CalHashTable_t * hashTable,
+                   CalHashTable_t * uniqueTableForId)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  Cal_BddId_t currentBddId = uniqueTableForId->bddId;
+  CalNodeManager_t *nodeManager = uniqueTableForId->nodeManager;
+  CalRequestNode_t *requestNode, *next;
+  CalBddNode_t *bddNode, *endNode;
+  Cal_Bdd_t thenBdd, elseBdd, result;
+  Cal_BddRefCount_t refCount;
+
+  endNode = hashTable->endNode;
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = next){
+      next = CalRequestNodeGetNextRequestNode(requestNode);
+      /* Process the requestNode */
+      CalRequestNodeGetThenRequest(requestNode, thenBdd);
+      CalRequestNodeGetElseRequest(requestNode, elseBdd);
+      CalRequestIsForwardedTo(thenBdd);
+      CalRequestIsForwardedTo(elseBdd);
+      if(CalBddIsEqual(thenBdd, elseBdd)){
+        CalRequestNodeGetRefCount(requestNode, refCount);
+        CalRequestAddRefCount(thenBdd, refCount - 2);
+        CalRequestNodePutThenRequest(requestNode, thenBdd);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+      else
+        if(CalUniqueTableForIdLookup(bddManager, uniqueTableForId,
+          thenBdd, elseBdd, &result) == 1){
+        CalBddDcrRefCount(thenBdd);
+        CalBddDcrRefCount(elseBdd);
+        CalRequestNodeGetRefCount(requestNode, refCount);
+        CalBddAddRefCount(result, refCount);
+        CalRequestNodePutThenRequest(requestNode, result);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+      else if(CalBddIsOutPos(thenBdd)){
+        CalRequestNodePutThenRequest(requestNode, thenBdd);
+        CalRequestNodePutElseRequest(requestNode, elseBdd);
+        CalHashTableAddDirect(uniqueTableForId, requestNode);
+        bddManager->numNodes++;
+        bddManager->gcCheck--;
+      }
+      else{
+        CalNodeManagerAllocNode(nodeManager, bddNode);
+        CalBddNodePutThenBddId(bddNode, CalBddGetBddId(thenBdd));
+        CalBddNodePutThenBddNode(bddNode, CalBddGetBddNodeNot(thenBdd));
+        CalBddNodePutElseBddId(bddNode, CalBddGetBddId(elseBdd));
+        CalBddNodePutElseBddNode(bddNode, CalBddGetBddNodeNot(elseBdd));
+        CalRequestNodeGetRefCount(requestNode, refCount);
+        CalBddNodePutRefCount(bddNode, refCount);
+        CalHashTableAddDirect(uniqueTableForId, bddNode);
+        bddManager->numNodes++;
+        bddManager->gcCheck--;
+        CalRequestNodePutThenRequestId(requestNode, currentBddId);
+        CalRequestNodePutThenRequestNode(requestNode, CalBddNodeNot(bddNode));
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+    }
+  }
+  memset((char *)bins, 0, hashTable->numBins * sizeof(CalBddNode_t *));
+  hashTable->endNode = endNode;
+}
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+  
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calAssociation.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calAssociation.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calAssociation.c	(revision 8)
@@ -0,0 +1,601 @@
+/**CFile***********************************************************************
+
+  FileName    [calAssociation.c]
+
+  PackageName [cal]
+
+  Synopsis    [Contains the routines related to the variable association.]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi  (sanghavi@eecs.berkeley.edu)
+               ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calAssociation.c,v 1.1.1.3 1998/05/04 00:58:50 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int AssociationIsEqual(Cal_BddManager_t * bddManager, Cal_Bdd_t * p, Cal_Bdd_t * q);
+static int CheckAssoc(Cal_BddManager_t *bddManager, Cal_Bdd *assocInfo, int pairs);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Creates or finds a variable association.]
+
+  Description [Creates or finds a variable association. The association is
+  specified by associationInfo, which is a an array of BDD with 
+  Cal_BddNull(bddManager) as the end marker. If pairs is 0, the array is
+  assumed to be an array of variables. In this case, each variable is paired
+  with constant BDD one. Such an association may viewed as specifying a set
+  of variables for use with routines such as Cal_BddExists. If pair is not 0,
+  then the even numbered array elements should be variables and the odd numbered
+  elements should be the BDDs which they are mapped to. In both cases, the 
+  return value is an integer identifier for this association. If the given
+  association is equivalent to one which already exists, the same identifier
+  is used for both, and the reference count of the association is increased by
+  one.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_AssociationQuit]
+
+******************************************************************************/
+int
+Cal_AssociationInit(Cal_BddManager bddManager,
+                    Cal_Bdd *associationInfoUserBdds,
+                    int  pairs)
+{
+  int i, numAssociations;
+  CalAssociation_t *p, **q;
+  Cal_Bdd_t f;
+  Cal_Bdd_t *varAssociation;
+  Cal_BddId_t j;
+  long last;
+  Cal_Bdd_t *associationInfo;
+  
+  if (!CheckAssoc(bddManager, associationInfoUserBdds, pairs)){
+    return (-1);
+  }
+
+
+/* First count the number of elements */
+  for (i=0; associationInfoUserBdds[i]; i++);
+  if (pairs)  numAssociations = i/2;
+  else numAssociations = i;
+  associationInfo = Cal_MemAlloc(Cal_Bdd_t, i+1);
+  for (j=0; j < i; j++){
+    associationInfo[j] =
+        CalBddGetInternalBdd(bddManager,associationInfoUserBdds[j]);
+  }
+  associationInfo[j] = bddManager->bddNull;
+
+  
+  varAssociation = Cal_MemAlloc(Cal_Bdd_t, bddManager->maxNumVars+1);
+  for(i = 0; i <= bddManager->maxNumVars; i++){
+    varAssociation[i] = bddManager->bddNull;
+  }
+
+  
+  if(pairs){
+    for(i = 0; i < numAssociations; i++){
+      f = associationInfo[(i<<1)];
+      varAssociation[CalBddGetBddId(f)] = associationInfo[(i<<1)+1];
+    }
+  }
+  else{
+    for(i = 0; i < numAssociations; i++){
+      f=associationInfo[i];
+      varAssociation[CalBddGetBddId(f)] = CalBddOne(bddManager);
+    }
+  }
+  /* Check for existence. */
+  for(p = bddManager->associationList; p; p = p->next){
+    if(AssociationIsEqual(bddManager, p->varAssociation, varAssociation)){
+	Cal_MemFree(varAssociation);
+    Cal_MemFree(associationInfo);
+	p->refCount++;
+	return (p->id);
+    }
+  }
+  /* Find the first unused id. */
+  for(q = &bddManager->associationList, p = *q, i = 0;
+      p && p->id == i; q = &p->next, p = *q, ++i){
+  }
+  /*p = Cal_MemAlloc(CalAssociation_t, 1);*/
+  /*p = CAL_BDD_NEW_REC(bddManager, CalAssociation_t);*/
+  p = Cal_MemAlloc(CalAssociation_t, 1);
+  p->id = i;
+  p->next = *q;
+  *q = p;
+  p->varAssociation = varAssociation;
+  last = -1;
+  if(pairs){
+    for(i = 0; i < numAssociations; i++){
+      f = associationInfo[(i<<1)];
+      j = CalBddGetBddIndex(bddManager, f);
+      if((long)j > last){
+	  last = j;
+      }
+    }
+  }
+  else{
+    for(i = 0; i < numAssociations; i++){
+      f = associationInfo[i];
+      j = CalBddGetBddIndex(bddManager, f);
+      if((long)j > last){
+	  last = j;
+      }
+    }
+  }
+  p->lastBddIndex = last;
+  p->refCount = 1;
+  /* Protect BDDs in the association. */
+  if(pairs){
+    for(i = 0; i < numAssociations; i++){
+      f = associationInfo[(i<<1)+1];
+      CalBddIcrRefCount(f);
+    }
+  }
+  Cal_MemFree(associationInfo);
+  return p->id;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes the variable association given by id]
+
+  Description [Decrements the reference count of the variable association with
+  identifier id, and frees it if the reference count becomes zero.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_AssociationInit]
+
+******************************************************************************/
+void
+Cal_AssociationQuit(Cal_BddManager bddManager, int  associationId)
+{
+  Cal_BddId_t i;
+  Cal_Bdd_t f;
+  CalAssociation_t *p, **q;
+
+  if(bddManager->currentAssociation->id == associationId){
+    bddManager->currentAssociation = bddManager->tempAssociation;
+  }
+  for(q = &bddManager->associationList, p = *q; p; q = &p->next, p = *q){
+    if(p->id == associationId){
+      p->refCount--;
+      if(!p->refCount){
+        /* Unprotect the BDDs in the association. */
+        for(i = 1; i <= bddManager->numVars; i++){
+          f = p->varAssociation[i];
+          if(!CalBddIsBddNull(bddManager, f)){
+            CalBddDcrRefCount(f);
+          }
+        }
+        *q = p->next;
+        Cal_MemFree(p->varAssociation);
+        /*CAL_BDD_FREE_REC(bddManager, p, CalAssociation_t);*/
+        Cal_MemFree(p);
+        CalCacheTableTwoFlushAssociationId(bddManager, associationId);
+      }
+      return;
+    }
+  }
+  CalBddWarningMessage("Cal_AssociationQuit: no association with specified ID");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the current variable association to the one given by id and
+  returns the ID of the old association.]
+
+  Description [Sets the current variable association to the one given by id and
+  returns the ID of the old association.  An id of -1 indicates the temporary
+  association]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+Cal_AssociationSetCurrent(Cal_BddManager bddManager, int  associationId)
+{
+  int oldAssociationId;
+  CalAssociation_t *p;
+
+  oldAssociationId = bddManager->currentAssociation->id;
+  if(associationId != -1){
+    for(p = bddManager->associationList; p; p = p->next){
+      if(p->id == associationId){
+        bddManager->currentAssociation = p;
+        return (oldAssociationId);
+      }
+    }
+    CalBddWarningMessage(
+        "Cal_AssociationSetCurrent: no variable association with specified ID.\n May have been discarded during dynamic reordering.");
+  }
+  bddManager->currentAssociation = bddManager->tempAssociation;
+  return oldAssociationId;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds to the temporary variable association.]
+
+  Description [Pairs is 0 if the information represents only a list of
+  variables rather than a full association.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cal_TempAssociationAugment(Cal_BddManager bddManager,
+                           Cal_Bdd *associationInfoUserBdds,
+                           int  pairs)
+{
+  int i, j, numAssociations;
+  Cal_Bdd_t f;
+  long last;
+  Cal_Bdd_t *associationInfo;
+  
+  if (CheckAssoc(bddManager, associationInfoUserBdds, pairs) == 0) {
+    return;
+  }
+
+  /*while (associationInfoUserBdds[i++]);*/
+  for (i=0; associationInfoUserBdds[i]; i++);
+  if (pairs) numAssociations = i/2;
+  else numAssociations = i;
+  associationInfo = Cal_MemAlloc(Cal_Bdd_t, i+1);
+  for (j=0; j < i; j++){
+    associationInfo[j] =
+        CalBddGetInternalBdd(bddManager,associationInfoUserBdds[j]);
+  }
+  associationInfo[j] = bddManager->bddNull;
+  
+  last = bddManager->tempAssociation->lastBddIndex;
+  if(pairs){
+    for(i = 0; i < numAssociations; i++){
+      f = associationInfo[(i<<1)];
+      j = CalBddGetBddId(f);
+      if(bddManager->idToIndex[j] > last){
+        last = bddManager->idToIndex[j];
+      }
+      f = bddManager->tempAssociation->varAssociation[j];
+      if(!CalBddIsBddNull(bddManager, f)){
+        CalBddDcrRefCount(f);
+      }
+      f = associationInfo[(i<<1)+1];
+      bddManager->tempAssociation->varAssociation[j] = f;
+      /* Protect BDDs in the association. */
+      CalBddIcrRefCount(f);
+    }
+  }
+  else{
+    for(i = 0; i < numAssociations; i++){
+      f = associationInfo[i];
+      j = CalBddGetBddId(f);
+      if(bddManager->idToIndex[j] > last){
+        last = bddManager->idToIndex[j];
+      }
+      f = bddManager->tempAssociation->varAssociation[j];
+      if(!CalBddIsBddNull(bddManager, f)){
+        CalBddDcrRefCount(f);
+      }
+      bddManager->tempAssociation->varAssociation[j] = CalBddOne(bddManager);
+    } 
+  }
+  bddManager->tempAssociation->lastBddIndex = last;
+  Cal_MemFree(associationInfo);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the temporary variable association.]
+  
+  Description [Pairs is 0 if the information represents only a list of
+  variables rather than a full association.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cal_TempAssociationInit(Cal_BddManager bddManager,
+                        Cal_Bdd *associationInfoUserBdds,
+                        int  pairs)
+{
+  long i;
+  Cal_Bdd_t f;
+
+  /* Clean up old temporary association. */
+  for(i = 1; i <= bddManager->numVars; i++){
+    f = bddManager->tempAssociation->varAssociation[i];
+    if(!CalBddIsBddNull(bddManager, f)){
+      CalBddDcrRefCount(f);
+      bddManager->tempAssociation->varAssociation[i] = bddManager->bddNull;
+    }
+  }
+  bddManager->tempAssociation->lastBddIndex = -1;
+  Cal_TempAssociationAugment(bddManager, associationInfoUserBdds, pairs);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Cleans up temporary association]
+
+  Description [Cleans up temporary associationoptional]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cal_TempAssociationQuit(Cal_BddManager bddManager)
+{
+  int i;
+  Cal_Bdd_t f;
+
+  /* Clean up old temporary association. */
+  for(i = 1; i <= bddManager->numVars; i++){
+    f = bddManager->tempAssociation->varAssociation[i];
+    if(!CalBddIsBddNull(bddManager, f)){
+      CalBddDcrRefCount(f);
+      bddManager->tempAssociation->varAssociation[i] = bddManager->bddNull;
+    }
+  }
+  bddManager->tempAssociation->lastBddIndex = -1;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Frees the variable associations]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalAssociationListFree(Cal_BddManager_t *  bddManager)
+{
+  CalAssociation_t *assoc, *nextAssoc;
+  
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    Cal_MemFree(assoc->varAssociation);
+    /*CAL_BDD_FREE_REC(bddManager, assoc, CalAssociation_t);*/
+    Cal_MemFree(assoc);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Need to be called after repacking.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalVarAssociationRepackUpdate(Cal_BddManager_t *  bddManager,
+                              Cal_BddId_t id)
+{
+  CalAssociation_t *assoc, *nextAssoc;
+  int i;
+  
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    for (i=1; i <= bddManager->numVars; i++){
+      if (CalBddGetBddId(assoc->varAssociation[i]) == id){
+        CalBddForward(assoc->varAssociation[i]);
+      }
+    }
+  }
+  /* fix temporary association */
+  assoc = bddManager->tempAssociation;
+  for (i=1; i <= bddManager->numVars; i++){
+    if (CalBddGetBddId(assoc->varAssociation[i]) == id){
+      CalBddForward(assoc->varAssociation[i]);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the validity of association.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalCheckAssociationValidity(Cal_BddManager_t *  bddManager)
+{
+  CalAssociation_t *assoc, *nextAssoc;
+  int i;
+  
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    for (i=1; i <= bddManager->numVars; i++){
+      Cal_Assert(CalBddIsForwarded(assoc->varAssociation[i]) == 0);
+    }
+  }
+  /* temporary association */
+  assoc = bddManager->tempAssociation;
+  for (i=1; i <= bddManager->numVars; i++){
+    Cal_Assert(CalBddIsForwarded(assoc->varAssociation[i]) == 0);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalReorderAssociationFix(Cal_BddManager_t *bddManager)
+{
+  CalAssociation_t *assoc, *nextAssoc;
+  int i;
+  
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    for (i=1; i <= bddManager->numVars; i++){
+        if (CalBddGetBddId(assoc->varAssociation[i]) != CAL_BDD_NULL_ID){
+            CalBddIsForwardedTo(assoc->varAssociation[i]);
+        }
+    }
+  }
+  /* fix temporary association */
+  assoc = bddManager->tempAssociation;
+  for (i=1; i <= bddManager->numVars; i++){
+      if (CalBddGetBddId(assoc->varAssociation[i]) != CAL_BDD_NULL_ID){
+          CalBddIsForwardedTo(assoc->varAssociation[i]);
+      }
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for equality of two associations]
+
+  Description [Checks for equality of two associations]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+AssociationIsEqual(Cal_BddManager_t * bddManager,
+                   Cal_Bdd_t * p,
+                   Cal_Bdd_t * q)
+{
+  int i;
+  for(i = 1; i <= bddManager->maxNumVars; i++){
+    if(CalBddIsEqual(p[i], q[i]) == 0){
+      return (0);
+    }
+  }
+  return (1);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static int
+CheckAssoc(Cal_BddManager_t *bddManager, Cal_Bdd *assocInfo, int pairs)
+{
+  CalBddArrayPreProcessing(bddManager, assocInfo);
+  if (pairs){
+    while (assocInfo[0] && assocInfo[1]){
+      if (CalBddTypeAux(bddManager,
+                        CalBddGetInternalBdd(bddManager, assocInfo[0])) !=
+          CAL_BDD_TYPE_POSVAR){  
+	    CalBddWarningMessage("CheckAssoc: first element in pair is not a positive variable"); 
+	    return (0);
+	  }
+      assocInfo+=2;
+    }
+  }
+  return (1);
+}
+
Index: /vis_dev/glu-2.1/src/calBdd/calBdd.make
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBdd.make	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBdd.make	(revision 8)
@@ -0,0 +1,21 @@
+CSRC_cal += 	cal.c calBddOp.c calBddManager.c calMemoryManagement.c\
+		calHashTable.c calUtil.c calGC.c \
+            	calTerminal.c calAssociation.c \
+            	calBddSubstitute.c calReduce.c calQuant.c \
+                calBddSwapVars.c calBddSatisfy.c calBddSize.c \
+                calBddSupport.c calPrint.c calPrintProfile.c calDump.c\
+		calHashTableOne.c calPipeline.c calPerformanceTest.c \
+                calHashTableThree.c calBddITE.c calBddCompose.c\
+		calCacheTableTwo.c calApplyReduce.c calBlk.c \
+		calReorderBF.c calReorderDF.c calInteract.c\
+		calBddVarSubstitute.c calReorderUtil.c calMem.c
+
+HEADERS_cal += cal.h calInt.h calMem.h
+
+MISC += calBddReorderTest.c calPerformanceTest.c calTest.c\
+	calAllAbs.html  calAllByFile.html calAllByFunc.html\
+	calAllDet.html  calAllFile.html calDesc.html\
+ 	calExt.html calExtAbs.html calExtDet.html calTitle.html credit.html\
+ 	calDoc.txt
+
+DEPENDENCYFILES = $(CSRC_cal)
Index: /vis_dev/glu-2.1/src/calBdd/calBddCompose.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddCompose.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddCompose.c	(revision 8)
@@ -0,0 +1,334 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddCompose.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routine for composing one BDD into another.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddCompose.c,v 1.1.1.3 1998/05/04 00:58:50 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [composition - substitute a BDD variable by a function]
+
+  Description [Returns the BDD obtained by substituting a variable by a function]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddCompose(Cal_BddManager bddManager, Cal_Bdd  fUserBdd,
+               Cal_Bdd  gUserBdd, Cal_Bdd hUserBdd)
+{
+  Cal_Bdd_t result;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t F, G, H;
+  
+  if (CalBddPreProcessing(bddManager, 3, fUserBdd, gUserBdd, hUserBdd) == 0){
+    result = bddManager->bddNull;
+  }
+  F = CalBddGetInternalBdd(bddManager, fUserBdd);
+  G = CalBddGetInternalBdd(bddManager, gUserBdd);
+  H = CalBddGetInternalBdd(bddManager, hUserBdd);
+
+  if(CalBddIsBddConst(G)){
+    CalBddNodeIcrRefCount(fUserBdd);
+    return fUserBdd;
+  }
+  CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], requestNode);
+  CalRequestNodePutF(requestNode, F);
+  CalRequestNodePutG(requestNode, H);
+  CalRequestNodePutNextRequestNode(requestNode, 0);
+  bddManager->requestNodeListArray[0] = requestNode;
+  /*
+  ** We can achieve a superscalar compose operation, provided G
+  ** is the same for all the compose operation 
+  */
+
+  CalRequestNodeListCompose(bddManager, bddManager->requestNodeListArray[0],
+      CalBddGetBddIndex(bddManager, G));
+
+  CalRequestNodeGetThenRequest(requestNode, result);
+  CalNodeManagerFreeNode(bddManager->nodeManagerArray[0], requestNode);
+  bddManager->requestNodeListArray[0] = Cal_Nil(CalRequestNode_t);
+
+  return CalBddGetExternalBdd(bddManager, result);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+  note        [THERE IS A POSSIBILITY OF HAVING A PIPELINED VERSION
+               NEED TO THINK IT THROUGH]
+
+******************************************************************************/
+void
+CalRequestNodeListCompose(Cal_BddManager_t * bddManager,
+                          CalRequestNode_t * requestNodeList,
+                          Cal_BddIndex_t  composeIndex)
+{
+  CalRequestNode_t *requestNode;
+  CalRequest_t F, H, result;
+  int bddId, bddIndex;
+  CalHashTable_t *hashTable, *uniqueTableForId;
+  CalHashTable_t **reqQueForCompose = bddManager->reqQue[0];
+  CalHashTable_t **reqQueForITE = bddManager->reqQue[1]; 
+  
+  /* ReqQueForComposeInsertUsingReqList */
+  for(requestNode = requestNodeList;
+      requestNode != Cal_Nil(CalRequestNode_t);
+      requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+    CalRequestNodeGetF(requestNode, F);
+    CalRequestNodeGetG(requestNode, H);
+    CalComposeRequestCreate(bddManager, F, H, composeIndex, 
+        reqQueForCompose, reqQueForITE, &result);
+    CalRequestNodePutThenRequest(requestNode, result);
+    CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+  }
+
+  /* ReqQueApply */
+  for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = reqQueForCompose[bddId];
+    if(hashTable->numEntries){
+      CalHashTableComposeApply(bddManager, hashTable, composeIndex, 
+          reqQueForCompose, reqQueForITE);
+    }
+    hashTable = reqQueForITE[bddId];
+    if(hashTable->numEntries){
+      CalHashTableITEApply(bddManager, hashTable, reqQueForITE);
+    }
+  }
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= 0; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = reqQueForCompose[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+    hashTable = reqQueForITE[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+  }
+
+  /* ReqListArrayReqForward */
+  for(requestNode = requestNodeList; requestNode != Cal_Nil(CalRequestNode_t);
+      requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+    CalRequestNodeGetThenRequest(requestNode, result);
+    CalRequestIsForwardedTo(result);
+    CalRequestNodePutThenRequest(requestNode, result);
+  }
+
+  /* ReqQueCleanUp */
+  for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+    CalHashTableCleanUp(reqQueForCompose[bddId]);
+    CalHashTableCleanUp(reqQueForITE[bddId]);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableComposeApply(Cal_BddManager_t *bddManager,
+                         CalHashTable_t *hashTable,
+                         Cal_BddIndex_t  gIndex,
+                         CalHashTable_t **reqQueForCompose,
+                         CalHashTable_t **reqQueForITE)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t fx, fxbar;
+  Cal_Bdd_t hx, hxbar;
+  Cal_Bdd_t calBdd1, calBdd2, calBdd3;
+  Cal_Bdd_t result;
+  Cal_BddId_t bddId;
+  Cal_BddIndex_t index;
+  
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+
+      /* Process the requestNode */
+      CalRequestNodeGetCofactors(bddManager, requestNode, fx, fxbar, hx, hxbar);
+
+      /* Process left cofactor */
+      index = CalBddGetBddIndex(bddManager, fx);
+      if(index > gIndex){
+        CalBddIcrRefCount(fx);
+        CalRequestNodePutThenRequest(requestNode, fx);
+      }
+      else if(index < gIndex){
+        CalBddGetMinId2(bddManager, fx, hx, bddId);
+        CalHashTableFindOrAdd(reqQueForCompose[bddId], fx, hx, &result);
+        CalBddIcrRefCount(result);
+        CalRequestNodePutThenRequest(requestNode, result);
+      }
+      else{
+        /* fxIndex == gIndex */
+        /* RequestNodeThen = ITE(hx, fxThen, fxElse) */
+        calBdd1 = hx;
+        CalBddGetThenBdd(fx, calBdd2);
+        CalBddGetElseBdd(fx, calBdd3);
+	result = CalOpITE(bddManager, calBdd1, calBdd2, calBdd3, reqQueForITE);
+        CalBddIcrRefCount(result);
+        CalRequestNodePutThenRequest(requestNode, result);
+      }
+
+      /* Process right cofactor */
+      index = CalBddGetBddIndex(bddManager, fxbar);
+      if(index > gIndex){
+        CalBddIcrRefCount(fxbar);
+        CalRequestNodePutElseRequest(requestNode, fxbar);
+      }
+      else if(index < gIndex){
+        CalBddGetMinId2(bddManager, fxbar, hxbar, bddId);
+        CalHashTableFindOrAdd(reqQueForCompose[bddId], fxbar, hxbar, &result);
+        CalBddIcrRefCount(result);
+        CalRequestNodePutElseRequest(requestNode, result);
+      }
+      else{
+        /* fxbarIndex == gIndex */
+        /* RequestNodeElse = ITE(hxbar, fxbarThen, fxbarElse) */
+        calBdd1 = hxbar;
+        CalBddGetThenBdd(fxbar, calBdd2);
+        CalBddGetElseBdd(fxbar, calBdd3);
+        result = CalOpITE(bddManager, calBdd1, calBdd2, calBdd3, reqQueForITE);
+        CalBddIcrRefCount(result);
+        CalRequestNodePutElseRequest(requestNode, result);
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalComposeRequestCreate(Cal_BddManager_t * bddManager,
+                        Cal_Bdd_t  f,
+                        Cal_Bdd_t  h,
+                        Cal_BddIndex_t  composeIndex,
+                        CalHashTable_t **reqQueForCompose,
+                        CalHashTable_t **reqQueForITE,
+                        Cal_Bdd_t *resultPtr)
+{
+  Cal_BddIndex_t index;
+  Cal_BddId_t bddId;
+
+  index = CalBddGetBddIndex(bddManager, f);
+  if(index > composeIndex){
+    *resultPtr = f;
+  }
+  else if(index < composeIndex){
+    CalBddGetMinId2(bddManager, f, h, bddId);
+    CalHashTableFindOrAdd(reqQueForCompose[bddId], f, h, resultPtr);
+  }
+  else{
+    Cal_Bdd_t calBdd1, calBdd2, calBdd3;
+    calBdd1 = h;
+    CalBddGetThenBdd(f, calBdd2);
+    CalBddGetElseBdd(f, calBdd3);
+    *resultPtr = CalOpITE(bddManager, calBdd1, calBdd2, calBdd3, reqQueForITE);
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: /vis_dev/glu-2.1/src/calBdd/calBddITE.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddITE.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddITE.c	(revision 8)
@@ -0,0 +1,333 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddITE.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routine for computing ITE of 3 BDD operands.]
+
+  Description []
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddITE.c,v 1.1.1.3 1998/05/04 00:58:51 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical If-Then-Else
+
+  Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+  - f g + f' h]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddAnd, Cal_BddNand, Cal_BddOr, Cal_BddNor, Cal_BddXor,
+  Cal_BddXnor]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddITE(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd,
+           Cal_Bdd hUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+  Cal_Bdd_t F, G, H;
+  if (CalBddPreProcessing(bddManager, 3, fUserBdd, gUserBdd, hUserBdd)){
+    F = CalBddGetInternalBdd(bddManager, fUserBdd);
+    G = CalBddGetInternalBdd(bddManager, gUserBdd);
+    H = CalBddGetInternalBdd(bddManager, hUserBdd);
+    result = CalBddOpITEBF(bddManager, F, G, H);
+  }
+  else {
+    return (Cal_Bdd) 0;
+  }
+  userResult =  CalBddGetExternalBdd(bddManager, result);
+  if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+    Cal_BddFree(bddManager, userResult);
+    Cal_BddManagerGC(bddManager);
+    return (Cal_Bdd) 0;
+  }
+  return userResult;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Name        [CalRequestNodeListArrayOp]
+
+  Synopsis    [required]
+
+  Description [This routine is to be used for pipelined and
+  superscalar ITE operations. Currently there is no user interface
+  provided to this routine.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalRequestNodeListArrayITE(Cal_BddManager_t *bddManager,
+                          CalRequestNode_t **requestNodeListArray)
+{
+  CalRequestNode_t *requestNode, *ptrIndirect;
+  CalRequest_t F, G, H, result;
+  int pipeDepth, bddId, bddIndex;
+  CalHashTable_t **reqQueAtPipeDepth, *hashTable, *uniqueTableForId;
+  CalHashTable_t ***reqQue = bddManager->reqQue;
+  
+  /* ReqQueInsertUsingReqListArray */
+  for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+    reqQueAtPipeDepth = reqQue[pipeDepth];
+    for(requestNode = requestNodeListArray[pipeDepth];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetThenRequest(requestNode, F);
+      CalRequestIsForwardedTo(F);
+      ptrIndirect = CalRequestNodeGetElseRequestNode(requestNode);
+      CalRequestNodeGetThenRequest(ptrIndirect, G);
+      CalRequestIsForwardedTo(G);
+      CalRequestNodeGetElseRequest(ptrIndirect, H);
+      CalRequestIsForwardedTo(H);
+      CalNodeManagerFreeNode(bddManager->nodeManagerArray[0], ptrIndirect);
+      result = CalOpITE(bddManager, F, G, H, reqQueAtPipeDepth);
+      CalRequestNodePutThenRequest(requestNode, result);
+      CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+    }
+  }
+
+  /* ReqQueApply */
+  for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+      reqQueAtPipeDepth = reqQue[pipeDepth];
+      hashTable = reqQueAtPipeDepth[bddId];
+      if(hashTable->numEntries){
+        CalHashTableITEApply(bddManager, hashTable, reqQueAtPipeDepth);
+      }
+    }
+  }
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= 0; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+      hashTable = reqQue[pipeDepth][bddId];
+      if(hashTable->numEntries){
+        CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+      }
+    }
+  }
+
+  /* ReqListArrayReqForward */
+  for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+    for(requestNode = requestNodeListArray[pipeDepth];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetThenRequest(requestNode, result);
+      CalRequestIsForwardedTo(result);
+      CalRequestNodePutThenRequest(requestNode, result);
+    }
+  }
+
+  /* ReqQueCleanUp */
+  for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+    reqQueAtPipeDepth = reqQue[pipeDepth];
+    for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+      CalHashTableCleanUp(reqQueAtPipeDepth[bddId]);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd_t
+CalBddOpITEBF(
+  Cal_BddManager_t *bddManager,
+  Cal_Bdd_t  f,
+  Cal_Bdd_t  g,
+  Cal_Bdd_t  h)
+{
+  Cal_Bdd_t result;
+  Cal_BddId_t bddId;
+  /*Cal_BddIndex_t minIndex;*/
+  int minIndex;
+  int bddIndex;
+  CalHashTable_t *hashTable;
+  CalHashTable_t *uniqueTableForId;
+  CalHashTable_t **reqQueForITE = bddManager->reqQue[0];
+  
+  result = CalOpITE(bddManager, f, g, h, reqQueForITE);
+  
+  CalBddGetMinIndex3(bddManager, f, g, h, minIndex);
+  /* ReqQueApply */
+  for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = reqQueForITE[bddId];
+    if(hashTable->numEntries){
+      CalHashTableITEApply(bddManager, hashTable, reqQueForITE);
+    }
+  }
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = reqQueForITE[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+  }
+
+  CalRequestIsForwardedTo(result);
+
+  /* Clean up */
+  for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(reqQueForITE[bddId]);
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableITEApply(
+  Cal_BddManager_t *bddManager,
+  CalHashTable_t *hashTable,
+  CalHashTable_t **reqQueAtPipeDepth)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t fx, gx, fxbar, gxbar, hx, hxbar, result;
+  CalNodeManager_t *nodeManager = hashTable->nodeManager;
+  
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      /* Process the requestNode */
+      CalITERequestNodeGetCofactors(bddManager, requestNode,
+          fx, fxbar, gx, gxbar, hx, hxbar);
+      result = CalOpITE(bddManager, fx, gx, hx, reqQueAtPipeDepth);
+      CalBddIcrRefCount(result);
+      CalRequestNodePutThenRequest(requestNode, result);
+      result = CalOpITE(bddManager, fxbar, gxbar, hxbar, reqQueAtPipeDepth);
+      CalBddIcrRefCount(result);
+      CalNodeManagerFreeNode(nodeManager,
+          CalRequestNodeGetElseRequestNode(requestNode));
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+}
+
+/**Function********************************************************************
+ 
+   Synopsis    [Returns the BDD for logical If-Then-Else
+ 
+   Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+   - f g + f' h]
+ 
+   SideEffects [None]
+ 
+   SeeAlso     [Cal_BddAnd, Cal_BddNand, Cal_BddOr, Cal_BddNor, Cal_BddXor,
+   Cal_BddXnor]
+ 
+******************************************************************************/
+Cal_Bdd_t
+CalBddITE(Cal_BddManager_t *bddManager, Cal_Bdd_t F, Cal_Bdd_t G,
+          Cal_Bdd_t H)
+{
+  Cal_Bdd_t result;
+  result = CalBddOpITEBF(bddManager, F, G, H);
+  CalBddIcrRefCount(result);
+  return result;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: /vis_dev/glu-2.1/src/calBdd/calBddManager.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddManager.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddManager.c	(revision 8)
@@ -0,0 +1,832 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddManager.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for maintaing the manager and creating
+  variables etc.]
+
+  Description []
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddManager.c,v 1.9 2002/09/21 20:39:24 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+unsigned long calPrimes[] = 
+{
+  1,
+  2,
+  3,
+  7,
+  13,
+  23,
+  59,
+  113,
+  241,
+  503,
+  1019,
+  2039,
+  4091,
+  8179,
+  11587,
+  16369,
+  23143,
+  32749,
+  46349,
+  65521,
+  92683,
+  131063,
+  185363,
+  262139,
+  330287,
+  416147,
+  524269,
+  660557,
+  832253,
+  1048571,
+  1321109,
+  1664501,
+  2097143,
+  2642201,
+  3328979,
+  4194287,
+  5284393,
+  6657919,
+  8388593,
+  10568797,
+  13315831,
+  16777199,
+  33554393,
+  67108859,
+  134217689,
+  268435399,
+  536870879,
+  1073741789,
+  2147483629
+};
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#define CalBddManagerGetNodeManager(bddManager, id) \
+    bddManager->nodeManagerArray[id]
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void BddDefaultTransformFn(Cal_BddManager_t * bddManager, CalAddress_t value1, CalAddress_t value2, CalAddress_t * result1, CalAddress_t * result2, Cal_Pointer_t pointer);
+#ifdef CALBDDMANAGER
+static int CalBddManagerPrint(Cal_BddManager_t *bddManager);
+#endif /* CALBDDMANAGER */
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Creates and initializes a new BDD manager.]
+
+  Description [Initializes and allocates fields of the BDD manager. Some of the
+  fields are initialized for maxNumVars+1 or numVars+1, whereas some of them are
+  initialized for maxNumVars or numVars. The first kind of fields are associated
+  with the id of a variable and the second ones are with the index of the
+  variable.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddManagerQuit]
+
+******************************************************************************/
+Cal_BddManager
+Cal_BddManagerInit(void)
+{
+  Cal_BddManager_t *bddManager;
+  int i;
+  CalBddNode_t *bddNode;
+  Cal_Bdd_t resultBdd;
+  
+    
+  bddManager = Cal_MemAlloc(Cal_BddManager_t, 1);
+
+  bddManager->numVars = 0;
+
+  bddManager->maxNumVars = 30;
+  
+  bddManager->varBdds = Cal_MemAlloc(Cal_Bdd_t, bddManager->maxNumVars+1);
+  
+  bddManager->pageManager1 = CalPageManagerInit(4);
+  bddManager->pageManager2 = CalPageManagerInit(NUM_PAGES_PER_SEGMENT);
+
+  bddManager->nodeManagerArray = Cal_MemAlloc(CalNodeManager_t*, bddManager->maxNumVars+1);
+
+  bddManager->nodeManagerArray[0] = CalNodeManagerInit(bddManager->pageManager1);
+  bddManager->uniqueTable = Cal_MemAlloc(CalHashTable_t *,
+                                         bddManager->maxNumVars+1);
+  bddManager->uniqueTable[0] = CalHashTableInit(bddManager, 0);
+  
+  /* Constant One */
+  CalBddPutBddId(bddManager->bddOne, CAL_BDD_CONST_ID);
+  CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], bddNode);
+  CalBddPutBddNode(bddManager->bddOne, bddNode);
+  /* ~0x0 put so that the node is not mistaken for forwarded node */
+  CalBddPutThenBddNode(bddManager->bddOne, (CalBddNode_t *)~0x0);
+  CalBddPutElseBddNode(bddManager->bddOne, (CalBddNode_t *)~0x0);
+  CalBddPutRefCount(bddManager->bddOne, CAL_MAX_REF_COUNT);
+  CalBddNot(bddManager->bddOne, bddManager->bddZero);
+
+  /* Create a user BDD */
+  CalHashTableAddDirectAux(bddManager->uniqueTable[0], bddManager->bddOne,
+                           bddManager->bddOne, &resultBdd);
+  CalBddPutRefCount(resultBdd, CAL_MAX_REF_COUNT);
+  bddManager->userOneBdd =  CalBddGetBddNode(resultBdd);
+  bddManager->userZeroBdd = CalBddNodeNot(bddManager->userOneBdd);
+  
+  /* Null BDD */
+  CalBddPutBddId(bddManager->bddNull, CAL_BDD_NULL_ID);
+  CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], bddNode);
+  CalBddPutBddNode(bddManager->bddNull, bddNode);
+  /* ~0x10 put so that the node is not mistaken for forwarded node or
+     the constant nodes. */
+  CalBddPutThenBddNode(bddManager->bddNull, (CalBddNode_t *)~0x10);
+  CalBddPutElseBddNode(bddManager->bddNull, (CalBddNode_t *)~0x10);
+  CalBddPutRefCount(bddManager->bddNull, CAL_MAX_REF_COUNT);
+  /* Put in the unique table, so that it gets locked */
+  /*CalHashTableAddDirect(bddManager->uniqueTable[0], bddNode);*/
+
+  bddManager->indexToId = Cal_MemAlloc(Cal_BddId_t, bddManager->maxNumVars);
+  bddManager->idToIndex = Cal_MemAlloc(Cal_BddIndex_t, bddManager->maxNumVars+1);
+  bddManager->idToIndex[CAL_BDD_CONST_ID] = CAL_BDD_CONST_INDEX;
+
+  bddManager->depth = DEFAULT_DEPTH;
+  bddManager->maxDepth = DEFAULT_MAX_DEPTH;
+  bddManager->pipelineState = READY;
+  bddManager->pipelineDepth = PIPELINE_EXECUTION_DEPTH;
+  bddManager->currentPipelineDepth = 0;
+  bddManager->pipelineFn = CalOpAnd;
+
+
+  bddManager->reqQue = Cal_MemAlloc(CalHashTable_t **, bddManager->maxDepth);
+  bddManager->cacheTable = CalCacheTableTwoInit(bddManager);
+  
+  for (i=0; i < bddManager->maxDepth; i++){
+    bddManager->reqQue[i] = Cal_MemAlloc(CalHashTable_t *,
+                                         bddManager->maxNumVars+1);
+    bddManager->reqQue[i][0] = CalHashTableInit(bddManager, 0);
+  }
+
+  bddManager->requestNodeListArray = Cal_MemAlloc(CalRequestNode_t*,
+                                                  MAX_INSERT_DEPTH);
+  for(i = 0; i < MAX_INSERT_DEPTH; i++){
+    bddManager->requestNodeListArray[i] = Cal_Nil(CalRequestNode_t);
+  }
+  bddManager->userProvisionalNodeList = Cal_Nil(CalRequestNode_t);
+
+  /* Garbage collection related information */
+  bddManager->numNodes = bddManager->numPeakNodes = 1;
+  bddManager->numNodesFreed = 0;
+  bddManager->gcCheck = CAL_GC_CHECK;
+  bddManager->uniqueTableGCLimit =  CAL_MIN_GC_LIMIT;
+  bddManager->numGC = 0;
+  bddManager->gcMode = 1;
+  bddManager->nodeLimit = 0;
+  bddManager->overflow = 0;
+  bddManager->repackAfterGCThreshold = CAL_REPACK_AFTER_GC_THRESHOLD;
+  
+
+  /* Special functions */
+  bddManager->TransformFn = BddDefaultTransformFn;
+  bddManager->transformEnv = 0;
+
+
+  /* Association related information */
+  bddManager->associationList = Cal_Nil(CalAssociation_t);
+  /*bddManager->tempAssociation = CAL_BDD_NEW_REC(bddManager, CalAssociation_t);*/
+  bddManager->tempAssociation = Cal_MemAlloc(CalAssociation_t, 1);
+  bddManager->tempAssociation->id = -1;
+  bddManager->tempAssociation->lastBddIndex = -1;
+  bddManager->tempAssociation->varAssociation =
+      Cal_MemAlloc(Cal_Bdd_t, bddManager->maxNumVars+1);
+  for(i = 0; i < bddManager->maxNumVars+1; i++){
+     bddManager->tempAssociation->varAssociation[i] = bddManager->bddNull;
+  }
+  bddManager->tempOpCode = -1;
+  bddManager->currentAssociation = bddManager->tempAssociation;
+
+  /* BDD reordering related information */
+  bddManager->dynamicReorderingEnableFlag = 1;
+  bddManager->reorderMethod = CAL_REORDER_METHOD_DF;
+  bddManager->reorderTechnique = CAL_REORDER_NONE;
+  bddManager->numForwardedNodes = 0;
+  bddManager->numReorderings = 0;
+  bddManager->maxNumVarsSiftedPerReordering = 1000;
+  bddManager->maxNumSwapsPerReordering = 2000000;
+  bddManager->numSwaps = 0;
+  bddManager->numTrivialSwaps = 0;
+  bddManager->maxSiftingGrowth = 2.0;
+  bddManager->reorderingThreshold = CAL_BDD_REORDER_THRESHOLD;
+  bddManager->maxForwardedNodes = CAL_NUM_FORWARDED_NODES_LIMIT;
+  bddManager->tableRepackThreshold = CAL_TABLE_REPACK_THRESHOLD;
+  
+
+  /*bddManager->superBlock = CAL_BDD_NEW_REC(bddManager, Cal_Block_t);*/
+  bddManager->superBlock = Cal_MemAlloc(Cal_Block_t, 1);
+  bddManager->superBlock->numChildren=0;
+  bddManager->superBlock->children=0;
+  bddManager->superBlock->reorderable=1;
+  bddManager->superBlock->firstIndex= -1;
+  bddManager->superBlock->lastIndex=0;
+  
+  bddManager->hooks = Cal_Nil(void);
+  
+  return bddManager;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the BDD manager and all the associated allocations]
+
+  Description [Frees the BDD manager and all the associated allocations]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddManagerInit]
+
+******************************************************************************/
+int
+Cal_BddManagerQuit(Cal_BddManager bddManager)
+{
+  int i, j;
+
+  if(bddManager == Cal_Nil(Cal_BddManager_t)) return 1;
+
+  for (i=0; i < bddManager->maxDepth; i++){
+    for (j=0; j <= bddManager->numVars; j++){
+      CalHashTableQuit(bddManager, bddManager->reqQue[i][j]);
+    }
+    Cal_MemFree(bddManager->reqQue[i]);
+  }
+  
+  for (i=0; i <= bddManager->numVars; i++){
+    CalHashTableQuit(bddManager, bddManager->uniqueTable[i]);
+    CalNodeManagerQuit(bddManager->nodeManagerArray[i]);
+  }
+
+  CalCacheTableTwoQuit(bddManager->cacheTable);
+  Cal_MemFree(bddManager->tempAssociation->varAssociation);
+  /*CAL_BDD_FREE_REC(bddManager, bddManager->tempAssociation, CalAssociation_t);*/
+  Cal_MemFree(bddManager->tempAssociation);
+  /*CAL_BDD_FREE_REC(bddManager, bddManager->superBlock, Cal_Block_t);*/
+  CalFreeBlockRecursively(bddManager->superBlock);
+  CalAssociationListFree(bddManager);
+  Cal_MemFree(bddManager->varBdds);
+  Cal_MemFree(bddManager->indexToId);
+  Cal_MemFree(bddManager->idToIndex);
+  Cal_MemFree(bddManager->uniqueTable);
+  Cal_MemFree(bddManager->reqQue);
+  Cal_MemFree(bddManager->requestNodeListArray);
+  Cal_MemFree(bddManager->nodeManagerArray);
+  CalPageManagerQuit(bddManager->pageManager1);
+  CalPageManagerQuit(bddManager->pageManager2);
+  Cal_MemFree(bddManager);
+
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets appropriate fields of BDD Manager.]
+
+  Description [This function is used to set the parameters which are
+  used to control the reordering process. "reorderingThreshold"
+  determines the number of nodes below which reordering will NOT be
+  invoked, "maxForwardedNodes" determines the maximum number of
+  forwarded nodes which are allowed (at that point the cleanup must be
+  done), and "repackingThreshold" determines the fraction of the page
+  utilized below which repacking has to be invoked. These parameters
+  have different effect on the computational and memory usage aspects
+  of reordeing. For instance, higher value of "maxForwardedNodes" will
+  result in process consuming more memory, and a lower value on the
+  other hand would invoke the cleanup process repeatedly resulting in
+  increased computation.]
+
+  SideEffects [Sets appropriate fields of BDD Manager]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cal_BddManagerSetParameters(Cal_BddManager bddManager,
+			    long reorderingThreshold,
+			    long maxForwardedNodes,
+                            double repackAfterGCThreshold,
+                            double tableRepackThreshold)
+{
+  if (reorderingThreshold >= 0){
+    bddManager->reorderingThreshold = reorderingThreshold;
+  }
+  if (maxForwardedNodes >= 0){
+    bddManager->maxForwardedNodes = maxForwardedNodes;
+  }
+  if (repackAfterGCThreshold >= 0.0){
+    bddManager->repackAfterGCThreshold = (float) repackAfterGCThreshold;
+  }
+  if (tableRepackThreshold >= 0.0){
+    bddManager->tableRepackThreshold = (float) tableRepackThreshold;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of BDD nodes]
+
+  Description [Returns the number of BDD nodes]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddTotalSize]
+
+******************************************************************************/
+unsigned long
+Cal_BddManagerGetNumNodes(Cal_BddManager bddManager)
+{
+  return  bddManager->numNodes;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates and returns a new variable at the start of the variable
+  order.]
+
+  Description [Creates and returns a new variable at the start of the
+  variable order.]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddManagerCreateNewVarFirst(Cal_BddManager bddManager)
+{
+  return CalBddGetExternalBdd(bddManager, CalBddManagerCreateNewVar(bddManager,
+                                                        (Cal_BddIndex_t)0));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates and returns a new variable at the end of the variable
+  order.]
+
+  Description [Creates and returns a new variable at the end of the variable
+  order.]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddManagerCreateNewVarLast(Cal_BddManager bddManager)
+{
+  return CalBddGetExternalBdd(bddManager,
+                              CalBddManagerCreateNewVar(bddManager,
+                                                        (Cal_BddIndex_t)
+                                                        bddManager->numVars));
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates and returns a new variable before the specified one in
+  the variable order.]
+
+  Description [Creates and returns a new variable before the specified one in
+  the variable order.]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddManagerCreateNewVarBefore(Cal_BddManager bddManager,
+                                 Cal_Bdd userBdd)
+{
+  Cal_Bdd_t calBdd = CalBddGetInternalBdd(bddManager, userBdd);
+  if (CalBddIsBddConst(calBdd)){
+    return Cal_BddManagerCreateNewVarLast(bddManager);
+  }
+  else{
+    return CalBddGetExternalBdd(bddManager,
+                                CalBddManagerCreateNewVar(bddManager,
+                                                          CalBddGetBddIndex(bddManager, 
+                                                  calBdd)));
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates and returns a new variable after the specified one in
+  the variable  order.]
+
+  Description [Creates and returns a new variable after the specified one in
+  the variable  order.]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddManagerCreateNewVarAfter(Cal_BddManager bddManager,
+                                Cal_Bdd userBdd)
+{
+  Cal_Bdd_t calBdd = CalBddGetInternalBdd(bddManager, userBdd);
+  if (CalBddIsBddConst(calBdd)){
+    return Cal_BddManagerCreateNewVarLast(bddManager);
+  }
+  else{
+    return CalBddGetExternalBdd(bddManager,
+                                CalBddManagerCreateNewVar(bddManager,
+                                                          CalBddGetBddIndex(bddManager, calBdd)+1));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the variable with the specified index, null if no
+  such variable exists]
+
+  Description [Returns the variable with the specified index, null if no
+  such variable exists]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddManagerGetVarWithIndex(Cal_BddManager bddManager, Cal_BddIndex_t  index)
+{
+  if (index >= bddManager->numVars){
+    CalBddWarningMessage("Index out of range");
+    return (Cal_Bdd) 0;
+  }
+  return CalBddGetExternalBdd(bddManager,
+                              bddManager->varBdds[bddManager->indexToId[index]]); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the variable with the specified id, null if no
+  such variable exists]
+
+  Description [Returns the variable with the specified id, null if no
+  such variable exists]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddManagerGetVarWithId(Cal_BddManager bddManager,  Cal_BddId_t  id)
+{
+  if (id <= 0 || id > bddManager->numVars){
+    CalBddWarningMessage("Id out of range");
+    return (Cal_Bdd) 0;
+  }
+  return CalBddGetExternalBdd(bddManager, bddManager->varBdds[id]);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [This function creates and returns a new variable with given
+  index value.]
+
+  Description [Right now this function does not handle the case when the
+  package is working in multiprocessor mode. We need to put in the necessary
+  code later.]
+
+  SideEffects [If the number of variables in the manager exceeds that of value
+  of numMaxVars, then we need to reallocate various fields of the manager. Also
+  depending upon the value of "index", idToIndex and indexToId tables would
+  change.]
+
+******************************************************************************/
+Cal_Bdd_t
+CalBddManagerCreateNewVar(Cal_BddManager_t * bddManager, Cal_BddIndex_t  index)
+{
+  Cal_Bdd_t calBdd;
+  Cal_BddId_t varId;
+  int totalNumVars, maxNumVars, i;
+  CalAssociation_t *association;
+  
+  if (bddManager->numVars == CAL_MAX_VAR_ID){
+    CalBddFatalMessage("Cannot create any new variable, no more Id left."); 
+  }
+
+  /*
+   * Get the total number of variables. If the index is more than the total
+   * number of variables, then report error.
+   */
+  totalNumVars = bddManager->numVars;
+  
+  if (index > totalNumVars){
+    CalBddFatalMessage("The variable index out of range");
+  }
+  
+
+  /*
+   * Create a new variable in the manager which contains this index.
+   * This might lead to change in the id->index, and index->id
+   * for other managers.
+   */
+
+  /*
+   * If the number of variables is equal to the maximum number of variables
+   * then reallocate memory.
+   */
+  if (bddManager->numVars == bddManager->maxNumVars){
+    int oldMaxNumVars;
+    CalAssociation_t *p;
+    
+    oldMaxNumVars = bddManager->maxNumVars;
+    if ((maxNumVars = 2*oldMaxNumVars) > CAL_MAX_VAR_ID){
+      maxNumVars = CAL_MAX_VAR_ID;
+    }
+    bddManager->maxNumVars = maxNumVars;
+    bddManager->varBdds = Cal_MemRealloc(Cal_Bdd_t,
+                                         bddManager->varBdds, maxNumVars+1); 
+    
+    bddManager->nodeManagerArray = Cal_MemRealloc(CalNodeManager_t *,
+                                                  bddManager->nodeManagerArray, 
+                                                  maxNumVars+1);
+
+    bddManager->idToIndex = Cal_MemRealloc(Cal_BddIndex_t, bddManager->idToIndex,
+                                        maxNumVars+1);
+
+    bddManager->indexToId = Cal_MemRealloc(Cal_BddIndex_t, bddManager->indexToId,
+                                        maxNumVars);
+
+    bddManager->uniqueTable = Cal_MemRealloc(CalHashTable_t *,
+                                          bddManager->uniqueTable, maxNumVars+1);
+    
+    for (i=0; i<bddManager->maxDepth; i++){
+      bddManager->reqQue[i] = Cal_MemRealloc(CalHashTable_t *, bddManager->reqQue[i],
+                                          maxNumVars+1);
+    }
+    bddManager->tempAssociation->varAssociation = 
+        Cal_MemRealloc(Cal_Bdd_t, bddManager->tempAssociation->varAssociation,
+        maxNumVars+1);
+    /* CHECK LOOP INDICES */
+    for(i = oldMaxNumVars+1; i < maxNumVars+1; i++){
+      bddManager->tempAssociation->varAssociation[i] = bddManager->bddNull;
+    }
+    for(p = bddManager->associationList; p; p = p->next){
+      p->varAssociation = 
+          Cal_MemRealloc(Cal_Bdd_t, p->varAssociation, maxNumVars+1);
+      /* CHECK LOOP INDICES */
+      for(i = oldMaxNumVars+1; i < maxNumVars+1; i++){
+        p->varAssociation[i] = bddManager->bddNull;
+      }
+    }
+  }
+
+  /* If the variable has been created in the middle, shift the indices. */
+  if (index != bddManager->numVars){
+    for (i=0; i<bddManager->numVars; i++){
+      if (bddManager->idToIndex[i+1] >= index){
+        bddManager->idToIndex[i+1]++;
+      }
+    }
+  }
+
+  /* Fix indexToId table */
+  for (i=bddManager->numVars; i>index; i--){
+    bddManager->indexToId[i] = bddManager->indexToId[i-1];
+  }
+
+  for(association = bddManager->associationList; association;
+                                              association =
+                                                  association->next){
+    if (association->lastBddIndex >= index){
+      association->lastBddIndex++;
+    }
+  }
+  if (bddManager->tempAssociation->lastBddIndex >= index){
+    bddManager->tempAssociation->lastBddIndex++;
+  }
+  
+  bddManager->numVars++;
+  varId = bddManager->numVars;
+
+  bddManager->idToIndex[varId] = index;
+  bddManager->indexToId[index] = varId;
+  
+  bddManager->nodeManagerArray[varId] =
+      CalNodeManagerInit(bddManager->pageManager2); 
+  bddManager->uniqueTable[varId] =
+      CalHashTableInit(bddManager, varId);
+    
+  /* insert node in the uniqueTableForId */
+  CalHashTableAddDirectAux(bddManager->uniqueTable[varId],
+                           bddManager->bddOne, bddManager->bddZero, &calBdd);
+  CalBddPutRefCount(calBdd, CAL_MAX_REF_COUNT);
+  bddManager->varBdds[varId] = calBdd;
+
+  bddManager->numNodes++;
+  
+#ifdef __OLD__
+  /* initialize req_que_for_id */
+  bddManager->reqQue[varId] = Cal_MemAlloc(CalHashTable_t*, bddManager->maxDepth);
+  for (i=0; i<manager->maxDepth; i++){
+    bddManager->reqQue[varId][i] = CalHashTableInit(bddManager, varId);
+  }
+#endif
+  
+  /* initialize req_que_for_id */
+  for (i=0; i<bddManager->maxDepth; i++){
+    bddManager->reqQue[i][varId] =
+        CalHashTableInit(bddManager, varId);
+  }
+  CalBddShiftBlock(bddManager, bddManager->superBlock, (long)index);
+  return calBdd;
+}
+
+  
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddDefaultTransformFn(
+  Cal_BddManager_t * bddManager,
+  CalAddress_t  value1,
+  CalAddress_t  value2,
+  CalAddress_t * result1,
+  CalAddress_t * result2,
+  Cal_Pointer_t  pointer)
+{
+  if (!value2)
+    /* Will be a carry when taking 2's complement of value2.  Thus, */
+    /* take 2's complement of high part. */
+    value1= -(long)value1;
+  else
+    {
+      value2= -(long)value2;
+      value1= ~value1;
+    }
+  *result1=value1;
+  *result2=value2;
+}
+
+#ifdef CALBDDMANAGER
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+CalBddManagerPrint(Cal_BddManager_t *bddManager)
+{
+  int i;
+  CalHashTable_t *uniqueTableForId;
+  printf("#####################   BDD MANAGER   #####################\n");
+  for(i = 1; i < bddManager->numVars; i++){
+    uniqueTableForId = bddManager->uniqueTable[i];
+    CalHashTablePrint(uniqueTableForId);
+  }
+  fflush(stdout);
+  return 0;
+}
+
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+	Cal_Bdd_t n;
+	Cal_BddManager_t *manager;
+
+	manager = CalBddManagerInit(argc, argv);
+	n = CalBddManagerCreateVariable(bddManager);
+	CalBddFunctionPrint(n);
+	n = CalBddManagerGetVariable(bddManager, 0);
+	CalBddFunctionPrint(n);
+}
+#endif /* CALBDDMANAGER */
+
+#ifdef __GC__
+main(argc, argv)
+int argc;
+char **argv;
+{
+  Cal_BddManager_t *manager;
+  Cal_Bdd_t vars[256];
+  Cal_Bdd_t function, tempFunction;
+  int i;
+  int numVars;
+  
+  if (argc >= 2)
+        numVars = atoi(argv[1]);
+  else
+    numVars = 3;
+  
+  manager = Cal_BddManagerInit();
+  
+  for (i = 0; i < numVars; i++){
+    vars[i] = Cal_BddManagerCreateNewVarLast(bddManager);
+  }
+  
+  function = vars[0];
+  for (i = 1; i < numVars - 1; i++){
+    tempFunction = Cal_BddITE(bddManager, vars[i], vars[i+1], function);
+    Cal_BddFree(function);
+    function = tempFunction;
+            /*fprintf(stdout, "i = %d\n", i);
+              unique_table_write(stdout, CalBddManager->unique_table);
+              */
+  }
+  fprintf(stdout, "\n******************Before Free****************\n");
+  for (i = 1; i <= numVars; i++){
+    CalHashTablePrint(bddManager->uniqueTable[i]);
+  }
+  Cal_BddFree(function);
+  fprintf(stdout, "\n****************After Free****************\n");
+  for (i = 1; i <= numVars; i++){
+    CalHashTablePrint(bddManager->uniqueTable[i]);
+  }
+  Cal_BddManagerGC(bddManager);
+  fprintf(stdout, "\n****************After GC****************\n");
+  for (i = 1; i <= numVars; i++){
+    CalHashTablePrint(bddManager->uniqueTable[i]);
+  }
+}
+#endif
Index: /vis_dev/glu-2.1/src/calBdd/calBddOp.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddOp.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddOp.c	(revision 8)
@@ -0,0 +1,1015 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddOp.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for performing simple boolean operations on a
+  pair of BDDs or on an array of pair of BDDs or on an array of BDDs.]
+
+  Description [The "cal" specific routines are "Cal_BddPairwiseAnd/Or",
+  "Cal_BddMultiwayAnd/Or".] 
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddOp.c,v 1.1.1.3 1998/05/04 00:58:52 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Cal_Bdd_t * BddArrayOpBF(Cal_BddManager_t * bddManager, Cal_Bdd_t* bddArray, int numFunction, CalOpProc_t calOpProc);
+static Cal_Bdd_t BddMultiwayOp(Cal_BddManager_t * bddManager, Cal_Bdd_t * calBddArray, int numBdds, CalOpProc_t op);
+static void BddArrayToRequestNodeListArray(Cal_BddManager_t * bddManager, Cal_Bdd_t * calBddArray, int numBdds);
+static int CeilLog2(int number);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical AND of argument BDDs]
+
+  Description [Returns the BDD for logical AND of f and g]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddAnd(
+  Cal_BddManager bddManager,
+  Cal_Bdd  fUserBdd,
+  Cal_Bdd  gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+  Cal_Bdd_t F, G;
+
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    F = CalBddGetInternalBdd(bddManager, fUserBdd);
+    G = CalBddGetInternalBdd(bddManager, gUserBdd);
+    result = CalBddOpBF(bddManager, CalOpAnd, F, G);
+  }
+  else {
+    return (Cal_Bdd)0;
+  }
+  userResult =  CalBddGetExternalBdd(bddManager, result);
+  if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+    Cal_BddFree(bddManager, userResult);
+    Cal_BddManagerGC(bddManager);
+    return (Cal_Bdd) 0;
+  }
+  return userResult;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical NAND of argument BDDs]
+
+  Description [Returns the BDD for logical NAND of f and g]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddNand(
+  Cal_BddManager bddManager,
+  Cal_Bdd fUserBdd,
+  Cal_Bdd gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd_t F, G;
+  Cal_Bdd userResult;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    F = CalBddGetInternalBdd(bddManager, fUserBdd); 
+    G = CalBddGetInternalBdd(bddManager, gUserBdd); 
+    result = CalBddOpBF(bddManager, CalOpNand, F, G);
+  }
+  else{
+    return (Cal_Bdd) 0;
+  }
+  userResult =  CalBddGetExternalBdd(bddManager, result);
+  if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+    Cal_BddFree(bddManager, userResult);
+    Cal_BddManagerGC(bddManager);
+    return (Cal_Bdd) 0;
+  }
+  return userResult;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical OR of argument BDDs]
+
+  Description [Returns the BDD for logical OR of f and g]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddOr(Cal_BddManager bddManager,
+          Cal_Bdd fUserBdd,
+          Cal_Bdd gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd_t F, G;
+  Cal_Bdd userResult;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    F = CalBddGetInternalBdd(bddManager, fUserBdd); 
+    G = CalBddGetInternalBdd(bddManager, gUserBdd); 
+    result = CalBddOpBF(bddManager, CalOpOr, F, G);
+  }
+  else{
+    return (Cal_Bdd) 0;
+  }
+  userResult =  CalBddGetExternalBdd(bddManager, result);
+  if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+    Cal_BddFree(bddManager, userResult);
+    Cal_BddManagerGC(bddManager);
+    return (Cal_Bdd) 0;
+  }
+  return userResult;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical NOR of argument BDDs]
+
+  Description [Returns the BDD for logical NOR of f and g]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddNor(Cal_BddManager bddManager,
+           Cal_Bdd fUserBdd,
+           Cal_Bdd gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+  Cal_Bdd_t F, G;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    F = CalBddGetInternalBdd(bddManager, fUserBdd); 
+    G = CalBddGetInternalBdd(bddManager, gUserBdd); 
+    result = CalBddOpBF(bddManager, CalOpOr, F, G);
+    CalBddNot(result, result);
+  }
+  else{
+    return (Cal_Bdd) 0;
+  }
+  userResult =  CalBddGetExternalBdd(bddManager, result);
+  if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+    Cal_BddFree(bddManager, userResult);
+    Cal_BddManagerGC(bddManager);
+    return (Cal_Bdd) 0;
+  }
+  return userResult;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical exclusive OR of argument BDDs]
+
+  Description [Returns the BDD for logical exclusive OR of f and g]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddXor(Cal_BddManager bddManager,
+           Cal_Bdd fUserBdd,
+           Cal_Bdd gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+  Cal_Bdd_t F, G;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    F = CalBddGetInternalBdd(bddManager, fUserBdd); 
+    G = CalBddGetInternalBdd(bddManager, gUserBdd); 
+    result = CalBddOpBF(bddManager, CalOpXor, F, G);
+  }
+  else{
+    return (Cal_Bdd) 0;
+  }
+  userResult =  CalBddGetExternalBdd(bddManager, result);
+  if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+    Cal_BddFree(bddManager, userResult);
+    Cal_BddManagerGC(bddManager);
+    return (Cal_Bdd) 0;
+  }
+  return userResult;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical exclusive NOR of argument BDDs]
+
+  Description [Returns the BDD for logical exclusive NOR of f and g]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddXnor(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+  Cal_Bdd_t F, G;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    F = CalBddGetInternalBdd(bddManager, fUserBdd); 
+    G = CalBddGetInternalBdd(bddManager, gUserBdd); 
+    result = CalBddOpBF(bddManager, CalOpXor, F, G);
+    CalBddNot(result, result);
+  }
+  else{
+    return (Cal_Bdd) 0;
+  }
+  userResult =  CalBddGetExternalBdd(bddManager, result);
+  if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+    Cal_BddFree(bddManager, userResult);
+    Cal_BddManagerGC(bddManager);
+    return (Cal_Bdd) 0;
+  }
+  return userResult;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of BDDs obtained by logical AND of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array]
+
+  Description [Returns an array of BDDs obtained by logical AND of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddPairwiseOr]
+
+******************************************************************************/
+Cal_Bdd *
+Cal_BddPairwiseAnd(Cal_BddManager bddManager, Cal_Bdd *userBddArray)
+{
+  int i, num;
+  Cal_Bdd_t *bddArray;
+  Cal_Bdd_t *resultArray;
+  Cal_Bdd userBdd;
+  Cal_Bdd *userResultArray;
+ 
+  for (num = 0; (userBdd = userBddArray[num]); num++){
+    if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+      return Cal_Nil(Cal_Bdd);
+    }
+  }
+  if ((num == 0) || (num%2 != 0)){
+    fprintf(stdout,"Odd number of arguments passed to array AND\n");
+    return Cal_Nil(Cal_Bdd);
+  }
+  bddArray = Cal_MemAlloc(Cal_Bdd_t, num);
+  for (i = 0; i < num; i++){
+    bddArray[i] = CalBddGetInternalBdd(bddManager, userBddArray[i]);
+  }
+  resultArray =  BddArrayOpBF(bddManager, bddArray, num, CalOpAnd);
+  userResultArray = Cal_MemAlloc(Cal_Bdd, num/2);
+  for (i=0; i<num/2; i++){
+    userResultArray[i] = CalBddGetExternalBdd(bddManager, resultArray[i]);
+  }
+  Cal_MemFree(bddArray);
+  Cal_MemFree(resultArray);
+  if (CalBddPostProcessing(bddManager)  == CAL_BDD_OVERFLOWED){
+    for (i=0; i<num/2; i++){
+      Cal_BddFree(bddManager, userResultArray[i]);
+      userResultArray[i] = (Cal_Bdd) 0;
+    }
+    Cal_BddManagerGC(bddManager);
+    return userResultArray;
+  }
+  return userResultArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of BDDs obtained by logical OR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array]
+
+  Description [Returns an array of BDDs obtained by logical OR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddPairwiseAnd]
+
+******************************************************************************/
+Cal_Bdd *
+Cal_BddPairwiseOr(Cal_BddManager bddManager, Cal_Bdd *userBddArray)
+{
+  int i, num=0;
+  Cal_Bdd_t *bddArray;
+  Cal_Bdd_t *resultArray;
+  Cal_Bdd userBdd;
+  Cal_Bdd *userResultArray;
+ 
+  for (num = 0; (userBdd = userBddArray[num]); num++){
+    if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+      return Cal_Nil(Cal_Bdd);
+    }
+  }
+  if ((num == 0) || (num%2 != 0)){
+    fprintf(stdout,"Odd number of arguments passed to array OR\n");
+    return Cal_Nil(Cal_Bdd);
+  }
+  bddArray = Cal_MemAlloc(Cal_Bdd_t, num);
+  for (i = 0; i < num; i++){
+    bddArray[i] = CalBddGetInternalBdd(bddManager, userBddArray[i]);
+  }
+  resultArray =  BddArrayOpBF(bddManager, bddArray, num, CalOpOr);
+  userResultArray = Cal_MemAlloc(Cal_Bdd, num/2);
+  for (i=0; i<num/2; i++){
+    userResultArray[i] = CalBddGetExternalBdd(bddManager, resultArray[i]);
+  }
+  Cal_MemFree(bddArray);
+  Cal_MemFree(resultArray);
+  return userResultArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of BDDs obtained by logical XOR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array]
+
+  Description [Returns an array of BDDs obtained by logical XOR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddPairwiseAnd]
+
+******************************************************************************/
+Cal_Bdd *
+Cal_BddPairwiseXor(Cal_BddManager bddManager, Cal_Bdd *userBddArray)
+{
+  int i, num=0;
+  Cal_Bdd_t *bddArray;
+  Cal_Bdd_t *resultArray;
+  Cal_Bdd userBdd;
+  Cal_Bdd *userResultArray;
+ 
+  for (num = 0; (userBdd = userBddArray[num]); num++){
+    if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+      return Cal_Nil(Cal_Bdd);
+    }
+  }
+  if ((num == 0) || (num%2 != 0)){
+    fprintf(stdout,"Odd number of arguments passed to array OR\n");
+    return Cal_Nil(Cal_Bdd);
+  }
+  bddArray = Cal_MemAlloc(Cal_Bdd_t, num);
+  for (i = 0; i < num; i++){
+    bddArray[i] = CalBddGetInternalBdd(bddManager, userBddArray[i]);
+  }
+  resultArray =  BddArrayOpBF(bddManager, bddArray, num, CalOpXor);
+  userResultArray = Cal_MemAlloc(Cal_Bdd, num/2);
+  for (i=0; i<num/2; i++){
+    userResultArray[i] = CalBddGetExternalBdd(bddManager, resultArray[i]);
+  }
+  Cal_MemFree(bddArray);
+  Cal_MemFree(resultArray);
+  return userResultArray;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical AND of argument BDDs]
+
+  Description [Returns the BDD for logical AND of set of BDDs in the bddArray]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddMultiwayAnd(Cal_BddManager bddManager, Cal_Bdd *userBddArray)
+{
+  int i, numBdds = 0;
+  Cal_Bdd_t result;
+  Cal_Bdd_t *calBddArray;
+  Cal_Bdd userBdd;
+
+  for (numBdds  = 0; (userBdd = userBddArray[numBdds]); numBdds++){
+    if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+      return (Cal_Bdd) 0;
+    }
+  }
+  
+  if (numBdds == 0){
+    CalBddWarningMessage("Multiway AND called with 0 length array");
+    return (Cal_Bdd) 0;
+  }
+  else if (numBdds == 1){
+    return Cal_BddIdentity(bddManager, userBddArray[0]);
+  }
+  else{
+    calBddArray = Cal_MemAlloc(Cal_Bdd_t, numBdds+1);
+    for (i = 0; i < numBdds; i++){
+      calBddArray[i] = CalBddGetInternalBdd(bddManager, userBddArray[i]);
+    }
+    result = BddMultiwayOp(bddManager, calBddArray, numBdds, CalOpAnd);
+    Cal_MemFree(calBddArray);
+  }
+  return CalBddGetExternalBdd(bddManager, result);
+}
+ 
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical OR of argument BDDs]
+
+  Description [Returns the BDD for logical OR of set of BDDs in the bddArray]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddMultiwayOr(Cal_BddManager bddManager, Cal_Bdd *userBddArray)
+{
+  int i, numBdds = 0;
+  Cal_Bdd_t result;
+  Cal_Bdd_t *calBddArray;
+  Cal_Bdd userBdd;
+
+  for (numBdds = 0; (userBdd = userBddArray[numBdds]); numBdds++){
+    if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+      return (Cal_Bdd) 0;
+    }
+  }
+  
+  if (numBdds == 0){
+    CalBddWarningMessage("Multiway OR called with 0 length array");
+    return (Cal_Bdd) 0;
+  }
+  else if (numBdds == 1){
+    return Cal_BddIdentity(bddManager, userBddArray[0]);
+  }
+  else{
+    calBddArray = Cal_MemAlloc(Cal_Bdd_t, numBdds+1);
+    for (i = 0; i < numBdds; i++){
+      calBddArray[i] = CalBddGetInternalBdd(bddManager, userBddArray[i]);
+    }
+    result = BddMultiwayOp(bddManager, calBddArray, numBdds, CalOpOr);
+    Cal_MemFree(calBddArray);
+  }
+  return CalBddGetExternalBdd(bddManager, result);
+}
+ 
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD for logical XOR of argument BDDs]
+
+  Description [Returns the BDD for logical XOR of set of BDDs in the bddArray]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddMultiwayXor(Cal_BddManager bddManager, Cal_Bdd *userBddArray)
+{
+  int i, numBdds = 0;
+  Cal_Bdd_t result;
+  Cal_Bdd_t *calBddArray;
+  Cal_Bdd userBdd;
+
+  for (numBdds = 0; (userBdd = userBddArray[numBdds]); numBdds++){
+    if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+      return (Cal_Bdd) 0;
+    }
+  }
+  
+  if (numBdds == 0){
+    CalBddWarningMessage("Multiway OR called with 0 length array");
+    return (Cal_Bdd) 0;
+  }
+  else if (numBdds == 1){
+    return Cal_BddIdentity(bddManager, userBddArray[0]);
+  }
+  else{
+    calBddArray = Cal_MemAlloc(Cal_Bdd_t, numBdds+1);
+    for (i = 0; i < numBdds; i++){
+      calBddArray[i] = CalBddGetInternalBdd(bddManager, userBddArray[i]);
+    }
+    result = BddMultiwayOp(bddManager, calBddArray, numBdds, CalOpXor);
+    Cal_MemFree(calBddArray);
+  }
+  return CalBddGetExternalBdd(bddManager, result);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes result BDDs for an array of lists, each entry of which 
+  is pair of pointers, each of which points to a operand BDD or an entry in
+  another list with a smaller array index]
+
+  Description [Computes result BDDs for an array of lists, each entry of which
+  is pair of pointers, each of which points to a operand BDD or an entry in
+  another list with a smaller array index]
+
+  SideEffects [ThenBDD pointer of an entry is over written by the result BDD
+  and ElseBDD pointer is marked using FORWARD_FLAG]
+
+******************************************************************************/
+void
+CalRequestNodeListArrayOp(Cal_BddManager_t * bddManager,
+                          CalRequestNode_t ** requestNodeListArray,
+                          CalOpProc_t calOpProc)
+{
+  CalRequestNode_t *requestNode;
+  CalRequest_t F, G, result;
+  int pipeDepth, bddId, bddIndex;
+  CalHashTable_t **reqQueAtPipeDepth, *hashTable, *uniqueTableForId;
+  CalHashTable_t ***reqQue = bddManager->reqQue;
+  
+  /* ReqQueInsertUsingReqListArray */
+  for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+    reqQueAtPipeDepth = reqQue[pipeDepth];
+    for(requestNode = requestNodeListArray[pipeDepth];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetF(requestNode, F);
+      CalRequestIsForwardedTo(F);
+      CalRequestNodeGetG(requestNode, G);
+      CalRequestIsForwardedTo(G);
+      if((*calOpProc)(bddManager, F, G, &result) == 0){
+        CalBddNormalize(F, G);
+        CalBddGetMinId2(bddManager, F, G, bddId);
+        CalHashTableFindOrAdd(reqQueAtPipeDepth[bddId], F, G, &result);
+      }
+      CalRequestNodePutThenRequest(requestNode, result);
+      CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+    }
+  }
+
+  /* ReqQueApply */
+  for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+      reqQueAtPipeDepth = reqQue[pipeDepth];
+      hashTable = reqQueAtPipeDepth[bddId];
+      if(hashTable->numEntries){
+        CalHashTableApply(bddManager, hashTable, reqQueAtPipeDepth, calOpProc);
+      }
+    }
+  }
+
+#ifdef COMPUTE_MEMORY_OVERHEAD
+  {
+    calNumEntriesAfterApply = 0;
+    for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+      bddId = bddManager->indexToId[bddIndex];
+      for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+        reqQueAtPipeDepth = reqQue[pipeDepth];
+        hashTable = reqQueAtPipeDepth[bddId];
+        calNumEntriesAfterApply += hashTable->numEntries;
+      }
+    }
+  }
+#endif
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= 0; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+      hashTable = reqQue[pipeDepth][bddId];
+      if(hashTable->numEntries){
+        CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+      }
+    }
+  }
+
+#ifdef COMPUTE_MEMORY_OVERHEAD
+  {
+    CalRequestNode_t *requestNode;
+    calNumEntriesAfterReduce = 0;
+    for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+      CalRequestNode_t *next;
+      Cal_BddId_t bddId;
+      bddId = bddManager->indexToId[bddIndex];
+      for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+        hashTable = reqQue[pipeDepth][bddId];
+        for (requestNode = hashTable->requestNodeList;
+             requestNode != Cal_Nil(CalRequestNode_t); requestNode = next){
+          next = CalRequestNodeGetNextRequestNode(requestNode);
+          calNumEntriesAfterReduce++;
+        }
+      }
+    }
+    calAfterReduceToAfterApplyNodesRatio =
+        ((double)calNumEntriesAfterReduce)/((double)calNumEntriesAfterApply); 
+    calAfterReduceToUniqueTableNodesRatio = 
+        ((double)calNumEntriesAfterReduce)/((double)bddManager->numNodes);
+  }
+#endif
+
+  /* ReqListArrayReqForward */
+  for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+    for(requestNode = requestNodeListArray[pipeDepth];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetThenRequest(requestNode, result);
+      CalRequestIsForwardedTo(result);
+      Cal_Assert(CalBddIsForwarded(result) == 0);
+      CalRequestNodePutThenRequest(requestNode, result);
+    }
+  }
+
+  /* ReqQueCleanUp */
+  for(pipeDepth = 0; pipeDepth < bddManager->depth; pipeDepth++){
+    reqQueAtPipeDepth = reqQue[pipeDepth];
+    for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+      CalHashTableCleanUp(reqQueAtPipeDepth[bddId]);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Internal routine to compute a logical operation on a pair of BDDs]
+
+  Description [Internal routine to compute a logical operation on a pair of BDDs]
+
+  SideEffects [None]
+
+******************************************************************************/
+Cal_Bdd_t
+CalBddOpBF(
+  Cal_BddManager_t * bddManager,
+  CalOpProc_t calOpProc,
+  Cal_Bdd_t  F,
+  Cal_Bdd_t  G)
+{
+  Cal_Bdd_t result;
+  Cal_BddId_t minId, bddId;
+  /*Cal_BddIndex_t minIndex; Commented out because of the problem on alpha*/ 
+  int minIndex;
+  int bddIndex;
+  CalHashTable_t *hashTable, **hashTableArray, *uniqueTableForId;
+  
+  if (calOpProc(bddManager, F, G, &result)){
+    return result;
+  }
+  CalBddGetMinIdAndMinIndex(bddManager, F, G, minId, minIndex);
+  hashTableArray = bddManager->reqQue[0];
+  CalHashTableFindOrAdd(hashTableArray[minId], F, G, &result);
+  
+  /* ReqQueApply */
+  for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = hashTableArray[bddId];
+    if(hashTable->numEntries){
+      CalHashTableApply(bddManager, hashTable, hashTableArray, calOpProc);
+    }
+  }
+#ifdef COMPUTE_MEMORY_OVERHEAD
+  {
+    calNumEntriesAfterApply = 0;
+    for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+      bddId = bddManager->indexToId[bddIndex];
+      hashTable = hashTableArray[bddId];
+      calNumEntriesAfterApply += hashTable->numEntries;
+    }
+  }
+#endif
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = hashTableArray[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+  }
+  CalRequestIsForwardedTo(result);
+
+#ifdef COMPUTE_MEMORY_OVERHEAD
+  {
+    CalRequestNode_t *requestNode;
+    calNumEntriesAfterReduce = 0;
+    for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+      CalRequestNode_t *next;
+      Cal_BddId_t bddId;
+      
+      bddId = bddManager->indexToId[bddIndex];
+      hashTable = hashTableArray[bddId];
+      for (requestNode = hashTable->requestNodeList; requestNode !=
+                                                         Cal_Nil(CalRequestNode_t);
+                                                     requestNode = next){
+        next = CalRequestNodeGetNextRequestNode(requestNode);
+        calNumEntriesAfterReduce++;
+      }
+    }
+    calAfterReduceToAfterApplyNodesRatio =
+        ((double)calNumEntriesAfterReduce)/((double)calNumEntriesAfterApply); 
+    calAfterReduceToUniqueTableNodesRatio = 
+        ((double)calNumEntriesAfterReduce)/((double)bddManager->numNodes);
+  }
+#endif
+
+  /* Clean up */
+  for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(hashTableArray[bddId]);
+  }
+  return result;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Internal common routine for Cal_BddPairwiseAnd and Cal_BddPairwiseOr]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Cal_Bdd_t *
+BddArrayOpBF(Cal_BddManager_t * bddManager, Cal_Bdd_t*  bddArray,
+                int numFunction, CalOpProc_t calOpProc)
+{
+  Cal_BddId_t minId, bddId;
+  /*Cal_BddIndex_t minIndex = 0;*/
+  int minIndex = 0;
+  int bddIndex;
+  CalHashTable_t *hashTable, **hashTableArray, *uniqueTableForId;
+  Cal_Bdd_t F, G, result;
+  int numPairs = numFunction/2;
+  Cal_Bdd_t *resultArray = Cal_MemAlloc(Cal_Bdd_t, numPairs);
+  int i;
+  
+  hashTableArray = bddManager->reqQue[0];
+  for (i=0; i<numPairs; i++){
+    F = bddArray[i<<1];
+    G = bddArray[(i<<1)+1];
+    if ((*calOpProc)(bddManager, F, G, &result) == 0){
+      CalBddGetMinIdAndMinIndex(bddManager, F, G, minId, minIndex);
+      CalHashTableFindOrAdd(hashTableArray[minId], F, G, &result);
+    }
+    resultArray[i] = result;
+  }
+  
+  
+  /* ReqQueApply */
+  for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = hashTableArray[bddId];
+    if(hashTable->numEntries){
+      CalHashTableApply(bddManager, hashTable, hashTableArray, calOpProc);
+    }
+  }
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = hashTableArray[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+  }
+  for (i=0; i<numPairs; i++){
+    CalRequestIsForwardedTo(resultArray[i]);
+  }
+  /* Clean up */
+  for(bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(hashTableArray[bddId]);
+  }
+  return resultArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Internal routine for multiway operations]
+
+  Description [Internal routine for multiway operations]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddMultiwayOp(Cal_BddManager_t * bddManager, Cal_Bdd_t * calBddArray,
+              int  numBdds, CalOpProc_t op)
+{
+  int pipeDepth;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t result;
+  
+  BddArrayToRequestNodeListArray(bddManager, calBddArray, numBdds);
+  CalRequestNodeListArrayOp(bddManager, bddManager->requestNodeListArray, op);
+  for(pipeDepth = 0; pipeDepth < bddManager->depth-1; pipeDepth++){
+    CalRequestNode_t *next;
+    for(requestNode = bddManager->requestNodeListArray[pipeDepth];
+        requestNode != Cal_Nil(CalRequestNode_t); requestNode = next){
+      next = CalRequestNodeGetNextRequestNode(requestNode);
+      CalNodeManagerFreeNode(bddManager->nodeManagerArray[0],
+                             requestNode);
+    }
+    bddManager->requestNodeListArray[pipeDepth] =
+        Cal_Nil(CalRequestNode_t);
+  }
+  requestNode = bddManager->requestNodeListArray[bddManager->depth-1];
+  bddManager->requestNodeListArray[bddManager->depth-1] =
+      Cal_Nil(CalRequestNode_t); 
+  CalRequestNodeGetThenRequest(requestNode, result); 
+  CalNodeManagerFreeNode(bddManager->nodeManagerArray[0],
+                         requestNode);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an array of BDDs to a list of requests representing BDD
+  pairs]
+
+  Description [Converts an array of BDDs to a list of requests representing BDD]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+BddArrayToRequestNodeListArray(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t * calBddArray,
+  int  numBdds)
+{
+  int i;
+  Cal_Bdd_t lastBdd;
+  CalRequestNode_t *even, *odd, *requestNode, *requestNodeList, *head;
+  
+  bddManager->depth = CeilLog2(numBdds);
+  if (bddManager->depth > 10){
+    CalBddFatalMessage("Don't be stooopid\n, Use lesser depth\n");
+  }
+    
+  if (bddManager->depth > bddManager->maxDepth){
+    /* Need to reallocate the memory for reqQue and
+       requestNodeListArray */
+    int oldMaxDepth = bddManager->maxDepth;
+    bddManager->maxDepth = bddManager->depth;
+    
+    for (i=0; i<bddManager->maxDepth; i++){
+      bddManager->requestNodeListArray[i] = Cal_Nil(CalRequestNode_t);
+    }
+
+    bddManager->reqQue = Cal_MemRealloc(CalHashTable_t **, bddManager->reqQue,
+                                 bddManager->maxDepth);
+    for (i=oldMaxDepth; i<bddManager->maxDepth; i++){
+      int j;
+      bddManager->reqQue[i] = Cal_MemAlloc(CalHashTable_t *, bddManager->maxNumVars+1);
+      for (j=0; j<bddManager->numVars+1; j++){
+        bddManager->reqQue[i][j] = CalHashTableInit(bddManager, j);
+      }
+    }
+  }
+  lastBdd = bddManager->bddNull;
+  if (numBdds%2 != 0){/* Odd number of Bdd's */
+    lastBdd = calBddArray[numBdds-1];
+  }
+  requestNodeList = bddManager->requestNodeListArray[0];
+  for (i=0; i<numBdds/2; i++){
+    CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], requestNode);
+    CalRequestNodePutF(requestNode, calBddArray[2*i]);
+    CalRequestNodePutG(requestNode, calBddArray[2*i+1]);
+    CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+    requestNodeList = requestNode;
+  }
+  bddManager->requestNodeListArray[0] = requestNodeList;
+
+  for (i=1; i<bddManager->depth; i++){
+    requestNodeList = bddManager->requestNodeListArray[i];
+    head = bddManager->requestNodeListArray[i-1];
+    while ((odd = head) && (even = head->nextBddNode)){
+      CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], requestNode);
+      /*
+       * We don't have to worry about the Id's attached with
+       * the requestNode or with the then and else part of it.
+       */
+      CalRequestNodePutThenRequestNode(requestNode, odd);
+      CalRequestNodePutElseRequestNode(requestNode, even);
+      CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+      requestNodeList = requestNode;
+      head = CalRequestNodeGetNextRequestNode(even);
+    }
+    if (odd != Cal_Nil(CalRequestNode_t)){/* There is an  odd node at this
+                                      level */
+      if (CalBddIsBddNull(bddManager,lastBdd)){ /* There are no odd nodes
+                                                 * from previous levels, so
+                                                 * make this an odd node.
+                                                 */
+        CalBddPutBddNode(lastBdd, odd);
+      }
+      else{ /* There exists an odd node, so make a pair now. */
+        CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], requestNode);
+        CalRequestNodePutThenRequestNode(requestNode, odd);
+        CalRequestNodePutElseRequest(requestNode, lastBdd);
+        CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+        lastBdd = bddManager->bddNull;
+        requestNodeList = requestNode;
+      }
+    }
+    bddManager->requestNodeListArray[i] = requestNodeList;
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the smallest integer greater than or equal to log2 of a
+  number]
+
+  Description [Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CeilLog2(
+  int  number)
+{
+  int num, count;
+  for (num=number, count=0; num > 1; num >>= 1, count++);
+  if ((1 << count) != number) count++;
+  return count;
+}
+
+
+  
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calBddReorderTest.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddReorderTest.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddReorderTest.c	(revision 8)
@@ -0,0 +1,253 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddReorderTest.c]
+
+  PackageName [cal]
+
+  Synopsis    [A test routine for checking the functionality of
+  dynamic reordering.] 
+
+  Description []
+
+  SeeAlso     [optional]
+
+  Author      [Wilsin Gosti    (wilsin@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddReorderTest.c,v 1.1.1.4 1998/05/04 00:58:52 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static CalAddress_t asDoubleSpace[2];
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define CalBddReorderBddIsForwarded(bdd) \
+  (CAL_BDD_POINTER(CalBddGetElseBddNode(bdd)) == FORWARD_FLAG)
+
+#define CalBddReorderBddNodeIsForwarded(bddNode) \
+  (CAL_BDD_POINTER(CalBddNodeGetElseBddNode(bddNode)) == FORWARD_FLAG)
+
+#define CalBddReorderForward(bdd) \
+{ \
+  CalBddNode_t *_bddNode, *_bddNodeTagged; \
+  _bddNodeTagged = CalBddGetBddNode(bdd); \
+  _bddNode = CAL_BDD_POINTER(_bddNodeTagged); \
+  (bdd).bddId = _bddNode->thenBddId; \
+  (bdd).bddNode = (CalBddNode_t*) \
+                  (((CalAddress_t)(_bddNode->thenBddNode) & ~0xe) \
+                   ^(CAL_TAG0(_bddNodeTagged))); \
+}
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static double cpuTime();
+static long elapsedTime();
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+main(int argc, char **argv)
+{
+  Cal_Bdd expected;
+  Cal_Bdd a[100];
+  Cal_Bdd temp1;
+  Cal_Bdd temp2;
+  Cal_Bdd b, c, d, e, f, g, result;
+  Cal_BddManager_t *bddManager;
+  CalBddNode_t *bddNode;
+  int i;
+  int numVars;
+  int siftFlag = 0;
+  
+  if (argc == 1) {
+    numVars = 5;
+  } else if (argc >= 2) {
+    numVars = atoi(argv[1]);
+  }
+  if (argc == 3) {
+    siftFlag = 1;
+  }
+
+  bddManager = Cal_BddManagerInit();
+
+  for (i = 0; i < 2 * numVars; i++) {
+    a[i] = Cal_BddManagerCreateNewVarLast(bddManager);
+  }
+
+  result = Cal_BddZero(bddManager);
+  for (i = 0; i < numVars; i++) {
+    temp1 = Cal_BddAnd(bddManager, a[i], a[numVars + i]);
+    temp2 = Cal_BddOr(bddManager, result, temp1);
+    Cal_BddFree(bddManager, temp1);
+    Cal_BddFree(bddManager, result);
+    result = temp2;
+  }
+  Cal_BddManagerGC(bddManager);
+  Cal_BddStats(bddManager, stdout);
+  cpuTime();
+  elapsedTime();
+  printf("%%%%%%%%%%%% Reordering %%%%%%%%%%%%%%%%%%%\n");
+  if (siftFlag){
+    printf("Using Sift Technique\n");
+    Cal_BddDynamicReordering(bddManager, CAL_REORDER_SIFT);
+  }
+  else{
+    printf("Using Window Technique\n");
+    Cal_BddDynamicReordering(bddManager, CAL_REORDER_WINDOW);
+  }
+  Cal_BddReorder(bddManager);
+  printf("CPU time: %-8.2f\t Elapsed Time = %-10ld\n", cpuTime(), elapsedTime());
+  printf("%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%\n");
+  Cal_BddManagerGC(bddManager);
+  Cal_BddStats(bddManager, stdout);
+  /*Cal_BddFunctionPrint(bddManager, result, "Result");*/
+  temp1 = Cal_BddZero(bddManager);
+  for (i = 0; i < numVars; i++) {
+    temp2 = Cal_BddAnd(bddManager, a[i], a[numVars + i]);
+    expected = Cal_BddOr(bddManager, temp1, temp2);
+    Cal_BddFree(bddManager, temp1);
+    Cal_BddFree(bddManager, temp2);
+    temp1 = expected;
+  }
+
+  if (!Cal_BddIsEqual(bddManager, result, expected)) {
+    printf("ERROR: BDDs are not equal\n");
+    Cal_BddFunctionPrint(bddManager, result, "Result");
+    Cal_BddFunctionPrint(bddManager, expected, "Expected");
+  }
+  printf("\n%%%%%%BDDs are equal\n");
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+  Cal_BddManagerGC(bddManager);
+  Cal_BddStats(bddManager, stdout);
+  Cal_BddManagerQuit(bddManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+cpuTime()
+{
+  static double timeNew, timeOld;
+  struct rusage rusage;
+  static flag = 0;
+
+  getrusage(RUSAGE_SELF, &rusage);
+  if (flag == 0){
+    timeOld = timeNew = rusage.ru_utime.tv_sec+
+        ((double)rusage.ru_utime.tv_usec)/1000000;
+    flag = 1;
+  }
+  else {
+    timeOld = timeNew;
+    timeNew = rusage.ru_utime.tv_sec+
+        ((float)rusage.ru_utime.tv_usec)/1000000;
+  }
+  return timeNew - timeOld;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the time.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static long
+elapsedTime()
+{
+  static long time_new, time_old;
+  struct timeval t;
+  struct timezone tz;
+  static flag = 0;
+  
+  gettimeofday(&t, &tz);
+  if (flag == 0){
+    time_old = time_new = t.tv_sec;
+    flag = 1;
+  }
+  else {
+    time_old = time_new;
+    time_new =  t.tv_sec;
+  }
+  return time_new-time_old;
+}
Index: /vis_dev/glu-2.1/src/calBdd/calBddSatisfy.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddSatisfy.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddSatisfy.c	(revision 8)
@@ -0,0 +1,373 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddSatisfy.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for BDD satisfying valuation.]
+              
+
+  Description [ ]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+              ] 
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddSatisfy.c,v 1.1.1.3 1998/05/04 00:58:53 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Cal_Bdd_t BddSatisfyStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f);
+static Cal_Bdd_t BddSatisfySupportStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_BddId_t * support);
+static int IndexCmp(const void * p1, const void * p2);
+static double BddSatisfyingFractionStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, CalHashTable_t * hashTable);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Name        [Cal_BddSatisfy]
+
+  Synopsis    [Returns a BDD which implies f, true for
+               some valuation on which f is true, and which has at most
+               one node at each level]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddSatisfy(Cal_BddManager bddManager, Cal_Bdd  fUserBdd)
+{
+  Cal_Bdd_t f;
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    if(CalBddIsBddZero(bddManager, f)){
+      CalBddWarningMessage("Cal_BddSatisfy: argument is false");
+      return (fUserBdd);
+    }
+    f = BddSatisfyStep(bddManager, f);
+    return CalBddGetExternalBdd(bddManager, f);
+  }
+  return (Cal_Bdd) 0;
+}
+
+
+/**Function********************************************************************
+
+  Name        [Cal_BddSatisfySupport]
+
+  Synopsis    [Returns a special cube contained in f.] 
+
+  Description [The returned BDD which implies f, is true for some valuation on
+               which f is true, which has at most one node at each level,
+               and which has exactly one node corresponding to each variable
+               which is associated with something in the current variable
+               association.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddSatisfySupport(Cal_BddManager bddManager, Cal_Bdd fUserBdd)
+{
+  Cal_BddId_t *support, *p;
+  long i;
+  Cal_Bdd_t result;
+  Cal_Bdd_t f;
+  
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    if(CalBddIsBddZero(bddManager, f)){
+      CalBddWarningMessage("Cal_BddSatisfySupport: argument is false");
+      return (fUserBdd);
+    }
+    support = Cal_MemAlloc(Cal_BddId_t, bddManager->numVars+1);
+    for(i = 1, p = support; i <= bddManager->numVars; i++){
+      if(!CalBddIsBddNull(bddManager,
+          bddManager->currentAssociation->varAssociation[i])){
+        *p = bddManager->idToIndex[i];
+        ++p;
+      }
+    }
+    *p = 0;
+    qsort(support, (unsigned)(p - support), sizeof(Cal_BddId_t), IndexCmp);
+    while(p != support){
+      --p;
+      *p = bddManager->indexToId[*p];
+    }
+    result = BddSatisfySupportStep(bddManager, f, support);
+    Cal_MemFree(support);
+    return CalBddGetExternalBdd(bddManager, result);
+  }
+  return (Cal_Bdd) 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the fraction of valuations which make f true. (Note that
+  this fraction is independent of whatever set of variables f is supposed to be
+  a function of)]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+double
+Cal_BddSatisfyingFraction(Cal_BddManager bddManager, Cal_Bdd fUserBdd)
+{
+  double fraction;
+  CalHashTable_t *hashTable;
+  Cal_Bdd_t f;
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    hashTable = CalHashTableOneInit(bddManager, sizeof(double));
+    fraction = BddSatisfyingFractionStep(bddManager, f, hashTable);
+    CalHashTableOneQuit(hashTable);
+    return fraction;
+  }
+  return 0.0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Name        [BddSatisfyStep]
+
+  Synopsis    [Returns a BDD which implies f, is true for some valuation
+  on which f is true, and which has at most one node at each level]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddSatisfyStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f)
+{
+  Cal_Bdd_t tempBdd;
+  Cal_Bdd_t result;
+
+  if(CalBddIsBddConst(f)){
+    return (f);
+  }
+  CalBddGetThenBdd(f, tempBdd);
+  if(CalBddIsBddZero(bddManager, tempBdd)){
+    CalBddGetElseBdd(f, tempBdd);
+    tempBdd = BddSatisfyStep(bddManager, tempBdd);
+    if(!CalUniqueTableForIdFindOrAdd(bddManager,
+        bddManager->uniqueTable[CalBddGetBddId(f)],
+        CalBddZero(bddManager), tempBdd, &result)){
+      CalBddIcrRefCount(tempBdd);
+    }
+  }
+  else{
+    tempBdd = BddSatisfyStep(bddManager, tempBdd);
+    if(!CalUniqueTableForIdFindOrAdd(bddManager,
+        bddManager->uniqueTable[CalBddGetBddId(f)],
+        tempBdd, CalBddZero(bddManager), &result)){
+      CalBddIcrRefCount(tempBdd);
+    }
+  }
+  return (result);
+}
+
+
+/**Function********************************************************************
+
+  Name        [BddSatisfySupportStep]
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddSatisfySupportStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  Cal_BddId_t * support)
+{
+  Cal_Bdd_t tempBdd;
+  Cal_Bdd_t result;
+
+  if(!*support){
+    return BddSatisfyStep(bddManager, f);
+  }
+  if(CalBddGetBddIndex(bddManager, f) <= bddManager->idToIndex[*support]){
+    if(CalBddGetBddId(f) == *support){
+	++support;
+    }
+    CalBddGetThenBdd(f, tempBdd);
+    if(CalBddIsBddZero(bddManager, tempBdd)){
+      CalBddGetElseBdd(f, tempBdd);
+      tempBdd = BddSatisfySupportStep(bddManager, tempBdd, support);
+      if(!CalUniqueTableForIdFindOrAdd(bddManager,
+          bddManager->uniqueTable[CalBddGetBddId(f)],
+          CalBddZero(bddManager), tempBdd, &result)){
+        CalBddIcrRefCount(tempBdd);
+      }
+    }
+    else{
+      tempBdd = BddSatisfySupportStep(bddManager, tempBdd, support);
+      if(!CalUniqueTableForIdFindOrAdd(bddManager,
+          bddManager->uniqueTable[CalBddGetBddId(f)],
+          tempBdd, CalBddZero(bddManager), &result)){
+        CalBddIcrRefCount(tempBdd);
+      }
+    }
+  }
+  else{
+    tempBdd = BddSatisfySupportStep(bddManager, f, support+1);
+    if(!CalUniqueTableForIdFindOrAdd(bddManager,
+        bddManager->uniqueTable[*support],
+        CalBddZero(bddManager), tempBdd, &result)){
+      CalBddIcrRefCount(tempBdd);
+    }
+  }
+  return (result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+IndexCmp(const void * p1, const void * p2)
+{
+  Cal_BddIndex_t i1, i2;
+
+  i1 = *(Cal_BddId_t *)p1;
+  i2 = *(Cal_BddId_t *)p2;
+  if(i1 < i2){
+    return (-1);
+  }
+  if(i1 > i2){
+    return (1);
+  }
+  return (0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+BddSatisfyingFractionStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  CalHashTable_t * hashTable)
+{
+  double *resultPtr, result;
+  Cal_Bdd_t thenBdd, elseBdd;
+
+  if(CalBddIsBddConst(f)){
+    if(CalBddIsBddZero(bddManager, f)){
+      return 0.0;
+    }
+    return 1.0;
+  }
+  if(CalHashTableOneLookup(hashTable, f, (char **)&resultPtr)){
+    return (*resultPtr);
+  }
+  CalBddGetThenBdd(f, thenBdd);
+  CalBddGetElseBdd(f, elseBdd);
+  result = 
+      0.5 * BddSatisfyingFractionStep(bddManager, thenBdd, hashTable) +
+      0.5 * BddSatisfyingFractionStep(bddManager, elseBdd, hashTable);
+  CalHashTableOneInsert(hashTable, f, (char *)&result);
+  return (result);
+}
+
Index: /vis_dev/glu-2.1/src/calBdd/calBddSize.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddSize.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddSize.c	(revision 8)
@@ -0,0 +1,624 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddSize.c]
+
+  PackageName [cal]
+
+  Synopsis    [BDD size and profile routines]
+              
+
+  Description [ ]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.
+              ] 
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddSize.c,v 1.3 2002/09/21 20:39:24 fabio Exp $]
+
+******************************************************************************/
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef int (*CountFn_t)(Cal_Bdd_t);
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void BddMarkBdd(Cal_Bdd_t f);
+static int BddCountNoNodes(Cal_Bdd_t f);
+static int BddCountNodes(Cal_Bdd_t f);
+static long BddSizeStep(Cal_Bdd_t f, CountFn_t countFn);
+static void BddProfileStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, long * levelCounts, CountFn_t countFn);
+static void BddHighestRefStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, CalHashTable_t * h);
+static void BddDominatedStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, long * funcCounts, CalHashTable_t * h);
+
+/**AutomaticEnd***************************************************************/
+
+static
+int (*(countingFns[]))(Cal_Bdd_t) = 
+{
+  BddCountNoNodes,
+  BddCountNodes,
+};
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes in f when negout is nonzero. If
+  negout is zero, we pretend that the BDDs don't have negative-output pointers.]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+long
+Cal_BddSize(Cal_BddManager bddManager, Cal_Bdd fUserBdd, int  negout)
+{
+  Cal_Bdd_t f, g;
+
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    g =  CalBddOne(bddManager);
+    CalBddPutMark(g, 0);
+    BddMarkBdd(f);
+    return BddSizeStep(f, countingFns[!negout]);
+  }
+  return (0l);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The routine is like Cal_BddSize, but takes a null-terminated
+               array of BDDs and accounts for sharing of nodes.]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+long
+Cal_BddSizeMultiple(Cal_BddManager bddManager, Cal_Bdd *fUserBddArray,
+                    int  negout)
+{
+  long size;
+  Cal_Bdd_t *f;
+  Cal_Bdd_t g;
+  Cal_Bdd_t *fArray;
+  int i, j;
+  
+  if (CalBddArrayPreProcessing(bddManager, fUserBddArray) == 0){
+    return -1;
+  }
+  
+  for(i = 0; fUserBddArray[i]; ++i);
+
+  fArray = Cal_MemAlloc(Cal_Bdd_t, i+1);
+  for (j=0; j < i; j++){
+    fArray[j] = CalBddGetInternalBdd(bddManager,fUserBddArray[j]);
+  }
+  fArray[j] = bddManager->bddNull;
+  
+  g  =  CalBddOne(bddManager);
+  CalBddPutMark(g, 0);
+  for(f = fArray; !CalBddIsBddNull(bddManager, *f); ++f){
+    BddMarkBdd(*f);
+  }
+  size  =  0l;
+  for(f = fArray; !CalBddIsBddNull(bddManager, *f); ++f){
+    size +=  BddSizeStep(*f, countingFns[!negout]);
+  }
+  Cal_MemFree(fArray);
+  return size;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a "node profile" of f, i.e., the number of nodes at each
+  level in f.]
+
+  Description [negout is as in Cal_BddSize. levelCounts should be an array of
+  size Cal_BddVars(bddManager)+1 to hold the profile.]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddProfile(Cal_BddManager bddManager, Cal_Bdd fUserBdd,
+               long * levelCounts, int  negout)
+{
+  Cal_BddIndex_t i;
+  Cal_Bdd_t f, g;
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    for(i = 0; i <=  bddManager->numVars; i++){
+      levelCounts[i] = 0l;
+    }
+    g = CalBddOne(bddManager);
+    CalBddPutMark(g, 0);
+    BddMarkBdd(f);
+    BddProfileStep(bddManager, f, levelCounts, countingFns[!negout]);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddProfileMultiple(Cal_BddManager bddManager, Cal_Bdd *fUserBddArray,
+                       long * levelCounts, int  negout)
+{
+  Cal_Bdd_t *f, *fArray;
+  Cal_Bdd_t g;
+  int i, j;
+  
+  CalBddArrayPreProcessing(bddManager, fUserBddArray);
+
+  for(i = 0; fUserBddArray[i]; ++i);
+
+  fArray = Cal_MemAlloc(Cal_Bdd_t, i+1);
+  for (j=0; j < i; j++){
+    fArray[j] = CalBddGetInternalBdd(bddManager,fUserBddArray[j]);
+  }
+  fArray[j] = bddManager->bddNull;
+    
+  for(i = 0; i <=  bddManager->numVars; i++){
+    levelCounts[i] = 0l;
+  }
+  g = CalBddOne(bddManager);
+  CalBddPutMark(g, 0);
+  for(f = fArray; !CalBddIsBddNull(bddManager, *f); ++f){
+    BddMarkBdd(*f);
+  }
+  for(f = fArray; !CalBddIsBddNull(bddManager, *f); ++f){
+    BddProfileStep(bddManager, *f, levelCounts, countingFns[!negout]);
+  }
+  Cal_MemFree(fArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a "function profile" for f.]
+
+  Description [The nth entry of the function
+  profile array is the number of subfunctions of f which may be obtained by 
+  restricting the variables whose index is less than n.  An entry of zero 
+  indicates that f is independent of the variable with the corresponding index.]
+
+  SideEffects []
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddFunctionProfile(Cal_BddManager bddManager, Cal_Bdd fUserBdd,
+                       long * funcCounts) 
+{
+  long i;
+  Cal_BddIndex_t j;
+  CalHashTable_t *h;
+  Cal_Bdd_t f;
+  
+  /* The number of subfunctions obtainable by restricting the */
+  /* variables of index < n is the number of subfunctions whose top */
+  /* variable has index n plus the number of subfunctions obtainable */
+  /* by restricting the variables of index < n+1 minus the number of */
+  /* these latter subfunctions whose highest reference is by a node at */
+  /* level n. */
+  /* The strategy will be to start with the number of subfunctions */
+  /* whose top variable has index n.  We compute the highest level at */
+  /* which each subfunction is referenced.  Then we work bottom up; at */
+  /* level n we add in the result from level n+1 and subtract the */
+  /* number of subfunctions whose highest reference is at level n. */
+
+  Cal_BddProfile(bddManager, fUserBdd, funcCounts, 0);
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    /* Encode the profile.  The low bit of a count will be zero for */
+    /* those levels where f actually has a node. */
+    for(j = 0; j < bddManager->numVars; ++j){
+      if(!funcCounts[j]){
+	funcCounts[j] = 1;
+      }
+      else{
+	funcCounts[j] <<= 1;
+      }
+    }
+    h = CalHashTableOneInit(bddManager, sizeof(int));
+    /* For each subfunction in f, compute the highest level where it is */
+    /* referenced.  f itself is conceptually referenced at the highest */
+    /* possible level, which we represent by -1. */
+    i =  -1;
+    CalHashTableOneInsert(h, f, (char *)&i);
+    BddHighestRefStep(bddManager, f, h);
+    /* Walk through these results.  For each subfunction, decrement the */
+    /* count at the highest level where it is referenced. */
+    BddDominatedStep(bddManager, f, funcCounts, h);
+    CalHashTableOneQuit(h);
+    /* Now add each level n+1 result to that of level n. */
+    for(i = bddManager->numVars-1, j = i+1; i>=  0; --i){
+      if(funcCounts[i] !=  1){
+	funcCounts[i] = (funcCounts[i] >> 1) + funcCounts[j];
+	j = i;
+      }
+      else{
+	  funcCounts[i] = 0;
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a "function profile" for fArray.]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddFunctionProfileMultiple(Cal_BddManager bddManager, Cal_Bdd
+                               *fUserBddArray, long * funcCounts)
+{
+  long i;
+  Cal_BddIndex_t j;
+  Cal_Bdd_t *f, *fArray;
+  CalHashTable_t *h;
+
+  CalBddArrayPreProcessing(bddManager, fUserBddArray);
+
+  for(i = 0; fUserBddArray[i]; ++i);
+
+  fArray = Cal_MemAlloc(Cal_Bdd_t, i+1);
+  for (j=0; j < i; j++){
+    fArray[j] = CalBddGetInternalBdd(bddManager,fUserBddArray[j]);
+  }
+  fArray[j] = bddManager->bddNull;
+
+  /* See cmu_bdd_function_profile for the strategy involved here. */
+  Cal_BddProfileMultiple(bddManager, fUserBddArray, funcCounts, 0);
+  for(j = 0; j < bddManager->numVars; ++j){
+    if(!funcCounts[j]){
+      funcCounts[j] = 1;
+    }
+    else{
+      funcCounts[j] <<= 1;
+    }
+  }
+  h = CalHashTableOneInit(bddManager, sizeof(int));
+  for(f = fArray; !CalBddIsBddNull(bddManager, *f); ++f){
+    BddHighestRefStep(bddManager, *f, h);
+  }
+  i = -1;
+  for(f = fArray; !CalBddIsBddNull(bddManager, *f); ++f){
+    CalHashTableOneInsert(h, *f, (char *)&i);
+  }
+  for(f = fArray; !CalBddIsBddNull(bddManager, *f); ++f){
+    BddDominatedStep(bddManager, *f, funcCounts, h);
+  }
+  CalHashTableOneQuit(h);
+  for(i = bddManager->numVars-1, j = i+1; i >=  0; --i){
+    if(funcCounts[i] !=  1){
+      funcCounts[i] = (funcCounts[i] >> 1) + funcCounts[j];
+      j = i;
+    }
+    else{
+      funcCounts[i] = 0;
+    }
+  }
+  Cal_MemFree(fArray);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddMarkBdd(Cal_Bdd_t  f)
+{
+  int currMarking, thisMarking;
+  Cal_Bdd_t thenBdd, elseBdd;
+
+  currMarking = CalBddGetMark(f);
+  thisMarking = (1 << CalBddIsComplement(f));
+  if(currMarking & thisMarking){
+    return;
+  }
+  CalBddPutMark(f, currMarking | thisMarking);
+  if(CalBddIsBddConst(f)){
+    return;
+  }
+  CalBddGetThenBdd(f, thenBdd);
+  BddMarkBdd(thenBdd);
+  CalBddGetElseBdd(f, elseBdd);
+  BddMarkBdd(elseBdd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+BddCountNoNodes(
+  Cal_Bdd_t  f)
+{
+  return (CalBddGetMark(f) > 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+BddCountNodes(
+  Cal_Bdd_t  f)
+{
+  int mark;
+
+  mark = CalBddGetMark(f);
+  return (((mark & 0x1) !=  0) + ((mark & 0x2) !=  0));
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static long
+BddSizeStep(
+  Cal_Bdd_t  f,
+  CountFn_t countFn)
+{
+  long result;
+  Cal_Bdd_t thenBdd, elseBdd;
+
+  if(!CalBddGetMark(f)){
+    return (0l);
+  }
+  result = (*countFn)(f);
+  if(!CalBddIsBddConst(f)){
+    CalBddGetThenBdd(f, thenBdd);
+    CalBddGetElseBdd(f, elseBdd);
+    result +=
+        BddSizeStep(thenBdd, countFn) +
+        BddSizeStep(elseBdd, countFn);
+  }
+  CalBddPutMark(f, 0);
+  return result;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddProfileStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  long * levelCounts,
+  CountFn_t countFn)
+{
+  Cal_Bdd_t thenBdd, elseBdd;
+  if(!CalBddGetMark(f)){
+    return;
+  }
+  if(CalBddIsBddConst(f)){
+    levelCounts[bddManager->numVars] += (*countFn)(f);
+  }
+  else{
+    levelCounts[CalBddGetBddIndex(bddManager, f)] += (*countFn)(f);
+    CalBddGetThenBdd(f, thenBdd);
+    BddProfileStep(bddManager, thenBdd, levelCounts, countFn);
+    CalBddGetElseBdd(f, elseBdd);
+    BddProfileStep(bddManager, elseBdd, levelCounts, countFn);
+  }
+  CalBddPutMark(f, 0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddHighestRefStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  CalHashTable_t * h)
+{
+  int fIndex;
+  Cal_Bdd_t keyBdd;
+  int *dataPtr;
+
+  if(CalBddIsBddConst(f)){
+    return;
+  }
+  fIndex = CalBddGetBddIndex(bddManager, f);
+  CalBddGetThenBdd(f, keyBdd);
+  if(CalHashTableOneLookup(h, keyBdd, (char **)&dataPtr)){
+    if(*dataPtr > fIndex){
+      *dataPtr = fIndex;
+    }
+  }
+  else{
+    CalHashTableOneInsert(h, keyBdd, (char *)&fIndex);
+    BddHighestRefStep(bddManager, keyBdd, h);
+  }
+  CalBddGetElseBdd(f, keyBdd);
+  if(CalHashTableOneLookup(h, keyBdd, (char **)&dataPtr)){
+    if(*dataPtr > fIndex){
+      *dataPtr = fIndex;
+    }
+  }
+  else{
+    CalHashTableOneInsert(h, keyBdd, (char *)&fIndex);
+    BddHighestRefStep(bddManager, keyBdd, h);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddDominatedStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  long * funcCounts,
+  CalHashTable_t * h)
+{
+  Cal_Bdd_t thenBdd, elseBdd;
+  int *dataPtr;
+
+  CalHashTableOneLookup(h, f, (char **)&dataPtr);
+  if(*dataPtr >=  0)
+    funcCounts[*dataPtr] -= 2;
+  if(*dataPtr > -2){
+    *dataPtr = -2;
+    if(!CalBddIsBddConst(f)){
+      CalBddGetThenBdd(f, thenBdd);
+      BddDominatedStep(bddManager, thenBdd, funcCounts, h);
+      CalBddGetElseBdd(f, elseBdd);
+      BddDominatedStep(bddManager, elseBdd, funcCounts, h);
+    }
+  }
+}
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calBddSubstitute.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddSubstitute.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddSubstitute.c	(revision 8)
@@ -0,0 +1,407 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddSubstitute.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routine for simultaneous substitution of an array of
+  variables with an array of functions.]
+
+  Description [Routine for simultaneous substitution of an array of
+  variables with an array of functions.]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddSubstitute.c,v 1.1.1.4 1998/05/04 00:58:54 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CalHashTableSubstituteApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, int lastIndex, CalHashTable_t ** reqQueForSubstitute);
+static void CalHashTableSubstituteReduce(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t ** reqQueForITE, CalHashTable_t * uniqueTableForId);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Substitute a set of variables by functions]
+
+  Description [Returns a BDD for f using the substitution defined by current
+  variable association. Each variable is replaced by its associated BDDs. The 
+  substitution is effective simultaneously]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddCompose]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddSubstitute(Cal_BddManager bddManager, Cal_Bdd fUserBdd)
+{
+  CalRequest_t result;
+  int bddId, bddIndex, lastIndex;
+  CalHashTable_t *hashTable;
+  CalHashTable_t *uniqueTableForId;
+  CalHashTable_t **reqQueForSubstitute = bddManager->reqQue[0];
+  CalHashTable_t **reqQueForITE = bddManager->reqQue[1]; 
+  Cal_Bdd_t f;
+  
+  if (CalBddPreProcessing(bddManager, 1, fUserBdd) == 0){
+    return (Cal_Bdd) 0;
+  }
+  f = CalBddGetInternalBdd(bddManager, fUserBdd);  
+  if(CalBddIsBddConst(f)){
+    return CalBddGetExternalBdd(bddManager, f);
+  }
+
+  CalHashTableFindOrAdd(reqQueForSubstitute[CalBddGetBddId(f)], f, 
+    bddManager->bddNull, &result);
+
+  /* ReqQueApply */
+  lastIndex = bddManager->currentAssociation->lastBddIndex;
+  for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = reqQueForSubstitute[bddId];
+    if(hashTable->numEntries){
+      CalHashTableSubstituteApply(bddManager, hashTable, lastIndex, 
+                                  reqQueForSubstitute);
+    }
+  }
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= 0; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = reqQueForSubstitute[bddId];
+    if(hashTable->numEntries){
+      CalHashTableSubstituteReduce(bddManager, hashTable,
+                                   reqQueForITE, uniqueTableForId);
+    }
+  }
+
+  CalRequestIsForwardedTo(result);
+
+  /* ReqQueCleanUp */
+  for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+    CalHashTableCleanUp(reqQueForSubstitute[bddId]);
+  }
+
+  return CalBddGetExternalBdd(bddManager, result);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableSubstituteApply(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  int  lastIndex,
+  CalHashTable_t ** reqQueForSubstitute)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_BddId_t bddId;
+  /*Cal_BddIndex_t bddIndex;*/
+  int bddIndex;
+  Cal_Bdd_t f, calBdd;
+  Cal_Bdd_t nullBdd = bddManager->bddNull;
+
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      /* Process the requestNode */
+      CalRequestNodeGetF(requestNode, f);
+      /* Process Left Cofactor */
+      CalBddGetThenBdd(f, calBdd);
+      bddId = CalBddGetBddId(calBdd);
+      bddIndex = bddManager->idToIndex[bddId];
+      if(bddIndex <= lastIndex){
+        CalHashTableFindOrAdd(reqQueForSubstitute[bddId], calBdd, nullBdd, 
+            &calBdd);
+      }
+      CalBddIcrRefCount(calBdd);
+      CalRequestNodePutThenRequest(requestNode, calBdd);
+      /* Process Right Cofactor */
+      CalBddGetElseBdd(f, calBdd);
+      bddId = CalBddGetBddId(calBdd);
+      bddIndex = bddManager->idToIndex[bddId];
+      if(bddIndex <= lastIndex){
+        CalHashTableFindOrAdd(reqQueForSubstitute[bddId], calBdd, nullBdd, 
+            &calBdd);
+      }
+      CalBddIcrRefCount(calBdd);
+      CalRequestNodePutElseRequest(requestNode, calBdd);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableSubstituteReduce(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  CalHashTable_t ** reqQueForITE,
+  CalHashTable_t * uniqueTableForId)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  Cal_BddId_t varBddId = hashTable->bddId;
+  CalNodeManager_t *nodeManager = hashTable->nodeManager;
+  /*CalRequestNode_t *requestNodeList = hashTable->requestNodeList;*/
+  CalRequestNode_t *endNode = hashTable->endNode;
+  CalRequestNode_t *requestNodeListForITE = Cal_Nil(CalRequestNode_t);
+  CalRequestNode_t *requestNode, *next;
+  CalBddNode_t *bddNode;
+  Cal_Bdd_t varBdd;
+  Cal_Bdd_t thenBdd, elseBdd, result;
+  Cal_Bdd_t h;
+  Cal_BddIndex_t varBddIndex;
+  Cal_BddRefCount_t refCount;
+  int bddId, bddIndex;
+  CalHashTable_t *hashTableForITE;
+
+  varBddIndex = bddManager->idToIndex[varBddId];
+  varBdd = bddManager->varBdds[varBddId];
+  h = bddManager->currentAssociation->varAssociation[varBddId];
+  if(!CalBddIsBddNull(bddManager, h)){
+    for(i = 0; i < numBins; i++){
+      for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+          requestNode != Cal_Nil(CalRequestNode_t);
+          requestNode = next){
+        next = CalRequestNodeGetNextRequestNode(requestNode);
+        /* Process the requestNode */
+        CalRequestNodeGetThenRequest(requestNode, thenBdd);
+        CalRequestNodeGetElseRequest(requestNode, elseBdd);
+        CalRequestIsForwardedTo(thenBdd);
+        CalRequestIsForwardedTo(elseBdd);
+        if(CalBddIsEqual(thenBdd, elseBdd)){
+          CalBddNodeGetRefCount(requestNode, refCount);
+          CalBddAddRefCount(thenBdd, refCount - 2);
+          CalRequestNodePutThenRequest(requestNode, thenBdd);
+          CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+          endNode->nextBddNode = requestNode;
+          endNode = requestNode;
+        }
+        else{
+          CalBddDcrRefCount(thenBdd);
+          CalBddDcrRefCount(elseBdd);
+          result = CalOpITE(bddManager, h, thenBdd, elseBdd, reqQueForITE);
+          CalRequestNodePutThenRequest(requestNode, result);
+          CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+          CalRequestNodePutNextRequestNode(requestNode,
+              requestNodeListForITE);
+          requestNodeListForITE = requestNode;
+        }
+      }
+    }
+  }
+  else{
+    for(i = 0; i < numBins; i++){
+      for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+          requestNode != Cal_Nil(CalRequestNode_t);
+          requestNode = next){
+        next = CalRequestNodeGetNextRequestNode(requestNode);
+        /* Process the requestNode */
+        CalRequestNodeGetThenRequest(requestNode, thenBdd);
+        CalRequestNodeGetElseRequest(requestNode, elseBdd);
+        CalRequestIsForwardedTo(thenBdd);
+        CalRequestIsForwardedTo(elseBdd);
+        if(CalBddIsEqual(thenBdd, elseBdd)){
+          CalBddNodeGetRefCount(requestNode, refCount);
+          CalBddAddRefCount(thenBdd, refCount - 2);
+          CalRequestNodePutThenRequest(requestNode, thenBdd);
+          CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+          endNode->nextBddNode = requestNode;
+          endNode = requestNode;
+        }
+        else if(varBddIndex < CalBddGetBddIndex(bddManager, thenBdd) &&
+            varBddIndex < CalBddGetBddIndex(bddManager, elseBdd)){
+          if(CalUniqueTableForIdLookup(bddManager, uniqueTableForId,
+              thenBdd, elseBdd, &result) == 1){
+            CalBddDcrRefCount(thenBdd);
+            CalBddDcrRefCount(elseBdd);
+            CalBddNodeGetRefCount(requestNode, refCount);
+            CalBddAddRefCount(result, refCount);
+            CalRequestNodePutThenRequest(requestNode, result);
+            CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+            endNode->nextBddNode = requestNode;
+            endNode = requestNode;
+          }
+          else if(CalBddIsOutPos(thenBdd)){
+            CalRequestNodePutThenRequest(requestNode, thenBdd);
+            CalRequestNodePutElseRequest(requestNode, elseBdd);
+            CalHashTableAddDirect(uniqueTableForId, requestNode);
+            bddManager->numNodes++;
+            bddManager->gcCheck--;
+          }
+          else{
+            CalNodeManagerAllocNode(nodeManager, bddNode);
+            CalBddNodePutThenBddId(bddNode, CalBddGetBddId(thenBdd));
+            CalBddNodePutThenBddNode(bddNode,
+                CalBddGetBddNodeNot(thenBdd));
+            CalBddNodePutElseBddId(bddNode, CalBddGetBddId(elseBdd));
+            CalBddNodePutElseBddNode(bddNode,
+                CalBddGetBddNodeNot(elseBdd));
+            CalBddNodeGetRefCount(requestNode, refCount);
+            CalBddNodePutRefCount(bddNode, refCount);
+            CalHashTableAddDirect(uniqueTableForId, bddNode);
+            bddManager->numNodes++;
+            bddManager->gcCheck--;
+            CalRequestNodePutThenRequestId(requestNode, varBddId);
+            CalRequestNodePutThenRequestNode(requestNode,
+                CalBddNodeNot(bddNode));
+            CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+            endNode->nextBddNode = requestNode;
+            endNode = requestNode;
+          }
+        }
+        else{
+          CalBddDcrRefCount(thenBdd);
+          CalBddDcrRefCount(elseBdd);
+          result = CalOpITE(bddManager, varBdd, thenBdd, elseBdd, reqQueForITE);
+          CalRequestNodePutThenRequest(requestNode, result);
+          CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+          CalRequestNodePutNextRequestNode(requestNode,
+              requestNodeListForITE);
+          requestNodeListForITE = requestNode;
+        }
+      }
+    }
+  }
+
+  /* ITE Apply */
+  for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTableForITE = reqQueForITE[bddId];
+    if(hashTableForITE->numEntries){
+      CalHashTableITEApply(bddManager, hashTableForITE, reqQueForITE);
+    }
+  }
+  /* ITE Reduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= 0; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTableForITE = reqQueForITE[bddId];
+    if(hashTableForITE->numEntries){
+      CalHashTableReduce(bddManager, hashTableForITE,
+          bddManager->uniqueTable[bddId]);
+    }
+  }
+    
+
+  /*last = Cal_Nil(CalRequestNode_t);*/
+  for(requestNode = requestNodeListForITE; 
+      requestNode != Cal_Nil(CalRequestNode_t);
+      /*last = requestNode, */
+      requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+    CalRequestNodeGetThenRequest(requestNode, result);
+    CalBddNodeGetRefCount(requestNode, refCount);
+    CalRequestIsForwardedTo(result);
+    CalBddAddRefCount(result, refCount);
+    CalRequestNodePutThenRequest(requestNode, result);
+  }
+
+  /*CalBddNodePutNextBddNode(endNode, requestNodeListForITE);*/
+  endNode->nextBddNode = requestNodeListForITE;
+  hashTable->endNode = endNode;
+  
+  /* ITE Cleanup */
+  for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+    CalHashTableCleanUp(reqQueForITE[bddId]);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calBddSupport.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddSupport.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddSupport.c	(revision 8)
@@ -0,0 +1,279 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddSupport.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines related to the support of a BDD.]
+              
+
+  Description [ ]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.
+              ] 
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddSupport.c,v 1.1.1.3 1998/05/04 00:58:54 hsv Exp $]
+
+******************************************************************************/
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Cal_Bdd_t * CalBddSupportStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t * support);
+static void CalBddUnmarkNodes(Cal_BddManager_t * bddManager, Cal_Bdd_t f);
+static int CalBddDependsOnStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_BddIndex_t varIndex, int mark);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Name        [Cal_BddSupport]
+
+  Synopsis    [returns the support of f as a null-terminated array of variables]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddSupport(Cal_BddManager bddManager, Cal_Bdd fUserBdd,
+               Cal_Bdd *support)
+{
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    Cal_Bdd_t f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    Cal_Bdd_t *internalSupport = Cal_MemAlloc(Cal_Bdd_t, bddManager->numVars+1);
+    Cal_Bdd_t *end;
+    int i = 0;
+    end = CalBddSupportStep(bddManager, f, internalSupport);
+    *end = CalBddNull(bddManager);
+    CalBddUnmarkNodes(bddManager, f);
+    while (CalBddIsBddNull(bddManager, internalSupport[i]) == 0){
+      *support = CalBddGetExternalBdd(bddManager, internalSupport[i]);
+      support++;
+      i++;
+    }
+    Cal_MemFree(internalSupport);
+  }
+  *support = (Cal_Bdd) 0;
+}
+
+/**Function********************************************************************
+
+  Name        [Cal_BddDependsOn]
+
+  Synopsis    [Returns 1 if f depends on var and returns 0 otherwise.]
+
+  Description [Returns 1 if f depends on var and returns 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+Cal_BddDependsOn(Cal_BddManager bddManager, Cal_Bdd  fUserBdd,
+                 Cal_Bdd varUserBdd)
+{
+  Cal_BddIndex_t bddIndex;
+  Cal_Bdd_t f, var;
+  
+  if(CalBddPreProcessing(bddManager, 2, fUserBdd, varUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    var = CalBddGetInternalBdd(bddManager, varUserBdd);
+    if(CalBddIsBddConst(var)){
+      return 1;
+    }
+    bddIndex = CalBddGetBddIndex(bddManager, var);
+    CalBddDependsOnStep(bddManager, f, bddIndex, 1);
+    return CalBddDependsOnStep(bddManager, f, bddIndex, 0);
+  }
+  return (0);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Name        [CalBddSupportStep]
+
+  Synopsis    [returns the support of f as a null-terminated array of variables]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t *
+CalBddSupportStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  Cal_Bdd_t * support)
+{
+  Cal_Bdd_t tempBdd;
+
+  if(CalBddIsMarked(f) || CalBddIsBddConst(f)){
+    return support;
+  }
+  tempBdd = bddManager->varBdds[CalBddGetBddId(f)];
+  if(!CalBddIsMarked(tempBdd)){
+    CalBddMark(tempBdd);
+    *support = tempBdd;
+    ++support;
+  }
+  CalBddMark(f);
+  CalBddGetThenBdd(f, tempBdd);
+  support = CalBddSupportStep(bddManager, tempBdd, support);
+  CalBddGetElseBdd(f, tempBdd);
+  return CalBddSupportStep(bddManager, tempBdd, support);
+}
+
+
+/**Function********************************************************************
+
+  Name        [CalBddUnmarkNodes]
+
+  Synopsis    [recursively unmarks the nodes]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalBddUnmarkNodes(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f)
+{
+  Cal_Bdd_t tempBdd;
+
+  if(!CalBddIsMarked(f) || CalBddIsBddConst(f)){
+    return;
+  }
+  CalBddUnmark(f);
+  tempBdd = bddManager->varBdds[CalBddGetBddId(f)];
+  CalBddUnmark(tempBdd);
+  CalBddGetThenBdd(f, tempBdd);
+  CalBddUnmarkNodes(bddManager, tempBdd);
+  CalBddGetElseBdd(f, tempBdd);
+  CalBddUnmarkNodes(bddManager, tempBdd);
+}
+
+
+/**Function********************************************************************
+
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+CalBddDependsOnStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  Cal_BddIndex_t  varIndex,
+  int  mark)
+{
+  Cal_BddIndex_t fIndex;
+  Cal_Bdd_t tempBdd;
+
+  fIndex=CalBddGetBddIndex(bddManager, f);
+  if(fIndex > varIndex){
+    return 0;
+  }
+  if(fIndex == varIndex){
+    return 1;
+  }
+  if((mark && CalBddIsMarked(f)) || (!mark && !CalBddIsMarked(f))){
+    return (0);
+  }
+  if(mark){
+    CalBddMark(f);
+  }
+  else{
+    CalBddUnmark(f);
+  }
+  CalBddGetThenBdd(f, tempBdd);
+  if(CalBddDependsOnStep(bddManager, tempBdd, varIndex, mark)){
+    return 1;
+  }
+  CalBddGetElseBdd(f, tempBdd);
+  return CalBddDependsOnStep(bddManager, tempBdd, varIndex, mark);
+}
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calBddSwapVars.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddSwapVars.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddSwapVars.c	(revision 8)
@@ -0,0 +1,581 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddSwapVars.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routine for swapping two variables.]
+
+  Description [Routine for swapping two variables.]
+
+  SeeAlso     [None]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddSwapVars.c,v 1.1.1.3 1998/05/04 00:58:55 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CalHashTableSwapVarsApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, Cal_BddIndex_t gIndex, Cal_BddIndex_t hIndex, CalHashTable_t ** reqQueForSwapVars, CalHashTable_t ** reqQueForSwapVarsPlus, CalHashTable_t ** reqQueForSwapVarsMinus, CalHashTable_t ** reqQueForCompose, CalHashTable_t ** reqQueForITE);
+static void CalHashTableSwapVarsPlusApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, Cal_BddIndex_t hIndex, CalHashTable_t ** reqQueForSwapVars, CalHashTable_t ** reqQueForSwapVarsPlus, CalHashTable_t ** reqQueForSwapVarsMinus, CalHashTable_t ** reqQueForCompose);
+static void CalHashTableSwapVarsMinusApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, Cal_BddIndex_t hIndex, CalHashTable_t ** reqQueForSwapVars, CalHashTable_t ** reqQueForSwapVarsPlus, CalHashTable_t ** reqQueForSwapVarsMinus, CalHashTable_t ** reqQueForCompose);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Return a function obtained by swapping two variables]
+
+  Description [Returns the BDD obtained by simultaneously substituting variable
+  g by variable h and variable h and variable g in the BDD f]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddSubstitute]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddSwapVars(Cal_BddManager  bddManager, Cal_Bdd  fUserBdd,
+                Cal_Bdd gUserBdd,
+                Cal_Bdd hUserBdd)
+{
+  Cal_Bdd_t f,g,h,tmpBdd;
+  Cal_BddIndex_t gIndex, hIndex;
+  CalRequest_t result;
+  int bddId, bddIndex;
+  CalHashTable_t *hashTable;
+  CalHashTable_t *uniqueTableForId;
+  CalHashTable_t **reqQueForSwapVars = bddManager->reqQue[0];
+  CalHashTable_t **reqQueForSwapVarsPlus = bddManager->reqQue[1];
+  CalHashTable_t **reqQueForSwapVarsMinus = bddManager->reqQue[2];
+  CalHashTable_t **reqQueForCompose = bddManager->reqQue[3];
+  CalHashTable_t **reqQueForITE = bddManager->reqQue[4]; 
+  
+  if (CalBddPreProcessing(bddManager, 3, fUserBdd, gUserBdd, hUserBdd) == 0){
+	return (Cal_Bdd) 0;
+  }
+  f = CalBddGetInternalBdd(bddManager, fUserBdd);
+  g = CalBddGetInternalBdd(bddManager, gUserBdd);
+  h = CalBddGetInternalBdd(bddManager, hUserBdd);
+
+  if(CalBddIsBddConst(g) || CalBddIsBddConst(h)){
+    CalBddWarningMessage("Unacceptable arguments for Cal_BddSwapVars");
+    return (Cal_Bdd) 0;
+  }
+  if(CalBddIsEqual(g, h)){
+    /*
+    CalBddIcrRefCount(f);
+    */
+    return CalBddGetExternalBdd(bddManager, f);
+  }
+  if(CalBddGetBddIndex(bddManager, g) > CalBddGetBddIndex(bddManager, h)){
+    tmpBdd = g;
+    g = h;
+    h = tmpBdd;
+  }
+
+  gIndex = CalBddGetBddIndex(bddManager, g);
+  hIndex = CalBddGetBddIndex(bddManager, h);
+
+  CalBddGetMinId2(bddManager, f, g, bddId);
+  CalHashTableFindOrAdd(reqQueForSwapVars[bddId], f, 
+      bddManager->bddNull, &result);
+
+  /* ReqQueApply */
+  for(bddIndex = 0; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = reqQueForSwapVars[bddId];
+    if(hashTable->numEntries){
+      CalHashTableSwapVarsApply(bddManager, hashTable, gIndex, hIndex,
+          reqQueForSwapVars, reqQueForSwapVarsPlus, reqQueForSwapVarsMinus,
+          reqQueForCompose, reqQueForITE);
+    }
+    hashTable = reqQueForSwapVarsPlus[bddId];
+    if(hashTable->numEntries){
+      CalHashTableSwapVarsPlusApply(bddManager, hashTable, hIndex,
+          reqQueForSwapVars, reqQueForSwapVarsPlus, reqQueForSwapVarsMinus,
+          reqQueForCompose);
+    }
+    hashTable = reqQueForSwapVarsMinus[bddId];
+    if(hashTable->numEntries){
+      CalHashTableSwapVarsMinusApply(bddManager, hashTable, hIndex,
+          reqQueForSwapVars, reqQueForSwapVarsPlus, reqQueForSwapVarsMinus,
+          reqQueForCompose);
+    }
+    hashTable = reqQueForCompose[bddId];
+    if(hashTable->numEntries){
+      CalHashTableComposeApply(bddManager, hashTable, hIndex,
+          reqQueForCompose, reqQueForITE);
+    }
+    hashTable = reqQueForITE[bddId];
+    if(hashTable->numEntries){
+      CalHashTableITEApply(bddManager, hashTable, reqQueForITE);
+    }
+  }
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= 0; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = reqQueForSwapVars[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+    hashTable = reqQueForSwapVarsPlus[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+    hashTable = reqQueForSwapVarsMinus[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+    hashTable = reqQueForCompose[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+    hashTable = reqQueForITE[bddId];
+    if(hashTable->numEntries){
+      CalHashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+  }
+
+  CalRequestIsForwardedTo(result);
+
+  /* ReqQueCleanUp */
+  for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+    CalHashTableCleanUp(reqQueForSwapVars[bddId]);
+    CalHashTableCleanUp(reqQueForSwapVarsPlus[bddId]);
+    CalHashTableCleanUp(reqQueForSwapVarsMinus[bddId]);
+    CalHashTableCleanUp(reqQueForCompose[bddId]);
+    CalHashTableCleanUp(reqQueForITE[bddId]);
+  }
+  return CalBddGetExternalBdd(bddManager, result);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableSwapVarsApply(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  Cal_BddIndex_t  gIndex,
+  Cal_BddIndex_t  hIndex,
+  CalHashTable_t ** reqQueForSwapVars,
+  CalHashTable_t ** reqQueForSwapVarsPlus,
+  CalHashTable_t ** reqQueForSwapVarsMinus,
+  CalHashTable_t ** reqQueForCompose,
+  CalHashTable_t ** reqQueForITE)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_BddId_t bddId;
+  Cal_BddIndex_t fIndex, bddIndex;
+  Cal_Bdd_t f, calBdd;
+  Cal_Bdd_t thenBdd, elseBdd;
+  Cal_Bdd_t nullBdd = bddManager->bddNull;
+  Cal_Bdd_t result;
+
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetF(requestNode, f);
+      fIndex = CalBddGetBddIndex(bddManager, f);
+      if(fIndex < gIndex){
+        /* left cofactor */
+        CalBddGetThenBdd(f, calBdd);
+        bddId = CalBddGetBddId(calBdd);
+        bddIndex = bddManager->idToIndex[bddId];
+        if(bddIndex <= hIndex){
+          if(bddIndex > gIndex){
+            bddId = bddManager->indexToId[gIndex];
+          }
+          CalHashTableFindOrAdd(reqQueForSwapVars[bddId],
+              calBdd, nullBdd, &calBdd);
+        }
+        CalBddIcrRefCount(calBdd);
+        CalRequestNodePutThenRequest(requestNode, calBdd);
+        /* right cofactor */
+        CalBddGetElseBdd(f, calBdd);
+        bddId = CalBddGetBddId(calBdd);
+        bddIndex = bddManager->idToIndex[bddId];
+        if(bddIndex <= hIndex){
+          if(bddIndex > gIndex){
+            bddId = bddManager->indexToId[gIndex];
+          }
+          CalHashTableFindOrAdd(reqQueForSwapVars[bddId],
+              calBdd, nullBdd, &calBdd);
+        }
+        CalBddIcrRefCount(calBdd);
+        CalRequestNodePutElseRequest(requestNode, calBdd);
+      }
+      else if(fIndex == gIndex){
+        /* SwapVarsPlus */
+        CalBddGetThenBdd(f, thenBdd);
+        CalBddGetElseBdd(f, elseBdd);
+        if(CalBddGetBddIndex(bddManager, thenBdd) == hIndex){
+          CalBddGetThenBdd(thenBdd, thenBdd);
+        }
+        if(CalBddGetBddIndex(bddManager, elseBdd) == hIndex){
+          CalBddGetThenBdd(elseBdd, elseBdd);
+        }
+        if(CalBddIsEqual(thenBdd, elseBdd)){
+          if(hIndex > CalBddGetBddIndex(bddManager, thenBdd)){
+            CalHashTableFindOrAdd(reqQueForCompose[CalBddGetBddId(thenBdd)], 
+                thenBdd, CalBddOne(bddManager), &result);
+          }
+          else{
+            result = thenBdd;
+          }
+        }
+        else if(hIndex < CalBddGetBddIndex(bddManager, thenBdd) &&
+            hIndex < CalBddGetBddIndex(bddManager, elseBdd)){
+          bddId = bddManager->indexToId[hIndex];
+          if(!CalUniqueTableForIdFindOrAdd(bddManager, 
+              bddManager->uniqueTable[bddId], thenBdd, elseBdd, &result)){
+            CalBddIcrRefCount(thenBdd);
+            CalBddIcrRefCount(elseBdd);
+          }
+        }
+        else{
+          CalBddGetMinId2(bddManager, thenBdd, elseBdd, bddId);
+          CalHashTableFindOrAdd(reqQueForSwapVarsPlus[bddId],
+              thenBdd, elseBdd, &result);
+        }
+        CalBddIcrRefCount(result);
+        CalRequestNodePutThenRequest(requestNode, result);
+        /* SwapVarsMinus */
+        CalBddGetThenBdd(f, thenBdd);
+        CalBddGetElseBdd(f, elseBdd);
+        if(CalBddGetBddIndex(bddManager, thenBdd) == hIndex){
+          CalBddGetElseBdd(thenBdd, thenBdd);
+        }
+        if(CalBddGetBddIndex(bddManager, elseBdd) == hIndex){
+          CalBddGetElseBdd(elseBdd, elseBdd);
+        }
+        if(CalBddIsEqual(thenBdd, elseBdd)){
+          if(hIndex > CalBddGetBddIndex(bddManager, thenBdd)){
+            CalHashTableFindOrAdd(reqQueForCompose[CalBddGetBddId(thenBdd)], 
+                thenBdd, CalBddZero(bddManager), &result);
+          }
+          else{
+            result = thenBdd;
+          }
+        }
+        else if(hIndex < CalBddGetBddIndex(bddManager, thenBdd) &&
+            hIndex < CalBddGetBddIndex(bddManager, elseBdd)){
+          bddId = bddManager->indexToId[hIndex];
+          if(!CalUniqueTableForIdFindOrAdd(bddManager, 
+              bddManager->uniqueTable[bddId], thenBdd, elseBdd, &result)){
+            CalBddIcrRefCount(thenBdd);
+            CalBddIcrRefCount(elseBdd);
+          }
+        }
+        else{
+          CalBddGetMinId2(bddManager, thenBdd, elseBdd, bddId);
+          CalHashTableFindOrAdd(reqQueForSwapVarsMinus[bddId],
+              thenBdd, elseBdd, &result);
+        }
+        CalBddIcrRefCount(result);
+        CalRequestNodePutElseRequest(requestNode, result);
+      }
+      else{ /* fIndex > gIndex */
+        CalComposeRequestCreate(bddManager,
+            f, CalBddOne(bddManager), hIndex,
+            reqQueForCompose, reqQueForITE, &result);
+        CalBddIcrRefCount(result);
+        CalRequestNodePutThenRequest(requestNode, result);
+        CalComposeRequestCreate(bddManager,
+            f, CalBddZero(bddManager), hIndex,
+            reqQueForCompose, reqQueForITE, &result);
+        CalBddIcrRefCount(result);
+        CalRequestNodePutElseRequest(requestNode, result);
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableSwapVarsPlusApply(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  Cal_BddIndex_t  hIndex,
+  CalHashTable_t ** reqQueForSwapVars,
+  CalHashTable_t ** reqQueForSwapVarsPlus,
+  CalHashTable_t ** reqQueForSwapVarsMinus,
+  CalHashTable_t ** reqQueForCompose)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_BddId_t bddId;
+  Cal_Bdd_t f1, f2, g1, g2;
+  Cal_Bdd_t result;
+
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetCofactors(bddManager, requestNode, f1, f2, g1, g2);
+      /* left cofactor */ 
+      if(CalBddGetBddIndex(bddManager, f1) == hIndex){
+        CalBddGetThenBdd(f1, f1);
+      }
+      if(CalBddGetBddIndex(bddManager, g1) == hIndex){
+        CalBddGetThenBdd(g1, g1);
+      }
+      if(CalBddIsEqual(f1, g1)){
+        if(hIndex > CalBddGetBddIndex(bddManager, f1)){
+          CalHashTableFindOrAdd(reqQueForCompose[CalBddGetBddId(f1)], 
+              f1, CalBddOne(bddManager), &result);
+        }
+        else{
+          result = f1;
+        }
+      }
+      else if(hIndex < CalBddGetBddIndex(bddManager, f1) &&
+          hIndex < CalBddGetBddIndex(bddManager, g1)){
+        bddId = bddManager->indexToId[hIndex];
+        if(!CalUniqueTableForIdFindOrAdd(bddManager, 
+            bddManager->uniqueTable[bddId], f1, g1, &result)){
+          CalBddIcrRefCount(f1);
+          CalBddIcrRefCount(g1);
+        }
+      }
+      else{
+        CalBddGetMinId2(bddManager, f1, g1, bddId);
+        CalHashTableFindOrAdd(reqQueForSwapVarsPlus[bddId], f1, g1, &result);
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutThenRequest(requestNode, result);
+      /* right cofactor */
+      if(CalBddGetBddIndex(bddManager, f2) == hIndex){
+        CalBddGetThenBdd(f2, f2);
+      }
+      if(CalBddGetBddIndex(bddManager, g2) == hIndex){
+        CalBddGetThenBdd(g2, g2);
+      }
+      if(CalBddIsEqual(f2, g2)){
+        if(hIndex > CalBddGetBddIndex(bddManager, f2)){
+          CalHashTableFindOrAdd(reqQueForCompose[CalBddGetBddId(f2)], 
+              f2, CalBddOne(bddManager), &result);
+        }
+        else{
+          result = f2;
+        }
+      }
+      else if(hIndex < CalBddGetBddIndex(bddManager, f2) &&
+          hIndex < CalBddGetBddIndex(bddManager, g2)){
+        bddId = bddManager->indexToId[hIndex];
+        if(!CalUniqueTableForIdFindOrAdd(bddManager, 
+            bddManager->uniqueTable[bddId], f2, g2, &result)){
+          CalBddIcrRefCount(f2);
+          CalBddIcrRefCount(g2);
+        }
+      }
+      else{
+        CalBddGetMinId2(bddManager, f2, g2, bddId);
+        CalHashTableFindOrAdd(reqQueForSwapVarsPlus[bddId], f2, g2, &result);
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableSwapVarsMinusApply(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  Cal_BddIndex_t  hIndex,
+  CalHashTable_t ** reqQueForSwapVars,
+  CalHashTable_t ** reqQueForSwapVarsPlus,
+  CalHashTable_t ** reqQueForSwapVarsMinus,
+  CalHashTable_t ** reqQueForCompose)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_BddId_t bddId;
+  Cal_Bdd_t f1, f2, g1, g2;
+  Cal_Bdd_t result;
+
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetCofactors(bddManager, requestNode, f1, f2, g1, g2);
+      /* left cofactor */ 
+      if(CalBddGetBddIndex(bddManager, f1) == hIndex){
+        CalBddGetElseBdd(f1, f1);
+      }
+      if(CalBddGetBddIndex(bddManager, g1) == hIndex){
+        CalBddGetElseBdd(g1, g1);
+      }
+      if(CalBddIsEqual(f1, g1)){
+        if(hIndex > CalBddGetBddIndex(bddManager, f1)){
+          CalHashTableFindOrAdd(reqQueForCompose[CalBddGetBddId(f1)], 
+              f1, CalBddZero(bddManager), &result);
+        }
+        else{
+          result = f1;
+        }
+      }
+      else if(hIndex < CalBddGetBddIndex(bddManager, f1) &&
+          hIndex < CalBddGetBddIndex(bddManager, g1)){
+        bddId = bddManager->indexToId[hIndex];
+        if(!CalUniqueTableForIdFindOrAdd(bddManager,
+            bddManager->uniqueTable[bddId], f1, g1, &result)){
+          CalBddIcrRefCount(f1);
+          CalBddIcrRefCount(g1);
+        }
+      }
+      else{
+        CalBddGetMinId2(bddManager, f1, g1, bddId);
+        CalHashTableFindOrAdd(reqQueForSwapVarsMinus[bddId], f1, g1, &result);
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutThenRequest(requestNode, result);
+      /* right cofactor */
+      if(CalBddGetBddIndex(bddManager, f2) == hIndex){
+        CalBddGetElseBdd(f2, f2);
+      }
+      if(CalBddGetBddIndex(bddManager, g2) == hIndex){
+        CalBddGetElseBdd(g2, g2);
+      }
+      if(CalBddIsEqual(f2, g2)){
+        if(hIndex > CalBddGetBddIndex(bddManager, f2)){
+          CalHashTableFindOrAdd(reqQueForCompose[CalBddGetBddId(f2)], 
+              f2, CalBddZero(bddManager), &result);
+        }
+        else{
+          result = f2;
+        }
+      }
+      else if(hIndex < CalBddGetBddIndex(bddManager, f2) &&
+          hIndex < CalBddGetBddIndex(bddManager, g2)){
+        bddId = bddManager->indexToId[hIndex];
+        if(!CalUniqueTableForIdFindOrAdd(bddManager, 
+            bddManager->uniqueTable[bddId], f2, g2, &result)){
+          CalBddIcrRefCount(f2);
+          CalBddIcrRefCount(g2);
+        }
+      }
+      else{
+        CalBddGetMinId2(bddManager, f2, g2, bddId);
+        CalHashTableFindOrAdd(reqQueForSwapVarsMinus[bddId], f2, g2, &result);
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calBddVarSubstitute.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBddVarSubstitute.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBddVarSubstitute.c	(revision 8)
@@ -0,0 +1,544 @@
+/**CFile***********************************************************************
+
+  FileName    [calBddVarSubstitute.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routine for simultaneous substitution of an array of
+  variables with another array of variables.]
+
+  Description []
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBddVarSubstitute.c,v 1.2 2002/09/10 00:27:21 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CalHashTableSubstituteApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, int lastIndex, CalHashTable_t ** reqQueForSubstitute, unsigned short opCode);
+static void CalHashTableSubstituteReduce(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t ** reqQueForITE, CalHashTable_t * uniqueTableForId, unsigned short opCode);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Substitute a set of variables by set of another variables.]
+
+  Description [Returns a BDD for f using the substitution defined by current
+  variable association. It is assumed that each variable is replaced
+  by another variable. For the substitution of a variable by a
+  function, use Cal_BddSubstitute instead.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddSubstitute]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddVarSubstitute(Cal_BddManager bddManager, Cal_Bdd fUserBdd)
+{
+  CalRequest_t result;
+  Cal_Bdd userResult;
+  
+  if (CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    Cal_Bdd_t f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    CalAssociation_t *assoc = bddManager->currentAssociation;
+    unsigned short opCode;
+    if (assoc->id == -1){
+      opCode = bddManager->tempOpCode--;
+    }
+    else {
+      opCode = CAL_OP_VAR_SUBSTITUTE + assoc->id;
+    }
+    result = CalBddVarSubstitute(bddManager, f, opCode, assoc);
+    userResult =  CalBddGetExternalBdd(bddManager, result);
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      Cal_BddFree(bddManager, userResult);
+      Cal_BddManagerGC(bddManager);
+      return (Cal_Bdd) 0;
+    }
+    return userResult;
+  }
+  return (Cal_Bdd) 0;
+}
+  
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Substitute a set of variables by functions]
+
+  Description [Returns a BDD for f using the substitution defined by current
+  variable association. Each variable is replaced by its associated BDDs. The 
+  substitution is effective simultaneously]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddCompose]
+
+******************************************************************************/
+Cal_Bdd_t
+CalBddVarSubstitute(Cal_BddManager bddManager, Cal_Bdd_t f, unsigned
+                    short opCode, CalAssociation_t *assoc)
+{
+  CalRequest_t result;
+  int bddId, bddIndex, lastIndex;
+  CalHashTable_t *hashTable;
+  CalHashTable_t *uniqueTableForId;
+  CalHashTable_t **reqQueForSubstitute = bddManager->reqQue[0];
+  CalHashTable_t **reqQueForITE = bddManager->reqQue[1]; 
+  Cal_BddId_t fId = CalBddGetBddId(f);
+  /*Cal_BddIndex_t fIndex = bddManager->idToIndex[fId];*/
+  int fIndex = bddManager->idToIndex[fId];
+  
+  if (CalOpBddVarSubstitute(bddManager, f, &result)){
+    return result;
+  }
+
+  if (CalCacheTableOneLookup(bddManager, f, opCode, &result)){
+    return result;
+  }
+  CalHashTableFindOrAdd(reqQueForSubstitute[fId], f, 
+    bddManager->bddNull, &result);
+
+  /* ReqQueApply */
+  lastIndex = assoc->lastBddIndex;
+  for(bddIndex = fIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = reqQueForSubstitute[bddId];
+    if(hashTable->numEntries){
+      CalHashTableSubstituteApply(bddManager, hashTable, lastIndex, 
+                                  reqQueForSubstitute, opCode);
+    }
+  }
+
+  /* ReqQueReduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= fIndex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = reqQueForSubstitute[bddId];
+    if(hashTable->numEntries){
+      CalHashTableSubstituteReduce(bddManager, hashTable,
+                                   reqQueForITE, uniqueTableForId,
+                                   opCode); 
+    }
+  }
+
+  CalRequestIsForwardedTo(result);
+
+  /* ReqQueCleanUp */
+  for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+    CalHashTableCleanUp(reqQueForSubstitute[bddId]);
+  }
+  CalCacheTableTwoFixResultPointers(bddManager);
+  CalCacheTableOneInsert(bddManager, f, result, opCode, 0);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpBddVarSubstitute(Cal_BddManager_t * bddManager, Cal_Bdd_t  f, Cal_Bdd_t *
+            resultBddPtr) 
+{
+  if (bddManager->idToIndex[CalBddGetBddId(f)] >
+      bddManager->currentAssociation->lastBddIndex){ 
+    *resultBddPtr = f;
+    return 1;
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableSubstituteApply(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  int  lastIndex,
+  CalHashTable_t ** reqQueForSubstitute,
+  unsigned short opCode)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_BddId_t bddId;
+  /*Cal_BddIndex_t bddIndex;*/
+  int bddIndex;
+  Cal_Bdd_t f, fx, fxBar, result;
+  Cal_Bdd_t nullBdd = bddManager->bddNull;
+
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      /* Process the requestNode */
+      CalRequestNodeGetF(requestNode, f);
+      /* Process Left Cofactor */
+      CalBddGetThenBdd(f, fx);
+      bddId = CalBddGetBddId(fx);
+      bddIndex = bddManager->idToIndex[bddId];
+      if(bddIndex <= lastIndex){
+          if (CalCacheTableOneLookup(bddManager, fx, opCode, &result)){ 
+            CalRequestIsForwardedTo(result);
+          }
+          else {
+            CalHashTableFindOrAdd(reqQueForSubstitute[bddId], fx, nullBdd, 
+                              &result);
+            CalCacheTableOneInsert(bddManager, fx, result,
+                                   opCode, 1);
+          }
+      }
+      else{
+        result = fx;
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutThenRequest(requestNode, result);
+      /* Process Right Cofactor */
+      CalBddGetElseBdd(f, fxBar);
+      bddId = CalBddGetBddId(fxBar);
+      bddIndex = bddManager->idToIndex[bddId];
+      if(bddIndex <= lastIndex){
+          if (CalCacheTableOneLookup(bddManager, fxBar, opCode, &result)){ 
+            CalRequestIsForwardedTo(result);
+          }
+          else {
+            CalHashTableFindOrAdd(reqQueForSubstitute[bddId], fxBar, nullBdd, 
+                              &result);
+            CalCacheTableOneInsert(bddManager, fxBar, result,
+                                   opCode, 1);
+          }
+      }
+      else{
+        result = fxBar;
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableSubstituteReduce(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  CalHashTable_t ** reqQueForITE,
+  CalHashTable_t * uniqueTableForId,
+  unsigned short opCode)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  Cal_BddId_t varBddId = hashTable->bddId;
+  CalNodeManager_t *nodeManager = hashTable->nodeManager;
+  /*CalRequestNode_t *requestNodeList = hashTable->requestNodeList;*/
+  CalRequestNode_t *endNode = hashTable->endNode;
+  CalRequestNode_t *requestNodeListForITE = Cal_Nil(CalRequestNode_t);
+  CalRequestNode_t *requestNode, *next;
+  CalBddNode_t *bddNode;
+  Cal_Bdd_t varBdd;
+  Cal_Bdd_t thenBdd, elseBdd, result;
+  Cal_Bdd_t h;
+  Cal_BddIndex_t resultIndex, varBddIndex;
+  int minITEindex = bddManager->numVars;
+  Cal_BddRefCount_t refCount;
+  int bddId, bddIndex;
+  CalHashTable_t *hashTableForITE;
+
+  varBddIndex = bddManager->idToIndex[varBddId];
+  varBdd = bddManager->varBdds[varBddId];
+  h = bddManager->currentAssociation->varAssociation[varBddId];
+  if(!CalBddIsBddNull(bddManager, h)){
+    Cal_BddId_t hId = CalBddGetBddId(h);
+    Cal_BddIndex_t hIndex = bddManager->idToIndex[hId];
+    for(i = 0; i < numBins; i++){
+      for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+          requestNode != Cal_Nil(CalRequestNode_t);
+          requestNode = next){
+        next = CalRequestNodeGetNextRequestNode(requestNode);
+        /* Process the requestNode */
+        CalRequestNodeGetThenRequest(requestNode, thenBdd);
+        CalRequestNodeGetElseRequest(requestNode, elseBdd);
+        CalRequestIsForwardedTo(thenBdd);
+        CalRequestIsForwardedTo(elseBdd);
+        if(CalBddIsEqual(thenBdd, elseBdd)){
+          CalBddNodeGetRefCount(requestNode, refCount);
+          CalBddAddRefCount(thenBdd, refCount - 2);
+          CalRequestNodePutThenRequest(requestNode, thenBdd);
+          CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+          endNode->nextBddNode = requestNode;
+          endNode = requestNode;
+        }
+        else{
+          if(hIndex < CalBddGetBddIndex(bddManager, thenBdd) &&
+             hIndex < CalBddGetBddIndex(bddManager, elseBdd)){
+            if(CalUniqueTableForIdLookup(bddManager, bddManager->uniqueTable[hId],
+                                         thenBdd, elseBdd, &result) == 1){
+              CalBddDcrRefCount(thenBdd);
+              CalBddDcrRefCount(elseBdd);
+              CalBddNodeGetRefCount(requestNode, refCount);
+              CalBddAddRefCount(result, refCount);
+              CalRequestNodePutThenRequest(requestNode, result);
+              CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+              endNode->nextBddNode = requestNode;
+              endNode = requestNode;
+            }
+            else if(CalBddIsOutPos(thenBdd)){
+              /* Get a node from the node manager of h */
+              CalNodeManager_t *hNodeManager =
+                  bddManager->nodeManagerArray[hId];
+              CalNodeManagerInitBddNode(hNodeManager, thenBdd, elseBdd,
+                                      Cal_Nil(CalBddNode_t), bddNode);
+              CalBddNodeGetRefCount(requestNode, refCount);
+              CalBddNodePutRefCount(bddNode, refCount);
+              CalHashTableAddDirect(bddManager->uniqueTable[hId], bddNode);
+              bddManager->numNodes++;
+              bddManager->gcCheck--;
+              CalRequestNodePutThenRequestId(requestNode, hId);
+              CalRequestNodePutThenRequestNode(requestNode, bddNode); 
+              CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+              endNode->nextBddNode = requestNode;
+              endNode = requestNode;
+            }
+            else{
+              /* Get a node from the node manager of h */
+              CalNodeManager_t *hNodeManager =
+                  bddManager->nodeManagerArray[hId];
+              CalBddNot(thenBdd, thenBdd);
+              CalBddNot(elseBdd, elseBdd);
+              CalNodeManagerInitBddNode(hNodeManager, thenBdd, elseBdd,
+                                      Cal_Nil(CalBddNode_t), bddNode);
+              CalBddNodeGetRefCount(requestNode, refCount);
+              CalBddNodePutRefCount(bddNode, refCount);
+              CalHashTableAddDirect(bddManager->uniqueTable[hId], bddNode);
+              bddManager->numNodes++;
+              bddManager->gcCheck--;
+              CalRequestNodePutThenRequestId(requestNode, hId);
+              CalRequestNodePutThenRequestNode(requestNode,
+                                               CalBddNodeNot(bddNode));
+              CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+              endNode->nextBddNode = requestNode;
+              endNode = requestNode;
+            }
+          }
+          else{
+            CalBddDcrRefCount(thenBdd);
+            CalBddDcrRefCount(elseBdd);
+            result = CalOpITE(bddManager, h, thenBdd, elseBdd, reqQueForITE);
+            if ((resultIndex = bddManager->idToIndex[CalBddGetBddId(result)]) < minITEindex){
+              minITEindex = resultIndex;
+            }
+            CalRequestNodePutThenRequest(requestNode, result);
+            CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+            CalRequestNodePutNextRequestNode(requestNode,
+                                             requestNodeListForITE);
+            requestNodeListForITE = requestNode;
+          }
+        }
+      }
+    }
+  }
+  else{
+    for(i = 0; i < numBins; i++){
+      for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+          requestNode != Cal_Nil(CalRequestNode_t);
+          requestNode = next){
+        next = CalRequestNodeGetNextRequestNode(requestNode);
+        /* Process the requestNode */
+        CalRequestNodeGetThenRequest(requestNode, thenBdd);
+        CalRequestNodeGetElseRequest(requestNode, elseBdd);
+        CalRequestIsForwardedTo(thenBdd);
+        CalRequestIsForwardedTo(elseBdd);
+        if(CalBddIsEqual(thenBdd, elseBdd)){
+          CalBddNodeGetRefCount(requestNode, refCount);
+          CalBddAddRefCount(thenBdd, refCount - 2);
+          CalRequestNodePutThenRequest(requestNode, thenBdd);
+          CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+          endNode->nextBddNode = requestNode;
+          endNode = requestNode;
+        }
+        else{
+          if(varBddIndex < CalBddGetBddIndex(bddManager, thenBdd) &&
+             varBddIndex < CalBddGetBddIndex(bddManager, elseBdd)){
+            if(CalUniqueTableForIdLookup(bddManager, uniqueTableForId,
+                                         thenBdd, elseBdd, &result) == 1){
+              CalBddDcrRefCount(thenBdd);
+              CalBddDcrRefCount(elseBdd);
+              CalBddNodeGetRefCount(requestNode, refCount);
+              CalBddAddRefCount(result, refCount);
+              CalRequestNodePutThenRequest(requestNode, result);
+              CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+              endNode->nextBddNode = requestNode;
+              endNode = requestNode;
+            }
+            else if(CalBddIsOutPos(thenBdd)){
+              CalRequestNodePutThenRequest(requestNode, thenBdd);
+              CalRequestNodePutElseRequest(requestNode, elseBdd);
+              CalHashTableAddDirect(uniqueTableForId, requestNode);
+              bddManager->numNodes++;
+              bddManager->gcCheck--;
+            }
+            else{
+              CalBddNot(thenBdd, thenBdd);
+              CalBddNot(elseBdd, elseBdd);
+              CalNodeManagerInitBddNode(nodeManager, thenBdd, elseBdd,
+                                      Cal_Nil(CalBddNode_t), bddNode);
+              CalBddNodeGetRefCount(requestNode, refCount);
+              CalBddNodePutRefCount(bddNode, refCount);
+              CalHashTableAddDirect(uniqueTableForId, bddNode);
+              bddManager->numNodes++;
+              bddManager->gcCheck--;
+              CalRequestNodePutThenRequestId(requestNode, varBddId);
+              CalRequestNodePutThenRequestNode(requestNode,
+                                               CalBddNodeNot(bddNode));
+              CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+              endNode->nextBddNode = requestNode;
+              endNode = requestNode;
+            }
+          }
+          else{
+            CalBddDcrRefCount(thenBdd);
+            CalBddDcrRefCount(elseBdd);
+            result = CalOpITE(bddManager, varBdd, thenBdd, elseBdd, reqQueForITE);
+            if ((resultIndex = bddManager->idToIndex[CalBddGetBddId(result)]) < minITEindex){
+              minITEindex = resultIndex;
+            }
+            CalRequestNodePutThenRequest(requestNode, result);
+            CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+            CalRequestNodePutNextRequestNode(requestNode,
+                                             requestNodeListForITE);
+            requestNodeListForITE = requestNode;
+          }
+        }
+      }
+    }
+  }
+
+  /* ITE Apply */
+  for(bddIndex = minITEindex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTableForITE = reqQueForITE[bddId];
+    if(hashTableForITE->numEntries){
+      CalHashTableITEApply(bddManager, hashTableForITE, reqQueForITE);
+    }
+  }
+  /* ITE Reduce */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minITEindex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTableForITE = reqQueForITE[bddId];
+    if(hashTableForITE->numEntries){
+      CalHashTableReduce(bddManager, hashTableForITE,
+          bddManager->uniqueTable[bddId]);
+    }
+  }
+    
+
+  for(requestNode = requestNodeListForITE; 
+      requestNode != Cal_Nil(CalRequestNode_t);
+      requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+    CalRequestNodeGetThenRequest(requestNode, result);
+    CalBddNodeGetRefCount(requestNode, refCount);
+    CalRequestIsForwardedTo(result);
+    CalBddAddRefCount(result, refCount);
+    CalRequestNodePutThenRequest(requestNode, result);
+  }
+
+  endNode->nextBddNode = requestNodeListForITE;
+  hashTable->endNode = endNode;
+  /* ITE Cleanup */
+  for(bddId = 1; bddId <= bddManager->numVars; bddId++){
+    CalHashTableCleanUp(reqQueForITE[bddId]);
+  }
+}
+
Index: /vis_dev/glu-2.1/src/calBdd/calBlk.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calBlk.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calBlk.c	(revision 8)
@@ -0,0 +1,348 @@
+/**CFile***********************************************************************
+
+  FileName    [calBlk.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for manipulating blocks of variables.]
+
+  Description [Routines for manipulating blocks of variables.]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu). Modelled on the BDD package
+  developed by David Long.]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calBlk.c,v 1.1.1.2 1998/05/04 00:59:05 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void AddBlock(Cal_Block b1, Cal_Block b2);
+
+/**AutomaticEnd***************************************************************/
+
+/* BDD variable block routines */
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis           [Creates and returns a variable block used for
+  controlling dynamic reordering.]
+
+  Description        [The block is specified by passing the first
+  variable and the length of the block. The "length" number of
+  consecutive variables starting from "variable" are put in the
+  block.]   
+
+  SideEffects        [A new block is created.]
+
+  SeeAlso            []
+
+******************************************************************************/
+Cal_Block
+Cal_BddNewVarBlock(Cal_BddManager bddManager, Cal_Bdd variable, long length)
+{
+  Cal_Block b;
+  Cal_Bdd_t calBdd = CalBddGetInternalBdd(bddManager, variable);
+  
+  if (CalBddTypeAux(bddManager, calBdd) != CAL_BDD_TYPE_POSVAR) {
+    CalBddWarningMessage("Cal_BddNewVarBlock: second argument is not a positive variable\n"); 
+    if (CalBddIsBddConst(calBdd)){
+      return (Cal_Block) 0;
+	}
+  }
+
+  /*b = CAL_BDD_NEW_REC(bddManager, Cal_Block_t);*/
+  b = Cal_MemAlloc(Cal_Block_t, 1);
+  b->reorderable = 0;
+  b->firstIndex = bddManager->idToIndex[calBdd.bddId];
+  if (length <= 0) {
+    CalBddWarningMessage("Cal_BddNewVarBlock: invalid final argument");
+    length = 1;
+  }
+  b->lastIndex = b->firstIndex + length - 1;
+  if (b->lastIndex >= bddManager->numVars) {
+    CalBddWarningMessage("Cal_BddNewVarBlock: range covers non-existent variables"); 
+    b->lastIndex = bddManager->numVars - 1;
+  }
+  AddBlock(bddManager->superBlock, b);
+  return (b);
+}
+/**Function********************************************************************
+
+  Synopsis           [Sets the reoderability of a particular block.]
+
+  Description        [If a block is reorderable, the child blocks are
+  recursively involved in swapping.]
+
+  SideEffects        [None.]
+
+  SeeAlso            []
+
+******************************************************************************/
+void
+Cal_BddVarBlockReorderable(Cal_BddManager bddManager, Cal_Block block,
+                           int reorderable)
+{
+  block->reorderable = reorderable;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+long
+CalBddFindBlock(Cal_Block block, long index)
+{
+  long i, j, k;
+
+  i = 0;
+  j = block->numChildren-1;
+  while (i <= j) {
+    k = (i+j)/2;
+    if (block->children[k]->firstIndex <= index &&
+        block->children[k]->lastIndex >= index){
+      return (k);
+    }
+    if (block->children[k]->firstIndex > index){
+      j = k-1;
+    }
+    else {
+      i = k+1;
+    }
+  }
+  return i;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddBlockDelta(Cal_Block b, long delta)
+{
+  long i;
+  b->firstIndex += delta;
+  b->lastIndex += delta;
+  for (i=0; i < b->numChildren; ++i)
+    CalBddBlockDelta(b->children[i], delta);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+Cal_Block
+CalBddShiftBlock(Cal_BddManager_t *bddManager, Cal_Block b, long index)
+{
+  long i, j;
+  Cal_Block p;
+
+  if (b->firstIndex >= index) {
+    CalBddBlockDelta(b, 1l);
+    return (b);
+  }
+  if (b->lastIndex < index) return (b);
+  b->lastIndex++;
+  i = CalBddFindBlock(b, index);
+  if (i == b->numChildren || b->children[i]->firstIndex == index) {
+    b->children = (Cal_Block *)
+        Cal_MemRealloc(Cal_Block, b->children, b->numChildren+1);
+    for (j = b->numChildren-1; j >= i; --j){
+      b->children[j+1] = CalBddShiftBlock(bddManager, b->children[j], index);
+    }
+    b->numChildren++;
+    /*p = CAL_BDD_NEW_REC(bddManager, Cal_Block_t);*/
+    p = Cal_MemAlloc(Cal_Block_t, 1);
+    p->reorderable = 0;
+    p->firstIndex = index;
+    p->lastIndex = index;
+    p->numChildren = 0;
+    p->children = 0;
+    b->children[i] = p;
+  }
+  else{
+    while (i < b->numChildren) {
+      CalBddShiftBlock(bddManager, b->children[i], index);
+      ++i;
+    }
+  }
+  return (b);
+}
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+unsigned long
+CalBlockMemoryConsumption(Cal_Block block)
+{
+  unsigned long totalBytes = 0;
+  int i;
+  
+  totalBytes += sizeof(Cal_Block);
+  for (i=0; i<block->numChildren; i++){
+    totalBytes += CalBlockMemoryConsumption(block->children[i]);
+  }
+  return totalBytes;
+}
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalFreeBlockRecursively(Cal_Block block)
+{
+  int i;
+  
+  for (i=0; i<block->numChildren; i++){
+    CalFreeBlockRecursively(block->children[i]);
+  }
+  Cal_MemFree(block->children);
+  Cal_MemFree(block);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+AddBlock(Cal_Block b1, Cal_Block b2)
+{
+  long i, j, k;
+  Cal_Block start, end;
+
+  if (b1->numChildren){
+    i = CalBddFindBlock(b1, b2->firstIndex);
+    start = b1->children[i];
+    j = CalBddFindBlock(b1, b2->lastIndex);
+    end = b1->children[j];
+    if (i == j) {
+      AddBlock(start, b2);
+    }
+    else {
+      if (start->firstIndex != b2->firstIndex ||
+          end->lastIndex != b2->lastIndex){
+        CalBddFatalMessage("AddBlock: illegal block overlap");
+      }
+      b2->numChildren = j-i+1;
+	  b2->children = Cal_MemAlloc(Cal_Block, b2->numChildren); 
+	  for (k=0; k < b2->numChildren; ++k){
+	    b2->children[k] = b1->children[i+k];
+      }
+	  b1->children[i] = b2;
+	  ++i;
+	  for (k=j+1; k < b1->numChildren; ++k, ++i){
+	    b1->children[i] = b1->children[k];
+      }
+	  b1->numChildren -= (b2->numChildren-1);
+	  b1->children = (Cal_Block *)
+          Cal_MemRealloc(Cal_Block, b1->children, b1->numChildren);
+	}
+  }
+  else {
+      /* b1 and b2 are blocks representing just single variables. */
+      b1->numChildren = 1;
+      b1->children = Cal_MemAlloc(Cal_Block, b1->numChildren); 
+      b1->children[0] = b2;
+      b2->numChildren = 0;
+      b2->children = 0;
+  }
+}
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calCacheTableTwo.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calCacheTableTwo.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calCacheTableTwo.c	(revision 8)
@@ -0,0 +1,751 @@
+/**CFile***********************************************************************
+
+  FileName    [calCacheTableTwo.c]
+
+  PackageName [cal]
+
+  Synopsis    [Functions to manage the Cache tables.]
+  Description [ ]
+
+  SeeAlso     [optional]
+
+  Author      [ Rajeev K. Ranjan   (rajeev@eecs.berkeley.edu)
+                Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+              ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calCacheTableTwo.c,v 1.4 1998/09/15 19:02:52 ravi Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* cache table management related constants */
+#define CACHE_TABLE_DEFAULT_SIZE_INDEX 16
+#define CACHE_TABLE_DEFAULT_CACHE_RATIO 4
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct CacheEntryStruct CacheEntry_t;
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+struct CalCacheTableStruct {
+  long numBins;
+  int sizeIndex;
+  CacheEntry_t *bins;
+  int cacheRatio;
+  long numInsertions;
+  long numEntries;
+  long numHits;
+  long numLookups;
+  long numCollisions;
+};
+
+struct CacheEntryStruct {
+  CalBddNode_t *operand1;
+  CalBddNode_t *operand2;
+  CalBddNode_t *resultBddNode;
+  Cal_BddId_t resultBddId;
+  unsigned short opCode;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#ifdef USE_POWER_OF_2
+#  define CacheTableTwoDoHash(table, operand1, operand2, opCode) \
+   (((((((CalAddress_t)(operand1)) +	((CalAddress_t)(operand2))) / NODE_SIZE) << 2) + opCode + ((CalAddress_t)operand1 & 0x1)+ (((CalAddress_t)operand2 & 0x1)<<1)) &((table)->numBins - 1))
+#else
+#  define CacheTableTwoDoHash(table, operand1, operand2, opCode) \
+   ((((((CalAddress_t)(operand1)) +	((CalAddress_t)(operand2))) / NODE_SIZE) + opCode + ((CalAddress_t)operand1 & 0x1)+ ((CalAddress_t)operand2 & 0x1)) %((table)->numBins))
+/*(((((CalAddress_t)(operand1)) +	((CalAddress_t)(operand2))) + opCode) &((table)->numBins - 1))
+((opCode + (((CalAddress_t)(operand1)) << 1) + (((CalAddress_t)(operand2)) <<2)) &((table)->numBins - 1))
+((opCode + ((((CalAddress_t)(operand1)) + ((CalAddress_t)(operand2))) )+(((CalAddress_t)operand1 & 0x1) << (table->sizeIndex-1)) + (((CalAddress_t)operand2 & 0x1) << (table->sizeIndex-2))) &((table)->numBins - 1))
+((opCode + (((CalAddress_t)(operand1)) << 1) + (((CalAddress_t)(operand2)) << 2)) &((table)->numBins - 1))
+*/
+#endif
+
+#define CacheTableTwoCompareCacheEntry(entry, _operand1, _operand2, _opCode)  \
+((((CalBddNode_t *)(((CalAddress_t)((entry)->operand1)) & ~0x2)) == (_operand1))\
+ &&								\
+ ((entry)->operand2 == (_operand2))\
+ &&								\
+ ((entry)->opCode == _opCode))
+
+#define CacheResultNodeIsForwardedTo(resultBddNode, resultBddId) \
+{ \
+  CalBddNode_t *__resultBddNode;\
+  __resultBddNode = CAL_BDD_POINTER(resultBddNode); \
+  if(CalRequestNodeGetElseRequestNode(__resultBddNode) == FORWARD_FLAG){ \
+    resultBddId = __resultBddNode->thenBddId; \
+    resultBddNode = (CalBddNode_t*) \
+                    (((CalAddress_t)(__resultBddNode->thenBddNode) & ~0xe)        \
+                         ^(CAL_TAG0(resultBddNode))); \
+  } \
+}
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CacheTableTwoRehash(CalCacheTable_t *cacheTable, int grow);
+static void CacheTablePrint(CalCacheTable_t *cacheTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Initialize a Cache table using default parameters.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+CalCacheTable_t *
+CalCacheTableTwoInit(Cal_BddManager_t *bddManager)
+{
+  CalCacheTable_t  *cacheTable;
+  cacheTable = Cal_MemAlloc(CalCacheTable_t, 1);
+  if (cacheTable == Cal_Nil(CalCacheTable_t)){
+    CalBddFatalMessage("out of memory");
+  }
+  cacheTable->sizeIndex = CACHE_TABLE_DEFAULT_SIZE_INDEX;
+  cacheTable->numBins = TABLE_SIZE(cacheTable->sizeIndex);
+  cacheTable->cacheRatio = CACHE_TABLE_DEFAULT_CACHE_RATIO;
+  cacheTable->bins = Cal_MemAlloc(CacheEntry_t, cacheTable->numBins);
+  if(cacheTable->bins == Cal_Nil(CacheEntry_t)){
+    CalBddFatalMessage("out of memory");
+  }		
+  memset((char *)cacheTable->bins, 0,
+	 cacheTable->numBins*sizeof(CacheEntry_t));
+  cacheTable->numInsertions = 0;
+  cacheTable->numEntries = 0;
+  cacheTable->numHits = 0;
+  cacheTable->numLookups = 0;
+  cacheTable->numCollisions = 0;
+  return cacheTable;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free a Cache table along with the associated storage.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalCacheTableTwoQuit(CalCacheTable_t *cacheTable)
+{
+  if(cacheTable == Cal_Nil(CalCacheTable_t))return 1;
+  Cal_MemFree(cacheTable->bins);
+  Cal_MemFree(cacheTable);
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Directly insert a BDD node in the Cache table.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalCacheTableTwoInsert(Cal_BddManager_t *bddManager, Cal_Bdd_t f,
+                       Cal_Bdd_t g, Cal_Bdd_t result, unsigned long
+                       opCode, int cacheLevel)
+{
+  int hashValue;
+  CalCacheTable_t *cacheTable;
+  CacheEntry_t *bin;
+  CalBddNode_t *operand1Node, *operand2Node;
+
+  cacheTable = bddManager->cacheTable;
+  cacheTable->numInsertions++;
+  hashValue = CacheTableTwoDoHash(cacheTable, CalBddGetBddNode(f),
+                                  CalBddGetBddNode(g), opCode); 
+
+  bin = cacheTable->bins + hashValue;
+  if (bin->opCode != CAL_OP_INVALID){
+    cacheTable->numCollisions++;
+  }
+  else{
+    cacheTable->numEntries++;
+  }
+  
+  bin->opCode = opCode;
+  if ((CalAddress_t)CalBddGetBddNode(f) >
+      (CalAddress_t)CalBddGetBddNode(g)){ 
+    operand1Node = CalBddGetBddNode(g);
+    operand2Node = CalBddGetBddNode(f);
+  }
+  else{
+    operand1Node = CalBddGetBddNode(f);
+    operand2Node = CalBddGetBddNode(g);
+  }
+  
+  if (cacheLevel){
+  /*
+   * Mark this result as temporary node to be forwarded at the end of
+   * operation. The reason we can use this tagging is because the
+   * size of the structure is 16 bytes and we are requiring 8 or 16 byte
+   * alignment (at least last 3 bits should be zero).
+   */
+    bin->operand1 = (CalBddNode_t *) (((CalAddress_t)operand1Node) | 0x2);
+  }
+  else {
+    bin->operand1 = operand1Node;
+  }
+  bin->operand2 = operand2Node;
+  bin->resultBddNode = CalBddGetBddNode(result);
+  bin->resultBddId = CalBddGetBddId(result);
+  return;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalCacheTableTwoLookup(Cal_BddManager_t *bddManager, Cal_Bdd_t f,
+                       Cal_Bdd_t g, unsigned long opCode, Cal_Bdd_t
+                       *resultBddPtr)  
+{
+  int hashValue;
+  CalCacheTable_t *cacheTable;
+  CacheEntry_t *bin;
+  CalBddNode_t *operand1Node, *operand2Node;
+  
+  cacheTable = bddManager->cacheTable;
+  cacheTable->numLookups++;
+  hashValue = CacheTableTwoDoHash(cacheTable, CalBddGetBddNode(f),
+                                  CalBddGetBddNode(g), opCode); 
+
+  bin = cacheTable->bins+hashValue;
+  
+  if ((CalAddress_t)CalBddGetBddNode(f) > (CalAddress_t)CalBddGetBddNode(g)){
+    operand1Node = CalBddGetBddNode(g);
+    operand2Node = CalBddGetBddNode(f);
+  }
+  else{
+    operand1Node = CalBddGetBddNode(f);
+    operand2Node = CalBddGetBddNode(g);
+  }
+  if (CacheTableTwoCompareCacheEntry(bin, operand1Node, operand2Node,
+                                     opCode)){
+    CalBddPutBddId((*resultBddPtr), bin->resultBddId);
+    CalBddPutBddNode((*resultBddPtr), bin->resultBddNode);
+    cacheTable->numHits++;
+    return 1;
+  }
+  *resultBddPtr = bddManager->bddNull;
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a Cache table along with the associated storage.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalCacheTableTwoFlush(CalCacheTable_t *cacheTable)
+{
+  memset((char *)cacheTable->bins, 0,
+	 cacheTable->numBins*sizeof(CacheEntry_t));
+  cacheTable->numEntries = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a Cache table along with the associated storage.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalCacheTableTwoFlushAll(CalCacheTable_t *cacheTable)
+{
+  CalCacheTableTwoFlush(cacheTable);
+  cacheTable->numInsertions = 0;
+  cacheTable->numCollisions = 0;
+  cacheTable->numLookups = 0;
+  cacheTable->numHits = 0;
+  return 0;
+}
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalCacheTableTwoGCFlush(CalCacheTable_t *cacheTable)
+{
+  int i;
+  CacheEntry_t *bin = cacheTable->bins;
+  int numBins = cacheTable->numBins;
+  if (cacheTable->numEntries == 0) return;
+  for (i=0; i<numBins; bin++,i++){
+    if (bin->opCode != CAL_OP_INVALID){
+      if (CalBddNodeIsMarked((CAL_BDD_POINTER(bin->operand1))) ||
+          CalBddNodeIsMarked((CAL_BDD_POINTER(bin->operand2))) ||
+          CalBddNodeIsMarked((CAL_BDD_POINTER(bin->resultBddNode)))){
+        /* This entry needs to be freed */
+        cacheTable->numEntries--;
+        memset((char *)bin, 0, sizeof(CacheEntry_t));
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalCacheTableTwoRepackUpdate(CalCacheTable_t *cacheTable)
+{
+  int i;
+  CacheEntry_t *bin = cacheTable->bins;
+  int numBins = cacheTable->numBins;
+  
+  for (i=0; i<numBins; bin++,i++){
+    if (bin->opCode != CAL_OP_INVALID){
+      if (CalBddNodeIsForwarded(CAL_BDD_POINTER(bin->operand1))){
+        CalBddNodeForward(bin->operand1);
+      }
+      if (CalBddNodeIsForwarded(CAL_BDD_POINTER(bin->operand2))){
+        CalBddNodeForward(bin->operand2);
+      }
+      if (CalBddNodeIsForwarded(CAL_BDD_POINTER(bin->resultBddNode))){
+        CalBddNodeForward(bin->resultBddNode);
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalCheckCacheTableValidity(Cal_BddManager bddManager)
+{
+  CalCacheTable_t *cacheTable = bddManager->cacheTable;
+  int i;
+  CacheEntry_t *bin = cacheTable->bins;
+  int numBins = cacheTable->numBins;
+  
+  for (i=0; i<numBins; bin++,i++){
+    if (bin->opCode != CAL_OP_INVALID){
+      Cal_Assert(CalBddNodeIsForwarded(CAL_BDD_POINTER(bin->operand1))
+                 == 0);
+      Cal_Assert(CalBddNodeIsForwarded(CAL_BDD_POINTER(bin->operand2))
+                 == 0);
+      Cal_Assert(CalBddNodeIsForwarded(CAL_BDD_POINTER(bin->resultBddNode))
+                 == 0);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalCacheTableTwoFixResultPointers(Cal_BddManager_t *bddManager)
+{
+  CalCacheTable_t *cacheTable = bddManager->cacheTable;
+  int i;
+  CacheEntry_t *bin = cacheTable->bins;
+  int numBins = cacheTable->numBins;
+  
+  for (i=0; i<numBins; bin++,i++){
+    if ((CalAddress_t)bin->operand1 & 0x2){ /* If the result node is temporary
+                                   node */
+      CacheResultNodeIsForwardedTo(bin->resultBddNode, bin->resultBddId);
+      bin->operand1 = (CalBddNode_t *)((CalAddress_t)bin->operand1 &
+                                       ~0x2); /* It is no longer temporary */
+    }
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalCacheTablePrint(Cal_BddManager_t *bddManager)
+{
+  CacheTablePrint(bddManager->cacheTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddManagerGetCacheTableData(Cal_BddManager_t *bddManager,
+                               unsigned long *cacheSize,
+                               unsigned long *cacheEntries,
+                               unsigned long *cacheInsertions,
+                               unsigned long *cacheLookups,
+                               unsigned long *cacheHits,
+                               unsigned long *cacheCollisions)
+{
+  CalCacheTable_t *cacheTable = bddManager->cacheTable;
+  *cacheSize += cacheTable->numBins;
+  *cacheEntries += cacheTable->numEntries;
+  *cacheInsertions += cacheTable->numInsertions;
+  *cacheLookups += cacheTable->numLookups;
+  *cacheHits += cacheTable->numHits;
+  *cacheCollisions += cacheTable->numCollisions;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalCacheTableRehash(Cal_BddManager_t *bddManager)
+{
+  CalCacheTable_t *cacheTable = bddManager->cacheTable;
+  if((3*cacheTable->numBins < cacheTable->cacheRatio*cacheTable->numEntries) &&
+     (32*cacheTable->numBins <
+      8*(bddManager->numNodes))){
+    CacheTableTwoRehash(cacheTable, 1);
+  }
+}
+/**Function********************************************************************
+
+  Synopsis           [Flushes the entries from the cache which
+                      correspond to the given associationId.]
+
+  Description        []
+
+  SideEffects        [Cache entries are affected.]
+
+  SeeAlso            []
+
+******************************************************************************/
+void
+CalCacheTableTwoFlushAssociationId(Cal_BddManager_t *bddManager, int
+                                   associationId)
+{
+  CalCacheTable_t *cacheTable =   bddManager->cacheTable;
+  int i;
+  CacheEntry_t *bin;
+  
+  for (i=0; i < cacheTable->numBins; i++){
+    bin = cacheTable->bins+i;
+    if ((bin->opCode == (CAL_OP_QUANT+associationId)) ||
+        (bin->opCode == (CAL_OP_REL_PROD+associationId)) ||
+        (bin->opCode == (CAL_OP_VAR_SUBSTITUTE+associationId))){
+      /* This entry needs to be freed */
+      cacheTable->numEntries--;
+      memset((char *)bin, 0, sizeof(CacheEntry_t));
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+unsigned long
+CalCacheTableMemoryConsumption(CalCacheTable_t *cacheTable)
+{
+  return (unsigned long) (sizeof(cacheTable)+cacheTable->numBins*sizeof(CacheEntry_t));
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CacheTableTwoRehash(CalCacheTable_t *cacheTable,int grow)
+{
+  CacheEntry_t *oldBins = cacheTable->bins;
+  int i, hashValue;
+  int oldNumBins = cacheTable->numBins;
+  CacheEntry_t *bin, *newBin;
+  
+  
+  if(grow){
+    cacheTable->sizeIndex++;
+  }
+  else{
+    if (cacheTable->sizeIndex <= CACHE_TABLE_DEFAULT_SIZE_INDEX){/* No need to Rehash */
+      return;
+    }
+    cacheTable->sizeIndex--;
+  }
+
+  cacheTable->numBins = TABLE_SIZE(cacheTable->sizeIndex);
+  cacheTable->bins = Cal_MemAlloc(CacheEntry_t, cacheTable->numBins);
+  if(cacheTable->bins == Cal_Nil(CacheEntry_t)){
+    CalBddFatalMessage("out of memory");
+  }
+  
+  memset((char *)cacheTable->bins, 0, 
+	 cacheTable->numBins*sizeof(CacheEntry_t));
+
+  for(i = 0; i < oldNumBins; i++){
+      bin  = oldBins+i;
+      if (bin->opCode == CAL_OP_INVALID) continue;
+      hashValue = CacheTableTwoDoHash(cacheTable,
+                                      bin->operand1,
+                                      bin->operand2,
+                                      bin->opCode);
+      newBin = cacheTable->bins+hashValue;
+      if (newBin->opCode != CAL_OP_INVALID){
+        cacheTable->numEntries--;
+      }
+      newBin->opCode = bin->opCode;
+      newBin->operand1 = bin->operand1;
+      newBin->operand2 = bin->operand2;
+      newBin->resultBddId = bin->resultBddId;
+      newBin->resultBddNode = bin->resultBddNode;
+  }
+  Cal_MemFree(oldBins);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CacheTablePrint(CalCacheTable_t *cacheTable)
+{
+  int i;
+  unsigned long opCode;
+  CacheEntry_t *bin;
+  
+  printf("cacheTable entries(%ld) bins(%ld)\n",
+         cacheTable->numEntries, cacheTable->numBins);
+  for(i = 0; i < cacheTable->numBins; i++){
+    bin = cacheTable->bins+i;
+    opCode = bin->opCode;
+    if (opCode != CAL_OP_INVALID){
+      fprintf(stdout,"Op = %s O1 = %lx, O2 = %lx RId = %d, RNode = %lx\n",
+              ((opCode == CAL_OP_OR) ? "OR" : ((opCode == CAL_OP_AND) ? "AND" :
+                                               ((opCode ==
+                                                            CAL_OP_QUANT) ?
+                                                           "QUANT" :
+                                                           ((opCode ==
+                                                             CAL_OP_REL_PROD)   
+                                                            ?
+                                                            "RELPROD"
+                                                            :
+                                                            "Nothing")))), 
+              (CalAddress_t)bin->operand1,
+              (CalAddress_t)bin->operand2, bin->resultBddId, 
+              (CalAddress_t)bin->resultBddNode);
+    }
+  }
+}
+
+
+#ifdef CACHE_TABLE_TWO_TEST
+main(int argc, char **argv)
+{
+  Cal_Bdd_t f1, f2, f3, f4, f5, result;
+  Cal_BddManager_t *bddManager = Cal_BddManagerInit();
+  int i;
+  CalCacheTable_t *cacheTable;
+  
+  for (i=0; i<5; i++){
+    Cal_BddManagerCreateNewVarLast(bddManager);
+  }
+
+  CalCacheTablePrint(bddManager);
+  
+  f1 = bddManager->varBdds[1];
+  f2 = bddManager->varBdds[2];
+  f3 = bddManager->varBdds[3];
+  f4 = bddManager->varBdds[4];
+  f5 = bddManager->varBdds[5];
+  
+  CalCacheTableTwoInsert(bddManager, f1, f2, f3, CAL_OP_OR, 0);
+  CalCacheTableTwoInsert(bddManager, f3, f2, f4, CAL_OP_AND,0);
+  CalCacheTableTwoInsert(bddManager, f3, f4, f5, CAL_OP_REL_PROD,0);
+  /*CacheTableTwoRehash(bddManager->cacheTableArray[2], 1);*/
+  CalCacheTablePrint(bddManager);
+  
+  /* Look up */
+  CalCacheTableTwoLookup(bddManager, f3, f2, CAL_OP_AND, &result);
+  assert(CalBddIsEqual(result, f4));
+
+  CalCacheTableTwoLookup(bddManager, f3, f2, CAL_OP_OR, &result);
+  assert(CalBddIsEqual(result, bddManager->bddNull));
+  
+  CalCacheTableTwoLookup(bddManager, f3, f1, CAL_OP_OR, &result);
+  assert(CalBddIsEqual(result, bddManager->bddNull));
+
+  /* Another look up */
+  CalCacheTableTwoLookup(bddManager, f4, f3, CAL_OP_REL_PROD, &result);
+  assert(CalBddIsEqual(result, f5));
+
+  /* It will bump off the entry (f2, f2, AND, f4)*/
+  CalCacheTableTwoInsert(bddManager, f3, f2, f1, CAL_OP_AND,0);
+  /* Do lookup and see if that's what happened */
+  CalCacheTableTwoLookup(bddManager, f3, f2, CAL_OP_AND, &result);
+  assert(CalBddIsEqual(result, f1));
+
+  /*
+   * Rehashing will visit (f2, f3, AND, f4) first and then (f2, f3,
+   * AND, f1)
+   * Hence the we should have (f2, f3, AND, f1) in the first slot
+   */
+  CacheTableTwoRehash(bddManager->cacheTable, 1);
+  CalCacheTableTwoLookup(bddManager, f3, f2, CAL_OP_AND, &result);
+  assert(CalBddIsEqual(result, f1));
+  Cal_BddManagerQuit(bddManager);
+  
+}
+#endif
Index: /vis_dev/glu-2.1/src/calBdd/calDesc.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calDesc.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calDesc.html	(revision 8)
@@ -0,0 +1,28 @@
+<HTML>
+<HEAD><TITLE>The cal package: Overview</TITLE></HEAD>
+<BODY>
+
+<H1>The cal package</H1>
+<H2>Header CAL file for exported data structures and functions.</H2>
+<H3>By Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu)</H3>
+
+<UL>
+ <LI> <A HREF="calExt.html" TARGET="_top">
+    Information for programmers</A>
+ <LI> <A HREF="calAllByFunc.html" TARGET="_top">
+    Information for developers sorted by function</A>
+ <LI> <A HREF="calAllByFile.html" TARGET="_top">
+    Information for developers sorted by file</A>
+</UL>
+
+<HR>
+
+
+
+<HR>
+
+Last updated on 970711 20h11
+
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calDoc.txt
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calDoc.txt	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calDoc.txt	(revision 8)
@@ -0,0 +1,1482 @@
+The cal package
+
+Header CAL file for exported data structures and functions.
+
+Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)                Jagesh V. Sanghavi
+(sanghavi@eecs.berkeley.edu)
+
+**********************************************************************
+
+Cal_AssociationInit()          Creates or finds a variable association.
+
+Cal_AssociationQuit()          Deletes the variable association given by id
+
+Cal_AssociationSetCurrent()    Sets the current variable association to the
+                               one given by id and   returns the ID of the old
+                               association.
+
+Cal_BddAnd()                   Returns the BDD for logical AND of argument
+                               BDDs
+
+Cal_BddBetween()               Returns a minimal BDD whose function contains
+                               fMin and is   contained in fMax.
+
+Cal_BddCofactor()              Returns the generalized cofactor of BDD f with
+                               respect   to BDD c.
+
+Cal_BddCompose()               composition - substitute a BDD variable by a
+                               function
+
+Cal_BddDependsOn()             Returns 1 if f depends on var and returns 0
+                               otherwise.
+
+Cal_BddDumpBdd()               Write a BDD to a file
+
+Cal_BddDynamicReordering()     Specify dynamic reordering technique.
+
+Cal_BddElse()                  Returns the negative cofactor of the argument
+                               BDD with   respect to the top variable of the
+                               BDD.
+
+Cal_BddExists()                Returns the result of existentially quantifying
+                               some   variables from the given BDD.
+
+Cal_BddForAll()                Returns the result of universally quantifying
+                               some   variables from the given BDD.
+
+Cal_BddFree()                  Frees the argument BDD.
+
+Cal_BddFunctionPrint()         Prints the function implemented by the argument
+                               BDD
+
+Cal_BddFunctionProfileMultiple()
+                               Returns a "function profile" for fArray.
+
+Cal_BddFunctionProfile()       Returns a "function profile" for f.
+
+Cal_BddGetIfId()               Returns the id of the top variable of the
+                               argument BDD.
+
+Cal_BddGetIfIndex()            Returns the index of the top variable of the
+                               argument BDD.
+
+Cal_BddGetRegular()            Returns a BDD with positive from a given BDD
+                               with arbitrary phase
+
+Cal_BddITE()                   Returns the BDD for logical If-Then-Else
+                               Description [Returns the BDD for the logical
+                               operation IF f THEN g ELSE h   - f g + f' h
+
+Cal_BddIdentity()              Returns the duplicate BDD of the argument BDD.
+
+Cal_BddIf()                    Returns the BDD corresponding to the top
+                               variable of   the argument BDD.
+
+Cal_BddImplies()               Computes a BDD that implies conjunction of f
+                               and Cal_BddNot(g)
+
+Cal_BddIntersects()            Computes a BDD that implies conjunction of f
+                               and g.
+
+Cal_BddIsBddConst()            Returns 1 if the argument BDD is a constant, 0
+                               otherwise.
+
+Cal_BddIsBddNull()             Returns 1 if the argument BDD is NULL, 0
+                               otherwise.
+
+Cal_BddIsBddOne()              Returns 1 if the argument BDD is constant one,
+                               0 otherwise.
+
+Cal_BddIsBddZero()             Returns 1 if the argument BDD is constant zero,
+                               0 otherwise.
+
+Cal_BddIsCube()                Returns 1 if the argument BDD is a cube, 0
+                               otherwise
+
+Cal_BddIsEqual()               Returns 1 if argument BDDs are equal, 0
+                               otherwise.
+
+Cal_BddIsProvisional()         Returns 1, if the given user BDD contains
+                               provisional BDD node.
+
+Cal_BddManagerCreateNewVarAfter()
+                               Creates and returns a new variable after the
+                               specified one in   the variable  order.
+
+Cal_BddManagerCreateNewVarBefore()
+                               Creates and returns a new variable before the
+                               specified one in   the variable order.
+
+Cal_BddManagerCreateNewVarFirst()
+                               Creates and returns a new variable at the start
+                               of the variable   order.
+
+Cal_BddManagerCreateNewVarLast()
+                               Creates and returns a new variable at the end
+                               of the variable   order.
+
+Cal_BddManagerGC()             Invokes the garbage collection at the manager
+                               level.
+
+Cal_BddManagerGetHooks()       Returns the hooks field of the manager.
+
+Cal_BddManagerGetNumNodes()    Returns the number of BDD nodes
+
+Cal_BddManagerGetVarWithId()   Returns the variable with the specified id,
+                               null if no   such variable exists
+
+Cal_BddManagerGetVarWithIndex()
+                               Returns the variable with the specified index,
+                               null if no   such variable exists
+
+Cal_BddManagerInit()           Creates and initializes a new BDD manager.
+
+Cal_BddManagerQuit()           Frees the BDD manager and all the associated
+                               allocations
+
+Cal_BddManagerSetGCLimit()     Sets the limit of the garbage collection.
+
+Cal_BddManagerSetHooks()       Sets the hooks field of the manager.
+
+Cal_BddManagerSetParameters()  Sets appropriate fields of BDD Manager.
+
+Cal_BddMultiwayAnd()           Returns the BDD for logical AND of argument
+                               BDDs
+
+Cal_BddMultiwayOr()            Returns the BDD for logical OR of argument BDDs
+
+Cal_BddMultiwayXor()           Returns the BDD for logical XOR of argument
+                               BDDs
+
+Cal_BddNand()                  Returns the BDD for logical NAND of argument
+                               BDDs
+
+Cal_BddNewVarBlock()           Creates and returns a variable block used for
+                               controlling dynamic reordering.
+
+Cal_BddNodeLimit()             Sets the node limit to new_limit and returns
+                               the old limit.
+
+Cal_BddNor()                   Returns the BDD for logical NOR of argument
+                               BDDs
+
+Cal_BddNot()                   Returns the complement of the argument BDD.
+
+Cal_BddOne()                   Returns the BDD for the constant one
+
+Cal_BddOr()                    Returns the BDD for logical OR of argument BDDs
+
+Cal_BddOverflow()              Returns 1 if the node limit has been exceeded,
+                               0 otherwise. The   overflow flag is cleared.
+
+Cal_BddPairwiseAnd()           Returns an array of BDDs obtained by logical
+                               AND of BDD pairs   specified by an BDD array in
+                               which a BDD at an even location is paired with
+                               a BDD at an odd location of the array
+
+Cal_BddPairwiseOr()            Returns an array of BDDs obtained by logical OR
+                               of BDD pairs   specified by an BDD array in
+                               which a BDD at an even location is paired with
+                               a BDD at an odd location of the array
+
+Cal_BddPairwiseXor()           Returns an array of BDDs obtained by logical
+                               XOR of BDD pairs   specified by an BDD array in
+                               which a BDD at an even location is paired with
+                               a BDD at an odd location of the array
+
+Cal_BddPrintBdd()              Prints a BDD in the human readable form.
+
+Cal_BddPrintFunctionProfileMultiple()
+                               Cal_BddPrintFunctionProfileMultiple is like
+                               Cal_BddPrintFunctionProfile except for multiple
+                               BDDs
+
+Cal_BddPrintFunctionProfile()  Cal_BddPrintFunctionProfile is like
+                               Cal_BddPrintProfile except                it
+                               displays a function profile for f
+
+Cal_BddPrintProfileMultiple()  Cal_BddPrintProfileMultiple is like
+                               Cal_BddPrintProfile except                it
+                               displays the profile for a set of BDDs
+
+Cal_BddPrintProfile()          Displays the node profile for f on fp.
+                               lineLength specifies                 the
+                               maximum line length.  varNamingFn is as in
+                               Cal_BddPrintBdd.
+
+Cal_BddProfileMultiple()
+
+Cal_BddProfile()               Returns a "node profile" of f, i.e., the number
+                               of nodes at each   level in f.
+
+Cal_BddReduce()                Returns a BDD which agrees with f for all
+                               valuations   which satisfy c.
+
+Cal_BddRelProd()               Returns the result of taking the logical AND of
+                               the   argument BDDs and existentially
+                               quantifying some variables from the   product.
+
+Cal_BddReorder()               Invoke the current dynamic reodering method.
+
+Cal_BddSatisfySupport()        Returns a special cube contained in f.
+
+Cal_BddSatisfyingFraction()    Returns the fraction of valuations which make f
+                               true. (Note that   this fraction is independent
+                               of whatever set of variables f is supposed to
+                               be   a function of)
+
+Cal_BddSatisfy()               Returns a BDD which implies f, true for
+                               some valuation on which f is true, and which
+                               has at most                one node at each
+                               level
+
+Cal_BddSetGCMode()             Sets the garbage collection mode, 0 means the
+                               garbage   collection should be turned off, 1
+                               means garbage collection should   be on.
+
+Cal_BddSizeMultiple()          The routine is like Cal_BddSize, but takes a
+                               null-terminated                array of BDDs
+                               and accounts for sharing of nodes.
+
+Cal_BddSize()                  Returns the number of nodes in f when negout is
+                               nonzero. If   negout is zero, we pretend that
+                               the BDDs don't have negative-output pointers.
+
+Cal_BddStats()                 Prints miscellaneous BDD statistics
+
+Cal_BddSubstitute()            Substitute a set of variables by functions
+
+Cal_BddSupport()               returns the support of f as a null-terminated
+                               array of variables
+
+Cal_BddSwapVars()              Return a function obtained by swapping two
+                               variables
+
+Cal_BddThen()                  Returns the positive cofactor of the argument
+                               BDD with   respect to the top variable of the
+                               BDD.
+
+Cal_BddTotalSize()             Returns the number of nodes in the Unique table
+
+Cal_BddType()                  Returns type of a BDD ( 0, 1, +var, -var,
+                               ovrflow, nonterminal)
+
+Cal_BddUnFree()                Unfrees the argument BDD.
+
+Cal_BddUndumpBdd()             Reads a BDD from a file
+
+Cal_BddVarBlockReorderable()   Sets the reoderability of a particular block.
+
+Cal_BddVarSubstitute()         Substitute a set of variables by set of another
+                               variables.
+
+Cal_BddVars()                  Returns the number of BDD variables
+
+Cal_BddXnor()                  Returns the BDD for logical exclusive NOR of
+                               argument BDDs
+
+Cal_BddXor()                   Returns the BDD for logical exclusive OR of
+                               argument BDDs
+
+Cal_BddZero()                  Returns the BDD for the constant zero
+
+Cal_MemAllocation()            Returns the memory allocated.
+
+Cal_MemFatal()                 Prints an error message and exits.
+
+Cal_MemFreeBlock()             Frees the block.
+
+Cal_MemFreeRecMgr()            Frees all the storage associated with the
+                               specified record manager.
+
+Cal_MemFreeRec()               Frees a record managed by the indicated record
+                               manager.
+
+Cal_MemGetBlock()              Allocates a new block of the specified size.
+
+Cal_MemNewRecMgr()             Creates a new record manager with the given
+                               record size.
+
+Cal_MemNewRec()                Allocates a record from the specified record
+                               manager.
+
+Cal_MemResizeBlock()           Expands or contracts the block to a new size.
+                               We try to avoid moving the block if possible.
+
+Cal_PerformanceTest()          Main routine for testing performances of
+                               various routines.
+
+Cal_PipelineCreateProvisionalBdd()
+                               Create a provisional BDD in the pipeline.
+
+Cal_PipelineExecute()          Executes a pipeline.
+
+Cal_PipelineInit()             Initialize a BDD pipeline.
+
+Cal_PipelineQuit()             Resets the pipeline freeing all resources.
+
+Cal_PipelineSetDepth()         Set depth of a BDD pipeline.
+
+Cal_PipelineUpdateProvisionalBdd()
+                               Update a provisional Bdd obtained during
+                               pipelining.
+
+Cal_TempAssociationAugment()   Adds to the temporary variable association.
+
+Cal_TempAssociationInit()      Sets the temporary variable association.
+
+Cal_TempAssociationQuit()      Cleans up temporary association
+
+**********************************************************************
+
+
+
+int
+Cal_AssociationInit(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         associationInfoU
+  int               pairs
+)
+  Creates or finds a variable association. The association is specified by
+  associationInfo, which is a an array of BDD with Cal_BddNull(bddManager) as
+  the end marker. If pairs is 0, the array is assumed to be an array of
+  variables. In this case, each variable is paired with constant BDD one. Such
+  an association may viewed as specifying a set of variables for use with
+  routines such as Cal_BddExists. If pair is not 0, then the even numbered
+  array elements should be variables and the odd numbered elements should be
+  the BDDs which they are mapped to. In both cases, the return value is an
+  integer identifier for this association. If the given association is
+  equivalent to one which already exists, the same identifier is used for
+  both, and the reference count of the association is increased by one.
+
+  Side Effects: None
+
+void
+Cal_AssociationQuit(
+  Cal_BddManager    bddManager,
+  int               associationId
+)
+  Decrements the reference count of the variable association with identifier
+  id, and frees it if the reference count becomes zero.
+
+  Side Effects: None
+
+int
+Cal_AssociationSetCurrent(
+  Cal_BddManager    bddManager,
+  int               associationId
+)
+  Sets the current variable association to the one given by id and returns the
+  ID of the old association. An id of -1 indicates the temporary association
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddAnd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Returns the BDD for logical AND of f and g
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddBetween(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fMinUserBdd,
+  Cal_Bdd           fMaxUserBdd
+)
+  Returns a minimal BDD f which is contains fMin and is contained in fMax (
+  fMin <= f <= fMax). This operation is typically used in state space searches
+  to simplify the representation for the set of states wich will be expanded
+  at each step (Rk Rk-1' <= f <= Rk).
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddCofactor(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           cUserBdd
+)
+  Returns the generalized cofactor of BDD f with respect to BDD c. The
+  constrain operator given by Coudert et al (ICCAD90) is used to find the
+  generalized cofactor.
+
+  Side Effects: None.
+
+Cal_Bdd
+Cal_BddCompose(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd,
+  Cal_Bdd           hUserBdd
+)
+  Returns the BDD obtained by substituting a variable by a function
+
+  Side Effects: None
+
+int
+Cal_BddDependsOn(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           varUserBdd
+)
+  Returns 1 if f depends on var and returns 0 otherwise.
+
+  Side Effects: None
+
+int
+Cal_BddDumpBdd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd *         userVars,
+  FILE *            fp
+)
+  Writes an encoded description of the BDD to the file given by fp. The
+  argument vars should be a null-terminated array of variables that include
+  the support of f . These variables need not be in order of increasing index.
+  The function returns a nonzero value if f was written to the file
+  successfully.
+
+  Side Effects: required
+
+void
+Cal_BddDynamicReordering(
+  Cal_BddManager    bddManager,
+  int               technique
+)
+  Selects the method for dynamic reordering.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddElse(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns the negative cofactor of the argument BDD with respect to the top
+  variable of the BDD.
+
+  Side Effects: The reference count of the returned BDD is increased by 1.
+
+Cal_Bdd
+Cal_BddExists(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  Returns the BDD for f with all the variables that are paired with something
+  in the current variable association existentially quantified out.
+
+  Side Effects: None.
+
+Cal_Bdd
+Cal_BddForAll(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  Returns the BDD for f with all the variables that are paired with something
+  in the current variable association universally quantified out.
+
+  Side Effects: None.
+
+void
+Cal_BddFree(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Frees the argument BDD. It is an error to free a BDD more than once.
+
+  Side Effects: The reference count of the argument BDD is decreased by 1.
+
+void
+Cal_BddFunctionPrint(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd,
+  char *            name
+)
+  Prints the function implemented by the argument BDD
+
+  Side Effects: None
+
+void
+Cal_BddFunctionProfileMultiple(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         fUserBddArray,
+  long *            funcCounts
+)
+  optional
+
+  Side Effects: None
+
+void
+Cal_BddFunctionProfile(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  long *            funcCounts
+)
+  The nth entry of the function profile array is the number of subfunctions of
+  f which may be obtained by restricting the variables whose index is less
+  than n. An entry of zero indicates that f is independent of the variable
+  with the corresponding index.
+
+
+Cal_BddId_t
+Cal_BddGetIfId(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns the id of the top variable of the argument BDD.
+
+  Side Effects: None
+
+Cal_BddId_t
+Cal_BddGetIfIndex(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns the index of the top variable of the argument BDD.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddGetRegular(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns a BDD with positive from a given BDD with arbitrary phase
+
+  Side Effects: None.
+
+Cal_Bdd
+Cal_BddITE(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd,
+  Cal_Bdd           hUserBdd
+)
+  Returns the BDD for logical If-Then-Else Description [Returns the BDD for
+  the logical operation IF f THEN g ELSE h - f g + f' h
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddIdentity(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns the duplicate BDD of the argument BDD.
+
+  Side Effects: The reference count of the BDD is increased by 1.
+
+Cal_Bdd
+Cal_BddIf(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns the BDD corresponding to the top variable of the argument BDD.
+
+  Side Effects: None.
+
+Cal_Bdd
+Cal_BddImplies(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Computes a BDD that implies conjunction of f and Cal_BddNot(g)
+
+  Side Effects: none
+
+Cal_Bdd
+Cal_BddIntersects(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Computes a BDD that implies conjunction of f and g.
+
+  Side Effects: None
+
+int
+Cal_BddIsBddConst(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns 1 if the argument BDD is either constant one or constant zero,
+  otherwise returns 0.
+
+  Side Effects: None.
+
+int
+Cal_BddIsBddNull(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns 1 if the argument BDD is NULL, 0 otherwise.
+
+  Side Effects: None.
+
+int
+Cal_BddIsBddOne(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns 1 if the argument BDD is constant one, 0 otherwise.
+
+  Side Effects: None.
+
+int
+Cal_BddIsBddZero(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns 1 if the argument BDD is constant zero, 0 otherwise.
+
+  Side Effects: None.
+
+int
+Cal_BddIsCube(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  Returns 1 if the argument BDD is a cube, 0 otherwise
+
+  Side Effects: None
+
+int
+Cal_BddIsEqual(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd1,
+  Cal_Bdd           userBdd2
+)
+  Returns 1 if argument BDDs are equal, 0 otherwise.
+
+  Side Effects: None.
+
+int
+Cal_BddIsProvisional(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns 1, if the given user BDD contains provisional BDD node.
+
+  Side Effects: None.
+
+Cal_Bdd
+Cal_BddManagerCreateNewVarAfter(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Creates and returns a new variable after the specified one in the variable
+  order.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddManagerCreateNewVarBefore(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Creates and returns a new variable before the specified one in the variable
+  order.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddManagerCreateNewVarFirst(
+  Cal_BddManager    bddManager
+)
+  Creates and returns a new variable at the start of the variable order.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddManagerCreateNewVarLast(
+  Cal_BddManager    bddManager
+)
+  Creates and returns a new variable at the end of the variable order.
+
+  Side Effects: None
+
+int
+Cal_BddManagerGC(
+  Cal_BddManager    bddManager
+)
+  For each variable in the increasing id free nodes with reference count equal
+  to zero freeing a node results in decrementing reference count of then and
+  else nodes by one.
+
+  Side Effects: None.
+
+void *
+Cal_BddManagerGetHooks(
+  Cal_BddManager    bddManager
+)
+  Returns the hooks field of the manager.
+
+  Side Effects: None
+
+unsigned long
+Cal_BddManagerGetNumNodes(
+  Cal_BddManager    bddManager
+)
+  Returns the number of BDD nodes
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddManagerGetVarWithId(
+  Cal_BddManager    bddManager,
+  Cal_BddId_t       id
+)
+  Returns the variable with the specified id, null if no such variable exists
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddManagerGetVarWithIndex(
+  Cal_BddManager    bddManager,
+  Cal_BddIndex_t    index
+)
+  Returns the variable with the specified index, null if no such variable
+  exists
+
+  Side Effects: None
+
+Cal_BddManager
+Cal_BddManagerInit(
+
+)
+  Initializes and allocates fields of the BDD manager. Some of the fields are
+  initialized for maxNumVars+1 or numVars+1, whereas some of them are
+  initialized for maxNumVars or numVars. The first kind of fields are
+  associated with the id of a variable and the second ones are with the index
+  of the variable.
+
+  Side Effects: None
+
+int
+Cal_BddManagerQuit(
+  Cal_BddManager    bddManager
+)
+  Frees the BDD manager and all the associated allocations
+
+  Side Effects: None
+
+void
+Cal_BddManagerSetGCLimit(
+  Cal_BddManager    manager
+)
+  It tries to set the limit at twice the number of nodes in the manager at the
+  current point. However, the limit is not allowed to fall below the
+  MIN_GC_LIMIT or to exceed the value of node limit (if one exists).
+
+  Side Effects: None.
+
+void
+Cal_BddManagerSetHooks(
+  Cal_BddManager    bddManager,
+  void *            hooks
+)
+  Sets the hooks field of the manager.
+
+  Side Effects: Hooks field changes.
+
+void
+Cal_BddManagerSetParameters(
+  Cal_BddManager    bddManager,
+  long              reorderingThresh
+  long              maxForwardedNode
+  double            repackAfterGCThr
+  double            tableRepackThres
+)
+  This function is used to set the parameters which are used to control the
+  reordering process. "reorderingThreshold" determines the number of nodes
+  below which reordering will NOT be invoked, "maxForwardedNodes" determines
+  the maximum number of forwarded nodes which are allowed (at that point the
+  cleanup must be done), and "repackingThreshold" determines the fraction of
+  the page utilized below which repacking has to be invoked. These parameters
+  have different affect on the computational and memory usage aspects of
+  reordeing. For instance, higher value of "maxForwardedNodes" will result in
+  process consuming more memory, and a lower value on the other hand would
+  invoke the cleanup process repeatedly resulting in increased computation.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddMultiwayAnd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBddArray
+)
+  Returns the BDD for logical AND of set of BDDs in the bddArray
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddMultiwayOr(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBddArray
+)
+  Returns the BDD for logical OR of set of BDDs in the bddArray
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddMultiwayXor(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBddArray
+)
+  Returns the BDD for logical XOR of set of BDDs in the bddArray
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddNand(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Returns the BDD for logical NAND of f and g
+
+  Side Effects: None
+
+Cal_Block
+Cal_BddNewVarBlock(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           variable,
+  long              length
+)
+  The block is specified by passing the first variable and the length of the
+  block. The "length" number of consecutive variables starting from "variable"
+  are put in the block.
+
+  Side Effects: A new block is created.
+
+long
+Cal_BddNodeLimit(
+  Cal_BddManager    bddManager,
+  long              newLimit
+)
+  Sets the node limit to new_limit and returns the old limit.
+
+  Side Effects: Threshold for garbage collection may change
+
+Cal_Bdd
+Cal_BddNor(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Returns the BDD for logical NOR of f and g
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddNot(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns the complement of the argument BDD.
+
+  Side Effects: The reference count of the argument BDD is increased by 1.
+
+Cal_Bdd
+Cal_BddOne(
+  Cal_BddManager    bddManager
+)
+  Returns the BDD for the constant one
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddOr(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Returns the BDD for logical OR of f and g
+
+  Side Effects: None
+
+int
+Cal_BddOverflow(
+  Cal_BddManager    bddManager
+)
+  Returns 1 if the node limit has been exceeded, 0 otherwise. The overflow
+  flag is cleared.
+
+  Side Effects: None
+
+Cal_Bdd *
+Cal_BddPairwiseAnd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBddArray
+)
+  Returns an array of BDDs obtained by logical AND of BDD pairs specified by
+  an BDD array in which a BDD at an even location is paired with a BDD at an
+  odd location of the array
+
+  Side Effects: None
+
+Cal_Bdd *
+Cal_BddPairwiseOr(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBddArray
+)
+  Returns an array of BDDs obtained by logical OR of BDD pairs specified by an
+  BDD array in which a BDD at an even location is paired with a BDD at an odd
+  location of the array
+
+  Side Effects: None
+
+Cal_Bdd *
+Cal_BddPairwiseXor(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBddArray
+)
+  Returns an array of BDDs obtained by logical XOR of BDD pairs specified by
+  an BDD array in which a BDD at an even location is paired with a BDD at an
+  odd location of the array
+
+  Side Effects: None
+
+void
+Cal_BddPrintBdd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_VarNamingFn_t VarNamingFn,
+  Cal_TerminalIdFn_ TerminalIdFn,
+  Cal_Pointer_t     env,
+  FILE *            fp
+)
+  Prints a human-readable representation of the BDD f to the file given by fp.
+  The namingFn should be a pointer to a function taking a bddManager, a BDD
+  and the pointer given by env. This function should return either a null
+  pointer or a srting that is the name of the supplied variable. If it returns
+  a null pointer, a default name is generated based on the index of the
+  variable. It is also legal for naminFN to e null; in this case, default
+  names are generated for all variables. The macro bddNamingFnNone is a null
+  pointer of suitable type. terminalIdFn should be apointer to a function
+  taking a bddManager and two longs. plus the pointer given by the env. It
+  should return either a null pointer. If it returns a null pointer, or if
+  terminalIdFn is null, then default names are generated for the terminals.
+  The macro bddTerminalIdFnNone is a null pointer of suitable type.
+
+  Side Effects: None.
+
+void
+Cal_BddPrintFunctionProfileMultiple(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBdds,
+  Cal_VarNamingFn_t varNamingProc,
+  char *            env,
+  int               lineLength,
+  FILE *            fp
+)
+  optional
+
+  Side Effects: None
+
+void
+Cal_BddPrintFunctionProfile(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           f,
+  Cal_VarNamingFn_t varNamingProc,
+  char *            env,
+  int               lineLength,
+  FILE *            fp
+)
+  optional
+
+  Side Effects: None
+
+void
+Cal_BddPrintProfileMultiple(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userBdds,
+  Cal_VarNamingFn_t varNamingProc,
+  char *            env,
+  int               lineLength,
+  FILE *            fp
+)
+  optional
+
+  Side Effects: None
+
+void
+Cal_BddPrintProfile(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_VarNamingFn_t varNamingProc,
+  char *            env,
+  int               lineLength,
+  FILE *            fp
+)
+  optional
+
+  Side Effects: None
+
+void
+Cal_BddProfileMultiple(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         fUserBddArray,
+  long *            levelCounts,
+  int               negout
+)
+  optional
+
+  Side Effects: None
+
+void
+Cal_BddProfile(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  long *            levelCounts,
+  int               negout
+)
+  negout is as in Cal_BddSize. levelCounts should be an array of size
+  Cal_BddVars(bddManager)+1 to hold the profile.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddReduce(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           cUserBdd
+)
+  Returns a BDD which agrees with f for all valuations which satisfy c. The
+  result is usually smaller in terms of number of BDD nodes than f. This
+  operation is typically used in state space searches to simplify the
+  representation for the set of states wich will be expanded at each step.
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddRelProd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Returns the BDD for the logical AND of f and g with all the variables that
+  are paired with something in the current variable association existentially
+  quantified out.
+
+  Side Effects: None.
+
+void
+Cal_BddReorder(
+  Cal_BddManager    bddManager
+)
+  Invoke the current dynamic reodering method.
+
+  Side Effects: Index of a variable may change due to reodering
+
+Cal_Bdd
+Cal_BddSatisfySupport(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  The returned BDD which implies f, is true for some valuation on which f is
+  true, which has at most one node at each level, and which has exactly one
+  node corresponding to each variable which is associated with something in
+  the current variable association.
+
+  Side Effects: required
+
+double
+Cal_BddSatisfyingFraction(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  optional
+
+  Side Effects: required
+
+Cal_Bdd
+Cal_BddSatisfy(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  optional
+
+  Side Effects: required
+
+void
+Cal_BddSetGCMode(
+  Cal_BddManager    bddManager,
+  int               gcMode
+)
+  Sets the garbage collection mode, 0 means the garbage collection should be
+  turned off, 1 means garbage collection should be on.
+
+  Side Effects: None.
+
+long
+Cal_BddSizeMultiple(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         fUserBddArray,
+  int               negout
+)
+  optional
+
+  Side Effects: None
+
+long
+Cal_BddSize(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  int               negout
+)
+  optional
+
+  Side Effects: None
+
+void
+Cal_BddStats(
+  Cal_BddManager    bddManager,
+  FILE *            fp
+)
+  Prints miscellaneous BDD statistics
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddSubstitute(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  Returns a BDD for f using the substitution defined by current variable
+  association. Each variable is replaced by its associated BDDs. The
+  substitution is effective simultaneously
+
+  Side Effects: None
+
+void
+Cal_BddSupport(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd *         support
+)
+  optional
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddSwapVars(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd,
+  Cal_Bdd           hUserBdd
+)
+  Returns the BDD obtained by simultaneously substituting variable g by
+  variable h and variable h and variable g in the BDD f
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddThen(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Returns the positive cofactor of the argument BDD with respect to the top
+  variable of the BDD.
+
+  Side Effects: The reference count of the returned BDD is increased by 1.
+
+unsigned long
+Cal_BddTotalSize(
+  Cal_BddManager    bddManager
+)
+  Returns the number of nodes in the Unique table
+
+  Side Effects: None
+
+int
+Cal_BddType(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  Returns BDD_TYPE_ZERO if f is false, BDD_TYPE_ONE if f is true,
+  BDD_TYPE_POSVAR is f is an unnegated variable, BDD_TYPE_NEGVAR if f is a
+  negated variable, BDD_TYPE_OVERFLOW if f is null, and BDD_TYPE_NONTERMINAL
+  otherwise.
+
+  Side Effects: None
+
+void
+Cal_BddUnFree(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           userBdd
+)
+  Unfrees the argument BDD. It is an error to pass a BDD with reference count
+  of zero to be unfreed.
+
+  Side Effects: The reference count of the argument BDD is increased by 1.
+
+Cal_Bdd
+Cal_BddUndumpBdd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         userVars,
+  FILE *            fp,
+  int *             error
+)
+  Loads an encoded description of a BDD from the file given by fp. The
+  argument vars should be a null terminated array of variables that will
+  become the support of the BDD. As in Cal_BddDumpBdd, these need not be in
+  the order of increasing index. If the same array of variables in used in
+  dumping and undumping, the BDD returned will be equal to the one that was
+  dumped. More generally, if array v1 is used when dumping, and the array v2
+  is used when undumping, the BDD returned will be equal to the original BDD
+  with the ith variable in v2 substituted for the ith variable in v1 for all
+  i. Null BDD is returned in the operation fails for reason (node limit
+  reached, I/O error, invalid file format, etc.). In this case, an error code
+  is stored in error. the code will be one of the following.
+  CAL_BDD_UNDUMP_FORMAT Invalid file format CAL_BDD_UNDUMP_OVERFLOW Node limit
+  exceeded CAL_BDD_UNDUMP_IOERROR File I/O error CAL_BDD_UNDUMP_EOF Unexpected
+  EOF
+
+  Side Effects: required
+
+void
+Cal_BddVarBlockReorderable(
+  Cal_BddManager    bddManager,
+  Cal_Block         block,
+  int               reorderable
+)
+  If a block is reorderable, the child blocks are recursively involved in
+  swapping.
+
+  Side Effects: None.
+
+Cal_Bdd
+Cal_BddVarSubstitute(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd
+)
+  Returns a BDD for f using the substitution defined by current variable
+  association. It is assumed that each variable is replaced by another
+  variable. For the substitution of a variable by a function, use
+  Cal_BddSubstitute instead.
+
+  Side Effects: None
+
+long
+Cal_BddVars(
+  Cal_BddManager    bddManager
+)
+  Returns the number of BDD variables
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddXnor(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Returns the BDD for logical exclusive NOR of f and g
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddXor(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  Returns the BDD for logical exclusive OR of f and g
+
+  Side Effects: None
+
+Cal_Bdd
+Cal_BddZero(
+  Cal_BddManager    bddManager
+)
+  Returns the BDD for the constant zero
+
+  Side Effects: None
+
+Cal_Address_t
+Cal_MemAllocation(
+
+)
+  Returns the memory allocated.
+
+  Side Effects: required
+
+void
+Cal_MemFatal(
+  char *            message
+)
+  Prints an error message and exits.
+
+  Side Effects: required
+
+void
+Cal_MemFreeBlock(
+  Cal_Pointer_t     p
+)
+  Frees the block.
+
+  Side Effects: required
+
+void
+Cal_MemFreeRecMgr(
+  Cal_RecMgr        mgr
+)
+  Frees all the storage associated with the specified record manager.
+
+  Side Effects: required
+
+void
+Cal_MemFreeRec(
+  Cal_RecMgr        mgr,
+  Cal_Pointer_t     rec
+)
+  Frees a record managed by the indicated record manager.
+
+  Side Effects: required
+
+Cal_Pointer_t
+Cal_MemGetBlock(
+  Cal_Address_t     size
+)
+  Allocates a new block of the specified size.
+
+  Side Effects: required
+
+Cal_RecMgr
+Cal_MemNewRecMgr(
+  int               size
+)
+  Creates a new record manager with the given record size.
+
+  Side Effects: required
+
+Cal_Pointer_t
+Cal_MemNewRec(
+  Cal_RecMgr        mgr
+)
+  Allocates a record from the specified record manager.
+
+  Side Effects: required
+
+Cal_Pointer_t
+Cal_MemResizeBlock(
+  Cal_Pointer_t     p,
+  Cal_Address_t     newSize
+)
+  Expands or contracts the block to a new size. We try to avoid moving the
+  block if possible.
+
+  Side Effects: required
+
+int
+Cal_PerformanceTest(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         outputBddArray,
+  int               numFunctions,
+  int               iteration,
+  int               seed,
+  int               andPerformanceFl
+  int               multiwayPerforma
+  int               onewayPerformanc
+  int               quantifyPerforma
+  int               composePerforman
+  int               relprodPerforman
+  int               swapPerformanceF
+  int               substitutePerfor
+  int               sanityCheckFlag,
+  int               computeMemoryOve
+  int               superscalarFlag
+)
+  optional
+
+  Side Effects: required
+
+Cal_Bdd
+Cal_PipelineCreateProvisionalBdd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           fUserBdd,
+  Cal_Bdd           gUserBdd
+)
+  The provisional BDD is automatically freed once the pipeline is quitted.
+
+
+int
+Cal_PipelineExecute(
+  Cal_BddManager    bddManager
+)
+  All the results are computed. User should update the BDDs of interest.
+  Eventually this feature would become transparent.
+
+  Side Effects: required
+
+int
+Cal_PipelineInit(
+  Cal_BddManager    bddManager,
+  Cal_BddOp_t       bddOp
+)
+  All the operations for this pipeline must be of the same kind.
+
+  Side Effects: None.
+
+void
+Cal_PipelineQuit(
+  Cal_BddManager    bddManager
+)
+  The user must make sure to update all provisional BDDs of interest before
+  calling this routine.
+
+
+void
+Cal_PipelineSetDepth(
+  Cal_BddManager    bddManager,
+  int               depth
+)
+  The "depth" determines the amount of dependency we would allow in pipelined
+  computation.
+
+  Side Effects: None.
+
+Cal_Bdd
+Cal_PipelineUpdateProvisionalBdd(
+  Cal_BddManager    bddManager,
+  Cal_Bdd           provisionalBdd
+)
+  The provisional BDD is automatically freed after quitting pipeline.
+
+
+void
+Cal_TempAssociationAugment(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         associationInfoU
+  int               pairs
+)
+  Pairs is 0 if the information represents only a list of variables rather
+  than a full association.
+
+  Side Effects: None
+
+void
+Cal_TempAssociationInit(
+  Cal_BddManager    bddManager,
+  Cal_Bdd *         associationInfoU
+  int               pairs
+)
+  Pairs is 0 if the information represents only a list of variables rather
+  than a full association.
+
+  Side Effects: None
+
+void
+Cal_TempAssociationQuit(
+  Cal_BddManager    bddManager
+)
+  Cleans up temporary associationoptional
+
+  Side Effects: None
+
Index: /vis_dev/glu-2.1/src/calBdd/calDump.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calDump.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calDump.c	(revision 8)
@@ -0,0 +1,628 @@
+/**CFile***********************************************************************
+
+  FileName    [calDump.c]
+
+  PackageName [cal]
+
+  Synopsis    [BDD library dump/undump routines]
+              
+
+  Description [ ]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.
+              ] 
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calDump.c,v 1.1.1.3 1998/05/04 00:58:56 hsv Exp $]
+
+******************************************************************************/
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define MAGIC_COOKIE 0x5e02f795l
+#define CAL_BDD_IOERROR 100
+
+#define TRUE_ENCODING 0xffffff00l
+#define FALSE_ENCODING 0xffffff01l
+#define POSVAR_ENCODING 0xffffff02l
+#define NEGVAR_ENCODING 0xffffff03l
+#define POSNODE_ENCODING 0xffffff04l
+#define NEGNODE_ENCODING 0xffffff05l
+#define NODELABEL_ENCODING 0xffffff06l
+#define CONSTANT_ENCODING 0xffffff07l
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+static long indexMask[] = {0xffl, 0xffffl, 0xffffffl};
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void Write(Cal_BddManager_t * bddManager, unsigned long n, int bytes, FILE * fp);
+static void BddDumpBddStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, FILE * fp, CalHashTable_t * h, Cal_BddIndex_t * normalizedIndexes, int indexSize, int nodeNumberSize);
+static unsigned long Read(int * error, int bytes, FILE * fp);
+static Cal_Bdd_t BddUndumpBddStep(Cal_BddManager_t * bddManager, Cal_Bdd_t * vars, FILE * fp, Cal_BddIndex_t numberVars, Cal_Bdd_t * shared, long numberShared, long * sharedSoFar, int indexSize, int nodeNumberSize, int * error);
+static int BytesNeeded(long n);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Reads a BDD from a file]
+
+  Description [Loads an encoded description of a BDD from the file given by
+  fp. The argument vars should be a null terminated array of variables that will
+  become the support of the BDD. As in Cal_BddDumpBdd, these need not be in
+  the order of increasing index. If the same array of variables in used in 
+  dumping and undumping, the BDD returned will be equal to the one that was 
+  dumped. More generally, if array v1 is used when dumping, and the array v2
+  is used when undumping, the BDD returned will be equal to the original BDD
+  with the ith variable in v2 substituted for the ith variable in v1 for all i.
+  Null BDD is returned in the operation fails for reason (node limit reached,
+  I/O error, invalid file format, etc.). In this case, an error code is stored
+  in error. the code will be one of the following. 
+  CAL_BDD_UNDUMP_FORMAT Invalid file format
+  CAL_BDD_UNDUMP_OVERFLOW Node limit exceeded
+  CAL_BDD_UNDUMP_IOERROR File I/O error
+  CAL_BDD_UNDUMP_EOF Unexpected EOF]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddUndumpBdd(
+  Cal_BddManager bddManager,
+  Cal_Bdd * userVars,
+  FILE * fp,
+  int * error)
+{
+  long i,j;
+  Cal_BddIndex_t numberVars;
+  long numberShared;
+  int indexSize;
+  int nodeNumberSize;
+  Cal_Bdd_t *shared;
+  long sharedSoFar;
+  Cal_Bdd_t v;
+  Cal_Bdd_t result;
+  Cal_Bdd_t *vars;
+
+  *error = 0;
+  for(i = 0; userVars[i]; ++i){
+    if(Cal_BddType(bddManager, userVars[i]) !=  CAL_BDD_TYPE_POSVAR){
+      CalBddWarningMessage("Cal_BddUndumpBdd: support is not all positive variables"); 
+      return (Cal_Bdd) 0;
+    }
+  }
+  vars = Cal_MemAlloc(Cal_Bdd_t, i);
+  for (j=0; j < i; j++){
+    vars[j] = CalBddGetInternalBdd(bddManager,userVars[j]);
+  }
+
+  if(Read(error, sizeof(long), fp) !=  MAGIC_COOKIE){
+    if(!*error){
+      *error = CAL_BDD_UNDUMP_FORMAT;
+    }
+    Cal_MemFree(vars);
+    return (Cal_Bdd) 0;
+  }
+  numberVars = Read(error, sizeof(Cal_BddIndex_t), fp);
+  if(*error){
+    Cal_MemFree(vars);
+    return (Cal_Bdd) 0;
+  }
+  if(numberVars !=  i){
+    *error = CAL_BDD_UNDUMP_FORMAT;
+    Cal_MemFree(vars);
+    return (Cal_Bdd) 0;
+  }
+  numberShared = Read(error, sizeof(long), fp);
+  if(*error){
+    Cal_MemFree(vars);
+    return (Cal_Bdd) 0;
+  }
+  indexSize = BytesNeeded(numberVars+1);
+  nodeNumberSize = BytesNeeded(numberShared);
+  if(numberShared < 0){
+    *error = CAL_BDD_UNDUMP_FORMAT;
+    Cal_MemFree(vars);
+    return (Cal_Bdd) 0;
+  }
+  shared = Cal_MemAlloc(Cal_Bdd_t, numberShared);
+  for(i = 0; i < numberShared; ++i){
+    shared[i] = CalBddNull(bddManager);
+  }
+  sharedSoFar = 0;
+  result = BddUndumpBddStep(bddManager, vars, fp, numberVars, shared,
+      numberShared, &sharedSoFar, indexSize, nodeNumberSize, error);
+  Cal_MemFree(vars);
+  
+  for(i = 0; i < numberShared; ++i){
+    v = shared[i];
+    if(!CalBddIsBddNull(bddManager, v)){
+      CalBddFree(v);
+    }
+  }
+  if(!*error && sharedSoFar !=  numberShared){
+    *error = CAL_BDD_UNDUMP_FORMAT;
+  }
+  Cal_MemFree(shared);
+  if(*error){
+    if(!CalBddIsBddNull(bddManager, result)){
+      CalBddFree(result);
+    }
+    return (Cal_Bdd) 0;
+  }
+  /*
+   * Decrement the reference count of result by 1. Since it has
+   * already been incremented in BddUndumpBddStep.
+   */
+  CalBddDcrRefCount(result);
+  return CalBddGetExternalBdd(bddManager, result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Write a BDD to a file]
+
+  Description [Writes an encoded description of the BDD to the file given by fp.
+  The argument vars should be a null-terminated array of variables that include
+  the support of f .  These variables need not be in order of increasing index.
+  The function returns a nonzero value if f was written to the file successfully.
+  ]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+Cal_BddDumpBdd(
+  Cal_BddManager bddManager,
+  Cal_Bdd  fUserBdd,
+  Cal_Bdd * userVars,
+  FILE * fp)
+{
+  long i;
+  Cal_BddIndex_t *normalizedIndexes;
+  Cal_BddIndex_t vIndex;
+  Cal_Bdd_t f;
+  Cal_BddIndex_t numberVars;
+  Cal_Bdd *support;
+  int ok;
+  CalHashTable_t *h;
+  int indexSize;
+  long next;
+  int nodeNumberSize;
+
+  if(CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    for(i = 0; userVars[i]; ++i){
+      if(Cal_BddType(bddManager, userVars[i]) !=  CAL_BDD_TYPE_POSVAR){
+        CalBddWarningMessage("Cal_BddDumpBdd: support is not all positive variables");
+        return (0);
+      }
+    }
+    normalizedIndexes = Cal_MemAlloc(Cal_BddIndex_t, bddManager->numVars);
+    for(i = 0; i < bddManager->numVars; ++i){
+      normalizedIndexes[i] = CAL_BDD_CONST_INDEX;
+    }
+    for(i = 0; userVars[i]; ++i){
+      vIndex = Cal_BddGetIfIndex(bddManager, userVars[i]);
+      if(normalizedIndexes[vIndex] !=  CAL_BDD_CONST_INDEX){
+        CalBddWarningMessage("Cal_BddDumpBdd: variables duplicated in support");
+        Cal_MemFree(normalizedIndexes);
+        return 0;
+      }
+      normalizedIndexes[vIndex] = i;
+    }
+    numberVars = i;
+    support = Cal_MemAlloc(Cal_Bdd, bddManager->numVars+1);
+    Cal_BddSupport(bddManager, fUserBdd, support);
+    ok = 1;
+    for(i = 0; ok && support[i]; ++i){
+      if(normalizedIndexes[Cal_BddGetIfIndex(bddManager, support[i])] == CAL_BDD_CONST_INDEX){
+        CalBddWarningMessage("Cal_BddDumpBdd: incomplete support specified");
+        ok = 0;
+      }
+    }
+    if(!ok){
+      Cal_MemFree(normalizedIndexes);
+      Cal_MemFree(support);
+      return 0;
+    }
+    Cal_MemFree(support);
+    /* Everything checked now; barring I/O errors, we should be able to */
+    /* Write a valid output file. */
+    f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    h = CalHashTableOneInit(bddManager, sizeof(long));
+    indexSize = BytesNeeded(numberVars+1);
+    CalBddMarkSharedNodes(bddManager, f);
+    next = 0;
+    CalBddNumberSharedNodes(bddManager, f, h, &next);
+    nodeNumberSize = BytesNeeded(next);
+    Write(bddManager, MAGIC_COOKIE, sizeof(long), fp);
+    Write(bddManager, (unsigned long)numberVars, sizeof(Cal_BddIndex_t), fp);
+    Write(bddManager, (unsigned long)next, sizeof(long), fp);
+    BddDumpBddStep(bddManager, f, fp, h, normalizedIndexes, indexSize, nodeNumberSize);
+    CalHashTableOneQuit(h);
+    Cal_MemFree(normalizedIndexes);
+    return (1);
+  }
+  return (0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+Write(
+  Cal_BddManager_t * bddManager,
+  unsigned long  n,
+  int  bytes,
+  FILE * fp)
+{
+  while(bytes){
+    if(fputc((char)(n >> (8*(bytes-1)) & 0xff), fp) == EOF){
+    }
+    --bytes;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddDumpBddStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  FILE * fp,
+  CalHashTable_t * h,
+  Cal_BddIndex_t * normalizedIndexes,
+  int  indexSize,
+  int  nodeNumberSize)
+{
+  int negated;
+  long *number;
+  Cal_Bdd_t thenBdd, elseBdd;
+
+  switch(CalBddTypeAux(bddManager, f)){
+  case CAL_BDD_TYPE_ZERO:
+    Write(bddManager, FALSE_ENCODING, indexSize+1, fp);
+    break;
+  case CAL_BDD_TYPE_ONE:
+    Write(bddManager, TRUE_ENCODING, indexSize+1, fp);
+    break;
+  case CAL_BDD_TYPE_CONSTANT:
+    Write(bddManager, CONSTANT_ENCODING, indexSize+1, fp);
+#ifdef JAGESH
+    Write(bddManager, (unsigned long)BDD_DATA(f)[0], sizeof(long), fp);
+    Write(bddManager, (unsigned long)BDD_DATA(f)[1], sizeof(long), fp);
+#endif
+    break;
+  case CAL_BDD_TYPE_POSVAR:
+    Write(bddManager, POSVAR_ENCODING, indexSize+1, fp);
+    Write(bddManager,
+        (unsigned long)normalizedIndexes[CalBddGetBddIndex(bddManager, f)],
+        indexSize, fp);
+    break;
+  case CAL_BDD_TYPE_NEGVAR:
+    Write(bddManager, NEGVAR_ENCODING, indexSize+1, fp);
+    Write(bddManager, 
+        (unsigned long)normalizedIndexes[CalBddGetBddIndex(bddManager, f)],
+        indexSize, fp);
+    break;
+  case CAL_BDD_TYPE_NONTERMINAL:
+    CalBddNot(f, f);
+    if(CalHashTableOneLookup(h, f, (char **)0)){
+      negated  =  1;
+    }
+    else{
+      CalBddNot(f, f);
+      negated = 0;
+    }
+    CalHashTableOneLookup(h, f, (char **)&number);
+    if(number && *number < 0){
+	  if(negated)
+	    Write(bddManager, NEGNODE_ENCODING, indexSize+1, fp);
+	  else
+	    Write(bddManager, POSNODE_ENCODING, indexSize+1, fp);
+	  Write(bddManager, (unsigned long)(-*number-1), nodeNumberSize, fp);
+    }
+    else{
+      if(number){
+	      Write(bddManager, NODELABEL_ENCODING, indexSize+1, fp);
+	      *number =  -*number-1;
+      }
+      Write(bddManager,
+          (unsigned long)normalizedIndexes[CalBddGetBddIndex(bddManager, f)],
+          indexSize, fp);
+      CalBddGetThenBdd(f, thenBdd);
+      BddDumpBddStep(bddManager, thenBdd, fp, h, normalizedIndexes,
+          indexSize, nodeNumberSize);
+      CalBddGetElseBdd(f, elseBdd);
+      BddDumpBddStep(bddManager, elseBdd, fp, h, normalizedIndexes,
+          indexSize, nodeNumberSize);
+    }
+    break;
+  default:
+    CalBddFatalMessage("BddDumpBddStep: unknown type returned by CalBddType");
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static unsigned long
+Read(
+  int * error,
+  int  bytes,
+  FILE * fp)
+{
+  int c;
+  long result;
+
+  result = 0;
+  if(*error){
+    return (result);
+  }
+  while(bytes){
+    c = fgetc(fp);
+    if(c == EOF){
+      if(ferror(fp)){
+        *error = CAL_BDD_UNDUMP_IOERROR;
+      }
+      else{
+        *error = CAL_BDD_UNDUMP_EOF;
+      }
+      return (0l);
+    }
+    result = (result << 8)+c;
+    --bytes;
+  } 
+  return (result);
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddUndumpBddStep(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t * vars,
+  FILE * fp,
+  Cal_BddIndex_t  numberVars,
+  Cal_Bdd_t * shared,
+  long  numberShared,
+  long * sharedSoFar,
+  int  indexSize,
+  int  nodeNumberSize,
+  int * error)
+{
+  long nodeNumber;
+  long encoding;
+  Cal_BddIndex_t i;
+  CalAddress_t value1, value2;
+  Cal_Bdd_t v;
+  Cal_Bdd_t temp1, temp2;
+  Cal_Bdd_t result;
+
+  i = Read(error, indexSize, fp);
+  if(*error){
+    return CalBddNull(bddManager);
+  }
+  if(i == indexMask[indexSize-1]){
+    encoding = 0xffffff00l+Read(error, 1, fp);
+    if(*error){
+      return CalBddNull(bddManager);
+    }
+    switch(encoding){
+    case TRUE_ENCODING:
+      return (CalBddOne(bddManager));
+    case FALSE_ENCODING:
+      return (CalBddZero(bddManager));
+    case CONSTANT_ENCODING:
+      value1 = Read(error, sizeof(long), fp);
+      value2 = Read(error, sizeof(long), fp);
+      if(*error){
+        return CalBddNull(bddManager);
+      }
+      *error = CAL_BDD_UNDUMP_OVERFLOW;
+      return CalBddNull(bddManager);
+    case POSVAR_ENCODING:
+    case NEGVAR_ENCODING:
+      i = Read(error, indexSize, fp);
+      if(!*error && i >=  numberVars){
+        *error = CAL_BDD_UNDUMP_FORMAT;
+      }
+      if(*error){
+        return CalBddNull(bddManager);
+      }
+      v = vars[i];
+      if(encoding == POSVAR_ENCODING){
+        return (v);
+      }
+      else{
+        CalBddNot(v, v);
+        return (v);
+      }
+    case POSNODE_ENCODING:
+    case NEGNODE_ENCODING:
+      nodeNumber = Read(error, nodeNumberSize, fp);
+      if(!*error && (nodeNumber >=  numberShared ||
+          CalBddIsBddNull(bddManager, shared[nodeNumber]))){
+        *error = CAL_BDD_UNDUMP_FORMAT;
+      }
+      if(*error){
+        return CalBddNull(bddManager);
+      }
+      v = shared[nodeNumber];
+      v = CalBddIdentity(bddManager, v);
+      if(encoding == POSNODE_ENCODING){
+        return (v);
+      }
+      else{
+        CalBddNot(v, v);
+        return (v);
+      }
+    case NODELABEL_ENCODING:
+      nodeNumber =  *sharedSoFar;
+      ++*sharedSoFar;
+      v = BddUndumpBddStep(bddManager, vars, fp, numberVars, shared,
+          numberShared, sharedSoFar, indexSize, nodeNumberSize, error);
+      shared[nodeNumber] = v;
+      v = CalBddIdentity(bddManager, v);
+      return (v);
+    default:
+      *error = CAL_BDD_UNDUMP_FORMAT;
+      return CalBddNull(bddManager);
+    }
+  }
+  if(i >= numberVars){
+    *error = CAL_BDD_UNDUMP_FORMAT;
+    return CalBddNull(bddManager);
+  }
+  temp1 = BddUndumpBddStep(bddManager, vars, fp, numberVars, shared,
+       numberShared, sharedSoFar, indexSize, nodeNumberSize, error);
+  temp2 = BddUndumpBddStep(bddManager, vars, fp, numberVars, shared,
+       numberShared, sharedSoFar, indexSize, nodeNumberSize, error);
+  if(*error){
+      CalBddFree(temp1);
+      return CalBddNull(bddManager);
+  }
+  result = CalBddITE(bddManager, vars[i], temp1, temp2);
+  CalBddFree(temp1);
+  CalBddFree(temp2);
+  if(CalBddIsBddNull(bddManager, result)){
+     *error = CAL_BDD_UNDUMP_OVERFLOW;
+  }
+  return (result);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+BytesNeeded(
+  long  n)
+{
+  if(n <= 0x100l){
+    return (1);
+  }
+  if(n <= 0x10000l){
+    return (2);
+  }
+  if(n <= 0x1000000l){
+    return (3);
+  }
+  return (4);
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calExt.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calExt.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calExt.html	(revision 8)
@@ -0,0 +1,13 @@
+<HTML>
+<HEAD><TITLE>The cal Package for Programmers</TITLE></HEAD>
+
+<FRAMESET ROWS="5%,90%,5%">
+  <FRAME SRC="calTitle.html">
+  <FRAMESET COLS="40%,60%">
+    <FRAME SRC="calExtAbs.html" NAME="ABSTRACT">
+    <FRAME SRC="calExtDet.html" NAME="MAIN">
+  </FRAMESET>
+  <FRAME SRC="credit.html">
+</FRAMESET>
+
+</HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calExtAbs.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calExtAbs.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calExtAbs.html	(revision 8)
@@ -0,0 +1,388 @@
+<html>
+<head><title>cal package abstract</title></head>
+<body>
+
+
+<!-- Function Abstracts -->
+
+<dl>
+<dt> <a href="calAllDet.html#Cal_AssociationInit" TARGET="MAIN"><code>Cal_AssociationInit()</code></a>
+<dd> Creates or finds a variable association.
+
+<dt> <a href="calAllDet.html#Cal_AssociationQuit" TARGET="MAIN"><code>Cal_AssociationQuit()</code></a>
+<dd> Deletes the variable association given by id
+
+<dt> <a href="calAllDet.html#Cal_AssociationSetCurrent" TARGET="MAIN"><code>Cal_AssociationSetCurrent()</code></a>
+<dd> Sets the current variable association to the one given by id and
+  returns the ID of the old association.
+
+<dt> <a href="calAllDet.html#Cal_BddAnd" TARGET="MAIN"><code>Cal_BddAnd()</code></a>
+<dd> Returns the BDD for logical AND of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddBetween" TARGET="MAIN"><code>Cal_BddBetween()</code></a>
+<dd> Returns a minimal BDD whose function contains fMin and is
+  contained in fMax.
+
+<dt> <a href="calAllDet.html#Cal_BddCofactor" TARGET="MAIN"><code>Cal_BddCofactor()</code></a>
+<dd> Returns the generalized cofactor of BDD f with respect
+  to BDD c.
+
+<dt> <a href="calAllDet.html#Cal_BddCompose" TARGET="MAIN"><code>Cal_BddCompose()</code></a>
+<dd> composition - substitute a BDD variable by a function
+
+<dt> <a href="calAllDet.html#Cal_BddDependsOn" TARGET="MAIN"><code>Cal_BddDependsOn()</code></a>
+<dd> Returns 1 if f depends on var and returns 0 otherwise.
+
+<dt> <a href="calAllDet.html#Cal_BddDumpBdd" TARGET="MAIN"><code>Cal_BddDumpBdd()</code></a>
+<dd> Write a BDD to a file
+
+<dt> <a href="calAllDet.html#Cal_BddDynamicReordering" TARGET="MAIN"><code>Cal_BddDynamicReordering()</code></a>
+<dd> Specify dynamic reordering technique.
+
+<dt> <a href="calAllDet.html#Cal_BddElse" TARGET="MAIN"><code>Cal_BddElse()</code></a>
+<dd> Returns the negative cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddExists" TARGET="MAIN"><code>Cal_BddExists()</code></a>
+<dd> Returns the result of existentially quantifying some
+  variables from the given BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddForAll" TARGET="MAIN"><code>Cal_BddForAll()</code></a>
+<dd> Returns the result of universally quantifying some
+  variables from the given BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddFree" TARGET="MAIN"><code>Cal_BddFree()</code></a>
+<dd> Frees the argument BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddFunctionPrint" TARGET="MAIN"><code>Cal_BddFunctionPrint()</code></a>
+<dd> Prints the function implemented by the argument BDD
+
+<dt> <a href="calAllDet.html#Cal_BddFunctionProfileMultiple" TARGET="MAIN"><code>Cal_BddFunctionProfileMultiple()</code></a>
+<dd> Returns a "function profile" for fArray.
+
+<dt> <a href="calAllDet.html#Cal_BddFunctionProfile" TARGET="MAIN"><code>Cal_BddFunctionProfile()</code></a>
+<dd> Returns a "function profile" for f.
+
+<dt> <a href="calAllDet.html#Cal_BddGetIfId" TARGET="MAIN"><code>Cal_BddGetIfId()</code></a>
+<dd> Returns the id of the top variable of the argument BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddGetIfIndex" TARGET="MAIN"><code>Cal_BddGetIfIndex()</code></a>
+<dd> Returns the index of the top variable of the argument BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddGetRegular" TARGET="MAIN"><code>Cal_BddGetRegular()</code></a>
+<dd> Returns a BDD with positive from a given BDD with arbitrary phase
+
+<dt> <a href="calAllDet.html#Cal_BddITE" TARGET="MAIN"><code>Cal_BddITE()</code></a>
+<dd> Returns the BDD for logical If-Then-Else
+
+  Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+  - f g + f' h
+
+<dt> <a href="calAllDet.html#Cal_BddIdentity" TARGET="MAIN"><code>Cal_BddIdentity()</code></a>
+<dd> Returns the duplicate BDD of the argument BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddIf" TARGET="MAIN"><code>Cal_BddIf()</code></a>
+<dd> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddImplies" TARGET="MAIN"><code>Cal_BddImplies()</code></a>
+<dd> Computes a BDD that implies conjunction of f and Cal_BddNot(g)
+
+<dt> <a href="calAllDet.html#Cal_BddIntersects" TARGET="MAIN"><code>Cal_BddIntersects()</code></a>
+<dd> Computes a BDD that implies conjunction of f and g.
+
+<dt> <a href="calAllDet.html#Cal_BddIsBddConst" TARGET="MAIN"><code>Cal_BddIsBddConst()</code></a>
+<dd> Returns 1 if the argument BDD is a constant, 0 otherwise.
+
+<dt> <a href="calAllDet.html#Cal_BddIsBddNull" TARGET="MAIN"><code>Cal_BddIsBddNull()</code></a>
+<dd> Returns 1 if the argument BDD is NULL, 0 otherwise.
+
+<dt> <a href="calAllDet.html#Cal_BddIsBddOne" TARGET="MAIN"><code>Cal_BddIsBddOne()</code></a>
+<dd> Returns 1 if the argument BDD is constant one, 0 otherwise.
+
+<dt> <a href="calAllDet.html#Cal_BddIsBddZero" TARGET="MAIN"><code>Cal_BddIsBddZero()</code></a>
+<dd> Returns 1 if the argument BDD is constant zero, 0 otherwise.
+
+<dt> <a href="calAllDet.html#Cal_BddIsCube" TARGET="MAIN"><code>Cal_BddIsCube()</code></a>
+<dd> Returns 1 if the argument BDD is a cube, 0 otherwise
+
+<dt> <a href="calAllDet.html#Cal_BddIsEqual" TARGET="MAIN"><code>Cal_BddIsEqual()</code></a>
+<dd> Returns 1 if argument BDDs are equal, 0 otherwise.
+
+<dt> <a href="calAllDet.html#Cal_BddIsProvisional" TARGET="MAIN"><code>Cal_BddIsProvisional()</code></a>
+<dd> Returns 1, if the given user BDD contains
+  provisional BDD node.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerCreateNewVarAfter" TARGET="MAIN"><code>Cal_BddManagerCreateNewVarAfter()</code></a>
+<dd> Creates and returns a new variable after the specified one in
+  the variable  order.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerCreateNewVarBefore" TARGET="MAIN"><code>Cal_BddManagerCreateNewVarBefore()</code></a>
+<dd> Creates and returns a new variable before the specified one in
+  the variable order.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerCreateNewVarFirst" TARGET="MAIN"><code>Cal_BddManagerCreateNewVarFirst()</code></a>
+<dd> Creates and returns a new variable at the start of the variable
+  order.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerCreateNewVarLast" TARGET="MAIN"><code>Cal_BddManagerCreateNewVarLast()</code></a>
+<dd> Creates and returns a new variable at the end of the variable
+  order.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerGC" TARGET="MAIN"><code>Cal_BddManagerGC()</code></a>
+<dd> Invokes the garbage collection at the manager level.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerGetHooks" TARGET="MAIN"><code>Cal_BddManagerGetHooks()</code></a>
+<dd> Returns the hooks field of the manager.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerGetNumNodes" TARGET="MAIN"><code>Cal_BddManagerGetNumNodes()</code></a>
+<dd> Returns the number of BDD nodes
+
+<dt> <a href="calAllDet.html#Cal_BddManagerGetVarWithId" TARGET="MAIN"><code>Cal_BddManagerGetVarWithId()</code></a>
+<dd> Returns the variable with the specified id, null if no
+  such variable exists
+
+<dt> <a href="calAllDet.html#Cal_BddManagerGetVarWithIndex" TARGET="MAIN"><code>Cal_BddManagerGetVarWithIndex()</code></a>
+<dd> Returns the variable with the specified index, null if no
+  such variable exists
+
+<dt> <a href="calAllDet.html#Cal_BddManagerInit" TARGET="MAIN"><code>Cal_BddManagerInit()</code></a>
+<dd> Creates and initializes a new BDD manager.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerQuit" TARGET="MAIN"><code>Cal_BddManagerQuit()</code></a>
+<dd> Frees the BDD manager and all the associated allocations
+
+<dt> <a href="calAllDet.html#Cal_BddManagerSetGCLimit" TARGET="MAIN"><code>Cal_BddManagerSetGCLimit()</code></a>
+<dd> Sets the limit of the garbage collection.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerSetHooks" TARGET="MAIN"><code>Cal_BddManagerSetHooks()</code></a>
+<dd> Sets the hooks field of the manager.
+
+<dt> <a href="calAllDet.html#Cal_BddManagerSetParameters" TARGET="MAIN"><code>Cal_BddManagerSetParameters()</code></a>
+<dd> Sets appropriate fields of BDD Manager.
+
+<dt> <a href="calAllDet.html#Cal_BddMultiwayAnd" TARGET="MAIN"><code>Cal_BddMultiwayAnd()</code></a>
+<dd> Returns the BDD for logical AND of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddMultiwayOr" TARGET="MAIN"><code>Cal_BddMultiwayOr()</code></a>
+<dd> Returns the BDD for logical OR of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddMultiwayXor" TARGET="MAIN"><code>Cal_BddMultiwayXor()</code></a>
+<dd> Returns the BDD for logical XOR of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddNand" TARGET="MAIN"><code>Cal_BddNand()</code></a>
+<dd> Returns the BDD for logical NAND of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddNewVarBlock" TARGET="MAIN"><code>Cal_BddNewVarBlock()</code></a>
+<dd> Creates and returns a variable block used for
+  controlling dynamic reordering.
+
+<dt> <a href="calAllDet.html#Cal_BddNodeLimit" TARGET="MAIN"><code>Cal_BddNodeLimit()</code></a>
+<dd> Sets the node limit to new_limit and returns the old limit.
+
+<dt> <a href="calAllDet.html#Cal_BddNor" TARGET="MAIN"><code>Cal_BddNor()</code></a>
+<dd> Returns the BDD for logical NOR of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddNot" TARGET="MAIN"><code>Cal_BddNot()</code></a>
+<dd> Returns the complement of the argument BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddOne" TARGET="MAIN"><code>Cal_BddOne()</code></a>
+<dd> Returns the BDD for the constant one
+
+<dt> <a href="calAllDet.html#Cal_BddOr" TARGET="MAIN"><code>Cal_BddOr()</code></a>
+<dd> Returns the BDD for logical OR of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddOverflow" TARGET="MAIN"><code>Cal_BddOverflow()</code></a>
+<dd> Returns 1 if the node limit has been exceeded, 0 otherwise. The
+  overflow flag is cleared.
+
+<dt> <a href="calAllDet.html#Cal_BddPairwiseAnd" TARGET="MAIN"><code>Cal_BddPairwiseAnd()</code></a>
+<dd> Returns an array of BDDs obtained by logical AND of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+<dt> <a href="calAllDet.html#Cal_BddPairwiseOr" TARGET="MAIN"><code>Cal_BddPairwiseOr()</code></a>
+<dd> Returns an array of BDDs obtained by logical OR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+<dt> <a href="calAllDet.html#Cal_BddPairwiseXor" TARGET="MAIN"><code>Cal_BddPairwiseXor()</code></a>
+<dd> Returns an array of BDDs obtained by logical XOR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+
+<dt> <a href="calAllDet.html#Cal_BddPrintBdd" TARGET="MAIN"><code>Cal_BddPrintBdd()</code></a>
+<dd> Prints a BDD in the human readable form.
+
+<dt> <a href="calAllDet.html#Cal_BddPrintFunctionProfileMultiple" TARGET="MAIN"><code>Cal_BddPrintFunctionProfileMultiple()</code></a>
+<dd> Cal_BddPrintFunctionProfileMultiple is like
+               Cal_BddPrintFunctionProfile except for multiple BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddPrintFunctionProfile" TARGET="MAIN"><code>Cal_BddPrintFunctionProfile()</code></a>
+<dd> Cal_BddPrintFunctionProfile is like Cal_BddPrintProfile except
+               it displays a function profile for f
+
+<dt> <a href="calAllDet.html#Cal_BddPrintProfileMultiple" TARGET="MAIN"><code>Cal_BddPrintProfileMultiple()</code></a>
+<dd> Cal_BddPrintProfileMultiple is like Cal_BddPrintProfile except
+               it displays the profile for a set of BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddPrintProfile" TARGET="MAIN"><code>Cal_BddPrintProfile()</code></a>
+<dd> Displays the node profile for f on fp. lineLength specifies 
+               the maximum line length.  varNamingFn is as in
+               Cal_BddPrintBdd.
+
+<dt> <a href="calAllDet.html#Cal_BddProfileMultiple" TARGET="MAIN"><code>Cal_BddProfileMultiple()</code></a>
+<dd> 
+
+<dt> <a href="calAllDet.html#Cal_BddProfile" TARGET="MAIN"><code>Cal_BddProfile()</code></a>
+<dd> Returns a "node profile" of f, i.e., the number of nodes at each
+  level in f.
+
+<dt> <a href="calAllDet.html#Cal_BddReduce" TARGET="MAIN"><code>Cal_BddReduce()</code></a>
+<dd> Returns a BDD which agrees with f for all valuations
+  which satisfy c.
+
+<dt> <a href="calAllDet.html#Cal_BddRelProd" TARGET="MAIN"><code>Cal_BddRelProd()</code></a>
+<dd> Returns the result of taking the logical AND of the
+  argument BDDs and existentially quantifying some variables from the
+  product.
+
+<dt> <a href="calAllDet.html#Cal_BddReorder" TARGET="MAIN"><code>Cal_BddReorder()</code></a>
+<dd> Invoke the current dynamic reodering method.
+
+<dt> <a href="calAllDet.html#Cal_BddSatisfySupport" TARGET="MAIN"><code>Cal_BddSatisfySupport()</code></a>
+<dd> Returns a special cube contained in f.
+
+<dt> <a href="calAllDet.html#Cal_BddSatisfyingFraction" TARGET="MAIN"><code>Cal_BddSatisfyingFraction()</code></a>
+<dd> Returns the fraction of valuations which make f true. (Note that
+  this fraction is independent of whatever set of variables f is supposed to be
+  a function of)
+
+<dt> <a href="calAllDet.html#Cal_BddSatisfy" TARGET="MAIN"><code>Cal_BddSatisfy()</code></a>
+<dd> Returns a BDD which implies f, true for
+               some valuation on which f is true, and which has at most
+               one node at each level
+
+<dt> <a href="calAllDet.html#Cal_BddSetGCMode" TARGET="MAIN"><code>Cal_BddSetGCMode()</code></a>
+<dd> Sets the garbage collection mode, 0 means the garbage
+  collection should be turned off, 1 means garbage collection should
+  be on.
+
+<dt> <a href="calAllDet.html#Cal_BddSizeMultiple" TARGET="MAIN"><code>Cal_BddSizeMultiple()</code></a>
+<dd> The routine is like Cal_BddSize, but takes a null-terminated
+               array of BDDs and accounts for sharing of nodes.
+
+<dt> <a href="calAllDet.html#Cal_BddSize" TARGET="MAIN"><code>Cal_BddSize()</code></a>
+<dd> Returns the number of nodes in f when negout is nonzero. If
+  negout is zero, we pretend that the BDDs don't have negative-output pointers.
+
+<dt> <a href="calAllDet.html#Cal_BddStats" TARGET="MAIN"><code>Cal_BddStats()</code></a>
+<dd> Prints miscellaneous BDD statistics
+
+<dt> <a href="calAllDet.html#Cal_BddSubstitute" TARGET="MAIN"><code>Cal_BddSubstitute()</code></a>
+<dd> Substitute a set of variables by functions
+
+<dt> <a href="calAllDet.html#Cal_BddSupport" TARGET="MAIN"><code>Cal_BddSupport()</code></a>
+<dd> returns the support of f as a null-terminated array of variables
+
+<dt> <a href="calAllDet.html#Cal_BddSwapVars" TARGET="MAIN"><code>Cal_BddSwapVars()</code></a>
+<dd> Return a function obtained by swapping two variables
+
+<dt> <a href="calAllDet.html#Cal_BddThen" TARGET="MAIN"><code>Cal_BddThen()</code></a>
+<dd> Returns the positive cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddTotalSize" TARGET="MAIN"><code>Cal_BddTotalSize()</code></a>
+<dd> Returns the number of nodes in the Unique table
+
+<dt> <a href="calAllDet.html#Cal_BddType" TARGET="MAIN"><code>Cal_BddType()</code></a>
+<dd> Returns type of a BDD ( 0, 1, +var, -var, ovrflow, nonterminal)
+
+<dt> <a href="calAllDet.html#Cal_BddUnFree" TARGET="MAIN"><code>Cal_BddUnFree()</code></a>
+<dd> Unfrees the argument BDD.
+
+<dt> <a href="calAllDet.html#Cal_BddUndumpBdd" TARGET="MAIN"><code>Cal_BddUndumpBdd()</code></a>
+<dd> Reads a BDD from a file
+
+<dt> <a href="calAllDet.html#Cal_BddVarBlockReorderable" TARGET="MAIN"><code>Cal_BddVarBlockReorderable()</code></a>
+<dd> Sets the reoderability of a particular block.
+
+<dt> <a href="calAllDet.html#Cal_BddVarSubstitute" TARGET="MAIN"><code>Cal_BddVarSubstitute()</code></a>
+<dd> Substitute a set of variables by set of another variables.
+
+<dt> <a href="calAllDet.html#Cal_BddVars" TARGET="MAIN"><code>Cal_BddVars()</code></a>
+<dd> Returns the number of BDD variables
+
+<dt> <a href="calAllDet.html#Cal_BddXnor" TARGET="MAIN"><code>Cal_BddXnor()</code></a>
+<dd> Returns the BDD for logical exclusive NOR of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddXor" TARGET="MAIN"><code>Cal_BddXor()</code></a>
+<dd> Returns the BDD for logical exclusive OR of argument BDDs
+
+<dt> <a href="calAllDet.html#Cal_BddZero" TARGET="MAIN"><code>Cal_BddZero()</code></a>
+<dd> Returns the BDD for the constant zero
+
+<dt> <a href="calAllDet.html#Cal_MemAllocation" TARGET="MAIN"><code>Cal_MemAllocation()</code></a>
+<dd> Returns the memory allocated.
+
+<dt> <a href="calAllDet.html#Cal_MemFatal" TARGET="MAIN"><code>Cal_MemFatal()</code></a>
+<dd> Prints an error message and exits.
+
+<dt> <a href="calAllDet.html#Cal_MemFreeBlock" TARGET="MAIN"><code>Cal_MemFreeBlock()</code></a>
+<dd> Frees the block.
+
+<dt> <a href="calAllDet.html#Cal_MemFreeRecMgr" TARGET="MAIN"><code>Cal_MemFreeRecMgr()</code></a>
+<dd> Frees all the storage associated with the specified record manager.
+
+<dt> <a href="calAllDet.html#Cal_MemFreeRec" TARGET="MAIN"><code>Cal_MemFreeRec()</code></a>
+<dd> Frees a record managed by the indicated record manager.
+
+<dt> <a href="calAllDet.html#Cal_MemGetBlock" TARGET="MAIN"><code>Cal_MemGetBlock()</code></a>
+<dd> Allocates a new block of the specified size.
+
+<dt> <a href="calAllDet.html#Cal_MemNewRecMgr" TARGET="MAIN"><code>Cal_MemNewRecMgr()</code></a>
+<dd> Creates a new record manager with the given  record size.
+
+<dt> <a href="calAllDet.html#Cal_MemNewRec" TARGET="MAIN"><code>Cal_MemNewRec()</code></a>
+<dd> Allocates a record from the specified record manager.
+
+<dt> <a href="calAllDet.html#Cal_MemResizeBlock" TARGET="MAIN"><code>Cal_MemResizeBlock()</code></a>
+<dd> Expands or contracts the block to a new size.
+  We try to avoid moving the block if possible.
+
+<dt> <a href="calAllDet.html#Cal_PerformanceTest" TARGET="MAIN"><code>Cal_PerformanceTest()</code></a>
+<dd> Main routine for testing performances of various routines.
+
+<dt> <a href="calAllDet.html#Cal_PipelineCreateProvisionalBdd" TARGET="MAIN"><code>Cal_PipelineCreateProvisionalBdd()</code></a>
+<dd> Create a provisional BDD in the pipeline.
+
+<dt> <a href="calAllDet.html#Cal_PipelineExecute" TARGET="MAIN"><code>Cal_PipelineExecute()</code></a>
+<dd> Executes a pipeline.
+
+<dt> <a href="calAllDet.html#Cal_PipelineInit" TARGET="MAIN"><code>Cal_PipelineInit()</code></a>
+<dd> Initialize a BDD pipeline.
+
+<dt> <a href="calAllDet.html#Cal_PipelineQuit" TARGET="MAIN"><code>Cal_PipelineQuit()</code></a>
+<dd> Resets the pipeline freeing all resources.
+
+<dt> <a href="calAllDet.html#Cal_PipelineSetDepth" TARGET="MAIN"><code>Cal_PipelineSetDepth()</code></a>
+<dd> Set depth of a BDD pipeline.
+
+<dt> <a href="calAllDet.html#Cal_PipelineUpdateProvisionalBdd" TARGET="MAIN"><code>Cal_PipelineUpdateProvisionalBdd()</code></a>
+<dd> Update a provisional Bdd obtained during pipelining.
+
+<dt> <a href="calAllDet.html#Cal_TempAssociationAugment" TARGET="MAIN"><code>Cal_TempAssociationAugment()</code></a>
+<dd> Adds to the temporary variable association.
+
+<dt> <a href="calAllDet.html#Cal_TempAssociationInit" TARGET="MAIN"><code>Cal_TempAssociationInit()</code></a>
+<dd> Sets the temporary variable association.
+
+<dt> <a href="calAllDet.html#Cal_TempAssociationQuit" TARGET="MAIN"><code>Cal_TempAssociationQuit()</code></a>
+<dd> Cleans up temporary association
+
+</dl>
+
+<hr>
+
+Last updated on 970711 20h11
+</body></html>
Index: /vis_dev/glu-2.1/src/calBdd/calExtDet.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calExtDet.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calExtDet.html	(revision 8)
@@ -0,0 +1,1924 @@
+<HTML>
+<HEAD><TITLE>The cal package</TITLE></HEAD>
+<BODY>
+
+<DL>
+<dt><pre>
+<A NAME="Cal_AssociationInit"></A>
+int <I></I>
+<B>Cal_AssociationInit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>associationInfoUserBdds</b>, <i></i>
+  int  <b>pairs</b> <i></i>
+)
+</pre>
+<dd> Creates or finds a variable association. The association is
+  specified by associationInfo, which is a an array of BDD with 
+  Cal_BddNull(bddManager) as the end marker. If pairs is 0, the array is
+  assumed to be an array of variables. In this case, each variable is paired
+  with constant BDD one. Such an association may viewed as specifying a set
+  of variables for use with routines such as Cal_BddExists. If pair is not 0,
+  then the even numbered array elements should be variables and the odd numbered
+  elements should be the BDDs which they are mapped to. In both cases, the 
+  return value is an integer identifier for this association. If the given
+  association is equivalent to one which already exists, the same identifier
+  is used for both, and the reference count of the association is increased by
+  one.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_AssociationQuit">Cal_AssociationQuit</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_AssociationQuit"></A>
+void <I></I>
+<B>Cal_AssociationQuit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>associationId</b> <i></i>
+)
+</pre>
+<dd> Decrements the reference count of the variable association with
+  identifier id, and frees it if the reference count becomes zero.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_AssociationInit">Cal_AssociationInit</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_AssociationSetCurrent"></A>
+int <I></I>
+<B>Cal_AssociationSetCurrent</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>associationId</b> <i></i>
+)
+</pre>
+<dd> Sets the current variable association to the one given by id and
+  returns the ID of the old association.  An id of -1 indicates the temporary
+  association
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddAnd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical AND of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddBetween"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddBetween</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fMinUserBdd</b>, <i></i>
+  Cal_Bdd  <b>fMaxUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a minimal BDD f which is contains fMin and is
+  contained in fMax ( fMin <= f <= fMax).
+  This operation is typically used in state space searches to simplify
+  the representation for the set of states wich will be expanded at
+  each step (Rk Rk-1' <= f <= Rk).
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddReduce">Cal_BddReduce</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddCofactor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddCofactor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>cUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the generalized cofactor of BDD f with respect
+  to BDD c. The constrain operator given by Coudert et al (ICCAD90) is
+  used to find the generalized cofactor.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddReduce">Cal_BddReduce</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddCompose"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddCompose</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b>, <i></i>
+  Cal_Bdd  <b>hUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD obtained by substituting a variable by a function
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddDependsOn"></A>
+int <I></I>
+<B>Cal_BddDependsOn</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>varUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f depends on var and returns 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddDumpBdd"></A>
+int <I></I>
+<B>Cal_BddDumpBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd * <b>userVars</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Writes an encoded description of the BDD to the file given by fp.
+  The argument vars should be a null-terminated array of variables that include
+  the support of f .  These variables need not be in order of increasing index.
+  The function returns a nonzero value if f was written to the file successfully.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddDynamicReordering"></A>
+void <I></I>
+<B>Cal_BddDynamicReordering</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>technique</b> <i></i>
+)
+</pre>
+<dd> Selects the method for dynamic reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddReorder">Cal_BddReorder</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddElse"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddElse</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the negative cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the returned BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddThen">Cal_BddThen</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddExists"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddExists</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for f with all the variables that are
+  paired with something in the current variable association
+  existentially quantified out.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddRelProd">Cal_BddRelProd</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddForAll"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddForAll</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for f with all the variables that are
+  paired with something in the current variable association
+  universally quantified out.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddFree"></A>
+void <I></I>
+<B>Cal_BddFree</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Frees the argument BDD. It is an error to free a BDD
+  more than once.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the argument BDD is decreased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddUnFree">Cal_BddUnFree</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddFunctionPrint"></A>
+void <I></I>
+<B>Cal_BddFunctionPrint</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b>, <i></i>
+  char * <b>name</b> <i></i>
+)
+</pre>
+<dd> Prints the function implemented by the argument BDD
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddFunctionProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddFunctionProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>fUserBddArray</b>, <i></i>
+  long * <b>funcCounts</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddFunctionProfile"></A>
+void <I></I>
+<B>Cal_BddFunctionProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  long * <b>funcCounts</b> <i></i>
+)
+</pre>
+<dd> The nth entry of the function
+  profile array is the number of subfunctions of f which may be obtained by 
+  restricting the variables whose index is less than n.  An entry of zero 
+  indicates that f is independent of the variable with the corresponding index.
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddGetIfId"></A>
+Cal_BddId_t <I></I>
+<B>Cal_BddGetIfId</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the id of the top variable of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddGetIfIndex">Cal_BddGetIfIndex</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddGetIfIndex"></A>
+Cal_BddId_t <I></I>
+<B>Cal_BddGetIfIndex</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the top variable of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddGetIfId">Cal_BddGetIfId</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddGetRegular"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddGetRegular</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD with positive from a given BDD with arbitrary phase
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddITE"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddITE</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b>, <i></i>
+  Cal_Bdd  <b>hUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical If-Then-Else
+
+  Description [Returns the BDD for the logical operation IF f THEN g ELSE h
+  - f g + f' h
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddAnd">Cal_BddAnd</a>
+<a href="#Cal_BddNand">Cal_BddNand</a>
+<a href="#Cal_BddOr">Cal_BddOr</a>
+<a href="#Cal_BddNor">Cal_BddNor</a>
+<a href="#Cal_BddXor">Cal_BddXor</a>
+<a href="#Cal_BddXnor">Cal_BddXnor</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddIdentity"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddIdentity</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the duplicate BDD of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddNot">Cal_BddNot</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddIf"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddIf</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD corresponding to the top variable of
+  the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddImplies"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddImplies</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Computes a BDD that implies conjunction of f and Cal_BddNot(g)
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIntersects">Cal_BddIntersects</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddIntersects"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddIntersects</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Computes a BDD that implies conjunction of f and g.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddImplies">Cal_BddImplies</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddConst"></A>
+int <I></I>
+<B>Cal_BddIsBddConst</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is either constant one or
+  constant zero, otherwise returns 0.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIsBddOne">Cal_BddIsBddOne</a>
+<a href="#Cal_BddIsBddZero">Cal_BddIsBddZero</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddNull"></A>
+int <I></I>
+<B>Cal_BddIsBddNull</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is NULL, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddOne"></A>
+int <I></I>
+<B>Cal_BddIsBddOne</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is constant one, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIsBddZero">Cal_BddIsBddZero</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddIsBddZero"></A>
+int <I></I>
+<B>Cal_BddIsBddZero</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is constant zero, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIsBddOne">Cal_BddIsBddOne</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddIsCube"></A>
+int <I></I>
+<B>Cal_BddIsCube</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the argument BDD is a cube, 0 otherwise
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddIsEqual"></A>
+int <I></I>
+<B>Cal_BddIsEqual</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd1</b>, <i></i>
+  Cal_Bdd  <b>userBdd2</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if argument BDDs are equal, 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddIsProvisional"></A>
+int <I></I>
+<B>Cal_BddIsProvisional</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns 1, if the given user BDD contains
+  provisional BDD node.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarAfter"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarAfter</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable after the specified one in
+  the variable  order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarBefore"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarBefore</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable before the specified one in
+  the variable order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarFirst"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarFirst</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable at the start of the
+  variable order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerCreateNewVarLast"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerCreateNewVarLast</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Creates and returns a new variable at the end of the variable
+  order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGC"></A>
+int <I></I>
+<B>Cal_BddManagerGC</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> For each variable in the increasing id free nodes with reference
+  count equal to zero freeing a node results in decrementing reference count of
+  then and else nodes by one.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetHooks"></A>
+void * <I></I>
+<B>Cal_BddManagerGetHooks</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the hooks field of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetNumNodes"></A>
+unsigned long <I></I>
+<B>Cal_BddManagerGetNumNodes</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the number of BDD nodes
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddTotalSize">Cal_BddTotalSize</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetVarWithId"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerGetVarWithId</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddId_t  <b>id</b> <i></i>
+)
+</pre>
+<dd> Returns the variable with the specified id, null if no
+  such variable exists
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddManagerGetVarWithIndex"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddManagerGetVarWithIndex</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddIndex_t  <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the variable with the specified index, null if no
+  such variable exists
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerInit"></A>
+Cal_BddManager <I></I>
+<B>Cal_BddManagerInit</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> Initializes and allocates fields of the BDD manager. Some of the
+  fields are initialized for maxNumVars+1 or numVars+1, whereas some of them are
+  initialized for maxNumVars or numVars. The first kind of fields are associated
+  with the id of a variable and the second ones are with the index of the
+  variable.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerQuit">Cal_BddManagerQuit</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddManagerQuit"></A>
+int <I></I>
+<B>Cal_BddManagerQuit</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Frees the BDD manager and all the associated allocations
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerInit">Cal_BddManagerInit</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddManagerSetGCLimit"></A>
+void <I></I>
+<B>Cal_BddManagerSetGCLimit</B>(
+  Cal_BddManager  <b>manager</b> <i></i>
+)
+</pre>
+<dd> It tries to set the limit at twice the number of nodes
+  in the manager at the current point. However, the limit is not
+  allowed to fall below the MIN_GC_LIMIT or to exceed the value of
+  node limit (if one exists).
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerSetHooks"></A>
+void <I></I>
+<B>Cal_BddManagerSetHooks</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  void * <b>hooks</b> <i></i>
+)
+</pre>
+<dd> Sets the hooks field of the manager.
+<p>
+
+<dd> <b>Side Effects</b> Hooks field changes.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddManagerSetParameters"></A>
+void <I></I>
+<B>Cal_BddManagerSetParameters</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  long  <b>reorderingThreshold</b>, <i></i>
+  long  <b>maxForwardedNodes</b>, <i></i>
+  double  <b>repackAfterGCThreshold</b>, <i></i>
+  double  <b>tableRepackThreshold</b> <i></i>
+)
+</pre>
+<dd> This function is used to set the parameters which are
+  used to control the reordering process. "reorderingThreshold"
+  determines the number of nodes below which reordering will NOT be
+  invoked, "maxForwardedNodes" determines the maximum number of
+  forwarded nodes which are allowed (at that point the cleanup must be
+  done), and "repackingThreshold" determines the fraction of the page
+  utilized below which repacking has to be invoked. These parameters
+  have different affect on the computational and memory usage aspects
+  of reordeing. For instance, higher value of "maxForwardedNodes" will
+  result in process consuming more memory, and a lower value on the
+  other hand would invoke the cleanup process repeatedly resulting in
+  increased computation.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddMultiwayAnd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddMultiwayAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical AND of set of BDDs in the bddArray
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddMultiwayOr"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddMultiwayOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical OR of set of BDDs in the bddArray
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddMultiwayXor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddMultiwayXor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical XOR of set of BDDs in the bddArray
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddNand"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddNand</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical NAND of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddNewVarBlock"></A>
+Cal_Block <I></I>
+<B>Cal_BddNewVarBlock</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>variable</b>, <i></i>
+  long  <b>length</b> <i></i>
+)
+</pre>
+<dd> The block is specified by passing the first
+  variable and the length of the block. The "length" number of
+  consecutive variables starting from "variable" are put in the
+  block.
+<p>
+
+<dd> <b>Side Effects</b> A new block is created.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddNodeLimit"></A>
+long <I></I>
+<B>Cal_BddNodeLimit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  long  <b>newLimit</b> <i></i>
+)
+</pre>
+<dd> Sets the node limit to new_limit and returns the old limit.
+<p>
+
+<dd> <b>Side Effects</b> Threshold for garbage collection may change
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerGC">Cal_BddManagerGC</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddNor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddNor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical NOR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddNot"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddNot</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the complement of the argument BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the argument BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddIdentity">Cal_BddIdentity</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddOne"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddOne</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for the constant one
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddZero">Cal_BddZero</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddOr"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical OR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddOverflow"></A>
+int <I></I>
+<B>Cal_BddOverflow</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the node limit has been exceeded, 0 otherwise. The
+  overflow flag is cleared.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddNodeLimit">Cal_BddNodeLimit</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddPairwiseAnd"></A>
+Cal_Bdd * <I></I>
+<B>Cal_BddPairwiseAnd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns an array of BDDs obtained by logical AND of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddPairwiseOr">Cal_BddPairwiseOr</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddPairwiseOr"></A>
+Cal_Bdd * <I></I>
+<B>Cal_BddPairwiseOr</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns an array of BDDs obtained by logical OR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddPairwiseAnd">Cal_BddPairwiseAnd</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddPairwiseXor"></A>
+Cal_Bdd * <I></I>
+<B>Cal_BddPairwiseXor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBddArray</b> <i></i>
+)
+</pre>
+<dd> Returns an array of BDDs obtained by logical XOR of BDD pairs
+  specified by an BDD array in which a BDD at an even location is paired with
+  a BDD at an odd location of the array
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddPairwiseAnd">Cal_BddPairwiseAnd</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddPrintBdd"></A>
+void <I></I>
+<B>Cal_BddPrintBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_VarNamingFn_t  <b>VarNamingFn</b>, <i></i>
+  Cal_TerminalIdFn_t  <b>TerminalIdFn</b>, <i></i>
+  Cal_Pointer_t  <b>env</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints a human-readable representation of the BDD f to
+  the file given by fp. The namingFn should be a pointer to a function
+  taking a bddManager, a BDD and the pointer given by env. This
+  function should return either a null pointer or a srting that is the
+  name of the supplied variable. If it returns a null pointer, a
+  default name is generated based on the index of the variable. It is
+  also legal for naminFN to e null; in this case, default names are
+  generated for all variables. The macro bddNamingFnNone is a null
+  pointer of suitable type. terminalIdFn should be apointer to a
+  function taking a bddManager and two longs. plus the pointer given
+  by the env. It should return either a null pointer. If it returns a
+  null pointer, or if terminalIdFn is null, then default names are
+  generated for the terminals. The macro bddTerminalIdFnNone is a null
+  pointer of suitable type.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddPrintFunctionProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddPrintFunctionProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBdds</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddPrintFunctionProfile"></A>
+void <I></I>
+<B>Cal_BddPrintFunctionProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>f</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddPrintProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddPrintProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userBdds</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddPrintProfile"></A>
+void <I></I>
+<B>Cal_BddPrintProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_VarNamingFn_t  <b>varNamingProc</b>, <i></i>
+  char * <b>env</b>, <i></i>
+  int  <b>lineLength</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddProfileMultiple"></A>
+void <I></I>
+<B>Cal_BddProfileMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>fUserBddArray</b>, <i></i>
+  long * <b>levelCounts</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddProfile"></A>
+void <I></I>
+<B>Cal_BddProfile</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  long * <b>levelCounts</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> negout is as in Cal_BddSize. levelCounts should be an array of
+  size Cal_BddVars(bddManager)+1 to hold the profile.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddReduce"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddReduce</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>cUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD which agrees with f for all valuations
+  which satisfy c. The result is usually smaller in terms of number of
+  BDD nodes than f. This operation is typically used in state space
+  searches to simplify the representation for the set of states wich
+  will be expanded at each step.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddCofactor">Cal_BddCofactor</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddRelProd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddRelProd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for the logical AND of f and g with all
+  the variables that are paired with something in the current variable
+  association existentially quantified out.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddReorder"></A>
+void <I></I>
+<B>Cal_BddReorder</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Invoke the current dynamic reodering method.
+<p>
+
+<dd> <b>Side Effects</b> Index of a variable may change due to reodering
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddDynamicReordering">Cal_BddDynamicReordering</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddSatisfySupport"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSatisfySupport</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> The returned BDD which implies f, is true for some valuation on
+               which f is true, which has at most one node at each level,
+               and which has exactly one node corresponding to each variable
+               which is associated with something in the current variable
+               association.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddSatisfyingFraction"></A>
+double <I></I>
+<B>Cal_BddSatisfyingFraction</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddSatisfy"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSatisfy</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddSetGCMode"></A>
+void <I></I>
+<B>Cal_BddSetGCMode</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>gcMode</b> <i></i>
+)
+</pre>
+<dd> Sets the garbage collection mode, 0 means the garbage
+  collection should be turned off, 1 means garbage collection should
+  be on.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddSizeMultiple"></A>
+long <I></I>
+<B>Cal_BddSizeMultiple</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>fUserBddArray</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddSize"></A>
+long <I></I>
+<B>Cal_BddSize</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  int  <b>negout</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddStats"></A>
+void <I></I>
+<B>Cal_BddStats</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints miscellaneous BDD statistics
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddSubstitute"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD for f using the substitution defined by current
+  variable association. Each variable is replaced by its associated BDDs. The 
+  substitution is effective simultaneously
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddCompose">Cal_BddCompose</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddSupport"></A>
+void <I></I>
+<B>Cal_BddSupport</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd * <b>support</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddSwapVars"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddSwapVars</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b>, <i></i>
+  Cal_Bdd  <b>hUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD obtained by simultaneously substituting variable
+  g by variable h and variable h and variable g in the BDD f
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddSubstitute">Cal_BddSubstitute</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddThen"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddThen</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the positive cofactor of the argument BDD with
+  respect to the top variable of the BDD.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the returned BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddElse">Cal_BddElse</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddTotalSize"></A>
+unsigned long <I></I>
+<B>Cal_BddTotalSize</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the number of nodes in the Unique table
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddManagerGetNumNodes">Cal_BddManagerGetNumNodes</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddType"></A>
+int <I></I>
+<B>Cal_BddType</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns BDD_TYPE_ZERO if f is false, BDD_TYPE_ONE 
+  if f is true, BDD_TYPE_POSVAR is f is an unnegated variable,
+  BDD_TYPE_NEGVAR if f is a negated variable, BDD_TYPE_OVERFLOW if f
+  is null, and BDD_TYPE_NONTERMINAL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddUnFree"></A>
+void <I></I>
+<B>Cal_BddUnFree</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>userBdd</b> <i></i>
+)
+</pre>
+<dd> Unfrees the argument BDD. It is an error to pass a BDD
+  with reference count of zero to be unfreed.
+<p>
+
+<dd> <b>Side Effects</b> The reference count of the argument BDD is increased by 1.
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddFree">Cal_BddFree</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddUndumpBdd"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddUndumpBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>userVars</b>, <i></i>
+  FILE * <b>fp</b>, <i></i>
+  int * <b>error</b> <i></i>
+)
+</pre>
+<dd> Loads an encoded description of a BDD from the file given by
+  fp. The argument vars should be a null terminated array of variables that will
+  become the support of the BDD. As in Cal_BddDumpBdd, these need not be in
+  the order of increasing index. If the same array of variables in used in 
+  dumping and undumping, the BDD returned will be equal to the one that was 
+  dumped. More generally, if array v1 is used when dumping, and the array v2
+  is used when undumping, the BDD returned will be equal to the original BDD
+  with the ith variable in v2 substituted for the ith variable in v1 for all i.
+  Null BDD is returned in the operation fails for reason (node limit reached,
+  I/O error, invalid file format, etc.). In this case, an error code is stored
+  in error. the code will be one of the following. 
+  CAL_BDD_UNDUMP_FORMAT Invalid file format
+  CAL_BDD_UNDUMP_OVERFLOW Node limit exceeded
+  CAL_BDD_UNDUMP_IOERROR File I/O error
+  CAL_BDD_UNDUMP_EOF Unexpected EOF
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddVarBlockReorderable"></A>
+void <I></I>
+<B>Cal_BddVarBlockReorderable</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Block  <b>block</b>, <i></i>
+  int  <b>reorderable</b> <i></i>
+)
+</pre>
+<dd> If a block is reorderable, the child blocks are
+  recursively involved in swapping.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddVarSubstitute"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddVarSubstitute</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns a BDD for f using the substitution defined by current
+  variable association. It is assumed that each variable is replaced
+  by another variable. For the substitution of a variable by a
+  function, use Cal_BddSubstitute instead.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddSubstitute">Cal_BddSubstitute</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_BddVars"></A>
+long <I></I>
+<B>Cal_BddVars</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the number of BDD variables
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddXnor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddXnor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical exclusive NOR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddXor"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddXor</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for logical exclusive OR of f and g
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_BddZero"></A>
+Cal_Bdd <I></I>
+<B>Cal_BddZero</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Returns the BDD for the constant zero
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="#Cal_BddOne">Cal_BddOne</a>
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemAllocation"></A>
+Cal_Address_t <I></I>
+<B>Cal_MemAllocation</B>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> Returns the memory allocated.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemFatal"></A>
+void <I></I>
+<B>Cal_MemFatal</B>(
+  char * <b>message</b> <i></i>
+)
+</pre>
+<dd> Prints an error message and exits.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemFreeBlock"></A>
+void <I></I>
+<B>Cal_MemFreeBlock</B>(
+  Cal_Pointer_t  <b>p</b> <i></i>
+)
+</pre>
+<dd> Frees the block.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemFreeRecMgr"></A>
+void <I></I>
+<B>Cal_MemFreeRecMgr</B>(
+  Cal_RecMgr  <b>mgr</b> <i></i>
+)
+</pre>
+<dd> Frees all the storage associated with the specified record manager.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemFreeRec"></A>
+void <I></I>
+<B>Cal_MemFreeRec</B>(
+  Cal_RecMgr  <b>mgr</b>, <i></i>
+  Cal_Pointer_t  <b>rec</b> <i></i>
+)
+</pre>
+<dd> Frees a record managed by the indicated record manager.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemGetBlock"></A>
+Cal_Pointer_t <I></I>
+<B>Cal_MemGetBlock</B>(
+  Cal_Address_t  <b>size</b> <i></i>
+)
+</pre>
+<dd> Allocates a new block of the specified size.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemNewRecMgr"></A>
+Cal_RecMgr <I></I>
+<B>Cal_MemNewRecMgr</B>(
+  int  <b>size</b> <i></i>
+)
+</pre>
+<dd> Creates a new record manager with the given  record size.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemNewRec"></A>
+Cal_Pointer_t <I></I>
+<B>Cal_MemNewRec</B>(
+  Cal_RecMgr  <b>mgr</b> <i></i>
+)
+</pre>
+<dd> Allocates a record from the specified record manager.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_MemResizeBlock"></A>
+Cal_Pointer_t <I></I>
+<B>Cal_MemResizeBlock</B>(
+  Cal_Pointer_t  <b>p</b>, <i></i>
+  Cal_Address_t  <b>newSize</b> <i></i>
+)
+</pre>
+<dd> Expands or contracts the block to a new size.
+  We try to avoid moving the block if possible.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_PerformanceTest"></A>
+int <I></I>
+<B>Cal_PerformanceTest</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>outputBddArray</b>, <i></i>
+  int  <b>numFunctions</b>, <i></i>
+  int  <b>iteration</b>, <i></i>
+  int  <b>seed</b>, <i></i>
+  int  <b>andPerformanceFlag</b>, <i></i>
+  int  <b>multiwayPerformanceFlag</b>, <i></i>
+  int  <b>onewayPerformanceFlag</b>, <i></i>
+  int  <b>quantifyPerformanceFlag</b>, <i></i>
+  int  <b>composePerformanceFlag</b>, <i></i>
+  int  <b>relprodPerformanceFlag</b>, <i></i>
+  int  <b>swapPerformanceFlag</b>, <i></i>
+  int  <b>substitutePerformanceFlag</b>, <i></i>
+  int  <b>sanityCheckFlag</b>, <i></i>
+  int  <b>computeMemoryOverheadFlag</b>, <i></i>
+  int  <b>superscalarFlag</b> <i></i>
+)
+</pre>
+<dd> optional
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_PipelineCreateProvisionalBdd"></A>
+Cal_Bdd <I></I>
+<B>Cal_PipelineCreateProvisionalBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>fUserBdd</b>, <i></i>
+  Cal_Bdd  <b>gUserBdd</b> <i></i>
+)
+</pre>
+<dd> The provisional BDD is automatically freed once the
+  pipeline is quitted.
+<p>
+
+<dt><pre>
+<A NAME="Cal_PipelineExecute"></A>
+int <I></I>
+<B>Cal_PipelineExecute</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> All the results are computed. User should update the
+  BDDs of interest. Eventually this feature would become transparent.
+<p>
+
+<dd> <b>Side Effects</b> required
+<p>
+
+<dd> <b>See Also</b> <code>optional
+</code>
+
+<dt><pre>
+<A NAME="Cal_PipelineInit"></A>
+int <I></I>
+<B>Cal_PipelineInit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_BddOp_t  <b>bddOp</b> <i></i>
+)
+</pre>
+<dd> All the operations for this pipeline must be of the
+  same kind.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_PipelineQuit"></A>
+void <I></I>
+<B>Cal_PipelineQuit</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> The user must make sure to update all provisional BDDs
+  of interest before calling this routine.
+<p>
+
+<dt><pre>
+<A NAME="Cal_PipelineSetDepth"></A>
+void <I></I>
+<B>Cal_PipelineSetDepth</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  int  <b>depth</b> <i></i>
+)
+</pre>
+<dd> The "depth" determines the amount of dependency we
+  would allow in pipelined computation.
+<p>
+
+<dd> <b>Side Effects</b> None.
+<p>
+
+<dt><pre>
+<A NAME="Cal_PipelineUpdateProvisionalBdd"></A>
+Cal_Bdd <I></I>
+<B>Cal_PipelineUpdateProvisionalBdd</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd  <b>provisionalBdd</b> <i></i>
+)
+</pre>
+<dd> The provisional BDD is automatically freed after
+  quitting pipeline.
+<p>
+
+<dt><pre>
+<A NAME="Cal_TempAssociationAugment"></A>
+void <I></I>
+<B>Cal_TempAssociationAugment</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>associationInfoUserBdds</b>, <i></i>
+  int  <b>pairs</b> <i></i>
+)
+</pre>
+<dd> Pairs is 0 if the information represents only a list of
+  variables rather than a full association.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_TempAssociationInit"></A>
+void <I></I>
+<B>Cal_TempAssociationInit</B>(
+  Cal_BddManager  <b>bddManager</b>, <i></i>
+  Cal_Bdd * <b>associationInfoUserBdds</b>, <i></i>
+  int  <b>pairs</b> <i></i>
+)
+</pre>
+<dd> Pairs is 0 if the information represents only a list of
+  variables rather than a full association.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+<A NAME="Cal_TempAssociationQuit"></A>
+void <I></I>
+<B>Cal_TempAssociationQuit</B>(
+  Cal_BddManager  <b>bddManager</b> <i></i>
+)
+</pre>
+<dd> Cleans up temporary associationoptional
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+
+</DL>
+<HR>
+Last updated on 970711 20h11
+</BODY></HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calGC.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calGC.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calGC.c	(revision 8)
@@ -0,0 +1,448 @@
+/**CFile***********************************************************************
+
+  FileName    [calGC.c]
+
+  PackageName [cal]
+
+  Synopsis    [Garbage collection routines]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan (rajeev@eecs.berkeley.edu)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calGC.c,v 1.2 1998/09/16 16:08:40 ravi Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CeilLog2(int number);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Sets the garbage collection mode, 0 means the garbage
+  collection should be turned off, 1 means garbage collection should
+  be on.]
+
+  Description [Sets the garbage collection mode, 0 means the garbage
+  collection should be turned off, 1 means garbage collection should
+  be on.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+void
+Cal_BddSetGCMode(
+  Cal_BddManager bddManager,
+  int  gcMode)
+{
+  bddManager->gcMode = gcMode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Invokes the garbage collection at the manager level.]
+
+  Description [For each variable in the increasing id free nodes with reference
+  count equal to zero freeing a node results in decrementing reference count of
+  then and else nodes by one.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+int
+Cal_BddManagerGC(Cal_BddManager bddManager)
+{
+  Cal_BddIndex_t index;
+  Cal_BddId_t id;
+  int numNodesFreed;
+  /* unsigned long origNodes = bddManager->numNodes; */
+  
+  if (bddManager->numPeakNodes < (bddManager->numNodes +
+                                  bddManager->numForwardedNodes)){
+    bddManager->numPeakNodes = bddManager->numNodes +
+        bddManager->numForwardedNodes ;
+  }
+  
+  CalHashTableGC(bddManager, bddManager->uniqueTable[0]);
+  for(index = 0; index < bddManager->numVars; index++){
+    id = bddManager->indexToId[index];
+    numNodesFreed = CalHashTableGC(bddManager, bddManager->uniqueTable[id]);
+    bddManager->numNodes -= numNodesFreed;
+    bddManager->numNodesFreed += numNodesFreed;
+  }
+  /* Free the cache entries related to unused BDD nodes */
+  /* The assumption is that during CalHashTableGC, the freed BDD nodes
+     are marked. However, since they are not touched after being put
+     on the free list, the mark should be unaffected and can be used
+     for cleaning up the cache table.
+     */
+  CalCacheTableTwoGCFlush(bddManager->cacheTable);
+  bddManager->numGC++;
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the limit of the garbage collection.]
+
+  Description [It tries to set the limit at twice the number of nodes
+  in the manager at the current point. However, the limit is not
+  allowed to fall below the MIN_GC_LIMIT or to exceed the value of
+  node limit (if one exists).]
+
+  SideEffects [None.]
+
+******************************************************************************/
+void
+Cal_BddManagerSetGCLimit(Cal_BddManager manager)
+{
+  manager->uniqueTableGCLimit = ((manager->numNodes) << 1);
+  if(manager->uniqueTableGCLimit < CAL_MIN_GC_LIMIT){
+    manager->uniqueTableGCLimit = CAL_MIN_GC_LIMIT;
+  }
+  if (manager->nodeLimit && (manager->uniqueTableGCLimit >
+                             manager->nodeLimit)){
+    manager->uniqueTableGCLimit = manager->nodeLimit;
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddManagerGCCheck(Cal_BddManager_t * bddManager)
+{
+  if (bddManager->gcMode == 0) return;
+  if (bddManager->gcCheck > 0) return;
+  bddManager->gcCheck = CAL_GC_CHECK;
+  if(bddManager->numNodes > bddManager->uniqueTableGCLimit){
+    Cal_BddManagerGC(bddManager);
+    Cal_BddManagerSetGCLimit(bddManager);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function performs the garbage collection operation
+  for a particular index.]
+
+  Description [The input is the hash table containing the nodes
+  belonging to that level. Each bin of the hash table is traversed and
+  the Bdd nodes with 0 reference count are put at the appropriate
+  level in the processing que of the manager.]
+
+  SideEffects [The number of nodes in the hash table can possibly decrease.]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalHashTableGC(Cal_BddManager_t *bddManager, CalHashTable_t *hashTable)
+{
+  CalBddNode_t *last, *next, *ptr, *thenBddNode, *elseBddNode;
+  int i;
+  int oldNumEntries;
+  
+  oldNumEntries = hashTable->numEntries;
+  for(i = 0; i < hashTable->numBins; i++){
+    last = NULL;
+    ptr = hashTable->bins[i];
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      next = CalBddNodeGetNextBddNode(ptr);
+      if(CalBddNodeIsRefCountZero(ptr)){
+        if (last == NULL){
+          hashTable->bins[i] = next;
+        }
+        else{
+          CalBddNodePutNextBddNode(last,next);
+        }
+        thenBddNode = CAL_BDD_POINTER(CalBddNodeGetThenBddNode(ptr));
+        elseBddNode = CAL_BDD_POINTER(CalBddNodeGetElseBddNode(ptr));
+        CalBddNodeDcrRefCount(thenBddNode);
+        CalBddNodeDcrRefCount(elseBddNode);
+        CalNodeManagerFreeNode(hashTable->nodeManager, ptr);
+        /* Mark the freed node for cache table clean up */
+        /* We have to make sure that the clean up routine is called */
+        /* right after this function (so that the marking remains */
+        /* valid) */
+        CalBddNodeMark(ptr);
+        hashTable->numEntries--;
+      }
+      else {
+        last = ptr;
+      }
+      ptr = next;
+    }
+  }
+  return oldNumEntries - hashTable->numEntries;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalRepackNodesAfterGC(Cal_BddManager_t *bddManager)
+{
+  int index, id, numPagesRequired, packingFlag, pageNum, nodeNum;
+  int rehashFlag = 0;
+  int newSizeIndex, hashValue;
+  CalNodeManager_t *nodeManager;
+  CalHashTable_t *uniqueTableForId;
+  CalBddNode_t *bddNode, *thenBddNode, *elseBddNode, *freeNodeList;
+  CalBddNode_t *newNode;
+  Cal_Bdd_t thenBdd, elseBdd;
+  
+  packingFlag = 0;
+  
+  for (index = bddManager->numVars-1; index >= 0; index--){
+    id = bddManager->indexToId[index];
+    uniqueTableForId = bddManager->uniqueTable[id];
+    nodeManager = uniqueTableForId->nodeManager;
+    if (CalBddIdNeedsRepacking(bddManager, id) == 0){
+      if (packingFlag == 0) continue; /* nothing needs to be done */
+      /* We just need to update the cofactors and continue; */
+      for (pageNum=0; pageNum < nodeManager->numPages; pageNum++){
+        for(nodeNum = 0,
+                bddNode = (CalBddNode_t *)nodeManager->pageList[pageNum]; 
+            nodeNum < NUM_NODES_PER_PAGE; nodeNum++, bddNode += 1){
+          if (CalBddNodeIsRefCountZero(bddNode) ||
+              CalBddNodeIsForwarded(bddNode)) continue;
+          thenBddNode = CalBddNodeGetThenBddNode(bddNode);
+          elseBddNode = CalBddNodeGetElseBddNode(bddNode);
+          CalBddNodeGetThenBdd(bddNode, thenBdd);
+          CalBddNodeGetElseBdd(bddNode, elseBdd);
+          if (CalBddIsForwarded(thenBdd)){
+            CalBddForward(thenBdd);
+            CalBddNodePutThenBdd(bddNode, thenBdd);
+            rehashFlag = 1;
+          }
+          if (CalBddIsForwarded(elseBdd)){
+            CalBddForward(elseBdd);
+            CalBddNodePutElseBdd(bddNode, elseBdd);
+            rehashFlag = 1;
+          }
+          Cal_Assert(!CalBddIsRefCountZero(thenBdd));
+          Cal_Assert(!CalBddIsRefCountZero(elseBdd));
+          Cal_Assert(bddManager->idToIndex[id] <
+                     bddManager->idToIndex[bddNode->thenBddId]);   
+          Cal_Assert(bddManager->idToIndex[id] < 
+                     bddManager->idToIndex[bddNode->elseBddId]);
+          if (rehashFlag){
+            CalUniqueTableForIdRehashNode(uniqueTableForId, bddNode,
+                                          thenBddNode, elseBddNode);
+          }
+        }
+      }
+      continue; /* move to next higher index */
+    }
+    packingFlag = 1;
+    if ((uniqueTableForId->numBins > uniqueTableForId->numEntries) &&
+        (uniqueTableForId->sizeIndex > HASH_TABLE_DEFAULT_SIZE_INDEX)){
+      /* Free the old bins */
+      Cal_MemFree(uniqueTableForId->bins);
+      /* Create the new set of bins */
+      newSizeIndex =
+          CeilLog2(uniqueTableForId->numEntries/HASH_TABLE_DEFAULT_MAX_DENSITY); 
+      if (newSizeIndex < HASH_TABLE_DEFAULT_SIZE_INDEX){
+        newSizeIndex = HASH_TABLE_DEFAULT_SIZE_INDEX;
+      }
+      uniqueTableForId->sizeIndex = newSizeIndex;
+      uniqueTableForId->numBins =  TABLE_SIZE(uniqueTableForId->sizeIndex);
+      uniqueTableForId->maxCapacity =
+          uniqueTableForId->numBins * HASH_TABLE_DEFAULT_MAX_DENSITY; 
+      uniqueTableForId->bins = Cal_MemAlloc(CalBddNode_t *,
+                                            uniqueTableForId->numBins); 
+      if(uniqueTableForId->bins == Cal_Nil(CalBddNode_t *)){
+        CalBddFatalMessage("out of memory");
+      }
+    }
+    /* Clear the unique table bins */
+    memset((char *)uniqueTableForId->bins, 0,
+           uniqueTableForId->numBins*sizeof(CalBddNode_t *));
+    numPagesRequired =
+        uniqueTableForId->numEntries/NUM_NODES_PER_PAGE+1;
+    /* Traverse the first numPagesRequired pages of this nodeManager */
+    /* Create the new free list */
+    nodeManager->freeNodeList = freeNodeList = Cal_Nil(CalBddNode_t);
+    for (pageNum = 0; pageNum < nodeManager->numPages; pageNum++){
+      for(nodeNum = 0,
+              bddNode = (CalBddNode_t *)nodeManager->pageList[pageNum]; 
+          nodeNum < NUM_NODES_PER_PAGE; nodeNum++, bddNode += 1){
+        if(CalBddNodeIsRefCountZero(bddNode) ||
+           CalBddNodeIsForwarded(bddNode)){
+          if (pageNum < numPagesRequired){
+            bddNode->nextBddNode = freeNodeList;
+            freeNodeList = bddNode;
+          }
+          continue;
+        }
+        CalBddNodeGetThenBdd(bddNode, thenBdd);
+        CalBddNodeGetElseBdd(bddNode, elseBdd);
+        if (CalBddIsForwarded(thenBdd)){
+          CalBddForward(thenBdd);
+          CalBddNodePutThenBdd(bddNode, thenBdd);
+        }
+        if (CalBddIsForwarded(elseBdd)){
+          CalBddForward(elseBdd);
+          CalBddNodePutElseBdd(bddNode, elseBdd); 
+        }
+        if (pageNum < numPagesRequired){
+          /* Simply insert the node in the unique table */
+          hashValue = CalDoHash2(thenBdd.bddNode, elseBdd.bddNode,
+                                 uniqueTableForId); 
+          CalBddNodePutNextBddNode(bddNode, uniqueTableForId->bins[hashValue]);
+          uniqueTableForId->bins[hashValue] = bddNode;
+        }
+        else {
+          /* Create a new node */
+          newNode = freeNodeList;
+          freeNodeList = newNode->nextBddNode;
+          newNode->thenBddNode = bddNode->thenBddNode;
+          newNode->elseBddNode = bddNode->elseBddNode;
+          newNode->thenBddId = bddNode->thenBddId;
+          newNode->elseBddId = bddNode->elseBddId;
+          newNode->nextBddNode = bddNode->nextBddNode;
+          bddNode->elseBddNode = FORWARD_FLAG;
+          bddNode->thenBddId = id;
+          bddNode->thenBddNode = newNode;
+          hashValue = CalDoHash2(thenBdd.bddNode, elseBdd.bddNode,
+                                 uniqueTableForId); 
+          CalBddNodePutNextBddNode(newNode, uniqueTableForId->bins[hashValue]);
+          uniqueTableForId->bins[hashValue] = newNode;
+        }
+      }
+      if (pageNum >= numPagesRequired){
+        /* Free this page. I am assuming that there would not be any
+           call to PageManagerAllocPage, until this function finishes */
+        /* Also, CalPageManagerFreePage overwrites only the first field of
+           the bdd node (the nextBddNode field), hence no relevant
+           information is lost */
+        CalPageManagerFreePage(nodeManager->pageManager,
+                               nodeManager->pageList[pageNum]);
+        nodeManager->pageList[pageNum] = 0;
+      }
+    }
+#ifdef _CAL_VERBOSE    
+    printf("Recycled %4d pages for %3d id\n",
+           nodeManager->numPages-numPagesRequired, id);
+#endif
+    nodeManager->numPages = numPagesRequired;
+    nodeManager->freeNodeList = freeNodeList;
+  }
+  /* Need to update the handles to the nodes being moved */
+  if (bddManager->pipelineState == CREATE){
+    /* There are some results computed in pipeline */
+    CalBddReorderFixProvisionalNodes(bddManager);
+  }
+  
+  CalCacheTableTwoRepackUpdate(bddManager->cacheTable);
+
+  /* Fix the user BDDs */
+  CalBddReorderFixUserBddPtrs(bddManager);
+
+  /* Fix the association */
+  CalReorderAssociationFix(bddManager);
+
+  Cal_Assert(CalCheckAssoc(bddManager));
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the smallest integer greater than or equal to log2 of a
+  number]
+
+  Description [Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CeilLog2(int  number)
+{
+  int num, count;
+  for (num=number, count=0; num > 1; num >>= 1, count++);
+  if ((1 << count) != number) count++;
+  return count;
+}
Index: /vis_dev/glu-2.1/src/calBdd/calHashTable.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calHashTable.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calHashTable.c	(revision 8)
@@ -0,0 +1,1048 @@
+/**CFile***********************************************************************
+
+  FileName    [calHashTable.c]
+
+  PackageName [cal]
+
+  Synopsis    [Functions to manage the hash tables that are a part of
+                  1. unique table
+                  2. request queue
+               ]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+                Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+              ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calHashTable.c,v 1.9 2002/09/21 20:39:25 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CeilLog2(int number);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize a hash table using default parameters.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+CalHashTable_t *
+CalHashTableInit(Cal_BddManager_t *bddManager, Cal_BddId_t  bddId)
+{
+  CalHashTable_t *hashTable;
+
+  hashTable = Cal_MemAlloc(CalHashTable_t, 1);
+  /*hashTable = CAL_BDD_NEW_REC(bddManager, CalHashTable_t);*/
+  if(hashTable == Cal_Nil(CalHashTable_t)){
+    CalBddFatalMessage("out of memory");
+  }
+  hashTable->sizeIndex = HASH_TABLE_DEFAULT_SIZE_INDEX;
+  hashTable->numBins = TABLE_SIZE(hashTable->sizeIndex);
+  hashTable->maxCapacity = hashTable->numBins*HASH_TABLE_DEFAULT_MAX_DENSITY;
+  hashTable->bins = Cal_MemAlloc(CalBddNode_t *, hashTable->numBins);
+  if(hashTable->bins == Cal_Nil(CalBddNode_t *)){
+    CalBddFatalMessage("out of memory");
+  }
+  memset((char *)hashTable->bins, 0,
+         hashTable->numBins*sizeof(CalBddNode_t *)); 
+  hashTable->bddId = bddId;
+  hashTable->nodeManager = bddManager->nodeManagerArray[bddId];
+  hashTable->requestNodeList = Cal_Nil(CalRequestNode_t);
+  memset((char *)(&(hashTable->startNode)), 0, sizeof(CalBddNode_t));
+  hashTable->endNode = &(hashTable->startNode);
+  hashTable->numEntries = 0;
+  return hashTable;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free a hash table along with the associated storage.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalHashTableQuit(Cal_BddManager_t *bddManager, CalHashTable_t * hashTable)
+{
+  if(hashTable == Cal_Nil(CalHashTable_t))return 1;
+  /*
+  for(i = 0; i < hashTable->numBins; i++){
+    ptr = hashTable->bins[i];
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      next = CalBddNodeGetNextBddNode(ptr);
+      CalNodeManagerFreeNode(hashTable->nodeManager, ptr);
+      ptr = next;
+    }
+  }
+  There is no need to free the nodes individually. They will be taken
+  care of by the PageManagerQuit.
+  We need to make sure that this function is called only during the global quitting.
+  If it need be called at some intermediate point, we need to free the BDD nodes 
+  appropriately.
+  */
+  
+  Cal_MemFree(hashTable->bins);
+  Cal_MemFree(hashTable);
+  /*CAL_BDD_FREE_REC(bddManager, hashTable, CalHashTable_t);*/
+  return 0;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Directly insert a BDD node in the hash table.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableAddDirect(CalHashTable_t * hashTable, CalBddNode_t * bddNode)
+{
+  int hashValue;
+  CalBddNode_t *thenBddNode, *elseBddNode;
+
+  hashTable->numEntries++;
+  if(hashTable->numEntries >= hashTable->maxCapacity){
+    CalHashTableRehash(hashTable, 1);
+  }
+  thenBddNode = CalBddNodeGetThenBddNode(bddNode);
+  elseBddNode = CalBddNodeGetElseBddNode(bddNode);
+  hashValue = CalDoHash2(thenBddNode, elseBddNode, hashTable);
+  CalBddNodePutNextBddNode(bddNode, hashTable->bins[hashValue]);
+  hashTable->bins[hashValue] = bddNode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalHashTableFindOrAdd(CalHashTable_t * hashTable,
+                      Cal_Bdd_t  thenBdd,
+                      Cal_Bdd_t  elseBdd,
+                      Cal_Bdd_t * bddPtr)
+{
+  CalBddNode_t *ptr;
+  Cal_Bdd_t tmpBdd;
+  int hashValue;
+  
+  hashValue = CalDoHash2(CalBddGetBddNode(thenBdd), 
+      CalBddGetBddNode(elseBdd), hashTable);
+  ptr = hashTable->bins[hashValue];
+  while(ptr != Cal_Nil(CalBddNode_t)){
+    CalBddNodeGetThenBdd(ptr, tmpBdd);
+    if(CalBddIsEqual(thenBdd, tmpBdd)){
+      CalBddNodeGetElseBdd(ptr, tmpBdd);
+      if(CalBddIsEqual(elseBdd, tmpBdd)){
+        CalBddPutBddId(*bddPtr, hashTable->bddId);
+        CalBddPutBddNode(*bddPtr, ptr);
+        return 1;
+      }
+    }
+    ptr = CalBddNodeGetNextBddNode(ptr);
+  }
+  hashTable->numEntries++;
+  if(hashTable->numEntries > hashTable->maxCapacity){
+    CalHashTableRehash(hashTable,1);
+    hashValue = CalDoHash2(CalBddGetBddNode(thenBdd),
+        CalBddGetBddNode(elseBdd), hashTable);
+  }
+  CalNodeManagerInitBddNode(hashTable->nodeManager, thenBdd, elseBdd, 
+      hashTable->bins[hashValue], ptr);
+  hashTable->bins[hashValue] = ptr;
+  CalBddPutBddId(*bddPtr, hashTable->bddId);
+  CalBddPutBddNode(*bddPtr, ptr);
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalHashTableAddDirectAux(CalHashTable_t * hashTable, Cal_Bdd_t
+                         thenBdd, Cal_Bdd_t  elseBdd, Cal_Bdd_t *
+                         bddPtr) 
+{
+  CalBddNode_t *ptr;
+  int hashValue;
+  
+  hashTable->numEntries++;
+  if(hashTable->numEntries >= hashTable->maxCapacity){
+    CalHashTableRehash(hashTable, 1);
+  }
+  hashValue = CalDoHash2(CalBddGetBddNode(thenBdd), CalBddGetBddNode(elseBdd),
+                         hashTable); 
+  CalNodeManagerInitBddNode(hashTable->nodeManager, thenBdd, elseBdd, 
+      hashTable->bins[hashValue], ptr);
+  hashTable->bins[hashValue] = ptr;
+  CalBddPutBddId(*bddPtr, hashTable->bddId);
+  CalBddPutBddNode(*bddPtr, ptr);
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableCleanUp(CalHashTable_t * hashTable)
+{
+  CalNodeManager_t *nodeManager;
+
+  nodeManager = hashTable->nodeManager;
+  hashTable->endNode->nextBddNode = nodeManager->freeNodeList;
+  nodeManager->freeNodeList = hashTable->startNode.nextBddNode;
+  hashTable->endNode = &(hashTable->startNode);
+  hashTable->numEntries = 0;
+  hashTable->startNode.nextBddNode = NULL;
+  Cal_Assert(!(hashTable->requestNodeList));
+  hashTable->requestNodeList = Cal_Nil(CalRequestNode_t);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalHashTableLookup(
+  CalHashTable_t * hashTable,
+  Cal_Bdd_t  thenBdd,
+  Cal_Bdd_t  elseBdd,
+  Cal_Bdd_t * bddPtr)
+{
+  CalBddNode_t *ptr;
+  Cal_Bdd_t tmpBdd;
+  int hashValue;
+  
+  hashValue = CalDoHash2(CalBddGetBddNode(thenBdd),
+      CalBddGetBddNode(elseBdd), hashTable);
+  ptr = hashTable->bins[hashValue];
+  while(ptr != Cal_Nil(CalBddNode_t)){
+    CalBddNodeGetThenBdd(ptr, tmpBdd);
+    if(CalBddIsEqual(thenBdd, tmpBdd)){
+      CalBddNodeGetElseBdd(ptr, tmpBdd);
+      if(CalBddIsEqual(elseBdd, tmpBdd)){
+        CalBddPutBddId(*bddPtr, hashTable->bddId);
+        CalBddPutBddNode(*bddPtr, ptr);
+        return 1;
+      }
+    }
+    ptr = CalBddNodeGetNextBddNode(ptr);
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes a BDD node in the hash table.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableDelete(CalHashTable_t * hashTable, CalBddNode_t * bddNode)
+{
+  int hashValue;
+  Cal_Bdd_t thenBdd, elseBdd;
+  CalBddNode_t  *ptr, *last;
+
+  CalBddNodeGetThenBdd(bddNode, thenBdd);
+  CalBddNodeGetElseBdd(bddNode, elseBdd);
+  hashValue =
+      CalDoHash2(CalBddGetBddNode(thenBdd), CalBddGetBddNode(elseBdd), hashTable);
+
+  last = Cal_Nil(CalBddNode_t);
+  ptr = hashTable->bins[hashValue];
+  while(ptr != Cal_Nil(CalBddNode_t)){
+    if(ptr == bddNode){
+      if(last == Cal_Nil(CalBddNode_t)){
+        hashTable->bins[hashValue] = CalBddNodeGetNextBddNode(ptr);
+      }
+      else{
+        CalBddNodePutNextBddNode(last, CalBddNodeGetNextBddNode(ptr));
+      }
+      hashTable->numEntries--;
+      CalNodeManagerFreeNode(hashTable->nodeManager, ptr);
+      return;
+    }
+    last = ptr;
+    ptr = CalBddNodeGetNextBddNode(ptr);
+  }
+  CalBddWarningMessage("Trying to delete a non-existent node\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Lookup unique table for id.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalUniqueTableForIdLookup(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  Cal_Bdd_t  thenBdd,
+  Cal_Bdd_t  elseBdd,
+  Cal_Bdd_t * bddPtr)
+{
+  CalBddNode_t *ptr;
+  Cal_Bdd_t tmpBdd;
+  int hashValue;
+  
+  hashValue = CalDoHash2(CalBddGetBddNode(thenBdd),
+      CalBddGetBddNode(elseBdd), hashTable);
+  ptr = hashTable->bins[hashValue];
+  if(CalBddIsOutPos(thenBdd)){
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      CalBddNodeGetThenBdd(ptr, tmpBdd);
+      if(CalBddIsEqual(thenBdd, tmpBdd)){
+        CalBddNodeGetElseBdd(ptr, tmpBdd);
+        if(CalBddIsEqual(elseBdd, tmpBdd)){
+          CalBddPutBddId(*bddPtr, hashTable->bddId);
+          CalBddPutBddNode(*bddPtr, ptr);
+          return 1;
+        }
+      }
+      ptr = CalBddNodeGetNextBddNode(ptr);
+    }
+  }
+  else{
+    CalBddNot(thenBdd, thenBdd);
+    CalBddNot(elseBdd, elseBdd);
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      CalBddNodeGetThenBdd(ptr, tmpBdd);
+      if(CalBddIsEqual(thenBdd, tmpBdd)){
+        CalBddNodeGetElseBdd(ptr, tmpBdd);
+        if(CalBddIsEqual(elseBdd, tmpBdd)){
+          CalBddPutBddId(*bddPtr, hashTable->bddId);
+          CalBddPutBddNode(*bddPtr, CalBddNodeNot(ptr));
+          return 1;
+        }
+      }
+      ptr = CalBddNodeGetNextBddNode(ptr);
+    }
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [find or add in the unique table for id.]
+
+  Description [optional]
+
+  SideEffects [If a new BDD node is created (found == false), then the
+  numNodes field of the manager needs to be incremented.]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalUniqueTableForIdFindOrAdd(
+  Cal_BddManager_t * bddManager,
+  CalHashTable_t * hashTable,
+  Cal_Bdd_t  thenBdd,
+  Cal_Bdd_t  elseBdd,
+  Cal_Bdd_t * bddPtr)
+{
+  int found = 0; 
+  if (CalBddIsEqual(thenBdd, elseBdd)){
+    *bddPtr = thenBdd;
+    found = 1;
+  }
+  else if(CalBddIsOutPos(thenBdd)){
+    found = CalHashTableFindOrAdd(hashTable, thenBdd, elseBdd, bddPtr);
+  }
+  else{
+    CalBddNot(thenBdd, thenBdd);
+    CalBddNot(elseBdd, elseBdd);
+    found = CalHashTableFindOrAdd(hashTable, thenBdd, elseBdd, bddPtr);
+    CalBddNot(*bddPtr, *bddPtr);
+  }
+  if (!found) bddManager->numNodes++;
+  return found;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+
+void
+CalHashTableRehash(CalHashTable_t *hashTable,int grow)
+{
+  CalBddNode_t *ptr, *next;
+  CalBddNode_t **oldBins = hashTable->bins;
+  int i, hashValue;
+  int oldNumBins = hashTable->numBins;
+
+  if(grow){
+    hashTable->sizeIndex++;
+  }
+  else{
+    if (hashTable->sizeIndex <= HASH_TABLE_DEFAULT_SIZE_INDEX){/* No need to rehash */
+      return;
+    }
+    hashTable->sizeIndex--;
+  }
+
+  hashTable->numBins = TABLE_SIZE(hashTable->sizeIndex);
+  hashTable->maxCapacity = hashTable->numBins * HASH_TABLE_DEFAULT_MAX_DENSITY;
+  hashTable->bins = Cal_MemAlloc(CalBddNode_t *, hashTable->numBins);
+  if(hashTable->bins == Cal_Nil(CalBddNode_t *)){
+    CalBddFatalMessage("out of memory");
+  }
+  /*
+  for(i = 0; i < hashTable->numBins; i++){
+    hashTable->bins[i] = Cal_Nil(CalBddNode_t);
+  }
+  */
+  memset((char *)hashTable->bins, 0,
+         hashTable->numBins*sizeof(CalBddNode_t *));
+
+  for(i = 0; i < oldNumBins; i++){
+    ptr = oldBins[i];
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      next = CalBddNodeGetNextBddNode(ptr);
+      hashValue = CalDoHash2(CalBddNodeGetThenBddNode(ptr),
+          CalBddNodeGetElseBddNode(ptr), hashTable);
+      CalBddNodePutNextBddNode(ptr, hashTable->bins[hashValue]);
+      hashTable->bins[hashValue] = ptr;
+      ptr = next;
+    }
+  }
+  Cal_MemFree(oldBins);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalUniqueTableForIdRehashNode(CalHashTable_t *hashTable, CalBddNode_t *bddNode,
+                              CalBddNode_t *thenBddNode,
+                              CalBddNode_t *elseBddNode)
+
+{
+  CalBddNode_t *nextBddNode;
+  CalBddNode_t *ptr;
+  int found;
+  int hashValue;
+  int oldHashValue;
+  Cal_Bdd_t thenBdd;
+
+  oldHashValue = CalDoHash2(thenBddNode, elseBddNode, hashTable);
+  hashValue = CalDoHash2(CalBddNodeGetThenBddNode(bddNode),
+                         CalBddNodeGetElseBddNode(bddNode),
+                         hashTable);
+  CalBddNodeGetThenBdd(bddNode, thenBdd);
+  if (CalBddIsComplement(thenBdd)) {
+    CalBddFatalMessage("Complement edge on then pointer");
+  }
+  if (oldHashValue == hashValue) {
+    return;
+  }
+
+  found = 0;
+  ptr = hashTable->bins[oldHashValue];
+  if ((ptr != Cal_Nil(CalBddNode_t)) && (ptr == bddNode)) {
+    hashTable->bins[oldHashValue] = CalBddNodeGetNextBddNode(bddNode);
+    found = 1;
+  } else {
+    while (ptr != Cal_Nil(CalBddNode_t)) {
+      nextBddNode = CalBddNodeGetNextBddNode(ptr);
+      if (nextBddNode == bddNode) {
+        CalBddNodePutNextBddNode(ptr, CalBddNodeGetNextBddNode(bddNode));
+        found = 1;
+        break;
+      }
+      ptr = nextBddNode;
+    }
+  }
+
+  if (!found) {
+    CalBddFatalMessage("Node not found in the unique table");
+  } else {
+    CalBddNodePutNextBddNode(bddNode, hashTable->bins[hashValue]);
+    hashTable->bins[hashValue] = bddNode;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+  
+unsigned long
+CalBddUniqueTableNumLockedNodes(Cal_BddManager_t *bddManager,
+                                CalHashTable_t *uniqueTableForId)
+{
+  CalBddNode_t *bddNode;
+  long i;
+  unsigned long numLockedNodes = 0;
+  
+  for(i=0; i<uniqueTableForId->numBins; i++){
+    bddNode = uniqueTableForId->bins[i];
+    while (bddNode){
+      numLockedNodes += CalBddNodeIsRefCountMax(bddNode);
+      bddNode = CalBddNodeGetNextBddNode(bddNode);
+    }
+  }
+  return numLockedNodes;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalPackNodes(Cal_BddManager_t *bddManager)
+{
+  int index, id;
+  
+  for (index = bddManager->numVars-1; index >= 0; index--){
+    id = bddManager->indexToId[index];
+    CalBddPackNodesForSingleId(bddManager, id);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddPackNodesForSingleId(Cal_BddManager_t *bddManager,
+                           Cal_BddId_t id)
+{
+  /* Need to copy the one for "AfterReorder" and suitably modify. */
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Packs the nodes if the variables which has just
+  been sifted.]
+  
+  Description        [fixForwardedNodesFlag: Whether we need to fix
+  the forwarded nodes of variables corresponding to bestIndex through
+  bottomIndex. If this flag is set, then the forwarded nodes of these
+  variables are traversed and updated after the nodes of the bestIndex
+  have been copied. At the end the forwarded nodes are freed. If this
+  flag is not set, it is assumed that the cleanup pass has already
+  been performed.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddPackNodesAfterReorderForSingleId(Cal_BddManager_t *bddManager,
+                                       int fixForwardedNodesFlag,
+                                       int bestIndex, 
+                                       int bottomIndex) 
+{
+  /* We need to pack the nodes for this id and fix the cofactors of
+     the upper indices.
+     */
+  CalBddNode_t *node, *nextBddNode, *dupNode, **oldBins;
+  CalBddNode_t *thenBddNode, *elseBddNode, *bddNode;
+  Cal_Bdd_t thenBdd;
+  CalAddress_t *page;
+  int id = bddManager->indexToId[bestIndex];
+  CalNodeManager_t *nodeManager = bddManager->nodeManagerArray[id];
+  CalAddress_t **oldPageList = nodeManager->pageList;
+  int oldNumPages = nodeManager->numPages;
+  CalHashTable_t *uniqueTableForId = bddManager->uniqueTable[id];
+  int numPagesRequired, newSizeIndex, index, i;
+  long oldNumBins, hashValue;
+  
+  
+#ifdef _CAL_VERBOSE
+  fprintf(stdout,"Repacking id %3d\n", id);
+#endif
+  
+
+  nodeManager->freeNodeList = Cal_Nil(CalBddNode_t);
+  nodeManager->numPages = 0;
+  numPagesRequired = uniqueTableForId->numEntries/NUM_NODES_PER_PAGE;
+  nodeManager->maxNumPages =
+      2*(numPagesRequired ? numPagesRequired : 1);
+
+  nodeManager->pageList = Cal_MemAlloc(CalAddress_t *,
+                                       nodeManager->maxNumPages); 
+  
+  oldBins = uniqueTableForId->bins;
+  oldNumBins = uniqueTableForId->numBins;
+  /* Create the new set of bins */
+  newSizeIndex =
+      CeilLog2(uniqueTableForId->numEntries/HASH_TABLE_DEFAULT_MAX_DENSITY);
+
+  if (newSizeIndex < HASH_TABLE_DEFAULT_SIZE_INDEX){
+    newSizeIndex = HASH_TABLE_DEFAULT_SIZE_INDEX;
+  }
+
+  uniqueTableForId->sizeIndex = newSizeIndex;
+  uniqueTableForId->numBins =  TABLE_SIZE(uniqueTableForId->sizeIndex);
+  uniqueTableForId->maxCapacity =
+      uniqueTableForId->numBins * HASH_TABLE_DEFAULT_MAX_DENSITY; 
+
+  uniqueTableForId->bins = Cal_MemAlloc(CalBddNode_t *,
+                                        uniqueTableForId->numBins); 
+  if(uniqueTableForId->bins == Cal_Nil(CalBddNode_t *)){
+    CalBddFatalMessage("out of memory");
+  }
+
+  memset((char *)uniqueTableForId->bins, 0, 
+        uniqueTableForId->numBins*sizeof(CalBddNode_t *)); 
+
+  for (i = 0; i < oldNumBins; i++){
+    node = oldBins[i];
+    while (node){
+      nextBddNode = CalBddNodeGetNextBddNode(node);
+      CalNodeManagerCreateAndDupBddNode(nodeManager, node, dupNode);
+      thenBddNode = CalBddNodeGetThenBddNode(dupNode);
+      elseBddNode = CalBddNodeGetElseBddNode(dupNode);
+      hashValue = CalDoHash2(thenBddNode, elseBddNode, uniqueTableForId);
+      CalBddNodePutNextBddNode(dupNode, uniqueTableForId->bins[hashValue]);
+      uniqueTableForId->bins[hashValue] = dupNode;
+      CalBddNodePutThenBddNode(node, dupNode);
+      CalBddNodePutThenBddId(node, id);
+      CalBddNodePutElseBddNode(node, FORWARD_FLAG);
+      node = nextBddNode;
+      Cal_Assert(!(CalBddNodeIsRefCountZero(dupNode)));
+    }
+  }
+  
+  if (fixForwardedNodesFlag){
+      CalBddNode_t *requestNodeList =
+          bddManager->uniqueTable[id]->startNode.nextBddNode;  
+      for (bddNode = requestNodeList; bddNode; bddNode = nextBddNode){
+        Cal_Assert(CalBddNodeIsForwarded(bddNode));
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        CalBddNodeGetThenBdd(bddNode, thenBdd);
+        if (CalBddGetBddId(thenBdd) == id){
+          if (CalBddIsForwarded(thenBdd)) {
+            CalBddForward(thenBdd);
+            Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+            CalBddNodePutThenBdd(bddNode, thenBdd);
+          }
+        }
+        Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+      }
+      for (index = bestIndex+1; index <= bottomIndex; index++){   
+      int varId = bddManager->indexToId[index];
+      requestNodeList =
+          bddManager->uniqueTable[varId]->startNode.nextBddNode;   
+      for (bddNode = requestNodeList; bddNode; bddNode = nextBddNode){
+        Cal_Assert(CalBddNodeIsForwarded(bddNode));
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        CalBddNodeGetThenBdd(bddNode, thenBdd);
+        if (CalBddIsForwarded(thenBdd)) {
+          CalBddForward(thenBdd);
+          Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+          CalBddNodePutThenBdd(bddNode, thenBdd);
+        }
+        Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+      }
+    }
+  }
+  
+/* Traverse the upper indices fixing the cofactors */
+  for (index = bestIndex-1; index >= 0; index--){
+    CalBddReorderFixCofactors(bddManager,
+                           bddManager->indexToId[index]); 
+  }
+
+  if (bddManager->pipelineState == CREATE){
+    /* There are some results computed in pipeline */
+    CalBddReorderFixProvisionalNodes(bddManager);
+  }
+  
+  /* Fix the user BDDs */
+  CalBddReorderFixUserBddPtrs(bddManager);
+
+  CalBddIsForwardedTo(bddManager->varBdds[id]);
+
+  /* Fix the association */
+  CalReorderAssociationFix(bddManager);
+  
+  /* Free the old bins */
+  Cal_MemFree(oldBins);
+
+  uniqueTableForId->endNode = &(uniqueTableForId->startNode);
+  uniqueTableForId->startNode.nextBddNode = NULL;
+  if (fixForwardedNodesFlag){
+    CalBddReorderReclaimForwardedNodes(bddManager, bestIndex+1,
+                                    bottomIndex);
+  }
+  /* Free the old pages */
+  for (i = 0; i < oldNumPages; i++){
+    page = oldPageList[i]; 
+    CalPageManagerFreePage(nodeManager->pageManager, page);
+  }
+  Cal_MemFree(oldPageList);
+  Cal_Assert(CalCheckAllValidity(bddManager));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddPackNodesForMultipleIds(Cal_BddManager_t *bddManager,
+                              Cal_BddId_t beginId, int numLevels)
+{
+  /* We need to pack the nodes for this id and fix the cofactors of
+     the upper indices.
+     */
+  int index = bddManager->idToIndex[beginId];
+  int level, id;
+  long i, j;
+  CalBddNode_t *node, *nextBddNode, *dupNode, *thenBddNode;
+  CalBddNode_t *elseBddNode, **oldBins;
+  Cal_Bdd_t thenBdd, elseBdd;
+  CalNodeManager_t *nodeManager;
+  CalHashTable_t *uniqueTableForId;
+  int someRepackingDone = 0;
+  long oldNumBins, hashValue;
+  int newSizeIndex;
+
+
+  CalAddress_t *page, ***oldPageListArray, **oldPageList;
+  int *oldNumPagesArray;
+  int numPagesRequired;
+  
+  oldPageListArray = Cal_MemAlloc(CalAddress_t **, numLevels);
+
+  oldNumPagesArray = Cal_MemAlloc(int, numLevels);
+  
+  for (level = numLevels-1; level >= 0; level--){
+    id = bddManager->indexToId[index+level];
+    oldNumPagesArray[level] = 0;
+    oldPageListArray[level] = Cal_Nil(CalAddress_t *);
+    if (CalBddIdNeedsRepacking(bddManager, id)){
+      nodeManager = bddManager->nodeManagerArray[id];
+      uniqueTableForId = bddManager->uniqueTable[id];
+      oldPageListArray[level] = nodeManager->pageList;
+      oldNumPagesArray[level] = nodeManager->numPages;
+      nodeManager->freeNodeList = Cal_Nil(CalBddNode_t);
+      nodeManager->numPages = 0;
+      numPagesRequired = uniqueTableForId->numEntries/NUM_NODES_PER_PAGE;
+      nodeManager->maxNumPages =
+          2*(numPagesRequired ? numPagesRequired : 1);
+      nodeManager->pageList = Cal_MemAlloc(CalAddress_t *,
+                                           nodeManager->maxNumPages); 
+      oldBins = uniqueTableForId->bins;
+      oldNumBins = uniqueTableForId->numBins;
+      /* Create the new set of bins */
+      newSizeIndex =
+          CeilLog2(uniqueTableForId->numEntries /
+                   HASH_TABLE_DEFAULT_MAX_DENSITY);  
+      if (newSizeIndex < HASH_TABLE_DEFAULT_SIZE_INDEX){
+        newSizeIndex = HASH_TABLE_DEFAULT_SIZE_INDEX;
+      }
+      uniqueTableForId->sizeIndex = newSizeIndex;
+      uniqueTableForId->numBins =  TABLE_SIZE(uniqueTableForId->sizeIndex);
+      uniqueTableForId->maxCapacity =
+          uniqueTableForId->numBins * HASH_TABLE_DEFAULT_MAX_DENSITY; 
+      
+      uniqueTableForId->bins = Cal_MemAlloc(CalBddNode_t *,
+                                            uniqueTableForId->numBins); 
+      if(uniqueTableForId->bins == Cal_Nil(CalBddNode_t *)){
+        CalBddFatalMessage("out of memory");
+      }
+      memset((char *)uniqueTableForId->bins, 0, 
+            uniqueTableForId->numBins*sizeof(CalBddNode_t *)); 
+      
+      for (i = 0; i < oldNumBins; i++){
+        node = oldBins[i];
+        while (node){
+          nextBddNode = CalBddNodeGetNextBddNode(node);
+          CalBddNodeGetThenBdd(node, thenBdd);
+          CalBddNodeGetElseBdd(node, elseBdd);
+          if (CalBddIsForwarded(thenBdd)){
+            CalBddForward(thenBdd);
+            CalBddNodePutThenBdd(node, thenBdd);
+          }
+          if (CalBddIsForwarded(elseBdd)){
+            CalBddForward(elseBdd);
+            CalBddNodePutElseBdd(node, elseBdd);
+          }
+          CalNodeManagerCreateAndDupBddNode(nodeManager, node, dupNode);
+          thenBddNode = CalBddNodeGetThenBddNode(dupNode);
+          elseBddNode = CalBddNodeGetElseBddNode(dupNode);
+          hashValue = CalDoHash2(thenBddNode, elseBddNode, uniqueTableForId);
+          CalBddNodePutNextBddNode(dupNode, uniqueTableForId->bins[hashValue]);
+          uniqueTableForId->bins[hashValue] = dupNode;
+          CalBddNodePutThenBddNode(node, dupNode);
+          CalBddNodePutThenBddId(node, id);
+          CalBddNodePutElseBddNode(node, FORWARD_FLAG);
+          node = nextBddNode;
+          Cal_Assert(!(CalBddNodeIsRefCountZero(dupNode)));
+        }
+      }
+
+#ifdef __FOO__
+      /*fprintf(stdout,"Repacking id = %d, index = %d\n", id, index+level);*/
+      /* First put all the nodes in that list */
+      nodeList = Cal_Nil(CalBddNode_t);
+      for (i = 0; i < uniqueTableForId->numBins; i++){
+        node = uniqueTableForId->bins[i];
+        while (node){
+          nextBddNode = CalBddNodeGetNextBddNode(node);
+          /* The "then" and "else" pointers could be forwarded */
+          CalBddNodeGetThenBdd(node, thenBdd);
+          CalBddNodeGetElseBdd(node, elseBdd);
+          if (CalBddIsForwarded(thenBdd)){
+            CalBddForward(thenBdd);
+            CalBddNodePutThenBdd(node, thenBdd);
+          }
+          if (CalBddIsForwarded(elseBdd)){
+            CalBddForward(elseBdd);
+            CalBddNodePutElseBdd(node, elseBdd);
+          }
+          CalBddNodePutNextBddNode(node, nodeList);
+          nodeList = node;
+          node = nextBddNode;
+        }
+        uniqueTableForId->bins[i] = Cal_Nil(CalBddNode_t);
+      }
+      uniqueTableForId->numEntries = 0;
+      
+      for (node = nodeList; node; node = nextBddNode){
+        nextBddNode = CalBddNodeGetNextBddNode(node);
+        CalNodeManagerCreateAndDupBddNode(nodeManager, node, dupNode);
+        /* Hash the dupNode */
+        CalHashTableAddDirect(uniqueTableForId, dupNode);
+        /* Make the original node a forwarding node */
+        CalBddNodePutThenBddNode(node, dupNode);
+        CalBddNodePutThenBddId(node, id);
+        CalBddNodePutElseBddNode(node, FORWARD_FLAG);
+      }
+#endif
+      someRepackingDone = 1;
+    }
+    else if (someRepackingDone){ /* Still need to fix the cofactors */
+      CalBddReorderFixCofactors(bddManager, id);
+    }
+  }
+  
+
+  /* Traverse the upper indices fixing the cofactors */
+  for (i = index-1; i >= 0; i--){
+    CalBddReorderFixCofactors(bddManager,
+                              bddManager->indexToId[i]);
+  }
+
+  /* Fix the user BDDs */
+  CalBddReorderFixUserBddPtrs(bddManager);
+  if (bddManager->pipelineState == CREATE){
+    /* There are some results computed in pipeline */
+    CalBddReorderFixProvisionalNodes(bddManager);
+  }
+  /* Fix Cache Tables */
+  (void)CalCacheTableTwoRepackUpdate(bddManager->cacheTable);
+  
+  for (level = numLevels - 1 ; level >= 0; level--){
+    id = bddManager->indexToId[index+level];
+    /* Update varBdd field of bdd manager */
+    CalBddIsForwardedTo(bddManager->varBdds[id]);
+    /* Fix associations */
+    CalVarAssociationRepackUpdate(bddManager, id);
+    /* Free the old pages */
+    nodeManager = bddManager->nodeManagerArray[id];
+    oldPageList = oldPageListArray[level];
+    for (j = 0; j < oldNumPagesArray[level]; j++){
+      page = oldPageList[j]; 
+      CalPageManagerFreePage(nodeManager->pageManager, page);
+    }
+    if ((unsigned long)oldPageList) Cal_MemFree(oldPageList);
+  }
+  Cal_MemFree(oldPageListArray);
+  Cal_MemFree(oldNumPagesArray);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns the smallest integer greater than or equal to log2 of a
+  number]
+
+  Description [Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CeilLog2(
+  int  number)
+{
+  int num, count;
+  for (num=number, count=0; num > 1; num >>= 1, count++);
+  if ((1 << count) != number) count++;
+  return count;
+}
Index: /vis_dev/glu-2.1/src/calBdd/calHashTableOne.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calHashTableOne.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calHashTableOne.c	(revision 8)
@@ -0,0 +1,298 @@
+/**CFile***********************************************************************
+
+  FileName    [calHashTableOne.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for managing hash table with Bdd is a key and
+               int, long, or double as a value]
+
+  Description [ ]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+              ] 
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calHashTableOne.c,v 1.1.1.3 1998/05/04 00:58:57 hsv Exp $]
+
+******************************************************************************/
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#ifdef USE_POWER_OF_2
+#  define HashTableOneDoHash(hashTable, keyBdd) \
+     (((CalAddress_t)(CalBddGetBddNode(keyBdd)) / NODE_SIZE) & ((hashTable)->numBins - 1))
+#else
+#  define HashTableOneDoHash(hashTable, keyBdd) \
+     (((CalAddress_t)(CalBddGetBddNode(keyBdd)) / NODE_SIZE) % hashTable->numBins)
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void HashTableOneRehash(CalHashTable_t * hashTable, int grow);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize a hash table using default parameters.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+CalHashTable_t *
+CalHashTableOneInit(Cal_BddManager_t * bddManager, int  itemSize)
+{
+  int i;
+  CalHashTable_t *hashTable;
+
+  hashTable = Cal_MemAlloc(CalHashTable_t, 1);
+  if(hashTable == Cal_Nil(CalHashTable_t)){
+    CalBddFatalMessage("out of memory");
+  }
+  hashTable->sizeIndex = HASH_TABLE_DEFAULT_SIZE_INDEX;
+  hashTable->numBins = TABLE_SIZE(hashTable->sizeIndex);
+  hashTable->maxCapacity = hashTable->numBins*HASH_TABLE_DEFAULT_MAX_DENSITY;
+  hashTable->bins = Cal_MemAlloc(CalBddNode_t *, hashTable->numBins);
+  if(hashTable->bins == Cal_Nil(CalBddNode_t *)){
+    CalBddFatalMessage("out of memory");
+  }
+  for(i = 0; i < hashTable->numBins; i++){
+    hashTable->bins[i] = Cal_Nil(CalBddNode_t);
+  }
+  hashTable->numEntries = 0;
+  hashTable->bddId = (Cal_BddId_t)itemSize;
+  if(itemSize > NODE_SIZE){
+    CalBddFatalMessage("CalHashTableOneInit: itemSize exceeds NODE_SIZE");
+  }
+  hashTable->nodeManager = bddManager->nodeManagerArray[0];
+  hashTable->requestNodeList = Cal_Nil(CalRequestNode_t);
+  return hashTable;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free a hash table along with the associated storage.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableOneQuit(
+  CalHashTable_t * hashTable)
+{
+  CalBddNode_t *ptr, *next, *node;
+  int i;
+  if(hashTable == Cal_Nil(CalHashTable_t))return;
+  for(i = 0; i < hashTable->numBins; i++){
+    ptr = hashTable->bins[i];
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      next = CalBddNodeGetNextBddNode(ptr);
+      node = CalBddNodeGetElseBddNode(ptr);
+      CalNodeManagerFreeNode(hashTable->nodeManager, node);
+      CalNodeManagerFreeNode(hashTable->nodeManager, ptr);
+      ptr = next;
+    }
+  }
+  Cal_MemFree(hashTable->bins);
+  Cal_MemFree(hashTable);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Directly insert a BDD node in the hash table.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableOneInsert(CalHashTable_t * hashTable, Cal_Bdd_t  keyBdd,
+                      char * valuePtr)
+{
+  int hashValue;
+  CalBddNode_t *bddNode, *dataPtr;
+
+  hashValue = HashTableOneDoHash(hashTable, keyBdd);
+  hashTable->numEntries++;
+  if(hashTable->numEntries >= hashTable->maxCapacity){
+    HashTableOneRehash(hashTable, 1);
+    hashValue = HashTableOneDoHash(hashTable, keyBdd);
+  }
+  CalNodeManagerAllocNode(hashTable->nodeManager, dataPtr);
+  memcpy(dataPtr, valuePtr, (size_t)hashTable->bddId);
+  CalNodeManagerAllocNode(hashTable->nodeManager, bddNode);
+  CalBddNodePutThenBdd(bddNode, keyBdd);
+  CalBddNodePutElseBddNode(bddNode, dataPtr);
+  CalBddNodePutNextBddNode(bddNode, hashTable->bins[hashValue]);
+  hashTable->bins[hashValue] = bddNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalHashTableOneLookup(CalHashTable_t * hashTable, Cal_Bdd_t  keyBdd,
+                      char ** valuePtrPtr)
+{
+  CalBddNode_t *ptr;
+  Cal_Bdd_t tmpBdd;
+  int hashValue;
+  
+  hashValue = HashTableOneDoHash(hashTable, keyBdd);
+  ptr = hashTable->bins[hashValue];
+  while(ptr != Cal_Nil(CalBddNode_t)){
+    CalBddNodeGetThenBdd(ptr, tmpBdd);
+    if(CalBddIsEqual(keyBdd, tmpBdd)){
+      if(valuePtrPtr){
+        *valuePtrPtr = (char *)CalBddNodeGetElseBddNode(ptr);
+      }
+      return 1;
+    }
+    ptr = CalBddNodeGetNextBddNode(ptr);
+  }
+  if(valuePtrPtr){
+    *valuePtrPtr = Cal_Nil(char);
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+HashTableOneRehash(
+  CalHashTable_t * hashTable,
+  int  grow)
+{
+  CalBddNode_t *ptr, *next;
+  CalBddNode_t **oldBins = hashTable->bins;
+  int i, hashValue;
+  int oldNumBins = hashTable->numBins;
+  Cal_Bdd_t keyBdd;
+
+  if(grow){
+    hashTable->sizeIndex++;
+  }
+  else{
+    if (hashTable->sizeIndex <= HASH_TABLE_DEFAULT_SIZE_INDEX){/* No need to rehash */
+      return;
+    }
+    hashTable->sizeIndex--;
+  }
+
+  hashTable->numBins = TABLE_SIZE(hashTable->sizeIndex);
+  hashTable->maxCapacity = hashTable->numBins * HASH_TABLE_DEFAULT_MAX_DENSITY;
+  hashTable->bins = Cal_MemAlloc(CalBddNode_t *, hashTable->numBins);
+  if(hashTable->bins == Cal_Nil(CalBddNode_t *)){
+    CalBddFatalMessage("out of memory");
+  }
+  for(i = 0; i < hashTable->numBins; i++){
+    hashTable->bins[i] = Cal_Nil(CalBddNode_t);
+  }
+
+  for(i = 0; i < oldNumBins; i++){
+    ptr = oldBins[i];
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      next = CalBddNodeGetNextBddNode(ptr);
+      CalBddNodeGetThenBdd(ptr, keyBdd);
+      hashValue = HashTableOneDoHash(hashTable, keyBdd);
+      CalBddNodePutNextBddNode(ptr, hashTable->bins[hashValue]);
+      hashTable->bins[hashValue] = ptr;
+      ptr = next;
+    }
+  }
+  Cal_MemFree(oldBins);
+}
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calHashTableThree.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calHashTableThree.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calHashTableThree.c	(revision 8)
@@ -0,0 +1,221 @@
+/**CFile***********************************************************************
+
+  FileName    [calHashTableThree.c]
+
+  PackageName [cal]
+
+  Synopsis    [Functions to manage the hash tables that are a part of
+                  ITE operation]
+
+  Description [CalHashTableThreeFindOrAdd]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+                Rajeev Ranjan   (rajeev@eecs.berkeley.edu)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calHashTableThree.c,v 1.1.1.3 1998/05/04 00:58:58 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#ifdef USE_POWER_OF_2
+#define CalDoHash3(fBddNode, gBddNode, hBddNode,table) \
+((((CalAddress_t)fBddNode + \
+   (CalAddress_t)gBddNode + \
+   (CalAddress_t) hBddNode) \
+  / NODE_SIZE) & ((table)->numBins-1))
+#else
+#define CalDoHash3(fBddNode, gBddNode, hBddNode,table) \
+  ((((CalAddress_t)fBddNode + \
+  (CalAddress_t)gBddNode + \
+  (CalAddress_t) hBddNode) \
+  / NODE_SIZE)% table->numBins)
+#endif
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CalHashTableThreeRehash(CalHashTable_t *hashTable, int grow);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalHashTableThreeFindOrAdd(CalHashTable_t * hashTable,
+                           Cal_Bdd_t  f,
+                           Cal_Bdd_t  g,
+                           Cal_Bdd_t  h,
+                           Cal_Bdd_t * bddPtr)
+{
+  CalBddNode_t *ptr, *ptrIndirect;
+  Cal_Bdd_t tmpBdd;
+  int hashValue;
+  
+  hashValue = CalDoHash3(CalBddGetBddNode(f), 
+      CalBddGetBddNode(g), CalBddGetBddNode(h), hashTable);
+  ptr = hashTable->bins[hashValue];
+  while(ptr != Cal_Nil(CalBddNode_t)){
+    CalBddNodeGetThenBdd(ptr, tmpBdd);
+    if(CalBddIsEqual(f, tmpBdd)){
+      ptrIndirect = CalBddNodeGetElseBddNode(ptr);
+      CalBddNodeGetThenBdd(ptrIndirect, tmpBdd);
+      if(CalBddIsEqual(g, tmpBdd)){
+        CalBddNodeGetElseBdd(ptrIndirect, tmpBdd);
+        if(CalBddIsEqual(h, tmpBdd)){
+          CalBddPutBddId(*bddPtr, hashTable->bddId);
+          CalBddPutBddNode(*bddPtr, ptr);
+          return 1;
+        }
+      }
+    }
+    ptr = CalBddNodeGetNextBddNode(ptr);
+  }
+  hashTable->numEntries++;
+  if(hashTable->numEntries > hashTable->maxCapacity){
+    CalHashTableThreeRehash(hashTable,1);
+    hashValue = CalDoHash3(CalBddGetBddNode(f),
+        CalBddGetBddNode(g), CalBddGetBddNode(h), hashTable);
+  }
+  CalNodeManagerAllocNode(hashTable->nodeManager, ptr);
+  CalNodeManagerAllocNode(hashTable->nodeManager, ptrIndirect);
+  CalBddNodePutThenBdd(ptr, f);
+  CalBddNodePutThenBdd(ptrIndirect, g);
+  CalBddNodePutElseBdd(ptrIndirect, h);
+  CalBddNodePutElseBddNode(ptr, ptrIndirect);
+  CalBddNodePutNextBddNode(ptr, hashTable->bins[hashValue]);
+  hashTable->bins[hashValue] = ptr;
+  CalBddPutBddId(*bddPtr, hashTable->bddId);
+  CalBddPutBddNode(*bddPtr, ptr);
+  return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalHashTableThreeRehash(CalHashTable_t *hashTable, int grow)
+{
+  CalBddNode_t *ptr, *ptrIndirect, *next;
+  CalBddNode_t **oldBins = hashTable->bins;
+  int i, hashValue;
+  int oldNumBins = hashTable->numBins;
+
+  if(grow){
+    hashTable->sizeIndex++;
+  }
+  else{
+    if (hashTable->sizeIndex <= HASH_TABLE_DEFAULT_SIZE_INDEX){/* No need to rehash */
+      return;
+    }
+    hashTable->sizeIndex--;
+  }
+
+  hashTable->numBins = TABLE_SIZE(hashTable->sizeIndex);
+  hashTable->numBins = hashTable->numBins;
+  hashTable->maxCapacity = hashTable->numBins * HASH_TABLE_DEFAULT_MAX_DENSITY;
+  hashTable->bins = Cal_MemAlloc(CalBddNode_t *, hashTable->numBins);
+  if(hashTable->bins == Cal_Nil(CalBddNode_t *)){
+    CalBddFatalMessage("out of memory");
+  }
+  for(i = 0; i < hashTable->numBins; i++){
+    hashTable->bins[i] = Cal_Nil(CalBddNode_t);
+  }
+
+  for(i = 0; i < oldNumBins; i++){
+    ptr = oldBins[i];
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      next = CalBddNodeGetNextBddNode(ptr);
+      ptrIndirect = CalBddNodeGetElseBddNode(ptr);
+      hashValue = CalDoHash3(CalBddNodeGetThenBddNode(ptr),
+          CalBddNodeGetThenBddNode(ptrIndirect),
+          CalBddNodeGetElseBddNode(ptrIndirect), hashTable);
+      CalBddNodePutNextBddNode(ptr, hashTable->bins[hashValue]);
+      hashTable->bins[hashValue] = ptr;
+      ptr = next;
+    }
+  }
+  Cal_MemFree(oldBins);
+}
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calInt.h
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calInt.h	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calInt.h	(revision 8)
@@ -0,0 +1,1578 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [calInt.h]
+
+  PackageName [cal]
+
+  Synopsis    [The internal data structures, macros and function declarations]
+
+  Description []
+
+  SeeAlso     [cal.h]
+
+  Author      [Rajeev K. Ranjan (rajeev@ic.eecs.berkeley.edu
+               Jagesh Sanghavi  (sanghavi@ic.eecs.berkeley.edu)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calInt.h,v 1.11 2002/09/14 20:19:58 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CALINT
+#define _CALINT
+
+#include "cal.h"
+
+/* Make sure variable argument lists work */
+#if HAVE_STDARG_H
+#  include <stdarg.h>
+#else
+#  if HAVE_VARARGS_H
+#    include <varargs.h>
+#  else
+#    error "Need to have HAVE_STDARG_H or HAVE_VARARGS_H defined for variable arguments"
+#  endif
+#endif
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* Begin Performance Related Constants */
+
+/* Garbage collection and reordering related constants */
+/* The following constants could significantly affect the
+   performance of the package */ 
+
+
+#define CAL_MIN_GC_LIMIT 10000 /* minimum number of nodes in the unique table
+                                  before performing garbage collection. It can
+                                  be overridden by user define node limit */
+
+
+
+
+#define CAL_REPACK_AFTER_GC_THRESHOLD 0.75 /* If the number of nodes fall below
+                                           this factor after garbage
+                                           collection, repacking should be
+                                           done */ 
+/* A note about repacking after garbage collection: Since repacking
+** moves the node pointers, it is important that "user" does not have
+** access to internal node pointers during such times. If for some
+** purposes the node handle is needed and also there is a possibility of
+** garbage collection being invoked, this field (repackAfterGCThreshold) of
+** the bdd manager should be set to 0.
+*/
+
+#define CAL_TABLE_REPACK_THRESHOLD 0.9 /* If the page utility of a unique
+                                            table (for some id) goes below this, repacking
+                                            would be done */ 
+
+#define CAL_BDD_REORDER_THRESHOLD 10000 /* Don't perform reordering below these
+                                           many nodes */
+
+#define CAL_NUM_PAGES_THRESHOLD 3
+
+#define CAL_NUM_FORWARDED_NODES_LIMIT 50000 /* maximum number of forwarded nodes 
+                                               allowed during BF reordering */
+
+#define CAL_GC_CHECK 100       /* garbage collection check performed after
+                                  addition of every GC_CHECK number of nodes to
+                                  the unique table */
+
+/* End Performance Related Constants */
+
+/* Memory Management related constants */
+#define NODE_SIZE sizeof(CalBddNode_t)		/* sizeof(CalBddNode_t) */
+
+#ifndef PAGE_SIZE
+#  define PAGE_SIZE 4096	/* size of a virtual memory page */
+#endif
+#ifndef LG_PAGE_SIZE
+#  define LG_PAGE_SIZE 12	/* log2 of the page size */
+#endif
+
+#define NUM_NODES_PER_PAGE (PAGE_SIZE/NODE_SIZE)
+
+#define MAX_NUM_SEGMENTS 32 
+#define NUM_PAGES_PER_SEGMENT 64 /* We start with grabbing 64 pages at a time */
+#define MIN_NUM_PAGES_PER_SEGMENT 4
+#define MAX_NUM_PAGES 10
+
+#define MIN_REC_SIZE CAL_ALLOC_ALIGNMENT
+#define MAX_REC_SIZE (sizeof(CalHashTable_t)) /* size of hash table */
+#define NUM_REC_MGRS (((MAX_REC_SIZE-MIN_REC_SIZE)/CAL_ALLOC_ALIGNMENT)+1)
+
+
+
+
+/* true / false */
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+
+
+/* Error Codes */
+#define CAL_BDD_OK 0
+#define CAL_BDD_OVERFLOWED 1
+
+/* bdd variable id and index related constants */
+#define CAL_BDD_NULL_ID ((unsigned short) ((1 << 8*sizeof(unsigned short)) - 1))
+#define CAL_BDD_CONST_ID 0
+#define CAL_MAX_VAR_ID ((unsigned short) (CAL_BDD_NULL_ID - 1))
+#define CAL_BDD_NULL_INDEX (unsigned short) ((1 << 8*sizeof(unsigned short)) - 1)
+#define CAL_BDD_CONST_INDEX CAL_BDD_NULL_INDEX
+#define CAL_MAX_VAR_INDEX (CAL_BDD_NULL_INDEX - 1)
+#define CAL_MAX_REF_COUNT (unsigned short)((1 << 8*sizeof(char)) - 1)
+#define CAL_INFINITY (1 << 20)
+
+/* Pipeline related constants */
+#define MAX_INSERT_DEPTH 256
+#define PIPELINE_EXECUTION_DEPTH 1
+#define DEFAULT_DEPTH 4
+#define DEFAULT_MAX_DEPTH 6
+
+
+#define FORWARD_FLAG 0     /* Flag used to identify redundant nodes */
+
+
+/* Hash table management related constants. */
+#define HASH_TABLE_DEFAULT_MAX_DENSITY 5
+#define HASH_TABLE_DEFAULT_SIZE_INDEX 8
+#define HASH_TABLE_DEFAULT_NUM_BINS TABLE_SIZE(HASH_TABLE_DEFAULT_SIZE_INDEX)
+#define HASH_TABLE_DEFAULT_MAX_CAPACITY HASH_TABLE_DEFAULT_NUM_BINS*HASH_TABLE_DEFAULT_MAX_DENSITY
+extern unsigned long calPrimes[];
+
+#define USE_POWER_OF_2
+#ifdef  USE_POWER_OF_2
+#define TABLE_SIZE(sizeIndex) (1<<sizeIndex)
+#else
+#define TABLE_SIZE(sizeIndex) (calPrimes[sizeIndex])
+#endif
+
+
+/* Codes to be used in cache table */
+#define  CAL_OP_INVALID 0x0000
+#define  CAL_OP_OR 0x1000
+#define  CAL_OP_AND 0x2000
+#define  CAL_OP_NAND 0x3000
+#define  CAL_OP_QUANT 0x4000
+#define  CAL_OP_REL_PROD 0x5000
+#define  CAL_OP_COMPOSE 0x6000
+#define  CAL_OP_SUBST 0x7000
+#define  CAL_OP_VAR_SUBSTITUTE 0x8000
+
+#define  CAL_LARGE_BDD (1<<19) /* For smaller BDDs, we would
+                                  use depth-first exist and forall routines */
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct Cal_BddStruct Cal_Bdd_t;
+typedef struct CalBddNodeStruct CalBddNode_t;
+typedef unsigned short Cal_BddRefCount_t;
+typedef struct CalPageManagerStruct CalPageManager_t;
+typedef struct CalNodeManagerStruct CalNodeManager_t;
+typedef struct CalListStruct CalList_t;
+typedef struct CalHashTableStruct CalHashTable_t;
+typedef struct CalHashTableStruct *CalReqQueForId_t;
+typedef struct CalHashTableStruct CalReqQueForIdAtDepth_t;
+typedef struct CalAssociationStruct CalAssociation_t;
+typedef struct CalBddNodeStruct CalRequestNode_t;
+typedef struct Cal_BddStruct CalRequest_t;
+typedef struct CalCacheTableStruct CalCacheTable_t;
+typedef int (*CalBddNodeToIndexFn_t)(CalBddNode_t*, Cal_BddId_t);
+typedef unsigned long CalAddress_t;
+typedef struct Cal_BlockStruct Cal_Block_t;
+
+struct Cal_BddStruct {
+  Cal_BddId_t bddId;      /* variable id */
+  CalBddNode_t *bddNode;  /* pointer to the bdd node */
+};
+
+typedef int (*CalOpProc_t) (Cal_BddManager, Cal_Bdd_t, Cal_Bdd_t, Cal_Bdd_t *); 
+typedef int (*CalOpProc1_t) (Cal_BddManager, Cal_Bdd_t, Cal_Bdd_t *); 
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+enum CalPipeStateEnum { READY, CREATE, UPDATE };
+typedef enum CalPipeStateEnum CalPipeState_t;
+
+struct CalNodeManagerStruct{
+  CalPageManager_t *pageManager;
+  CalBddNode_t *freeNodeList;
+  int numPages;
+  int maxNumPages;
+  CalAddress_t **pageList;
+};
+
+struct CalPageManagerStruct {
+  CalAddress_t *freePageList;
+  CalAddress_t **pageSegmentArray; /* Array of pointers to segments */
+  int *numPagesArray; /* Number of pages in each segment */
+  int numSegments;
+  int totalNumPages; /* Total number of pages = sum of elements of numPagesArray */
+  int numPagesPerSegment;
+  int maxNumSegments;
+};
+
+struct CalBddNodeStruct {
+  CalBddNode_t *nextBddNode; /* Attn: CalPageManagerFreePage overwrites this field of the node. Hence need to be aware of the consequences if the order of the fields is changed */
+
+  CalBddNode_t *thenBddNode;
+  CalBddNode_t *elseBddNode;
+  Cal_BddId_t thenBddId;
+  Cal_BddId_t elseBddId;
+};
+
+struct CalHashTableStruct {
+  int sizeIndex;
+  long numBins;
+  long maxCapacity;
+  CalBddNode_t **bins;
+  Cal_BddId_t bddId;
+  CalNodeManager_t *nodeManager;
+  CalBddNode_t *requestNodeList;
+ /* The following two fields are added to improve the performance of hash table clean up.*/
+  CalBddNode_t startNode;
+  CalBddNode_t *endNode;
+  long numEntries;
+};
+
+struct CalAssociationStruct {
+  Cal_Bdd_t *varAssociation;
+  int lastBddIndex;
+  int id;
+  int refCount;
+  CalAssociation_t *next;
+};
+
+struct Cal_BlockStruct
+{
+  long numChildren;
+  Cal_Block_t **children;
+  int reorderable;
+  long firstIndex;
+  long lastIndex;
+};
+
+/* Cal_BddManager_t - manages the BDD nodes */
+struct Cal_BddManagerStruct {
+
+  int numVars; /*
+                * Number of BDD variables present in the manager. This does
+                * not include the constant. The maximum number of variables 
+                * manager can have is CAL_MAX_VAR_ID (as opposed to
+                CAL_MAX_VAR_ID+1, id "0" being used for constant).
+                * CAL_MAX_VAR_ID = (((1 << 16) - 1) -1 )
+                */
+  int maxNumVars; /* Maximum number of variables which can be created without
+                     reallocating memory */
+
+  Cal_Bdd_t *varBdds; /* Array of Cal_Bdd_t's. Cal_Bdd_t[i] is the BDD
+                         corresponding to variable with id "i". */
+  
+  /* memory management */
+  CalPageManager_t *pageManager1;  /* manages memory pages */
+  CalPageManager_t *pageManager2;  /* manages memory pages */
+  CalNodeManager_t **nodeManagerArray; /*
+                                        * nodeManagerArray[i] is the node
+                                        * manager for the variable with id = i.
+                                        */     
+  /* special nodes */
+  Cal_Bdd_t bddOne; /* Constant: Id = 0; Index = CAL_MAX_INDEX */
+  Cal_Bdd_t bddZero;
+  Cal_Bdd_t bddNull;
+  CalBddNode_t *userOneBdd;
+  CalBddNode_t *userZeroBdd;
+
+  Cal_BddId_t *indexToId; /*
+                           * Table mapping index to id. If there are n
+                           * variables, then this table has n entries from
+                           * 0 to n-1 (indexToId[0] through indexToId[n-1]).
+                           */
+  Cal_BddIndex_t *idToIndex; /*
+                              * Table mapping id to index:
+                              * idToIndex[0] = CAL_MAX_INDEX
+                              * If there are n variables in the manager, then
+                              * corresponding to these variables this table
+                              * has entries from 1 to n (idToIndex[1] through
+                              * idToIndex[n]).
+                              */
+  
+  CalHashTable_t **uniqueTable; /* uniqueTable[i] is the unique table for the
+                                 * variable id " i". Unique table for an id is
+                                 * a hash table of the nodes with that
+                                 * variable id.
+                                 */
+  CalCacheTable_t *cacheTable; /* Computed table */
+
+  /* Special functions */
+  void (*TransformFn) (Cal_BddManager_t*, CalAddress_t, CalAddress_t,
+       CalAddress_t*, CalAddress_t*, Cal_Pointer_t);
+  Cal_Pointer_t transformEnv;
+
+  /* logic operation management */
+  CalHashTable_t ***reqQue;     /* reqQue[depth][id] is the hash table of
+                                 * requests corresponding to variable id "id"
+                                 * and the request depth "depth".
+                                 */
+                               
+  /* Pipeline related information */
+  int depth;
+  int maxDepth;
+  CalPipeState_t pipelineState;
+  CalOpProc_t pipelineFn;
+  int pipelineDepth;
+  int currentPipelineDepth;
+  CalRequestNode_t **requestNodeArray;/* Used for pipelined operations. */
+  CalRequestNode_t *userProvisionalNodeList;   /* List of user BDD nodes
+                                                  pointing to provisional
+                                                  BDDs */
+  CalRequestNode_t **requestNodeListArray;
+  
+
+  /* garbage collection related information */
+  unsigned long numNodes;
+  unsigned long numPeakNodes;
+  unsigned long numNodesFreed;
+  int gcCheck;
+  unsigned long uniqueTableGCLimit;
+  int  numGC;
+  int gcMode;
+  unsigned long nodeLimit;
+  int overflow;
+  float repackAfterGCThreshold;
+  
+
+  /* Association related stuff */
+  CalAssociation_t *currentAssociation;
+  CalAssociation_t *associationList;
+  CalAssociation_t *tempAssociation;
+  unsigned short tempOpCode; /* To store the id of temporary associations. */
+  
+  /* Variable reordering related stuff */
+  long *interact; /* Interaction matrix */
+  int dynamicReorderingEnableFlag;
+  int reorderMethod;
+  int reorderTechnique;
+  long numForwardedNodes;
+  int numReorderings;
+  long maxNumVarsSiftedPerReordering;
+  long numSwaps;
+  long numTrivialSwaps;
+  long maxNumSwapsPerReordering;
+  double maxSiftingGrowth;
+  long reorderingThreshold;
+  long maxForwardedNodes;
+  float tableRepackThreshold;
+  Cal_Block superBlock; /* Variable blocks */
+
+
+  void *hooks;
+  int debugFlag;
+
+  
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#ifdef COMPUTE_MEMORY_OVERHEAD
+long calNumEntriesAfterReduce, calNumEntriesAfterApply;
+double calAfterReduceToAfterApplyNodesRatio, calAfterReduceToUniqueTableNodesRatio;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/ 
+
+
+#define CalNodeManagerAllocNode(nodeManager, node)                          \
+{                                                                           \
+  if((nodeManager)->freeNodeList != Cal_Nil(CalBddNode_t)){                 \
+    node = nodeManager->freeNodeList;                                       \
+    nodeManager->freeNodeList = ((CalBddNode_t *)(node))->nextBddNode;      \
+    Cal_Assert(!((CalAddress_t)nodeManager->freeNodeList & 0xf));\
+  }                                                                         \
+  else{                                                                     \
+    CalBddNode_t *_freeNodeList, *_nextNode, *_node;                        \
+    _freeNodeList =                                                         \
+        (CalBddNode_t *)CalPageManagerAllocPage(nodeManager->pageManager);  \
+    for(_node = _freeNodeList + NUM_NODES_PER_PAGE - 1, _nextNode =0;       \
+        _node != _freeNodeList; _nextNode = _node--){                       \
+      _node->nextBddNode = _nextNode;                                       \
+    }                                                                       \
+    nodeManager->freeNodeList = _freeNodeList + 1;                          \
+    node = _node;                                                           \
+    if ((nodeManager)->numPages == (nodeManager)->maxNumPages){             \
+      (nodeManager)->maxNumPages *= 2;                                      \
+      (nodeManager)->pageList =                                            \
+          Cal_MemRealloc(CalAddress_t *, (nodeManager)->pageList,          \
+                         (nodeManager)->maxNumPages);                       \
+    }                                                                       \
+    (nodeManager)->pageList[(nodeManager)->numPages++] = (CalAddress_t *)_freeNodeList;    \
+  }                                                                         \
+  ((CalBddNode_t *)(node))->nextBddNode = 0;                                \
+  ((CalBddNode_t *)(node))->thenBddId = 0;                                  \
+  ((CalBddNode_t *)(node))->elseBddId = 0;                                  \
+  ((CalBddNode_t *)(node))->thenBddNode = 0;                                \
+  ((CalBddNode_t *)(node))->elseBddNode = 0;                                \
+}
+
+#define CalNodeManagerFreeNode(nodeManager, node) \
+{ \
+  (node)->nextBddNode = (nodeManager)->freeNodeList; \
+  (nodeManager)->freeNodeList = node; \
+}
+#define CalNodeManagerInitBddNode(nodeManager, thenBdd, elseBdd, next, node) \
+{ \
+  if((nodeManager)->freeNodeList != Cal_Nil(CalBddNode_t)){ \
+    node = nodeManager->freeNodeList; \
+    nodeManager->freeNodeList = ((CalBddNode_t *)(node))->nextBddNode; \
+    Cal_Assert(!((CalAddress_t)nodeManager->freeNodeList & 0xf));\
+  } \
+  else{ \
+    CalBddNode_t *_freeNodeList, *_nextNode, *_node; \
+    _freeNodeList = \
+        (CalBddNode_t *)CalPageManagerAllocPage(nodeManager->pageManager); \
+    for(_node = _freeNodeList + NUM_NODES_PER_PAGE - 1, _nextNode =0; \
+        _node != _freeNodeList; _nextNode = _node--){ \
+      _node->nextBddNode = _nextNode; \
+    } \
+    nodeManager->freeNodeList = _freeNodeList + 1; \
+    node = _node; \
+    if ((nodeManager)->numPages == (nodeManager)->maxNumPages){             \
+      (nodeManager)->maxNumPages *= 2;                                      \
+      (nodeManager)->pageList =                                            \
+          Cal_MemRealloc(CalAddress_t *, (nodeManager)->pageList,          \
+                         (nodeManager)->maxNumPages);                       \
+    }                                                                       \
+    (nodeManager)->pageList[(nodeManager)->numPages++] = (CalAddress_t *)_freeNodeList;    \
+  } \
+  ((CalBddNode_t *)(node))->nextBddNode = next; \
+  ((CalBddNode_t *)(node))->thenBddId = CalBddGetBddId(thenBdd); \
+  ((CalBddNode_t *)(node))->elseBddId = CalBddGetBddId(elseBdd); \
+  ((CalBddNode_t *)(node))->thenBddNode = CalBddGetBddNode(thenBdd); \
+  ((CalBddNode_t *)(node))->elseBddNode = CalBddGetBddNode(elseBdd); \
+}
+
+#define CalNodeManagerCreateAndDupBddNode(nodeManager, node, dupNode)\
+{ \
+  if((nodeManager)->freeNodeList != Cal_Nil(CalBddNode_t)){ \
+    dupNode = nodeManager->freeNodeList; \
+    nodeManager->freeNodeList = ((CalBddNode_t *)(dupNode))->nextBddNode; \
+  } \
+  else{ \
+    CalBddNode_t *_freeNodeList, *_nextNode, *_node; \
+    _freeNodeList = \
+        (CalBddNode_t *)CalPageManagerAllocPage(nodeManager->pageManager); \
+    for(_node = _freeNodeList + NUM_NODES_PER_PAGE - 1, _nextNode =0; \
+        _node != _freeNodeList; _nextNode = _node--){ \
+      _node->nextBddNode = _nextNode; \
+    } \
+    nodeManager->freeNodeList = _freeNodeList + 1; \
+    dupNode = _node; \
+    if ((nodeManager)->numPages == (nodeManager)->maxNumPages){             \
+      (nodeManager)->maxNumPages *= 2;                                      \
+      (nodeManager)->pageList =                                            \
+          Cal_MemRealloc(CalAddress_t *, (nodeManager)->pageList,          \
+                         (nodeManager)->maxNumPages);                       \
+    }                                                                       \
+    (nodeManager)->pageList[(nodeManager)->numPages++] = (CalAddress_t *)_freeNodeList;    \
+  } \
+  ((CalBddNode_t *)(dupNode))->nextBddNode = (node)->nextBddNode; \
+  ((CalBddNode_t *)(dupNode))->thenBddId = (node)->thenBddId;\
+  ((CalBddNode_t *)(dupNode))->elseBddId = (node)->elseBddId;\
+  ((CalBddNode_t *)(dupNode))->thenBddNode = (node)->thenBddNode;\
+  ((CalBddNode_t *)(dupNode))->elseBddNode = (node)->elseBddNode; \
+}
+
+/* Record manager size range stuff */
+
+#define CAL_BDD_NEW_REC(bddManager, type) ((type *)Cal_MemNewRec((bddManager)->recordMgrArray[(CAL_ROUNDUP(sizeof(type))-MIN_REC_SIZE)/CAL_ALLOC_ALIGNMENT]))
+#define CAL_BDD_FREE_REC(bddManager, rec, type) Cal_MemFreeRec((bddManager)->recordMgrArray[(CAL_ROUNDUP(sizeof(type))-MIN_REC_SIZE)/CAL_ALLOC_ALIGNMENT], (rec))
+
+/*
+** We would like to do repacking if :
+** i) The id has more than minimum number of pages.
+** ii) The ratio between the actual number of entries and the capacity is
+**     less than a threshold.
+*/
+#define CalBddIdNeedsRepacking(bddManager, id)                              \
+((bddManager->nodeManagerArray[id]->numPages > CAL_NUM_PAGES_THRESHOLD) && (bddManager->uniqueTable[id]->numEntries < bddManager->tableRepackThreshold *  \
+  bddManager->nodeManagerArray[id]->numPages * NUM_NODES_PER_PAGE))
+
+
+/*
+ * Macros for managing Cal_Bdd_t and CalBddNode_t.
+ * INTERNAL FUNCTIONS SHOULD NOT TOUCH THE INTERNAL FIELDS
+ * FUNCTIONS IN calTerminal.c ARE EXCEPTION TO THIS GENERAL RULE
+ *
+ * {CalBdd} X {Get, Put} X {ThenBddId, ElseBddId, ThenBddNode, ElseBddNode,
+ *     ThenBdd, ElseBdd, BddId, BddNode, NextBddNode}
+ * {CalBdd} X {Get, Put, Icr, Dcr, Add} X {RefCount}
+ * {CalBdd,CalBddNode} X {Get} X {BddIndex}
+ * {CalBdd} X {Is} X {RefCountZero, OutPos, BddOne, BddZero, BddNull, BddConst} 
+ * {CalBddManager} X {Get} X {BddZero, BddOne, BddNull}
+ * {CalBddNode} X {Get, Put} X {ThenBddId, ElseBddId, ThenBddNode, ElseBddNode,
+ *     ThenBdd, ElseBdd, NextBddNode}
+ * {CalBddNode} X {Get, Put, Icr, Dcr, Add} X {RefCount}
+ * {CalBddNode} X {Is} X {RefCountZero, OutPos}
+ * {CalBddEqual, CalBddNodeEqual}
+ *
+ * {CalRequest} X {Get, Put} X {ThenRequestId, ElseRequestId, ThenRequestNode,
+ *     ElseRequestNode, ThenRequest, ElseRequest, RequestId, RequestNode,
+ *     F, G, Next}
+ * {CalRequest} X {Is} X {Null}
+ * {CalRequestNode} X {Get, Put} X {ThenRequestId, ElseRequestId,
+ *     ThenRequestNode, ElseRequestNode, ThenRequest, ElseRequest, F, G, Next}
+ */
+
+#define CAL_BDD_POINTER(f) ((CalBddNode_t *)(((CalAddress_t)f) & \
+    ~(CalAddress_t)0xf))
+#define CAL_TAG0(pointer) ((CalAddress_t)((CalAddress_t)(pointer) & 0x1))
+#define CalBddIsComplement(calBdd) ((int)CAL_TAG0((calBdd).bddNode))
+#define CalBddUpdatePhase(calBdd, complement) \
+    ((calBdd).bddNode = \
+    (CalBddNode_t *)((CalAddress_t)((calBdd).bddNode) ^ complement))
+
+#define CalBddZero(bddManager) ((bddManager)->bddZero)
+#define CalBddOne(bddManager) ((bddManager)->bddOne)
+#define CalBddNull(bddManager) ((bddManager)->bddNull)
+#define CalBddIsBddConst(calBdd) ((calBdd).bddId == 0)
+/* We are cheating here. Ideally we should compare both the id as well as the bdd node */
+#define CalBddIsEqual(calBdd1, calBdd2)\
+    (((calBdd1).bddNode == (calBdd2).bddNode))
+#define CalBddIsComplementEqual(calBdd1, calBdd2) \
+    (((calBdd1).bddNode == \
+    (CalBddNode_t *)(((CalAddress_t)(calBdd2).bddNode) ^ 0x1)))
+#define CalBddSameOrNegation(calBdd1, calBdd2)	\
+    (CAL_BDD_POINTER((calBdd1).bddNode) == CAL_BDD_POINTER((calBdd2).bddNode))
+
+/* CAUTION: MACRO ASSUMES THAT THE INDEX CORRESPONDING TO varId IS LESS THAN OR
+ * EQUAL TO THE INDEX OF calBdd */
+#define CalBddGetCofactors(calBdd, varId, fx, fxbar) \
+{ \
+    if(varId == (calBdd).bddId){ \
+      CalBddGetThenBdd(calBdd, fx); \
+      CalBddGetElseBdd(calBdd, fxbar); \
+    } \
+    else{ \
+      fx = calBdd; \
+      fxbar = calBdd; \
+    } \
+}
+
+#define CalBddGetThenBddId(calBdd) CAL_BDD_POINTER((calBdd).bddNode)->thenBddId
+#define CalBddGetElseBddId(calBdd) CAL_BDD_POINTER((calBdd).bddNode)->elseBddId
+#define CalBddGetThenBddIndex(bddManager, calBdd) \
+    (bddManager->idToIndex[CAL_BDD_POINTER((calBdd).bddNode)->thenBddId])
+#define CalBddGetElseBddIndex(bddManager, calBdd) \
+    (bddManager->idToIndex[CAL_BDD_POINTER((calBdd).bddNode)->elseBddId])
+
+#define CalBddGetThenBddNode(calBdd) \
+    ((CalBddNode_t*) \
+    (((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->thenBddNode) \
+    & ~0xe) ^ (CAL_TAG0((calBdd).bddNode))))
+
+#define CalBddGetElseBddNode(calBdd) \
+    ((CalBddNode_t*) \
+    (((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->elseBddNode) \
+    & ~0xe) ^ (CAL_TAG0((calBdd).bddNode))))
+ 
+#define CalBddGetThenBdd(calBdd, _thenBdd) \
+{ \
+  CalBddNode_t *_bddNode, *_bddNodeTagged; \
+  _bddNodeTagged = (calBdd).bddNode; \
+  _bddNode = CAL_BDD_POINTER(_bddNodeTagged); \
+  (_thenBdd).bddId = _bddNode->thenBddId; \
+  (_thenBdd).bddNode = (CalBddNode_t*) (((CalAddress_t) (_bddNode->thenBddNode) \
+      & ~0xe)^(CAL_TAG0(_bddNodeTagged))); \
+}
+
+#define CalBddGetElseBdd(calBdd, _elseBdd) \
+{ \
+  CalBddNode_t *_bddNode, *_bddNodeTagged; \
+  _bddNodeTagged = (calBdd).bddNode; \
+  _bddNode = CAL_BDD_POINTER(_bddNodeTagged); \
+  (_elseBdd).bddId = _bddNode->elseBddId; \
+  (_elseBdd).bddNode = (CalBddNode_t*) (((CalAddress_t) (_bddNode->elseBddNode) \
+        & ~0xe)^(CAL_TAG0(_bddNodeTagged)));\
+}
+
+
+#define CalBddGetBddId(calBdd) ((calBdd).bddId)
+#define CalBddGetBddIndex(bddManager, calBdd) \
+    (bddManager->idToIndex[(calBdd).bddId])
+#define CalBddGetBddNode(calBdd) ((calBdd).bddNode)
+#define CalBddGetBddNodeNot(calBdd) \
+    ((CalBddNode_t*)(((CalAddress_t)((calBdd).bddNode))^0x1))
+
+#define CalBddGetNextBddNode(calBdd) \
+    ((CalBddNode_t *)(((CalAddress_t) \
+    (CAL_BDD_POINTER((calBdd).bddNode)->nextBddNode)) & ~0xf))
+
+#define CalBddPutThenBddId(calBdd, _thenBddId) \
+    (CAL_BDD_POINTER((calBdd).bddNode)->thenBddId = _thenBddId)
+#define CalBddPutElseBddId(calBdd, _elseBddId) \
+    (CAL_BDD_POINTER((calBdd).bddNode)->elseBddId = _elseBddId)
+
+#define CalBddPutThenBddNode(calBdd, _thenBddNode) \
+{ \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  _bddNode->thenBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)(_bddNode->thenBddNode) & 0xe)| \
+      (((CalAddress_t) _thenBddNode) & ~0xe)); \
+}
+
+#define CalBddPutElseBddNode(calBdd, _elseBddNode) \
+{ \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  _bddNode->elseBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)(_bddNode->elseBddNode) & 0xe)| \
+      (((CalAddress_t) _elseBddNode) & ~0xe));	\
+}
+ 
+#define CalBddPutThenBdd(calBdd, thenBdd) \
+{ \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  _bddNode->thenBddId = (thenBdd).bddId; \
+  _bddNode->thenBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)(_bddNode->thenBddNode) & 0xe)| \
+      (((CalAddress_t)(thenBdd).bddNode) & ~0xe)); \
+}
+
+#define CalBddPutElseBdd(calBdd, elseBdd) \
+{ \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  _bddNode->elseBddId = (elseBdd).bddId; \
+  _bddNode->elseBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)(_bddNode->elseBddNode) & 0xe)| \
+      (((CalAddress_t)(elseBdd).bddNode) & ~0xe)); \
+}
+
+#define CalBddPutBddId(calBdd, _bddId) ((calBdd).bddId = _bddId)
+#define CalBddPutBddNode(calBdd, _bddNode) ((calBdd).bddNode = _bddNode)
+#define CalBddPutNextBddNode(calBdd, _nextBddNode) \
+{ \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  _bddNode->nextBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)(_bddNode->nextBddNode) & 0xf)|  \
+      (((CalAddress_t) _nextBddNode) & ~0xf));	 \
+}
+
+#define CalBddGetRefCount(calBdd, refCount) \
+{ \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  refCount = ((CalAddress_t)(_bddNode->thenBddNode) & 0x2); \
+  refCount <<= 3; \
+  refCount |= ((CalAddress_t)(_bddNode->elseBddNode) & 0xe); \
+  refCount <<= 3; \
+  refCount |= ((CalAddress_t)(_bddNode->nextBddNode) & 0xf); \
+}
+                                        
+#define CalBddPutRefCount(calBdd, count) \
+{ \
+  Cal_BddRefCount_t _nextTag, _thenTag, _elseTag; \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  _nextTag = (count & 0xf); \
+  _thenTag = ((count >> 6) & 0x2); \
+  _elseTag = ((count >> 3) & 0xe); \
+  _bddNode->nextBddNode = (CalBddNode_t*) \
+      ((((CalAddress_t)(_bddNode->nextBddNode)) & ~0xf) | _nextTag); \
+  _bddNode->thenBddNode = (CalBddNode_t*) \
+      ((((CalAddress_t)(_bddNode->thenBddNode)) & ~0x2) | _thenTag); \
+  _bddNode->elseBddNode = (CalBddNode_t*) \
+      ((((CalAddress_t)(_bddNode->elseBddNode)) & ~0xe) | _elseTag); \
+}
+
+#define CalBddIcrRefCount(calBdd) \
+{ CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  if(((CalAddress_t)(_bddNode->nextBddNode) & 0xf) != 0xf){ \
+    _bddNode->nextBddNode = \
+        (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) + 1); \
+  } \
+  else{ \
+    if(((CalAddress_t)(_bddNode->elseBddNode) & 0xe) != 0xe){ \
+      _bddNode->nextBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) & ~0xf); \
+      _bddNode->elseBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) + 0x2); \
+    } \
+    else{ \
+      if(((CalAddress_t)(_bddNode->thenBddNode) & 0x2) == 0){ \
+        _bddNode->nextBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) & ~0xf); \
+        _bddNode->elseBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) & ~0xe); \
+        _bddNode->thenBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->thenBddNode) | 0x2); \
+      } \
+    } \
+  } \
+}
+
+#define CalBddDcrRefCount(calBdd) \
+{ CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER((calBdd).bddNode);	\
+  if(((CalAddress_t)(_bddNode->nextBddNode) & 0xf) == 0x0){ \
+    if(((CalAddress_t)(_bddNode->elseBddNode) & 0xe) == 0x0){ \
+      if(((CalAddress_t)(_bddNode->thenBddNode) & 0x2) == 0x0){ \
+        CalBddWarningMessage("Trying to decrement reference count below zero"); \
+      } \
+      else{ \
+        _bddNode->thenBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->thenBddNode) & ~0x2); \
+        _bddNode->elseBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) | 0xe); \
+        _bddNode->nextBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) | 0xf); \
+      } \
+    } \
+    else{ \
+      _bddNode->elseBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) - 0x2); \
+      _bddNode->nextBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) | 0xf); \
+    } \
+  } \
+  else if(((CalAddress_t)(_bddNode->nextBddNode) & 0xf) != 0xf \
+      ||  ((CalAddress_t)(_bddNode->elseBddNode) & 0xe) != 0xe  \
+      ||  ((CalAddress_t)(_bddNode->thenBddNode) & 0x2) != 0x2){ \
+    _bddNode->nextBddNode = \
+        (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) - 1); \
+  } \
+}
+
+#define CalBddAddRefCount(calBdd, num) \
+{ \
+  Cal_BddRefCount_t _count; \
+  CalBddGetRefCount(calBdd, _count); \
+  if(_count < CAL_MAX_REF_COUNT){ \
+    _count += num; \
+    if(_count > CAL_MAX_REF_COUNT){ \
+      _count = CAL_MAX_REF_COUNT; \
+    } \
+    CalBddPutRefCount(calBdd, _count); \
+  } \
+}
+
+#define CalBddIsRefCountZero(calBdd) \
+    (((((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->thenBddNode)) & 0x2) \
+    || (((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->elseBddNode)) & 0xe)\
+    || (((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->nextBddNode)) & 0xf))\
+    ? 0 : 1)
+
+#define CalBddIsRefCountMax(calBdd) \
+    ((((((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->thenBddNode)) & 0x2) == 0x2) \
+    && ((((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->elseBddNode)) & 0xe) == 0xe)\
+    && ((((CalAddress_t)(CAL_BDD_POINTER((calBdd).bddNode)->nextBddNode)) & 0xf) == 0xf))\
+    ? 1 : 0)
+
+#define CalBddFree(calBdd) CalBddDcrRefCount(calBdd)
+
+#define CalBddIsOutPos(calBdd)  (!(((CalAddress_t)(calBdd).bddNode) & 0x1))
+
+#define CalBddIsBddOne(manager, calBdd) CalBddIsEqual(calBdd, (manager)->bddOne)
+#define CalBddIsBddZero(manager, calBdd) CalBddIsEqual(calBdd, (manager)->bddZero)
+#define CalBddIsBddNull(manager, calBdd) CalBddIsEqual(calBdd,(manager)->bddNull)
+#define CalBddManagerGetBddOne(manager) ((manager)->bddOne)
+#define CalBddManagerGetBddZero(manager) ((manager)->bddZero)
+#define CalBddManagerGetBddNull(manager) (manager)->bddNull
+
+
+
+#define CalBddGetMinId2(bddManager, calBdd1, calBdd2, topId) \
+{ \
+  Cal_BddId_t _id1, _id2; \
+  Cal_BddIndex_t _index1, _index2; \
+  _id1 = CalBddGetBddId((calBdd1)); \
+  _id2 = CalBddGetBddId((calBdd2)); \
+  _index1 = (bddManager)->idToIndex[_id1]; \
+  _index2 = (bddManager)->idToIndex[_id2]; \
+  if (_index1 < _index2) topId = _id1; \
+  else topId = _id2; \
+}
+
+#define CalBddGetMinId3(bddManager, calBdd1, calBdd2, calBdd3, topId) \
+{ \
+  Cal_BddId_t _id1, _id2, _id3; \
+  Cal_BddIndex_t _index1, _index2, _index3; \
+  _id1 = CalBddGetBddId((calBdd1)); \
+  _id2 = CalBddGetBddId((calBdd2)); \
+  _id3 = CalBddGetBddId((calBdd3)); \
+  _index1 = (bddManager)->idToIndex[_id1]; \
+  _index2 = (bddManager)->idToIndex[_id2]; \
+  _index3 = (bddManager)->idToIndex[_id3]; \
+  if(_index1 <= _index2){ \
+    if(_index1 <= _index3){ \
+      topId = _id1; \
+    } \
+    else{ \
+      topId = _id3; \
+    } \
+  } \
+  else{ \
+    if(_index2 <= _index3){ \
+      topId = _id2; \
+    } \
+    else{ \
+      topId = _id3; \
+    } \
+  } \
+}
+
+#define CalBddGetMinIndex2(bddManager, calBdd1, calBdd2, topIndex) \
+{ \
+  Cal_BddIndex_t _index1, _index2; \
+  _index1 = bddManager->idToIndex[CalBddGetBddId(calBdd1)]; \
+  _index2 = bddManager->idToIndex[CalBddGetBddId(calBdd2)]; \
+  if (_index1 < _index2) topIndex = _index1; \
+  else topIndex = _index2; \
+}
+
+#define CalBddGetMinIndex3(bddManager, calBdd1, calBdd2, calBdd3, topIndex) \
+{ \
+  Cal_BddId_t _id1, _id2, _id3; \
+  Cal_BddIndex_t _index1, _index2, _index3; \
+  _id1 = CalBddGetBddId((calBdd1)); \
+  _id2 = CalBddGetBddId((calBdd2)); \
+  _id3 = CalBddGetBddId((calBdd3)); \
+  _index1 = (bddManager)->idToIndex[_id1]; \
+  _index2 = (bddManager)->idToIndex[_id2]; \
+  _index3 = (bddManager)->idToIndex[_id3]; \
+  if(_index1 <= _index2){ \
+    if(_index1 <= _index3){ \
+      topIndex = _index1; \
+    } \
+    else{ \
+      topIndex = _index3; \
+    } \
+  } \
+  else{ \
+    if(_index2 <= _index3){ \
+      topIndex = _index2; \
+    } \
+    else{ \
+      topIndex = _index3; \
+    } \
+  } \
+}
+
+#define CalBddGetMinIdAndMinIndex(bddManager, calBdd1, calBdd2, topId, topIndex)\
+{ \
+  Cal_BddId_t _id1, _id2; \
+  Cal_BddIndex_t _index1, _index2; \
+  _id1 = CalBddGetBddId((calBdd1)); \
+  _id2 = CalBddGetBddId((calBdd2)); \
+  _index1 = (bddManager)->idToIndex[_id1]; \
+  _index2 = (bddManager)->idToIndex[_id2]; \
+  if (_index1 < _index2){ \
+    topId = _id1; \
+    topIndex = _index1; \
+  } \
+  else { \
+    topId = _id2; \
+    topIndex = _index2; \
+  } \
+}
+
+#define CalBddNot(calBdd1, calBdd2) \
+{ \
+  (calBdd2).bddId = (calBdd1).bddId; \
+  (calBdd2).bddNode = (CalBddNode_t *)((CalAddress_t)(calBdd1).bddNode ^ 0x1); \
+}
+
+#define CAL_BDD_OUT_OF_ORDER(f, g) \
+    ((CalAddress_t)CalBddGetBddNode(f) > (CalAddress_t)CalBddGetBddNode(g))
+
+#define CAL_BDD_SWAP(f, g) \
+{ \
+  Cal_Bdd_t _tmp; \
+  _tmp = f; \
+  f = g; \
+  g = _tmp; \
+}
+
+
+/* BddNode related Macros */
+#define CalBddNodeGetThenBddId(_bddNode) ((_bddNode)->thenBddId)
+#define CalBddNodeGetElseBddId(_bddNode) ((_bddNode)->elseBddId)
+#define CalBddNodeGetThenBddIndex(bddManager, _bddNode) \
+    bddManager->idToIndex[((_bddNode)->thenBddId)]
+#define CalBddNodeGetElseBddIndex(bddManager, _bddNode) \
+    bddManager->idToIndex[((_bddNode)->elseBddId)]
+#define CalBddNodeGetThenBddNode(_bddNode) \
+    ((CalBddNode_t *)((CalAddress_t)((_bddNode)->thenBddNode) & ~0xe))
+#define CalBddNodeGetElseBddNode(_bddNode) \
+    ((CalBddNode_t *)((CalAddress_t)((_bddNode)->elseBddNode) & ~0xe))
+ 
+#define CalBddNodeGetThenBdd(_bddNode, _thenBdd) \
+{ \
+  (_thenBdd).bddId = (_bddNode)->thenBddId; \
+  (_thenBdd).bddNode =  \
+      (CalBddNode_t*) (((CalAddress_t) ((_bddNode)->thenBddNode) & ~0xe)); \
+}
+
+#define CalBddNodeGetElseBdd(_bddNode, _elseBdd) \
+{ \
+  (_elseBdd).bddId = (_bddNode)->elseBddId; \
+  (_elseBdd).bddNode = \
+      (CalBddNode_t*) (((CalAddress_t) ((_bddNode)->elseBddNode) & ~0xe)); \
+}
+
+#define CalBddNodeGetNextBddNode(_bddNode) \
+    ((CalBddNode_t *)(((CalAddress_t) ((_bddNode)->nextBddNode)) & ~0xf))
+
+#define CalBddNodePutThenBddId(_bddNode, _thenBddId) \
+    ((_bddNode)->thenBddId = _thenBddId)
+
+#define CalBddNodePutElseBddId(_bddNode, _elseBddId) \
+    ((_bddNode)->elseBddId = _elseBddId)
+
+#define CalBddNodePutThenBddNode(_bddNode, _thenBddNode) \
+{ \
+  (_bddNode)->thenBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)((_bddNode)->thenBddNode) & 0xe)| \
+       (((CalAddress_t) _thenBddNode) & ~0xe));	\
+}
+
+#define CalBddNodePutElseBddNode(_bddNode, _elseBddNode) \
+{ \
+  (_bddNode)->elseBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)((_bddNode)->elseBddNode) & 0xe)| \
+      (((CalAddress_t) _elseBddNode) & ~0xe));	\
+}
+ 
+#define CalBddNodePutThenBdd(_bddNode, _thenBdd) \
+{ \
+  (_bddNode)->thenBddId = (_thenBdd).bddId; \
+  (_bddNode)->thenBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)((_bddNode)->thenBddNode) & 0xe)| \
+       (((CalAddress_t)(_thenBdd).bddNode) & ~0xe)); \
+}
+
+#define CalBddNodePutElseBdd(_bddNode, _elseBdd) \
+{ \
+  (_bddNode)->elseBddId = (_elseBdd).bddId; \
+  (_bddNode)->elseBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)((_bddNode)->elseBddNode) & 0xe)| \
+       (((CalAddress_t) (_elseBdd).bddNode) & ~0xe)); \
+}
+
+#define CalBddNodePutNextBddNode(_bddNode, _nextBddNode) \
+{ \
+  (_bddNode)->nextBddNode = (CalBddNode_t*) \
+      (((CalAddress_t)((_bddNode)->nextBddNode) & 0xf)|  \
+       (((CalAddress_t) _nextBddNode) & ~0xf));	 \
+}
+
+
+#define CalBddNodeGetRefCount(_bddNode, refCount) \
+{ \
+  refCount = ((CalAddress_t)(_bddNode->thenBddNode) & 0x2); \
+  refCount <<= 3; \
+  refCount |= ((CalAddress_t)(_bddNode->elseBddNode) & 0xe); \
+  refCount <<= 3; \
+  refCount |= ((CalAddress_t)(_bddNode->nextBddNode) & 0xf); \
+}
+                                        
+#define CalBddNodePutRefCount(_bddNode, count) \
+{ \
+  Cal_BddRefCount_t _nextTag, _thenTag, _elseTag; \
+  _nextTag = (count & 0xf); \
+  _thenTag = ((count >> 6) & 0x2); \
+  _elseTag = ((count >> 3) & 0xe); \
+  _bddNode->nextBddNode = (CalBddNode_t*) \
+      ((((CalAddress_t)(_bddNode->nextBddNode)) & ~0xf) | _nextTag); \
+  _bddNode->thenBddNode = (CalBddNode_t*) \
+      ((((CalAddress_t)(_bddNode->thenBddNode)) & ~0x2) | _thenTag); \
+  _bddNode->elseBddNode = (CalBddNode_t*) \
+      ((((CalAddress_t)(_bddNode->elseBddNode)) & ~0xe) | _elseTag); \
+}
+
+#define CalBddNodeDcrRefCount(_bddNode) \
+{ \
+  if(((CalAddress_t)(_bddNode->nextBddNode) & 0xf) == 0x0){ \
+    if(((CalAddress_t)(_bddNode->elseBddNode) & 0xe) == 0x0){ \
+      if(((CalAddress_t)(_bddNode->thenBddNode) & 0x2) == 0x0){ \
+        CalBddWarningMessage("Trying to decrement reference count below zero"); \
+      } \
+      else{ \
+        _bddNode->thenBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->thenBddNode) & ~0x2); \
+        _bddNode->elseBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) | 0xe); \
+        _bddNode->nextBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) | 0xf); \
+      } \
+    } \
+    else{ \
+      _bddNode->elseBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) - 0x2); \
+      _bddNode->nextBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) | 0xf); \
+    } \
+  } \
+  else if(((CalAddress_t)(_bddNode->nextBddNode) & 0xf) != 0xf \
+      ||  ((CalAddress_t)(_bddNode->elseBddNode) & 0xe) != 0xe  \
+      ||  ((CalAddress_t)(_bddNode->thenBddNode) & 0x2) != 0x2){ \
+    _bddNode->nextBddNode = \
+        (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) - 1); \
+  } \
+}
+
+#define CalBddNodeIcrRefCount(_bddNode) \
+{ \
+  if(((CalAddress_t)(_bddNode->nextBddNode) & 0xf) != 0xf){ \
+    _bddNode->nextBddNode = \
+        (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) + 1); \
+  } \
+  else{ \
+    if(((CalAddress_t)(_bddNode->elseBddNode) & 0xe) != 0xe){ \
+      _bddNode->nextBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) & ~0xf); \
+      _bddNode->elseBddNode = \
+          (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) + 0x2); \
+    } \
+    else{ \
+      if(((CalAddress_t)(_bddNode->thenBddNode) & 0x2) == 0){ \
+        _bddNode->nextBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->nextBddNode) & ~0xf); \
+        _bddNode->elseBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->elseBddNode) & ~0xe); \
+        _bddNode->thenBddNode = \
+            (CalBddNode_t *)((CalAddress_t)(_bddNode->thenBddNode) | 0x2); \
+      } \
+    } \
+  } \
+}
+
+#define CalBddNodeAddRefCount(__bddNode, num)				\
+{ \
+  Cal_BddRefCount_t _count; \
+  CalBddNodeGetRefCount(__bddNode, _count); \
+  _count += num; \
+  if(_count > CAL_MAX_REF_COUNT){ \
+    _count = CAL_MAX_REF_COUNT; \
+  } \
+  CalBddNodePutRefCount(__bddNode, _count); \
+}
+
+#define CalBddNodeIsRefCountZero(_bddNode) \
+    (((((CalAddress_t) ((_bddNode)->thenBddNode)) & 0x2) || \
+    (((CalAddress_t) ((_bddNode)->elseBddNode)) & 0xe) || \
+    (((CalAddress_t) ((_bddNode)->nextBddNode)) & 0xf)) \
+    ? 0 : 1)
+
+#define CalBddNodeIsRefCountMax(_bddNode) \
+    ((((((CalAddress_t) ((_bddNode)->thenBddNode)) & 0x2) == 0x2)&& \
+    ((((CalAddress_t) ((_bddNode)->elseBddNode)) & 0xe) == 0xe)&& \
+    ((((CalAddress_t) ((_bddNode)->nextBddNode)) & 0xf) == 0xf)) \
+    ? 1 : 0)
+
+#define CalBddNodeIsOutPos(bddNode)  (!(((CalAddress_t)bddNode) & 0x1))
+#define CalBddNodeRegular(bddNode) ((CalBddNode_t *)(((unsigned long)(bddNode)) & ~01))
+#define CalBddRegular(calBdd1, calBdd2)                 \
+{                                                       \
+  calBdd2.bddId = calBdd1.bddId;                        \
+  calBdd2.bddNode = CalBddNodeRegular(calBdd1.bddNode); \
+}
+
+#define CalBddNodeEqual(calBddNode1, calBddNode2)\
+  ((CalAddress_t)calBddNode1 == (CalAddress_t)calBddNode2)
+
+#define CalBddNodeNot(bddNode) ((CalBddNode_t*)(((CalAddress_t)(bddNode))^0x1))
+
+/* Mark / Unmark */
+#define CalBddIsMarked(calBdd) \
+    CalBddNodeIsMarked(CAL_BDD_POINTER((calBdd).bddNode))
+
+#define CalBddMark(calBdd) \
+    CalBddNodeMark(CAL_BDD_POINTER((calBdd).bddNode))
+
+#define CalBddUnmark(calBdd) \
+    CalBddNodeUnmark(CAL_BDD_POINTER((calBdd).bddNode))
+
+#define CalBddGetMark(calBdd) \
+    CalBddNodeGetMark(CAL_BDD_POINTER((calBdd).bddNode))
+
+#define CalBddPutMark(calBdd, mark) \
+    CalBddNodePutMark(CAL_BDD_POINTER((calBdd).bddNode), (mark))
+
+#define CalBddNodeIsMarked(bddNode) \
+  ((((CalAddress_t)((bddNode)->thenBddNode)) & 0x4) >> 2)
+
+#define CalBddNodeMark(bddNode) \
+  ((bddNode)->thenBddNode = \
+     (CalBddNode_t *)(((CalAddress_t)(bddNode)->thenBddNode) | 0x4))
+
+#define CalBddNodeUnmark(bddNode) \
+  ((bddNode)->thenBddNode = \
+     (CalBddNode_t *)(((CalAddress_t)(bddNode)->thenBddNode) & ~0x4))
+
+#define CalBddNodeGetMark(bddNode) \
+  ((((CalAddress_t)((bddNode)->thenBddNode)) & 0xc) >> 2)
+
+#define CalBddNodePutMark(bddNode, mark) \
+  ((bddNode)->thenBddNode = (CalBddNode_t *) \
+      ((((CalAddress_t)(bddNode)->thenBddNode) & ~0xc) | ((mark) << 2)))
+
+
+/* THIS SHOULD BE CHANGED TO MACROS WITH ARGUMENTS */
+#define CalRequestGetThenRequestId  CalBddGetThenBddId
+#define CalRequestGetElseRequestId CalBddGetElseBddId
+#define CalRequestGetThenRequestNode   CalBddGetThenBddNode
+#define CalRequestGetElseRequestNode  CalBddGetElseBddNode
+#define CalRequestGetThenRequest  CalBddGetThenBdd
+#define CalRequestGetElseRequest  CalBddGetElseBdd
+#define CalRequestGetRequestId  CalBddGetBddId
+#define CalRequestGetRequestNode CalBddGetBddNode
+#define CalRequestGetF CalBddGetThenBdd
+#define CalRequestGetG CalBddGetElseBdd
+#define CalRequestGetNextNode CalBddGetNextBddNode
+
+#define CalRequestPutThenRequestId  CalBddPutThenBddId
+#define CalRequestPutElseRequestId CalBddPutElseBddId
+#define CalRequestPutThenRequestNode   CalBddPutThenBddNode
+#define CalRequestPutElseRequestNode  CalBddPutElseBddNode
+#define CalRequestPutThenRequest  CalBddPutThenBdd
+#define CalRequestPutElseRequest  CalBddPutElseBdd
+#define CalRequestPutRequestId  CalBddPutBddId
+#define CalRequestPutRequestNode CalBddPutBddNode
+#define CalRequestPutF CalBddPutThenBdd
+#define CalRequestPutG CalBddPutElseBdd
+#define CalRequestPutNextNode CalBddPutNextBddNode
+
+/* Macros related to the CalRequestNode */
+
+#define CalRequestNodeGetThenRequestId  CalBddNodeGetThenBddId
+#define CalRequestNodeGetElseRequestId CalBddNodeGetElseBddId
+#define CalRequestNodeGetThenRequestNode   CalBddNodeGetThenBddNode
+#define CalRequestNodeGetElseRequestNode  CalBddNodeGetElseBddNode
+#define CalRequestNodeGetThenRequest  CalBddNodeGetThenBdd
+#define CalRequestNodeGetElseRequest  CalBddNodeGetElseBdd
+#define CalRequestNodeGetF CalBddNodeGetThenBdd
+#define CalRequestNodeGetG CalBddNodeGetElseBdd
+#define CalRequestNodeGetNextRequestNode CalBddNodeGetNextBddNode
+
+#define CalRequestNodePutThenRequestId  CalBddNodePutThenBddId
+#define CalRequestNodePutElseRequestId CalBddNodePutElseBddId
+#define CalRequestNodePutThenRequestNode   CalBddNodePutThenBddNode
+#define CalRequestNodePutElseRequestNode  CalBddNodePutElseBddNode
+#define CalRequestNodePutThenRequest  CalBddNodePutThenBdd
+#define CalRequestNodePutElseRequest  CalBddNodePutElseBdd
+#define CalRequestNodePutF CalBddNodePutThenBdd
+#define CalRequestNodePutG CalBddNodePutElseBdd
+#define CalRequestNodePutNextRequestNode CalBddNodePutNextBddNode
+#define CalRequestIsNull(calRequest) \
+    ((CalRequestGetRequestId(calRequest) == 0) \
+    && (CalRequestGetRequestNode(calRequest) == 0))
+                                      
+#define CalRequestIsMarked CalBddIsMarked
+#define CalRequestMark CalBddMark
+#define CalRequestUnmark CalBddUnmark
+#define CalRequestGetMark CalBddGetMark
+#define CalRequestPutMark CalBddPutMark
+#define CalRequestNodeIsMarked CalBddNodeIsMarked
+#define CalRequestNodeMark CalBddNodeMark
+#define CalRequestNodeUnmark CalBddNodeUnmark
+#define CalRequestNodeGetMark CalBddNodeGetMark
+#define CalRequestNodePutMark CalBddNodePutMark
+
+#define CalRequestNodeGetCofactors(bddManager,requestNode,fx,fxbar,gx,gxbar) \
+{ \
+  Cal_Bdd_t __f, __g; \
+  Cal_BddIndex_t __index1, __index2; \
+  CalRequestNodeGetF(requestNode, __f); \
+  CalRequestNodeGetG(requestNode, __g); \
+  __index1 = (bddManager)->idToIndex[CalBddGetBddId(__f)]; \
+  __index2 = (bddManager)->idToIndex[CalBddGetBddId(__g)]; \
+  if(__index1 == __index2){ \
+    CalBddGetThenBdd(__f, fx); \
+    CalBddGetElseBdd(__f, fxbar); \
+    CalBddGetThenBdd(__g, gx); \
+    CalBddGetElseBdd(__g, gxbar); \
+  } \
+  else if(__index1 < __index2){ \
+    CalBddGetThenBdd(__f, fx); \
+    CalBddGetElseBdd(__f, fxbar); \
+    gx = gxbar = __g; \
+  } \
+  else{ \
+    fx = fxbar = __f; \
+    CalBddGetThenBdd(__g, gx); \
+    CalBddGetElseBdd(__g, gxbar); \
+  } \
+}
+
+#define CalBddPairGetCofactors(bddManager,f,g,fx,fxbar,gx,gxbar) \
+{ \
+  Cal_BddIndex_t __index1, __index2; \
+  __index1 = (bddManager)->idToIndex[CalBddGetBddId(f)]; \
+  __index2 = (bddManager)->idToIndex[CalBddGetBddId(g)]; \
+  if(__index1 == __index2){ \
+    CalBddGetThenBdd(f, fx); \
+    CalBddGetElseBdd(f, fxbar); \
+    CalBddGetThenBdd(g, gx); \
+    CalBddGetElseBdd(g, gxbar); \
+  } \
+  else if(__index1 < __index2){ \
+    CalBddGetThenBdd(f, fx); \
+    CalBddGetElseBdd(f, fxbar); \
+    gx = gxbar = g; \
+  } \
+  else{ \
+    fx = fxbar = f; \
+    CalBddGetThenBdd(g, gx); \
+    CalBddGetElseBdd(g, gxbar); \
+  } \
+}
+
+#define CalBddIsForwarded(bdd) \
+  (CAL_BDD_POINTER(CalBddGetElseBddNode(bdd)) == FORWARD_FLAG)
+
+#define CalBddNodeIsForwarded(bddNode) \
+  (((CalAddress_t)(CAL_BDD_POINTER(CalBddNodeGetElseBddNode(bddNode)))) == FORWARD_FLAG)
+
+#define CalBddForward(bdd) \
+{ \
+  CalBddNode_t *_bddNode, *_bddNodeTagged; \
+  _bddNodeTagged = CalBddGetBddNode(bdd); \
+  _bddNode = CAL_BDD_POINTER(_bddNodeTagged); \
+  (bdd).bddId = _bddNode->thenBddId; \
+  (bdd).bddNode = (CalBddNode_t*) \
+                  (((CalAddress_t)(_bddNode->thenBddNode) & ~0xe) \
+                   ^(CAL_TAG0(_bddNodeTagged))); \
+}
+
+#define CalBddNodeForward(_bddNodeTagged) \
+{ \
+  CalBddNode_t *_bddNode; \
+  _bddNode = CAL_BDD_POINTER(_bddNodeTagged); \
+  _bddNodeTagged = (CalBddNode_t*) \
+                  (((CalAddress_t)(_bddNode->thenBddNode) & ~0xe) \
+                   ^(CAL_TAG0(_bddNodeTagged))); \
+}
+
+#define CalBddNodeIsForwardedTo(_bddNodeTagged) \
+{ \
+  CalBddNode_t *__bddNode;\
+  __bddNode = CAL_BDD_POINTER(_bddNodeTagged); \
+  if(CalBddNodeGetElseBddNode(__bddNode) == FORWARD_FLAG){ \
+    _bddNodeTagged = (CalBddNode_t*) \
+                     (((CalAddress_t)(__bddNode->thenBddNode) & ~0xe)        \
+                      ^(CAL_TAG0(_bddNodeTagged))); \
+  } \
+}
+
+#define CalRequestIsForwardedTo(request) \
+{ \
+  CalBddNode_t *__bddNode, *__bddNodeTagged; \
+  __bddNodeTagged = (request).bddNode; \
+  __bddNode = CAL_BDD_POINTER(__bddNodeTagged); \
+  if(CalRequestNodeGetElseRequestNode(__bddNode) == FORWARD_FLAG){ \
+    (request).bddId = __bddNode->thenBddId; \
+    (request).bddNode = (CalBddNode_t*) \
+                        (((CalAddress_t)(__bddNode->thenBddNode) & ~0xe)        \
+                         ^(CAL_TAG0(__bddNodeTagged))); \
+  } \
+}
+
+#define CalBddIsForwardedTo CalRequestIsForwardedTo
+
+#define CalBddNormalize(fBdd, gBdd) \
+{ \
+  Cal_Bdd_t _tmpBdd; \
+  if((unsigned long)CAL_BDD_POINTER(CalBddGetBddNode(gBdd)) < \
+      (unsigned long)CAL_BDD_POINTER(CalBddGetBddNode(fBdd))){ \
+    _tmpBdd = fBdd; \
+    fBdd = gBdd; \
+    gBdd = _tmpBdd; \
+  } \
+}
+
+/* Depth aliased as RefCount */
+#define CalBddGetDepth CalBddGetRefCount
+#define CalBddPutDepth CalBddPutRefCount
+#define CalRequestNodeGetDepth CalBddNodeGetRefCount
+#define CalRequestNodeGetRefCount CalBddNodeGetRefCount
+#define CalRequestNodeAddRefCount CalBddNodeAddRefCount
+#define CalRequestAddRefCount CalBddAddRefCount
+#define CalRequestNodePutDepth CalBddNodePutRefCount
+
+#define CalITERequestNodeGetCofactors(bddManager, requestNode, fx, fxbar, gx, gxbar, hx, hxbar) \
+{ \
+  Cal_Bdd_t __f, __g, __h; \
+  Cal_BddIndex_t __index1, __index2, __index3; \
+  CalBddNode_t *__ptrIndirect; \
+  CalRequestNodeGetThenRequest(requestNode, __f); \
+  __ptrIndirect = CalRequestNodeGetElseRequestNode(requestNode); \
+  CalRequestNodeGetThenRequest(__ptrIndirect, __g); \
+  CalRequestNodeGetElseRequest(__ptrIndirect, __h); \
+  __index1 = (bddManager)->idToIndex[CalBddGetBddId(__f)]; \
+  __index2 = (bddManager)->idToIndex[CalBddGetBddId(__g)]; \
+  __index3 = (bddManager)->idToIndex[CalBddGetBddId(__h)]; \
+  if(__index1 == __index2){ \
+    if(__index3 == __index1){ \
+      CalBddGetThenBdd(__f, fx); \
+      CalBddGetElseBdd(__f, fxbar); \
+      CalBddGetThenBdd(__g, gx); \
+      CalBddGetElseBdd(__g, gxbar); \
+      CalBddGetThenBdd(__h, hx); \
+      CalBddGetElseBdd(__h, hxbar); \
+    } \
+    else if(__index3 < __index1){ \
+      fx = fxbar = __f; \
+      gx = gxbar = __g; \
+      CalBddGetThenBdd(__h, hx); \
+      CalBddGetElseBdd(__h, hxbar); \
+    } \
+    else{ \
+      CalBddGetThenBdd(__f, fx); \
+      CalBddGetElseBdd(__f, fxbar); \
+      CalBddGetThenBdd(__g, gx); \
+      CalBddGetElseBdd(__g, gxbar); \
+      hx = hxbar = __h; \
+    } \
+  } \
+  else if(__index1 < __index2){ \
+    if(__index3 == __index1){ \
+      CalBddGetThenBdd(__f, fx); \
+      CalBddGetElseBdd(__f, fxbar); \
+      gx = gxbar = __g; \
+      CalBddGetThenBdd(__h, hx); \
+      CalBddGetElseBdd(__h, hxbar); \
+    } \
+    else if(__index3 < __index1){ \
+      fx = fxbar = __f; \
+      gx = gxbar = __g; \
+      CalBddGetThenBdd(__h, hx); \
+      CalBddGetElseBdd(__h, hxbar); \
+    } \
+    else{ \
+      CalBddGetThenBdd(__f, fx); \
+      CalBddGetElseBdd(__f, fxbar); \
+      gx = gxbar = __g; \
+      hx = hxbar = __h; \
+    } \
+  } \
+  else{ \
+    if(__index3 == __index2){ \
+      fx = fxbar = __f; \
+      CalBddGetThenBdd(__g, gx); \
+      CalBddGetElseBdd(__g, gxbar); \
+      CalBddGetThenBdd(__h, hx); \
+      CalBddGetElseBdd(__h, hxbar); \
+    } \
+    else if(__index3 < __index2){ \
+      fx = fxbar = __f; \
+      gx = gxbar = __g; \
+      CalBddGetThenBdd(__h, hx); \
+      CalBddGetElseBdd(__h, hxbar); \
+    } \
+    else{ \
+      fx = fxbar = __f; \
+      CalBddGetThenBdd(__g, gx); \
+      CalBddGetElseBdd(__g, gxbar); \
+      hx = hxbar = __h; \
+    } \
+  } \
+}
+
+
+#define CalCacheTableOneInsert(bddManager, f, result, opCode, cacheLevel) CalCacheTableTwoInsert(bddManager, f, (bddManager)->bddOne, result, opCode, cacheLevel)
+
+#define CalCacheTableOneLookup(bddManager, f, opCode, resultPtr) CalCacheTableTwoLookup(bddManager, f, (bddManager)->bddOne, opCode, resultPtr)
+
+#ifdef USE_POWER_OF_2
+#define CalDoHash2(thenBddNode, elseBddNode, table) \
+   (((((CalAddress_t)thenBddNode) + ((CalAddress_t)elseBddNode)) / NODE_SIZE) & ((table)->numBins - 1))
+#else
+#define CalDoHash2(thenBddNode, elseBddNode, table) \
+                              (((((CalAddress_t)thenBddNode) + \
+                                 ((CalAddress_t)elseBddNode)) / NODE_SIZE)% \
+                               (table)->numBins)
+#endif
+
+#if HAVE_STDARG_H
+EXTERN int CalBddPreProcessing(Cal_BddManager_t *bddManager, int count, ...);
+#else
+EXTERN int CalBddPreProcessing();
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN Cal_Bdd_t CalBddIf(Cal_BddManager bddManager, Cal_Bdd_t F);
+EXTERN int CalBddIsCubeStep(Cal_BddManager bddManager, Cal_Bdd_t f);
+EXTERN int CalBddTypeAux(Cal_BddManager_t * bddManager, Cal_Bdd_t f);
+EXTERN Cal_Bdd_t CalBddIdentity(Cal_BddManager_t *bddManager, Cal_Bdd_t calBdd);
+EXTERN void CalHashTableApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t ** reqQueAtPipeDepth, CalOpProc_t calOpProc);
+EXTERN void CalHashTableReduce(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t * uniqueTableForId);
+EXTERN void CalAssociationListFree(Cal_BddManager_t * bddManager);
+EXTERN void CalVarAssociationRepackUpdate(Cal_BddManager_t * bddManager, Cal_BddId_t id);
+EXTERN void CalCheckAssociationValidity(Cal_BddManager_t * bddManager);
+EXTERN void CalReorderAssociationFix(Cal_BddManager_t *bddManager);
+EXTERN void CalRequestNodeListCompose(Cal_BddManager_t * bddManager, CalRequestNode_t * requestNodeList, Cal_BddIndex_t composeIndex);
+EXTERN void CalHashTableComposeApply(Cal_BddManager_t *bddManager, CalHashTable_t *hashTable, Cal_BddIndex_t gIndex, CalHashTable_t **reqQueForCompose, CalHashTable_t **reqQueForITE);
+EXTERN void CalComposeRequestCreate(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t h, Cal_BddIndex_t composeIndex, CalHashTable_t **reqQueForCompose, CalHashTable_t **reqQueForITE, Cal_Bdd_t *resultPtr);
+EXTERN void CalRequestNodeListArrayITE(Cal_BddManager_t *bddManager, CalRequestNode_t **requestNodeListArray);
+EXTERN Cal_Bdd_t CalBddOpITEBF(Cal_BddManager_t *bddManager, Cal_Bdd_t f, Cal_Bdd_t g, Cal_Bdd_t h);
+EXTERN void CalHashTableITEApply(Cal_BddManager_t *bddManager, CalHashTable_t *hashTable, CalHashTable_t **reqQueAtPipeDepth);
+EXTERN Cal_Bdd_t CalBddITE(Cal_BddManager_t *bddManager, Cal_Bdd_t F, Cal_Bdd_t G, Cal_Bdd_t H);
+EXTERN Cal_Bdd_t CalBddManagerCreateNewVar(Cal_BddManager_t * bddManager, Cal_BddIndex_t index);
+EXTERN void CalRequestNodeListArrayOp(Cal_BddManager_t * bddManager, CalRequestNode_t ** requestNodeListArray, CalOpProc_t calOpProc);
+EXTERN Cal_Bdd_t CalBddOpBF(Cal_BddManager_t * bddManager, CalOpProc_t calOpProc, Cal_Bdd_t F, Cal_Bdd_t G);
+EXTERN int main(int argc, char **argv);
+EXTERN Cal_Bdd_t CalBddVarSubstitute(Cal_BddManager bddManager, Cal_Bdd_t f, unsigned short opCode, CalAssociation_t *assoc);
+EXTERN int CalOpBddVarSubstitute(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t * resultBddPtr);
+EXTERN long CalBddFindBlock(Cal_Block block, long index);
+EXTERN void CalBddBlockDelta(Cal_Block b, long delta);
+EXTERN Cal_Block CalBddShiftBlock(Cal_BddManager_t *bddManager, Cal_Block b, long index);
+EXTERN unsigned long CalBlockMemoryConsumption(Cal_Block block);
+EXTERN void CalFreeBlockRecursively(Cal_Block block);
+EXTERN CalCacheTable_t * CalCacheTableTwoInit(Cal_BddManager_t *bddManager);
+EXTERN int CalCacheTableTwoQuit(CalCacheTable_t *cacheTable);
+EXTERN void CalCacheTableTwoInsert(Cal_BddManager_t *bddManager, Cal_Bdd_t f, Cal_Bdd_t g, Cal_Bdd_t result, unsigned long opCode, int cacheLevel);
+EXTERN int CalCacheTableTwoLookup(Cal_BddManager_t *bddManager, Cal_Bdd_t f, Cal_Bdd_t g, unsigned long opCode, Cal_Bdd_t *resultBddPtr);
+EXTERN void CalCacheTableTwoFlush(CalCacheTable_t *cacheTable);
+EXTERN int CalCacheTableTwoFlushAll(CalCacheTable_t *cacheTable);
+EXTERN void CalCacheTableTwoGCFlush(CalCacheTable_t *cacheTable);
+EXTERN void CalCacheTableTwoRepackUpdate(CalCacheTable_t *cacheTable);
+EXTERN void CalCheckCacheTableValidity(Cal_BddManager bddManager);
+EXTERN void CalCacheTableTwoFixResultPointers(Cal_BddManager_t *bddManager);
+EXTERN void CalCacheTablePrint(Cal_BddManager_t *bddManager);
+EXTERN void CalBddManagerGetCacheTableData(Cal_BddManager_t *bddManager, unsigned long *cacheSize, unsigned long *cacheEntries, unsigned long *cacheInsertions, unsigned long *cacheLookups, unsigned long *cacheHits, unsigned long *cacheCollisions);
+EXTERN void CalCacheTableRehash(Cal_BddManager_t *bddManager);
+EXTERN void CalCacheTableTwoFlushAssociationId(Cal_BddManager_t *bddManager, int associationId);
+EXTERN unsigned long CalCacheTableMemoryConsumption(CalCacheTable_t *cacheTable);
+EXTERN void CalBddManagerGCCheck(Cal_BddManager_t * bddManager);
+EXTERN int CalHashTableGC(Cal_BddManager_t *bddManager, CalHashTable_t *hashTable);
+EXTERN void CalRepackNodesAfterGC(Cal_BddManager_t *bddManager);
+EXTERN CalHashTable_t * CalHashTableInit(Cal_BddManager_t *bddManager, Cal_BddId_t bddId);
+EXTERN int CalHashTableQuit(Cal_BddManager_t *bddManager, CalHashTable_t * hashTable);
+EXTERN void CalHashTableAddDirect(CalHashTable_t * hashTable, CalBddNode_t * bddNode);
+EXTERN int CalHashTableFindOrAdd(CalHashTable_t * hashTable, Cal_Bdd_t thenBdd, Cal_Bdd_t elseBdd, Cal_Bdd_t * bddPtr);
+EXTERN int CalHashTableAddDirectAux(CalHashTable_t * hashTable, Cal_Bdd_t thenBdd, Cal_Bdd_t elseBdd, Cal_Bdd_t * bddPtr);
+EXTERN void CalHashTableCleanUp(CalHashTable_t * hashTable);
+EXTERN int CalHashTableLookup(CalHashTable_t * hashTable, Cal_Bdd_t thenBdd, Cal_Bdd_t elseBdd, Cal_Bdd_t * bddPtr);
+EXTERN void CalHashTableDelete(CalHashTable_t * hashTable, CalBddNode_t * bddNode);
+EXTERN int CalUniqueTableForIdLookup(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, Cal_Bdd_t thenBdd, Cal_Bdd_t elseBdd, Cal_Bdd_t * bddPtr);
+EXTERN int CalUniqueTableForIdFindOrAdd(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, Cal_Bdd_t thenBdd, Cal_Bdd_t elseBdd, Cal_Bdd_t * bddPtr);
+EXTERN void CalHashTableRehash(CalHashTable_t *hashTable, int grow);
+EXTERN void CalUniqueTableForIdRehashNode(CalHashTable_t *hashTable, CalBddNode_t *bddNode, CalBddNode_t *thenBddNode, CalBddNode_t *elseBddNode);
+EXTERN unsigned long CalBddUniqueTableNumLockedNodes(Cal_BddManager_t *bddManager, CalHashTable_t *uniqueTableForId);
+EXTERN void CalPackNodes(Cal_BddManager_t *bddManager);
+EXTERN void CalBddPackNodesForSingleId(Cal_BddManager_t *bddManager, Cal_BddId_t id);
+EXTERN void CalBddPackNodesAfterReorderForSingleId(Cal_BddManager_t *bddManager, int fixForwardedNodesFlag, int bestIndex, int bottomIndex);
+EXTERN void CalBddPackNodesForMultipleIds(Cal_BddManager_t *bddManager, Cal_BddId_t beginId, int numLevels);
+EXTERN CalHashTable_t * CalHashTableOneInit(Cal_BddManager_t * bddManager, int itemSize);
+EXTERN void CalHashTableOneQuit(CalHashTable_t * hashTable);
+EXTERN void CalHashTableOneInsert(CalHashTable_t * hashTable, Cal_Bdd_t keyBdd, char * valuePtr);
+EXTERN int CalHashTableOneLookup(CalHashTable_t * hashTable, Cal_Bdd_t keyBdd, char ** valuePtrPtr);
+EXTERN int CalHashTableThreeFindOrAdd(CalHashTable_t * hashTable, Cal_Bdd_t f, Cal_Bdd_t g, Cal_Bdd_t h, Cal_Bdd_t * bddPtr);
+EXTERN void CalSetInteract(Cal_BddManager_t *bddManager, int x, int y);
+EXTERN int CalTestInteract(Cal_BddManager_t *bddManager, int x, int y);
+EXTERN int CalInitInteract(Cal_BddManager_t *bddManager);
+EXTERN CalPageManager_t * CalPageManagerInit(int numPagesPerSegment);
+EXTERN int CalPageManagerQuit(CalPageManager_t * pageManager);
+EXTERN void CalPageManagerPrint(CalPageManager_t * pageManager);
+EXTERN CalNodeManager_t * CalNodeManagerInit(CalPageManager_t * pageManager);
+EXTERN int CalNodeManagerQuit(CalNodeManager_t * nodeManager);
+EXTERN void CalNodeManagerPrint(CalNodeManager_t * nodeManager);
+EXTERN CalAddress_t * CalPageManagerAllocPage(CalPageManager_t * pageManager);
+EXTERN void CalPageManagerFreePage(CalPageManager_t * pageManager, CalAddress_t * page);
+EXTERN int CalIncreasingOrderCompare(const void *a, const void *b);
+EXTERN int CalDecreasingOrderCompare(const void *a, const void *b);
+EXTERN void CalBddReorderFixProvisionalNodes(Cal_BddManager_t *bddManager);
+EXTERN void CalCheckPipelineValidity(Cal_BddManager_t *bddManager);
+EXTERN char * CalBddVarName(Cal_BddManager_t *bddManager, Cal_Bdd_t v, Cal_VarNamingFn_t VarNamingFn, Cal_Pointer_t env);
+EXTERN void CalBddNumberSharedNodes(Cal_BddManager_t *bddManager, Cal_Bdd_t f, CalHashTable_t *hashTable, long *next);
+EXTERN void CalBddMarkSharedNodes(Cal_BddManager_t *bddManager, Cal_Bdd_t f);
+EXTERN int CalOpExists(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t * resultBddPtr);
+EXTERN int CalOpRelProd(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t g, Cal_Bdd_t * resultBddPtr);
+EXTERN int CalOpCofactor(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t c, Cal_Bdd_t * resultBddPtr);
+EXTERN void CalBddReorderAuxBF(Cal_BddManager_t * bddManager);
+EXTERN void CalBddReorderFixCofactors(Cal_BddManager bddManager, Cal_BddId_t id);
+EXTERN void CalFixupAssoc(Cal_BddManager_t *bddManager, long id1, long id2, CalAssociation_t *assoc);
+EXTERN void CalBddReorderReclaimForwardedNodes(Cal_BddManager bddManager, int startIndex, int endIndex);
+EXTERN void CalBddReorderBlockSift(Cal_BddManager_t *bddManager, double maxSizeFactor);
+EXTERN void CalBddReorderBlockWindow(Cal_BddManager bddManager, Cal_Block block, char *levels);
+EXTERN void CalBddReorderAuxDF(Cal_BddManager_t *bddManager);
+EXTERN void CalAlignCollisionChains(Cal_BddManager_t *bddManager);
+EXTERN void CalBddReorderFixUserBddPtrs(Cal_BddManager bddManager);
+EXTERN int CalCheckAllValidity(Cal_BddManager bddManager);
+EXTERN int CalCheckValidityOfNodesForId(Cal_BddManager bddManager, int id);
+EXTERN int CalCheckValidityOfNodesForWindow(Cal_BddManager bddManager, Cal_BddIndex_t index, int numLevels);
+EXTERN int CalCheckValidityOfANode(Cal_BddManager_t *bddManager, CalBddNode_t *bddNode, int id);
+EXTERN void CalCheckRefCountValidity(Cal_BddManager_t *bddManager);
+EXTERN int CalCheckAssoc(Cal_BddManager_t *bddManager);
+EXTERN void CalBddReorderVarSift(Cal_BddManager bddManager, double maxSizeFactor);
+EXTERN void CalBddReorderVarWindow(Cal_BddManager bddManager, char *levels);
+EXTERN int CalOpAnd(Cal_BddManager_t * bddManager, Cal_Bdd_t F, Cal_Bdd_t G, Cal_Bdd_t * resultBddPtr);
+EXTERN int CalOpNand(Cal_BddManager_t * bddManager, Cal_Bdd_t F, Cal_Bdd_t G, Cal_Bdd_t * resultBddPtr);
+EXTERN int CalOpOr(Cal_BddManager_t * bddManager, Cal_Bdd_t F, Cal_Bdd_t G, Cal_Bdd_t * resultBddPtr);
+EXTERN int CalOpXor(Cal_BddManager_t * bddManager, Cal_Bdd_t F, Cal_Bdd_t G, Cal_Bdd_t * resultBddPtr);
+EXTERN Cal_Bdd_t CalOpITE(Cal_BddManager_t *bddManager, Cal_Bdd_t f, Cal_Bdd_t g, Cal_Bdd_t h, CalHashTable_t **reqQueForITE);
+EXTERN int main(int argc, char ** argv);
+EXTERN void CalUniqueTablePrint(Cal_BddManager_t *bddManager);
+EXTERN void CalBddFunctionPrint(Cal_BddManager_t * bddManager, Cal_Bdd_t calBdd, char * name);
+EXTERN int CalBddPreProcessing(Cal_BddManager_t *bddManager, int count, ...);
+EXTERN int CalBddPostProcessing(Cal_BddManager_t *bddManager);
+EXTERN int CalBddArrayPreProcessing(Cal_BddManager_t *bddManager, Cal_Bdd *userBddArray);
+EXTERN Cal_Bdd_t CalBddGetInternalBdd(Cal_BddManager bddManager, Cal_Bdd userBdd);
+EXTERN Cal_Bdd CalBddGetExternalBdd(Cal_BddManager_t *bddManager, Cal_Bdd_t internalBdd);
+EXTERN void CalBddFatalMessage(char *string);
+EXTERN void CalBddWarningMessage(char *string);
+EXTERN void CalBddNodePrint(CalBddNode_t *bddNode);
+EXTERN void CalBddPrint(Cal_Bdd_t calBdd);
+EXTERN void CalHashTablePrint(CalHashTable_t *hashTable);
+EXTERN void CalHashTableOnePrint(CalHashTable_t *hashTable, int flag);
+EXTERN void CalUtilSRandom(long seed);
+EXTERN long CalUtilRandom(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _INT */
Index: /vis_dev/glu-2.1/src/calBdd/calInteract.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calInteract.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calInteract.c	(revision 8)
@@ -0,0 +1,348 @@
+/**CFile***********************************************************************
+
+  FileName    [calInteract.c]
+
+  PackageName [cal]
+
+  Synopsis    [Functions to manipulate the variable interaction matrix.]
+
+  Description [
+  The interaction matrix tells whether two variables are
+  both in the support of some function of the DD. The main use of the
+  interaction matrix is in the in-place swapping. Indeed, if two
+  variables do not interact, there is no arc connecting the two layers;
+  therefore, the swap can be performed in constant time, without
+  scanning the subtables. Another use of the interaction matrix is in
+  the computation of the lower bounds for sifting. Finally, the
+  interaction matrix can be used to speed up aggregation checks in
+  symmetric and group sifting.<p>
+  The computation of the interaction matrix is done with a series of
+  depth-first searches. The searches start from those nodes that have
+  only external references. The matrix is stored as a packed array of bits;
+  since it is symmetric, only the upper triangle is kept in memory.
+  As a final remark, we note that there may be variables that do
+  intercat, but that for a given variable order have no arc connecting
+  their layers when they are adjacent.]
+
+  SeeAlso     []
+
+  Author      [Original author:Fabio Somenzi. Modified for CAL package
+  by Rajeev K. Ranjan]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#if SIZEOF_LONG == 8
+#define BPL 64
+#define LOGBPL 6
+#else
+#define BPL 32
+#define LOGBPL 5
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ddSuppInteract(Cal_BddManager_t *bddManager, Cal_Bdd_t f, int *support);
+static void ddClearLocal(Cal_Bdd_t f);
+static void ddUpdateInteract(Cal_BddManager_t *bddManager, int *support);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set interaction matrix entries.]
+
+  Description [Given a pair of variables 0 <= x < y < table->size,
+  sets the corresponding bit of the interaction matrix to 1.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+CalSetInteract(Cal_BddManager_t *bddManager, int x, int y)
+{
+    int posn, word, bit;
+
+    Cal_Assert(x < y);
+    Cal_Assert(y < bddManager->numVars);
+    Cal_Assert(x >= 0);
+
+    posn = ((((bddManager->numVars << 1) - x - 3) * x) >> 1) + y - 1;
+    word = posn >> LOGBPL;
+    bit = posn & (BPL-1);
+    bddManager->interact[word] |= 1 << bit;
+
+} /* end of CalSetInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Test interaction matrix entries.]
+
+  Description [Given a pair of variables 0 <= x < y < bddManager->numVars,
+  tests whether the corresponding bit of the interaction matrix is 1.
+  Returns the value of the bit.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+CalTestInteract(Cal_BddManager_t *bddManager, int x, int y)
+{
+    int posn, word, bit, result;
+
+    x -= 1; 
+    y -= 1;
+    
+    if (x > y) {
+	int tmp = x;
+	x = y;
+	y = tmp;
+    }
+    Cal_Assert(x < y);
+    Cal_Assert(y < bddManager->numVars);
+    Cal_Assert(x >= 0);
+
+    posn = ((((bddManager->numVars << 1) - x - 3) * x) >> 1) + y - 1;
+    word = posn >> LOGBPL;
+    bit = posn & (BPL-1);
+    result = (bddManager->interact[word] >> bit) & 1;
+    return(result);
+
+} /* end of CalTestInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the interaction matrix.]
+
+  Description [Initializes the interaction matrix. The interaction
+  matrix is implemented as a bit vector storing the upper triangle of
+  the symmetric interaction matrix. The bit vector is kept in an array
+  of long integers. The computation is based on a series of depth-first
+  searches, one for each root of the DAG. A local flag (the mark bits)
+  is used.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+CalInitInteract(Cal_BddManager_t *bddManager)
+{
+  int i,k;
+  int words;
+  long *interact;
+  int *support;
+  long numBins;
+  CalBddNode_t **bins, *bddNode, *nextBddNode;
+  
+  int n = bddManager->numVars;
+  
+  words = ((n * (n-1)) >> (1 + LOGBPL)) + 1;
+  bddManager->interact = interact = Cal_MemAlloc(long, words);
+  if (interact == NULL) return(0);
+  for (i = 0; i < words; i++) {
+      interact[i] = 0;
+  }
+  
+  support = Cal_MemAlloc(int, n);
+  if (support == Cal_Nil(int)) {
+    Cal_MemFree(interact);
+    return(0);
+  }
+  bins = bddManager->uniqueTable[0]->bins;
+  numBins = bddManager->uniqueTable[0]->numBins;
+  for (i=0; i<numBins; i++){
+    for (bddNode = bins[i]; bddNode; bddNode = nextBddNode) {
+      Cal_Bdd_t internalBdd;
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodeGetThenBdd(bddNode, internalBdd);
+      for (k = 0; k < n; k++) {
+        support[k] = 0;
+      }
+      ddSuppInteract(bddManager, internalBdd, support);
+      ddClearLocal(internalBdd);
+      ddUpdateInteract(bddManager, support);
+    }
+  }
+  /* If there are some results pending in the pipeline, we need to
+     take those into account as well */
+
+  if (bddManager->pipelineState == CREATE){
+    CalRequestNode_t **requestNodeListArray =
+        bddManager->requestNodeListArray; 
+    Cal_Bdd_t resultBdd;
+    for (i=0;
+         i<bddManager->pipelineDepth-bddManager->currentPipelineDepth;
+         i++){
+      for (bddNode = *requestNodeListArray; bddNode;
+           bddNode = nextBddNode){ 
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        Cal_Assert(CalBddNodeIsForwarded(bddNode));
+        CalBddNodeGetThenBdd(bddNode, resultBdd);
+        Cal_Assert(CalBddIsForwarded(resultBdd) == 0);
+        for (k = 0; k < n; k++) {
+          support[k] = 0;
+        }
+        ddSuppInteract(bddManager, resultBdd, support);
+        ddClearLocal(resultBdd);
+        ddUpdateInteract(bddManager, support);
+      }
+      requestNodeListArray++;
+    }
+  }
+  
+  
+  Cal_MemFree(support);
+  return(1);
+  
+} /* end of CalInitInteract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find the support of f.]
+
+  Description [Performs a DFS from f. Uses the LSB of the then pointer
+  as visited flag.]
+
+  SideEffects [Accumulates in support the variables on which f depends.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddSuppInteract(Cal_BddManager_t *bddManager, Cal_Bdd_t f, int *support)
+{
+  Cal_Bdd_t thenBdd, elseBdd;
+
+  if (CalBddIsBddConst(f) || CalBddIsMarked(f)){
+    return;
+  }
+  support[f.bddId-1] = 1;
+  CalBddGetThenBdd(f, thenBdd);
+  CalBddGetElseBdd(f, elseBdd);
+  ddSuppInteract(bddManager, thenBdd, support);
+  ddSuppInteract(bddManager, elseBdd, support);
+  CalBddMark(f);
+  return;
+} /* end of ddSuppInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a DFS from f, clearing the LSB of the then pointers.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddClearLocal(Cal_Bdd_t f)
+{
+  Cal_Bdd_t thenBdd;
+  Cal_Bdd_t elseBdd;
+  CalBddGetElseBdd(f, elseBdd);  
+  if (CalBddIsBddConst(f) || !CalBddIsMarked(f)){
+    return;
+  }
+  /* clear visited flag */
+  CalBddUnmark(f);
+  CalBddGetThenBdd(f, thenBdd);
+  CalBddGetElseBdd(f, elseBdd);
+  ddClearLocal(thenBdd);
+  ddClearLocal(elseBdd);
+  return;
+} /* end of ddClearLocal */
+
+
+/**Function********************************************************************
+
+  Synopsis [Marks as interacting all pairs of variables that appear in
+  support.]
+
+  Description [If support[i] == support[j] == 1, sets the (i,j) entry
+  of the interaction matrix to 1.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddUpdateInteract(Cal_BddManager_t *bddManager, int *support)
+{
+  int i,j;
+  int n = bddManager->numVars;
+  
+  for (i = 0; i < n-1; i++) {
+	if (support[i] == 1) {
+      for (j = i+1; j < n; j++) {
+		if (support[j] == 1) {
+          CalSetInteract(bddManager, i, j);
+		}
+      }
+	}
+  }
+} /* end of ddUpdateInteract */
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calMem.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calMem.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calMem.c	(revision 8)
@@ -0,0 +1,723 @@
+/**CFile*****************************************************************
+
+  FileName    [calMem.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for memory management.]
+
+  Description [Contains allocation, free, resize routines. Also has
+  routines for managing records of fixed size.]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu). Originally
+  written by David Long.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision   [$Id: calMem.c,v 1.4 2002/08/25 05:29:59 fabio Exp $]
+
+******************************************************************************/
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#endif
+#include "calMem.h"
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct BlockStruct *Block;
+typedef struct BlockStruct Block_t;
+typedef struct SegmentStruct *Segment;
+typedef struct SegmentStruct Segment_t;
+typedef struct ListStruct *List;
+typedef struct ListStruct List_t;
+typedef struct Cal_RecMgrStruct Cal_RecMgr_t;
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* #define DEBUG_MEM */
+#define MAGIC_COOKIE 0x34f21ab3l
+#define MAGIC_COOKIE1 0x432fa13bl
+struct SegmentStruct
+{
+  Cal_Pointer_t baseAddress;
+  Cal_Address_t limit;
+};
+
+struct BlockStruct
+{
+  int used;
+  int sizeIndex;
+  unsigned long dummy;
+  Block_t *next;
+  Block_t *prev;
+  Segment seg;
+};
+#define HEADER_SIZE ((Cal_Address_t)CAL_ROUNDUP(sizeof(Block_t)))
+#define MAX_SIZEINDEX (8*sizeof(Cal_Address_t)-2)
+#define MAX_SEG_SIZE ((Cal_Address_t)1 << MAX_SIZEINDEX)
+#define MAX_SIZE ((Cal_Address_t)(MAX_SEG_SIZE-HEADER_SIZE))
+#define NICE_BLOCK_SIZE ((Cal_Address_t)PAGE_SIZE-CAL_ROUNDUP(sizeof(Block_t)))
+#define ALLOC_SIZE NICE_BLOCK_SIZE
+#define MIN_ALLOC_SIZEINDEX 15
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+struct ListStruct
+{
+  List_t *next;
+};
+
+struct Cal_RecMgrStruct
+{
+  int size;
+  int recsPerBlock;
+  List free;
+  List blocks;
+  int numBlocks;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static Cal_Address_t blockAllocation;
+static Block avail[MAX_SIZEINDEX+1];
+
+
+/* Bogus segment for initialization */
+
+static Segment_t dummySeg={(Cal_Pointer_t)0, (Cal_Address_t)0};
+
+
+/* Current segment */
+
+static Segment currSeg= &dummySeg;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#define SBRK(size) ((Cal_Pointer_t)sbrk((long)(size)))
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CeilingLog2(Cal_Address_t i);
+static int BlockSizeIndex(Cal_Address_t size);
+static void AddToFreeList(Block b);
+static Block RemoveFromFreeList(Block b);
+static Block Buddy(Block b);
+static void TrimToSize(Block b, int sizeIndex);
+static void MergeAndFree(Block b);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [Prints an error message and exits.]
+
+  Description        [Prints an error message and exits.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+Cal_MemFatal(char *message)
+{
+  fprintf(stderr, "Memory management library: error: %s\n", message);
+  exit(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Returns the memory allocated.]
+
+  Description        [Returns the memory allocated.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+Cal_Address_t
+Cal_MemAllocation(void)
+{
+  return (blockAllocation);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Allocates a new block of the specified size.]
+
+  Description        [Allocates a new block of the specified size.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+Cal_Pointer_t
+Cal_MemGetBlock(Cal_Address_t size)
+{
+  int i;
+  int sizeIndex;
+  int allocSizeIndex;
+  int newSeg;
+  Cal_Address_t allocSize;
+  Cal_Pointer_t sbrkRet;
+  Block b;
+
+  if ((sizeIndex = BlockSizeIndex(size)) < 0) return ((Cal_Pointer_t)0);
+  
+  /* Find smallest free block which is large enough. */
+  for (i = sizeIndex; i <= MAX_SIZEINDEX && !avail[i]; ++i);
+  if (i > MAX_SIZEINDEX) {
+    /* We must get more storage; don't allocate less than */
+    /* 2^MIN_ALLOC_SIZE_INDEX */
+    if (sizeIndex < MIN_ALLOC_SIZEINDEX) allocSizeIndex=MIN_ALLOC_SIZEINDEX;
+    else allocSizeIndex=sizeIndex;
+    allocSize=((Cal_Address_t)1 << allocSizeIndex);
+    
+    /* Pad current segment to be a multiple of 2^allocSizeIndex in */
+    /* length. */
+    allocSize += ((currSeg->limit + allocSize - 1) &
+                  ~(allocSize - 1)) - currSeg->limit;
+    if ((sbrkRet=(Cal_Pointer_t)SBRK(0)) !=
+        (Cal_Pointer_t)((Cal_Address_t)currSeg->baseAddress+currSeg->limit) || 
+        allocSize+currSeg->limit > MAX_SEG_SIZE) {
+      
+      /* Segment is too large or someone else has moved the break. */
+      /* Pad to get to appropriate boundary. */
+      allocSize=CAL_ROUNDUP((Cal_Address_t)sbrkRet)-(Cal_Address_t)sbrkRet;
+      
+      /* Pad allocation request with storage for new segment */
+      /* information and indicate that a new segment must be */
+        /* created. */
+      allocSize+=((Cal_Address_t)1 << allocSizeIndex)+CAL_ROUNDUP(sizeof(Segment_t));
+      newSeg=1;
+    }
+    else newSeg=0;
+    sbrkRet=(Cal_Pointer_t)SBRK(allocSize);
+    if (sbrkRet == (Cal_Pointer_t) -1) Cal_MemFatal("Cal_MemGetBlock: allocation failed");
+    blockAllocation += allocSize;
+    if (newSeg){
+      currSeg = (Segment) CAL_ROUNDUP((Cal_Address_t)sbrkRet);
+      currSeg->baseAddress=(Cal_Pointer_t)((Cal_Address_t)currSeg+CAL_ROUNDUP(sizeof(Segment_t)));
+      currSeg->limit=0;
+      /* Readjust allocation size. */
+      allocSize=(1l << allocSizeIndex);
+      }
+    /* Carve allocated space up into blocks and add to free lists. */
+    while (allocSize){
+      size = allocSize - (allocSize & (allocSize-1));
+      b = (Block) ((Cal_Address_t)currSeg->baseAddress+currSeg->limit);
+      b->sizeIndex = CeilingLog2(size);
+      b->seg = currSeg;
+      AddToFreeList(b);
+        currSeg->limit += size;
+        allocSize -= size;
+    }
+    /* Find free block of appropriate size. */
+    for (i=sizeIndex; i <= MAX_SIZEINDEX && !avail[i]; ++i);
+  }
+  b = RemoveFromFreeList(avail[i]);
+  TrimToSize(b, sizeIndex);
+  return ((Cal_Pointer_t)((Cal_Address_t)b + HEADER_SIZE));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Frees the block.]
+
+  Description        [Frees the block.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/void
+Cal_MemFreeBlock(Cal_Pointer_t p)
+{
+  Block b;
+
+  if (!p) return;
+  b = (Block) ((Cal_Address_t)p-HEADER_SIZE);
+  if (!b->used) Cal_MemFatal("Cal_MemFreeBlock: block not in use");
+  if (b->sizeIndex < 0 || b->sizeIndex > MAX_SIZEINDEX) Cal_MemFatal("Cal_MemFreeBlock: invalid block header");
+  MergeAndFree(b);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [Expands or contracts the block to a new size.
+  We try to avoid moving the block if possible. ]
+
+  Description        [Expands or contracts the block to a new size.
+  We try to avoid moving the block if possible. ]  
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+Cal_Pointer_t
+Cal_MemResizeBlock(Cal_Pointer_t p, Cal_Address_t newSize)
+{
+  int newSizeIndex;
+  Block b;
+  Block bb;
+  Cal_Pointer_t q;
+  Cal_Address_t oldSize;
+
+  if (!p) return (Cal_MemGetBlock(newSize));
+  b = (Block) ((Cal_Address_t)p - HEADER_SIZE);
+  if (!b->used) Cal_MemFatal("Cal_MemResizeBlock: block not in use");
+  if (b->sizeIndex < 0 || b->sizeIndex > MAX_SIZEINDEX){
+    Cal_MemFatal("Cal_MemResizeBlock: invalid block header");
+  }
+  if ((newSizeIndex = BlockSizeIndex(newSize)) < 0){
+    Cal_MemFreeBlock(p);
+    return ((Cal_Pointer_t)0);
+  }
+  if (b->sizeIndex >= newSizeIndex){
+    /* Shrink block. */
+    TrimToSize(b, newSizeIndex);
+    return (p);
+  }
+  oldSize=(1l << b->sizeIndex) - HEADER_SIZE;
+  /* Try to expand by adding buddies at higher addresses. */
+  for (bb=Buddy(b);
+       bb && (Cal_Address_t)b < (Cal_Address_t)bb && !bb->used && bb->sizeIndex == b->sizeIndex;
+       bb=Buddy(b)) {
+    RemoveFromFreeList(bb);
+    if (++(b->sizeIndex) == newSizeIndex) return (p);
+  }
+  /* Couldn't expand all the way to needed size; allocate a new block */
+  /* and move the contents of the old one. */
+  q = (Cal_Pointer_t) Cal_MemGetBlock(newSize);
+  Cal_MemCopy(q, p, oldSize);
+  MergeAndFree(b);
+  return (q);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Allocates a record from the specified record manager. ]
+
+  Description        [Allocates a record from the specified record manager. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+Cal_Pointer_t
+Cal_MemNewRec(Cal_RecMgr mgr)
+{
+  int i;
+  Cal_Pointer_t p;
+  List new_;
+  
+  if (!mgr->free) {
+    /* Allocate a new block. */
+    new_ = (List) Cal_MemGetBlock(ALLOC_SIZE);
+    mgr->numBlocks++;
+    new_->next=mgr->blocks;
+    mgr->blocks=new_;
+    mgr->free=(List)((Cal_Address_t)new_+CAL_ROUNDUP(sizeof(List_t)));
+    p=(Cal_Pointer_t)(mgr->free);
+    /* Carve the block into pieces. */
+    for (i=1; i < mgr->recsPerBlock; ++i) {
+      ((List)p)->next=(List)((Cal_Address_t)p+mgr->size);
+#if defined(DEBUG_MEM)
+      if (mgr->size >= sizeof(long)+sizeof(List_t))
+        *(long *)(sizeof(List_t)+(Cal_Address_t)p)=MAGIC_COOKIE;
+#endif
+      p=(Cal_Pointer_t)((Cal_Address_t)p+mgr->size);
+    }
+    ((List)p)->next=0;
+#if defined(DEBUG_MEM)
+    if (mgr->size >= sizeof(long)+sizeof(List_t)){
+      *(long *)(sizeof(List_t)+(Cal_Address_t)p)=MAGIC_COOKIE;
+    }
+#endif
+  }
+  new_ = mgr->free;
+#if defined(DEBUG_MEM)
+  if (mgr->size >= sizeof(long)+sizeof(List_t)){
+    if (*(long *)(sizeof(List_t)+(Cal_Address_t)new_) != MAGIC_COOKIE)
+      fprintf(stderr, "record at 0x%lx may be in use\n", (Cal_Address_t)new_);
+    else
+      *(long *)(sizeof(struct
+                       list_)+(Cal_Address_t)new)=MAGIC_COOKIE1;
+  }
+#endif
+  mgr->free = mgr->free->next;
+  return ((Cal_Pointer_t)new_);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Frees a record managed by the indicated record manager. ]
+
+  Description        [Frees a record managed by the indicated record manager. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+Cal_MemFreeRec(Cal_RecMgr mgr, Cal_Pointer_t rec)
+{
+#if defined(DEBUG_MEM)
+  if (mgr->size >= sizeof(long)+sizeof(List_t))
+    if (*(long *)(sizeof(List_t)+(Cal_Address_t)rec) == MAGIC_COOKIE)
+      fprintf(stderr, "record at 0x%lx may already be freed\n", (Cal_Address_t)rec);
+#endif
+  ((List)rec)->next=mgr->free;
+#if defined(DEBUG_MEM)
+  if (mgr->size >= sizeof(long)+sizeof(List_t))
+    *(long *)(sizeof(List_t)+(Cal_Address_t)rec)=MAGIC_COOKIE;
+#endif
+  mgr->free=(List)rec;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [Creates a new record manager with the given  record size.]
+
+  Description        [Creates a new record manager with the given  record size.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+Cal_RecMgr
+Cal_MemNewRecMgr(int size)
+{
+  Cal_RecMgr mgr;
+
+  if (size < sizeof(List_t)) size=sizeof(List_t);
+  size=CAL_ROUNDUP(size);
+  if (size > ALLOC_SIZE-CAL_ROUNDUP(sizeof(List_t)))
+    Cal_MemFatal("Cal_MemNewRecMgr: record size too large");
+  mgr = (Cal_RecMgr)Cal_MemGetBlock((Cal_Address_t)sizeof(Cal_RecMgr_t));
+  mgr->size=size;
+  mgr->recsPerBlock=(ALLOC_SIZE-CAL_ROUNDUP(sizeof(List_t)))/size;
+  mgr->free=0;
+  mgr->blocks=0;
+  mgr->numBlocks = 0;
+  return (mgr);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Frees all the storage associated with the specified record manager.]
+
+  Description        [Frees all the storage associated with the specified record manager.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+Cal_MemFreeRecMgr(Cal_RecMgr mgr)
+{
+  List p, q;
+  for (p=mgr->blocks; p; p=q){
+    q=p->next;
+    Cal_MemFreeBlock((Cal_Pointer_t)p);
+  }
+  Cal_MemFreeBlock((Cal_Pointer_t)mgr);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+  CommandName        [optional] 	   
+
+  CommandSynopsis    [optional]  
+
+  CommandArguments   [optional]  
+
+  CommandDescription [optional]  
+
+******************************************************************************/
+static int
+CeilingLog2(Cal_Address_t i)
+{
+  Cal_Address_t j;
+  int result;
+
+  for (result=0, j=1; j < i; ++result, j*=2);
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [BlockSizeIndex(size) return the coded size for a block. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+  CommandName        [optional] 	   
+
+  CommandSynopsis    [optional]  
+
+  CommandArguments   [optional]  
+
+  CommandDescription [optional]  
+
+******************************************************************************/
+static int
+BlockSizeIndex(Cal_Address_t size)
+{
+  if (size < 1)
+    return (-1);
+  if (size > MAX_SIZE)
+    Cal_MemFatal("BlockSizeIndex: block size too large");
+  else
+    size+=HEADER_SIZE;
+  return (CeilingLog2(size));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [AddToFreeList(b) adds b to the appropriate free list. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+  CommandName        [optional] 	   
+
+  CommandSynopsis    [optional]  
+
+  CommandArguments   [optional]  
+
+  CommandDescription [optional]  
+
+******************************************************************************/
+static void
+AddToFreeList(Block b)
+{
+  int i;
+
+  i=b->sizeIndex;
+  if (!avail[i]){
+      b->next=b;
+      b->prev=b;
+      avail[i]=b;
+  }
+  else {
+    b->next=avail[i]->next;
+    avail[i]->next->prev=b;
+    avail[i]->next=b;
+    b->prev=avail[i];
+  }
+  b->used=0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [RemoveFromFreeList(b) removes b from the free list which it is on. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+  CommandName        [optional] 	   
+
+  CommandSynopsis    [optional]  
+
+  CommandArguments   [optional]  
+
+  CommandDescription [optional]  
+
+******************************************************************************/
+static Block
+RemoveFromFreeList(Block b)
+{
+  int i;
+
+  i=b->sizeIndex;
+  if (b->next == b)
+    avail[i]=0;
+  else {
+    b->next->prev=b->prev;
+    b->prev->next=b->next;
+    if (avail[i] == b) avail[i]=b->next;
+  }
+  b->used=1;
+  return (b);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [Buddy(b) returns the Buddy block of b, or null if there is no  Buddy. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+  CommandName        [optional] 	   
+
+  CommandSynopsis    [optional]  
+
+  CommandArguments   [optional]  
+
+  CommandDescription [optional]  
+
+******************************************************************************/
+
+static Block
+Buddy(Block b)
+{
+  Cal_Address_t Buddy_offset;
+
+  Buddy_offset=(Cal_Address_t)(((Cal_Address_t)b-(Cal_Address_t)b->seg->baseAddress) ^
+                               ((Cal_Address_t)1 << b->sizeIndex));
+  if (Buddy_offset < b->seg->limit)
+    return ((Block)((Cal_Address_t)b->seg->baseAddress+Buddy_offset));
+  else
+    return ((Block)0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [TrimToSize(b, sizeIndex) repeatedly splits b until it has  the indicated size.  Blocks which are split off are added to the appropriate free list. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+  CommandName        [optional] 	   
+
+  CommandSynopsis    [optional]  
+
+  CommandArguments   [optional]  
+
+  CommandDescription [optional]  
+
+******************************************************************************/
+static void
+TrimToSize(Block b, int sizeIndex)
+{
+  Block bb;
+
+  while (b->sizeIndex > sizeIndex) {
+    b->sizeIndex--;
+    bb=Buddy(b);
+    bb->sizeIndex=b->sizeIndex;
+    bb->seg=b->seg;
+    AddToFreeList(bb);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [MergeAndFree(b) repeatedly merges b its Buddy until b has no Buddy or the Buddy isn't free, then adds the result to the  appropriate free list. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+  CommandName        [optional] 	   
+
+  CommandSynopsis    [optional]  
+
+  CommandArguments   [optional]  
+
+  CommandDescription [optional]  
+
+******************************************************************************/
+static void
+MergeAndFree(Block b)
+{
+  Block bb;
+  
+  for (bb=Buddy(b); bb && !bb->used && bb->sizeIndex == b->sizeIndex;
+       bb=Buddy(b)) { 
+    RemoveFromFreeList(bb);
+    if ((Cal_Address_t)bb < (Cal_Address_t)b) b=bb;
+    b->sizeIndex++;
+  }
+  AddToFreeList(b);
+}
Index: /vis_dev/glu-2.1/src/calBdd/calMem.h
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calMem.h	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calMem.h	(revision 8)
@@ -0,0 +1,116 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [calMem.h]
+
+  PackageName [cal]
+
+  Synopsis    [Header file for memory management]
+
+  Description [ ]
+
+  SeeAlso     []
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu). Originally written by David Long. ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calMem.h,v 1.3 2002/08/28 16:01:01 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CAL_MEM
+#define _CAL_MEM
+
+#include <stdio.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* CAL_ALLOC_ALIGNMENT is the alignment for all storage returned by the */
+/* storage allocation routines. */
+/* was 16 for __osf__ systems, 8 otherwise */
+
+#define CAL_ALLOC_ALIGNMENT sizeof(void *)
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct Cal_RecMgrStruct * Cal_RecMgr;
+typedef void *Cal_Pointer_t;
+typedef size_t Cal_Address_t;
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#ifndef EXTERN
+#  ifdef __cplusplus
+#    define EXTERN	extern "C"
+#  else
+#    define EXTERN	extern
+#  endif
+#endif
+#define Cal_Nil(obj) ((obj *)0)
+#define USE_OS_MEMORY_MANAGEMENT
+#ifdef USE_OS_MEMORY_MANAGEMENT
+#define Cal_MemAlloc(type, num) ((type *) malloc(sizeof(type) * (num)))
+#define Cal_MemRealloc(type, obj, num)	\
+    (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
+    ((type *) malloc(sizeof(type) * (num)))
+#define Cal_MemFree(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#else
+#define Cal_MemAlloc(type, num) ((type *) Cal_MemGetBlock(sizeof(type) * (num)))
+#define Cal_MemRealloc(type, obj, num)	\
+    (obj) ? ((type *) Cal_MemResizeBlock((Cal_Pointer_t) obj, sizeof(type) * (num))) : \
+    ((type *) Cal_MemGetBlock(sizeof(type) * (num)))
+#define Cal_MemFree(obj) ((obj) ? (Cal_MemFreeBlock((Cal_Pointer_t) (obj)), (obj) = 0) : 0)
+#endif
+#define Cal_MemCopy(dest, src, size)  ((void *) memcpy((void *)dest, (const void *)src, (size_t)size));
+#define Cal_MemZero(ptr, size) ((void)memset((void *)(ptr), 0, (Cal_Address_t)(size)))
+
+/* Round a size up for alignment */
+
+#define CAL_ROUNDUP(size) ((((size)+CAL_ALLOC_ALIGNMENT-1)/CAL_ALLOC_ALIGNMENT)*CAL_ALLOC_ALIGNMENT)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+EXTERN void Cal_MemFatal(char *message);
+EXTERN Cal_Address_t Cal_MemAllocation(void);
+EXTERN Cal_Pointer_t Cal_MemGetBlock(Cal_Address_t size);
+EXTERN void Cal_MemFreeBlock(Cal_Pointer_t p);
+EXTERN Cal_Pointer_t Cal_MemResizeBlock(Cal_Pointer_t p, Cal_Address_t newSize);
+EXTERN Cal_Pointer_t Cal_MemNewRec(Cal_RecMgr mgr);
+EXTERN void Cal_MemFreeRec(Cal_RecMgr mgr, Cal_Pointer_t rec);
+EXTERN Cal_RecMgr Cal_MemNewRecMgr(int size);
+EXTERN void Cal_MemFreeRecMgr(Cal_RecMgr mgr);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CAL */
Index: /vis_dev/glu-2.1/src/calBdd/calMemoryManagement.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calMemoryManagement.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calMemoryManagement.c	(revision 8)
@@ -0,0 +1,593 @@
+/**CFile***********************************************************************
+
+  FileName    [calMemoryManagement.c]
+
+  PackageName [cal]
+
+  Synopsis    [Special memory management routines specific to CAL.]
+
+  Description [Functions for managing the system memory using a set of 
+              nodeManagers. Each nodeManager manages a set of fixed size
+              nodes obtained from a set of pages. When additional memory
+              is required, nodeManager obtains a new page from the pageManager.
+              The new page is divided into ( PAGE_SIZE/NODE_SIZE ) number of
+              nodes.]
+
+  SeeAlso     []
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+              ] 
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calMemoryManagement.c,v 1.6 2005/04/30 01:50:53 fabio Exp $]
+
+******************************************************************************/
+#include "malloc.h"
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#ifndef HAVE_VALLOC
+#define __NOVALLOC__
+#else
+#if HAVE_VALLOC != 1
+#define __NOVALLOC__
+#endif
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int PageManagerExpandStorage(CalPageManager_t * pageManager);
+static CalAddress_t * PageAlign(CalAddress_t * p);
+static int SegmentToPageList(CalAddress_t * segment, int numPages, CalAddress_t * lastPointer);
+
+/**AutomaticEnd***************************************************************/
+
+/*
+ * object: pageManager
+ * operations: Init, Quit, AllocPage, FreePage, Print
+ */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Name        [CalPageMangerInit]
+
+  Synopsis    [Initializes a pageManager.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+CalPageManager_t *
+CalPageManagerInit(int numPagesPerSegment)
+{
+  CalPageManager_t *pageManager;
+  pageManager = Cal_MemAlloc(CalPageManager_t, 1);
+  pageManager->totalNumPages = 0;
+  pageManager->numSegments = 0;
+  pageManager->numPagesPerSegment = numPagesPerSegment;
+  pageManager->maxNumSegments = MAX_NUM_SEGMENTS;
+  pageManager->pageSegmentArray 
+      = Cal_MemAlloc(CalAddress_t *, pageManager->maxNumSegments);
+  pageManager->numPagesArray 
+      = Cal_MemAlloc(int, pageManager->maxNumSegments);
+  pageManager->freePageList = Cal_Nil(CalAddress_t);
+  if(PageManagerExpandStorage(pageManager) == FALSE){
+    Cal_MemFree(pageManager->pageSegmentArray);
+    Cal_MemFree(pageManager);
+    return Cal_Nil(CalPageManager_t);
+  }
+  return pageManager;
+}
+
+
+/**Function********************************************************************
+
+  Name        [CalPageMangerQuit]
+
+  Synopsis    [Frees pageManager and associated pages.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalPageManagerQuit(
+  CalPageManager_t * pageManager)
+{
+  int i;
+  if(pageManager == Cal_Nil(CalPageManager_t)){
+    return 1;
+  }
+  for(i = 0; i < pageManager->numSegments; i++){
+    free(pageManager->pageSegmentArray[i]);
+  }
+  Cal_MemFree(pageManager->pageSegmentArray);
+  Cal_MemFree(pageManager->numPagesArray);
+  Cal_MemFree(pageManager);
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Name        [CalPageMangerPrint]
+
+  Synopsis    [Prints address of each memory segment and address of each page.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalPageManagerPrint(
+  CalPageManager_t * pageManager)
+{
+  int i;
+  CalAddress_t *page;
+  printf("****************** pageManager ********************\n");
+  printf("allocationList:\n");
+  for(i = 0; i < pageManager->numSegments; i++){
+    page = pageManager->pageSegmentArray[i];
+    printf("%lx%c", (CalAddress_t)page, (i+1)%5?' ':'\n');
+  }
+  printf("\n");
+  printf("freePageList:\n");
+  i = 0;
+  page = pageManager->freePageList;
+  while(page){
+    printf("%lx%c", (CalAddress_t)page, (i+1)%5?' ':'\n');
+    i++;
+    page = (CalAddress_t *)*page;
+  }
+  printf("\n");
+}
+
+
+/**Function********************************************************************
+
+  Name        [CalNodeManagerInit]
+
+  Synopsis    [Initializes a node manager.]
+
+  Description [optional]
+
+  SideEffects []
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+CalNodeManager_t *
+CalNodeManagerInit(CalPageManager_t * pageManager)
+{
+  CalNodeManager_t *nodeManager;
+  nodeManager = Cal_MemAlloc(CalNodeManager_t, 1);
+  nodeManager->freeNodeList = Cal_Nil(CalBddNode_t);
+  nodeManager->pageManager = pageManager;
+  nodeManager->numPages = 0;
+  nodeManager->maxNumPages = 10;
+  nodeManager->pageList = Cal_MemAlloc(CalAddress_t *,
+                                        nodeManager->maxNumPages);
+  return nodeManager;
+}
+
+
+/**Function********************************************************************
+
+  Name        [CalNodeManagerQuit]
+
+  Synopsis    [Frees a node manager.]
+
+  Description [optional]
+
+  SideEffects [The associated nodes are lost.]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalNodeManagerQuit(CalNodeManager_t * nodeManager)
+{
+  if(nodeManager == Cal_Nil(CalNodeManager_t)){
+    return 1;
+  }
+  else{
+    int i;
+    for (i = 0; i < nodeManager->numPages; i++){
+      CalPageManagerFreePage(nodeManager->pageManager,
+                             nodeManager->pageList[i]);
+    }
+    Cal_MemFree(nodeManager->pageList);
+    Cal_MemFree(nodeManager);
+    return 0;
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Name        [CalNodeManagerPrint]
+
+  Synopsis    [Prints address of each free node.]
+
+  Description [optional]
+
+  SideEffects []
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalNodeManagerPrint(
+  CalNodeManager_t * nodeManager)
+{
+  int i;
+  CalBddNode_t *node;
+  printf("****************** nodeManager ********************\n");
+  printf("freeNodeList:\n");
+  i = 0;
+  node = nodeManager->freeNodeList;
+  while(node){
+    printf("%lx%c", (CalAddress_t)node, (i+1)%5?' ':'\n');
+    i++;
+    node = node->nextBddNode;
+  }
+  printf("\n");
+}
+
+
+/**Function********************************************************************
+
+  Name        [PageMangerAllocPage]
+
+  Synopsis    [Allocs a new page.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+CalAddress_t *
+CalPageManagerAllocPage(CalPageManager_t * pageManager)
+{
+  CalAddress_t *page;
+  char buffer[512];
+  if(pageManager->freePageList == Cal_Nil(CalAddress_t)){
+    if(PageManagerExpandStorage(pageManager) == FALSE){
+      sprintf(buffer,
+              "out of memory : Number of pages allocated = %d\n", 
+              pageManager->totalNumPages);
+      CalBddFatalMessage(buffer);
+    }
+  }
+  page = pageManager->freePageList;
+  pageManager->freePageList = (CalAddress_t *)*page;
+  return page;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Name        [PageMangerFreePage]
+
+  Synopsis    [Free a page.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalPageManagerFreePage(CalPageManager_t * pageManager, CalAddress_t * page)
+{
+  *page = (CalAddress_t)(pageManager->freePageList);
+  pageManager->freePageList = page;
+}
+
+
+/**Function********************************************************************
+
+  Name        [PageManagerExpandStorage]
+
+  Synopsis    [Allocates a segment of memory to expand the storage managed by
+              pageManager. The allocated segment is divided into free pages
+              which are linked as a freePageList.]
+
+  Description [optional]
+
+  SideEffects [The size of the segment is stored in one of the fields
+              of page manager - numPagesPerSegment. If a memory
+              segment of a specific size cannot be allocated, the
+              routine calls itself recursively by reducing
+              numPagesPerSegment by a factor of 2.]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+PageManagerExpandStorage(CalPageManager_t * pageManager)
+{
+  CalAddress_t *p;
+  CalAddress_t *segment;
+  int numUsefulPages;
+
+  int numPagesPerSegment = pageManager->numPagesPerSegment;
+
+#ifdef __NOVALLOC__
+  p = (CalAddress_t *) malloc(numPagesPerSegment*PAGE_SIZE);
+#else
+  p = (CalAddress_t *) valloc(numPagesPerSegment*PAGE_SIZE);
+#endif
+  /* Just check the page boundary correctness */
+  Cal_Assert(((CalAddress_t)p & ((1 << LG_PAGE_SIZE)-1)) == 0);
+  if(p == Cal_Nil(CalAddress_t)){
+    numPagesPerSegment = numPagesPerSegment / 2;
+    if(numPagesPerSegment < MIN_NUM_PAGES_PER_SEGMENT){
+      return FALSE;
+    }
+    pageManager->numPagesPerSegment = numPagesPerSegment;
+    return PageManagerExpandStorage(pageManager);  
+  }
+
+#ifdef __NOVALLOC__
+  /* No need to do it anymore, since I am using valloc */
+  /* align the memory segment to a page boundary */
+  segment = PageAlign(p);  
+
+  /* if memory segment is already page aligned, all pages in the memory
+   * segment are useful, otherwise, one page is wasted
+   */
+  if(segment == p){
+    numUsefulPages = numPagesPerSegment;
+  }
+  else{
+    numUsefulPages = numPagesPerSegment - 1;
+  }
+#else
+  segment = p;
+  numUsefulPages = numPagesPerSegment;
+#endif
+  
+  /* Initialize the pages  */
+  memset((char *)segment, 0, numUsefulPages*PAGE_SIZE);
+
+  /* Keep track of the number of pages allocated */
+  pageManager->totalNumPages += numUsefulPages;
+  
+  /* increase the size of the allocation list if neccessary */
+  if(pageManager->numSegments == pageManager->maxNumSegments){
+    pageManager->maxNumSegments = pageManager->maxNumSegments * 2;
+    pageManager->pageSegmentArray = Cal_MemRealloc(CalAddress_t *,
+                                                   pageManager->pageSegmentArray, 
+                                                   pageManager->maxNumSegments);
+    pageManager->numPagesArray = Cal_MemRealloc(int,
+                                                pageManager->numPagesArray, 
+                                                pageManager->maxNumSegments);
+    
+  }
+
+  pageManager->pageSegmentArray[pageManager->numSegments] = p;
+  pageManager->numPagesArray[pageManager->numSegments++] =
+      numUsefulPages;
+  
+  SegmentToPageList(segment, numUsefulPages, pageManager->freePageList);
+  pageManager->freePageList = segment;
+  return TRUE;
+}
+
+
+/**Function********************************************************************
+
+  Name        [PageAlign]
+
+  Synopsis    [Return page aligned address greater than or equal to
+  the pointer.]
+
+  Description [optional]
+
+  SideEffects []
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static CalAddress_t *
+PageAlign(
+  CalAddress_t * p)
+{
+  if((CalAddress_t)p & (PAGE_SIZE - 1)){
+    p = (CalAddress_t *)( (CalAddress_t)p >> LG_PAGE_SIZE );
+    p = (CalAddress_t *)( ((CalAddress_t)p << LG_PAGE_SIZE) + PAGE_SIZE );
+  }
+  return p;
+}
+
+
+/**Function********************************************************************
+
+  Name        [SegmentToPageList]
+
+  Synopsis    [Converts a memory segment into a linked list of pages.
+              if p is a pointer to a page, *p contains address of the next page
+              if p is a pointer to the last page, *p contains lastPointer.]
+
+  Description [optional]
+
+  SideEffects []
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+SegmentToPageList(CalAddress_t * segment,
+                  int  numPages,
+                  CalAddress_t * lastPointer)
+{
+  int i;
+  unsigned long thisPageOffset, nextPageOffset;
+
+  if(numPages > 0){
+    for(i = 0; i < numPages - 1; i++){
+      thisPageOffset = (i<<LG_PAGE_SIZE)/sizeof(CalAddress_t);
+      nextPageOffset = ((i+1)<<LG_PAGE_SIZE)/sizeof(CalAddress_t);
+      *(segment + thisPageOffset) =
+          (CalAddress_t)(segment + nextPageOffset);
+    }
+    thisPageOffset = ((numPages - 1)<<LG_PAGE_SIZE)/sizeof(CalAddress_t);
+    *(segment + thisPageOffset) = (CalAddress_t)lastPointer;
+  }
+  else{
+    CalBddFatalMessage("out of memory");
+  }
+  return 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Module Testing                                                            */
+/*---------------------------------------------------------------------------*/
+#ifdef PAGE_MANAGER
+main(argc, argv)
+int argc;
+char **argv;
+{
+  CalPageManager_t *pageManager;
+  CalAddress_t *page, *pageArray[10];
+  int i;
+
+  pageManager = CalPageManagerInit();
+  CalPageManagerPrint(pageManager);
+
+  page = CalPageManagerAllocPage(pageManager);
+  printf("PAGE - %x\n", (CalAddress_t)page);
+  CalPageManagerPrint(pageManager);
+
+  PageManagerFreePage(pageManager, page);
+  CalPageManagerPrint(pageManager);
+
+  printf("Cal_MemAllocATING PAGES\n");
+  for(i = 0; i < 10; i++){
+    pageArray[i] = CalPageManagerAllocPage(pageManager);
+    CalPageManagerPrint(pageManager);
+    printf("\n");
+  }
+  printf("\n");
+
+  printf("FREEING PAGES\n");
+  for(i = 0; i < 10; i++){
+    PageManagerFreePage(pageManager, pageArray[i] );
+    CalPageManagerPrint(pageManager);
+    printf("\n");
+  }    
+  printf("\n");
+  CalPageManagerQuit(pageManager);
+}
+#endif
+
+#ifdef NODE_MANAGER
+main(argc, argv)
+int argc;
+char **argv;
+{
+  CalPageManager_t *pageManager;
+  CalNodeManager_t *nodeManagerArray[5], *nodeManager;
+  CalBddNode_t *node, *nodeArray[5][10];
+  int numNodeManagers = 5;
+  int numNodes = 10;
+  int i,j;
+  
+
+  pageManager = CalPageManagerInit();
+  /*CalNodeManagerPrint(nodeManager);*/
+
+  printf("Allocating Nodes\n");
+  for(i = 0; i < numNodeManagers; i++){
+    nodeManagerArray[i] = CalNodeManagerInit(pageManager);
+    for (j=0; j < numNodes; j++){
+      CalNodeManagerAllocNode(nodeManagerArray[i], nodeArray[i][j]);
+      CalBddNodePutRefCount(nodeArray[i][j], i+j);
+    }
+  }
+  for(i = 0; i < numNodeManagers; i++){
+    printf("i = %3d\n", i);
+    for (j=0; j < numNodes; j++){
+      CalBddNodePrint(nodeArray[i][j]);
+    }
+    printf("\n");
+  }
+
+  printf("FREEING NODES\n");
+  for(i = 0; i < numNodeManagers; i++){
+    for(j = 0; j < numNodes; j++){
+      CalNodeManagerFreeNode(nodeManagerArray[i], nodeArray[i][j] );
+    }    
+    CalNodeManagerQuit(nodeManagerArray[i]);
+  }
+  CalPageManagerQuit(pageManager);
+}
+#endif
Index: /vis_dev/glu-2.1/src/calBdd/calPerformanceTest.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calPerformanceTest.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calPerformanceTest.c	(revision 8)
@@ -0,0 +1,999 @@
+/**CFile***********************************************************************
+
+  FileName    [calPerformanceTest.c]
+
+  PackageName [cal]
+
+  Synopsis    [This file contains the performance test routines for
+  the CAL package.] 
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi  (sanghavi@eecs.berkeley.edu)
+              ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calPerformanceTest.c,v 1.10 2005/04/30 22:57:39 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+#include <unistd.h>
+#include <sys/types.h>
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static int ITERATION;
+
+                        
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CalPerformanceTestAnd(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+#ifdef COMPUTE_MEMORY_OVERHEAD
+static void CalPerformanceMemoryOverhead(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+#endif
+static void CalPerformaceTestSuperscalar(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static void CalPerformanceTestNonSuperscalar(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static void CalPerformanceTestMultiway(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static void CalPerformanceTestOneway(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static void CalPerformanceTestCompose(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static void CalPerformanceTestQuantifyAllTogether(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions, int bfZeroBFPlusDFOne, int cacheExistsResultsFlag, int cacheOrResultsFlag);
+static void CalQuantifySanityCheck(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static void CalPerformanceTestRelProd(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions, int bfZeroBFPlusDFOne, int cacheRelProdResultsFlag, int cacheAndResultsFlag, int cacheOrResultsFlag);
+static void CalPerformanceTestSubstitute(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static void CalPerformanceTestSwapVars(Cal_BddManager bddManager, Cal_Bdd *outputBddArray, int numFunctions);
+static long elapsedTime(void);
+static double cpuTime(void);
+static long pageFaults(void);
+static void GetRandomNumbers(int lowerBound, int upperBound, int count, int *resultVector);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Main routine for testing performances of various routines.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+Cal_PerformanceTest(Cal_BddManager bddManager, Cal_Bdd
+                   *outputBddArray, int numFunctions, int iteration, int seed,
+                    int andPerformanceFlag, int
+                    multiwayPerformanceFlag, int
+                    onewayPerformanceFlag,  int
+                    quantifyPerformanceFlag, 
+                    int composePerformanceFlag, int relprodPerformanceFlag,
+                    int swapPerformanceFlag,
+                    int substitutePerformanceFlag, int
+                    sanityCheckFlag, int computeMemoryOverheadFlag,
+                    int superscalarFlag) 
+{
+  
+  CalUtilSRandom((long)seed);
+  
+  ITERATION = iteration;
+  fprintf(stdout,"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
+  fprintf(stdout, "Performing %d iterations for each function\n", iteration);
+  Cal_BddSetGCMode(bddManager, 0);
+#ifdef QUANTIFY
+  quantify_start_recording_data();
+#endif
+
+#ifdef PURECOV
+	purecov_clear_data();
+#endif
+
+  if (relprodPerformanceFlag){
+    CalPerformanceTestRelProd(bddManager, outputBddArray, numFunctions, 1, 1,
+                              1, 1);
+    CalUtilSRandom((long)seed);
+
+  }
+  if (sanityCheckFlag == 1){
+    CalQuantifySanityCheck(bddManager, outputBddArray,
+                           numFunctions);
+    CalUtilSRandom((long)seed);
+  }
+  if (quantifyPerformanceFlag){
+    CalPerformanceTestQuantifyAllTogether(bddManager, outputBddArray,
+                                          numFunctions, 1, 1, 1);
+    CalUtilSRandom((long)seed);
+	/*
+    CalPerformanceTestNonSuperscalarQuant(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+	*/
+  }
+
+  if (multiwayPerformanceFlag){
+    CalPerformanceTestMultiway(bddManager, outputBddArray, numFunctions); 
+    CalUtilSRandom((long)seed);
+  }
+  if (onewayPerformanceFlag){
+    CalPerformanceTestOneway(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+  }
+  if (andPerformanceFlag){
+    CalPerformanceTestAnd(bddManager, outputBddArray, numFunctions); 
+    CalUtilSRandom((long)seed);
+  }
+  if (composePerformanceFlag){
+    CalPerformanceTestCompose(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+  }
+  if (swapPerformanceFlag){
+    CalPerformanceTestSwapVars(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+  }
+  if (substitutePerformanceFlag){
+    CalPerformanceTestSubstitute(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+  }
+#ifdef COMPUTE_MEMORY_OVERHEAD
+  if (computeMemoryOverheadFlag){
+    CalPerformaceMemoryOverhead(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+  }
+#endif
+  if (superscalarFlag){
+    CalPerformaceTestSuperscalar(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+    CalPerformanceTestNonSuperscalar(bddManager, outputBddArray, numFunctions);
+    CalUtilSRandom((long)seed);
+  }
+#ifdef QUANTIFY
+  quantify_stop_recording_data();
+#endif
+#ifdef PURECOV
+	purecov_save_data();
+	purecov_disable_save();
+#endif
+  fprintf(stdout,"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
+  Cal_BddSetGCMode(bddManager, 1);
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalIncreasingOrderCompare(const void *a, const void *b)
+{
+  return (*(int *)b-*(int *)a);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalDecreasingOrderCompare(const void *a, const void *b)
+{
+  return (*(int *)a-*(int *)b);
+}
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestAnd(Cal_BddManager bddManager, Cal_Bdd
+                      *outputBddArray, int numFunctions)
+{
+  int i;
+  Cal_Bdd function1, function2;
+  Cal_Bdd result;
+  
+  
+  (void) elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION; i++){
+    function1 = outputBddArray[CalUtilRandom()%numFunctions];
+    function2 = outputBddArray[CalUtilRandom()%numFunctions];
+    result = Cal_BddAnd(bddManager, function1, function2);
+    Cal_BddFree(bddManager, result);
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "AND", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_BddManagerGC(bddManager);
+}
+
+
+
+#ifdef COMPUTE_MEMORY_OVERHEAD
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceMemoryOverhead(Cal_BddManager bddManager, Cal_Bdd
+                            *outputBddArray, int numFunctions)
+{
+  int i, j, *varIdArray;
+  Cal_Bdd function1, function2;
+  Cal_Bdd result, *bddArray;
+  double maxReduceToApplyRatio = 0;
+  double maxReduceToUniqueTableRatio = 0;
+  int num, power;
+
+  if (numFunctions <= 1) return;
+
+  for (i=0; i<ITERATION; i++){
+    function1 = outputBddArray[CalUtilRandom()%numFunctions];
+    function2 = outputBddArray[CalUtilRandom()%numFunctions];
+    result = Cal_BddAnd(bddManager, function1, function2);
+    Cal_BddFree(bddManager, result);
+    if (maxReduceToApplyRatio < calAfterReduceToAfterApplyNodesRatio){
+      maxReduceToApplyRatio = calAfterReduceToAfterApplyNodesRatio;
+    }
+    if (maxReduceToUniqueTableRatio < calAfterReduceToUniqueTableNodesRatio){
+      maxReduceToUniqueTableRatio = calAfterReduceToUniqueTableNodesRatio;
+    }
+  }
+
+  fprintf(stdout, "%-20s Max R/A: %-8.6f Max R/U: %-8.6f\n", "MEMORYOVERHEAD-AND",
+          calAfterReduceToAfterApplyNodesRatio,
+          calAfterReduceToUniqueTableNodesRatio);
+  Cal_BddManagerGC(bddManager);
+
+  for (power = 1; power <= 5; power++){
+    num = (1<<power);
+    if (num > numFunctions) return;
+    varIdArray = Cal_MemAlloc(int, num);
+    bddArray = Cal_MemAlloc(Cal_Bdd, num+1);
+    bddArray[num] = Cal_BddGetNullBdd(bddManager);
+    
+    maxReduceToApplyRatio = 0;
+    maxReduceToUniqueTableRatio = 0;
+    
+    for (i=0; i<ITERATION; i++){
+      GetRandomNumbers(0, numFunctions-1, num, varIdArray);
+      for (j=0; j<num; j++){
+        bddArray[j] = outputBddArray[varIdArray[j]];
+      }
+      result = Cal_BddMultiwayAnd(bddManager, bddArray);
+      Cal_BddFree(bddManager, result);
+      if (maxReduceToApplyRatio < calAfterReduceToAfterApplyNodesRatio){
+        maxReduceToApplyRatio = calAfterReduceToAfterApplyNodesRatio;
+      }
+      if (maxReduceToUniqueTableRatio <
+          calAfterReduceToUniqueTableNodesRatio){ 
+        maxReduceToUniqueTableRatio = calAfterReduceToUniqueTableNodesRatio;
+      }
+    }
+    
+    fprintf(stdout, "%-16s%4d Max R/A: %-8.6f Max R/U: %-8.6f\n",
+            "MH-MULTIWAY-AND", num,
+            calAfterReduceToAfterApplyNodesRatio, 
+            calAfterReduceToUniqueTableNodesRatio);
+    Cal_MemFree(varIdArray);
+    Cal_MemFree(bddArray);
+    Cal_BddManagerGC(bddManager);
+  }
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformaceTestSuperscalar(Cal_BddManager bddManager, Cal_Bdd
+                         *outputBddArray, int numFunctions)
+{
+  int i,j;
+  Cal_Bdd *bddArray, *resultArray;
+  int *varIdArray;
+  int num = (((numFunctions%2) == 0)? numFunctions : (numFunctions-1));
+  if (num == 0) return;
+  if (num > 100) num = 100;
+  varIdArray = Cal_MemAlloc(int, num);
+  bddArray = Cal_MemAlloc(Cal_Bdd, num+1);
+  bddArray[num] = (Cal_Bdd) 0;
+  
+  
+  (void) elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION; i++){
+    GetRandomNumbers(0, numFunctions-1, num, varIdArray);
+    for (j=0; j<num; j++){
+      bddArray[j] = outputBddArray[varIdArray[j]];
+    }
+    resultArray = Cal_BddPairwiseAnd(bddManager, bddArray);
+    for (j=0; j<num/2; j++){
+      Cal_BddFree(bddManager, resultArray[j]);
+    }
+    Cal_MemFree(resultArray);
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "SUPERSCALARAND", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_MemFree(varIdArray);
+  Cal_MemFree(bddArray);
+  Cal_BddManagerGC(bddManager);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestNonSuperscalar(Cal_BddManager bddManager, Cal_Bdd
+                                 *outputBddArray, int numFunctions)
+{
+  int i, j;
+  Cal_Bdd *bddArray, *resultArray;
+  int *varIdArray;
+
+  int num = (((numFunctions%2) == 0)? numFunctions : (numFunctions-1));
+
+  if (num == 0) return;
+  if (num > 100) num = 100;
+
+  varIdArray = Cal_MemAlloc(int, num);
+  bddArray = Cal_MemAlloc(Cal_Bdd, num+1);
+  bddArray[num] = (Cal_Bdd) 0;
+  resultArray = Cal_MemAlloc(Cal_Bdd, num/2);
+  
+  (void) elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION; i++){
+    GetRandomNumbers(0, numFunctions-1, num, varIdArray);
+    for (j=0; j<num/2; j++){
+      resultArray[j] = Cal_BddAnd(bddManager,
+                          outputBddArray[varIdArray[j<<1]],
+                          outputBddArray[varIdArray[(j<<1)+1]]);  
+    }
+    for (j=0; j<num/2; j++){
+      Cal_BddFree(bddManager, resultArray[j]);
+    }
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "NONSUPERSCALARAND", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_MemFree(resultArray);
+  Cal_MemFree(bddArray);
+  Cal_MemFree(varIdArray);
+  Cal_BddManagerGC(bddManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestMultiway(Cal_BddManager bddManager, Cal_Bdd
+                           *outputBddArray, int numFunctions)
+{
+  int i,j;
+  Cal_Bdd result, *bddArray;
+  int *varIdArray;
+  int power;
+  int num;
+  
+  if (numFunctions <= 1) return;
+  for (power = 1; power <= 5; power++){
+    num = (1<<power);
+    if (num > numFunctions) return;
+    varIdArray = Cal_MemAlloc(int, num);
+    bddArray = Cal_MemAlloc(Cal_Bdd, num+1);
+    bddArray[num] = (Cal_Bdd) 0;
+    (void) elapsedTime();
+    cpuTime();
+    pageFaults();
+    for (i=0; i<ITERATION; i++){
+      GetRandomNumbers(0, numFunctions-1, num, varIdArray);
+      for (j=0; j<num; j++){
+        bddArray[j] = outputBddArray[varIdArray[j]];
+      }
+      result = Cal_BddMultiwayAnd(bddManager, bddArray);
+      Cal_BddFree(bddManager, result);
+    }
+    fprintf(stdout, "%-20s%-4d%-10ld%-8.2f%-10ld\n", "MULTIWAYAND", num,
+            elapsedTime(), cpuTime(), pageFaults());
+    Cal_MemFree(varIdArray);
+    Cal_MemFree(bddArray);
+    Cal_BddManagerGC(bddManager);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestOneway(Cal_BddManager bddManager, Cal_Bdd
+                         *outputBddArray, int numFunctions)
+{
+  int i, j;
+  Cal_Bdd result, tempResult;
+  int *varIdArray;
+  int power, num;
+  
+  if (numFunctions <= 1) return;
+  
+  for (power = 1; power <= 5; power++){
+    num = (1<<power);
+    if (num > numFunctions) return;
+    varIdArray = Cal_MemAlloc(int, num);
+    (void) elapsedTime();
+    cpuTime();
+    pageFaults();
+    for (i=0; i<ITERATION; i++){
+      GetRandomNumbers(0, numFunctions-1, num, varIdArray);
+      result = Cal_BddOne(bddManager);
+      for (j=0; j<num; j++){
+        tempResult = Cal_BddAnd(bddManager, result,
+                                outputBddArray[varIdArray[j]]); 
+        Cal_BddFree(bddManager, result);
+        result = tempResult;
+      }
+      Cal_BddFree(bddManager, result);
+    }
+    fprintf(stdout, "%-20s%-4d%-10ld%-8.2f%-10ld\n", "ONEWAYAND", num,
+            elapsedTime(), cpuTime(), pageFaults());
+    Cal_MemFree(varIdArray);
+    Cal_BddManagerGC(bddManager);
+  }
+}
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestCompose(Cal_BddManager bddManager, Cal_Bdd
+                                   *outputBddArray, int numFunctions)
+{
+  int i;
+  int numVars = Cal_BddVars(bddManager);
+  Cal_Bdd function;
+  Cal_Bdd variable;
+  Cal_Bdd substituteFunction;
+  Cal_Bdd result;
+  
+  
+  (void) elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION; i++){
+    function = outputBddArray[CalUtilRandom()%numFunctions];
+    variable = Cal_BddManagerGetVarWithId(bddManager,(Cal_BddId_t)CalUtilRandom()%numVars+1);
+    substituteFunction = outputBddArray[CalUtilRandom()%numFunctions];
+    result = Cal_BddCompose(bddManager, function, variable,
+                                    substituteFunction);
+    Cal_BddFree(bddManager, result);
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "COMPOSE", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_BddManagerGC(bddManager);
+}
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestQuantifyAllTogether(Cal_BddManager bddManager, Cal_Bdd
+                                      *outputBddArray, int numFunctions,
+                                      int bfZeroBFPlusDFOne, int
+                                      cacheExistsResultsFlag, int
+                                      cacheOrResultsFlag)
+{
+  int i, j;
+  int numVars = Cal_BddVars(bddManager);
+  int numQuantifyVars = numVars/2;
+  int *varIdArray = Cal_MemAlloc(int, numQuantifyVars);
+  Cal_Bdd *assoc = Cal_MemAlloc(Cal_Bdd, numQuantifyVars+1);
+  Cal_Bdd function, result;
+  int assocId;
+  
+  for (i=0; i <= numQuantifyVars; i++){
+    assoc[i] = (Cal_Bdd) 0;
+  }
+  
+  (void) elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION; i++){
+    function = outputBddArray[CalUtilRandom()%numFunctions];
+    GetRandomNumbers(1, numVars, numQuantifyVars, varIdArray);
+    for (j=0; j<numQuantifyVars; j++){
+      assoc[j] = Cal_BddManagerGetVarWithId(bddManager, varIdArray[j]);
+    }
+    assocId = Cal_AssociationInit(bddManager, assoc, 0);
+    Cal_AssociationSetCurrent(bddManager, assocId);
+    result = Cal_BddExists(bddManager, function);
+    Cal_BddFree(bddManager, result); 
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "QUANTIFY", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_MemFree(assoc);
+  Cal_MemFree(varIdArray);
+  Cal_BddManagerGC(bddManager);
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalQuantifySanityCheck(Cal_BddManager bddManager, Cal_Bdd
+                       *outputBddArray, int numFunctions) 
+{
+  int i, j;
+  int numVars = Cal_BddVars(bddManager);
+  int numQuantifyVars = numVars/2;
+  int *varIdArray = Cal_MemAlloc(int, numQuantifyVars);
+  Cal_Bdd *assoc = Cal_MemAlloc(Cal_Bdd, numQuantifyVars+1);
+  Cal_Bdd function, oneAtATimeResult, allTogetherResult, tempResult, nonSuperscalarResult;
+  
+  
+  for (i=0; i <= numQuantifyVars; i++){
+    assoc[i] = (Cal_Bdd) 0;
+  }
+  
+  (void) elapsedTime();
+  for (i=0; i<ITERATION; i++){
+    function = outputBddArray[CalUtilRandom()%numFunctions];
+    GetRandomNumbers(1, numVars, numQuantifyVars, varIdArray);
+    for (j=0; j<numQuantifyVars; j++){
+      assoc[j] = Cal_BddManagerGetVarWithId(bddManager, varIdArray[j]);
+    }
+    Cal_TempAssociationInit(bddManager, assoc, 0);
+    Cal_AssociationSetCurrent(bddManager, -1);
+    allTogetherResult = Cal_BddExists(bddManager, function);
+
+    oneAtATimeResult = Cal_BddIdentity(bddManager, function);
+    qsort((void *) varIdArray, (size_t)numQuantifyVars, (size_t)sizeof(int),
+          CalDecreasingOrderCompare);
+    for (j=0; j<numQuantifyVars; j++){
+      assoc[0] =
+          Cal_BddManagerGetVarWithId(bddManager,varIdArray[j]); 
+      assoc[1] = (Cal_Bdd) 0;
+      Cal_TempAssociationAugment(bddManager, assoc, 0);
+      tempResult = Cal_BddExists(bddManager, oneAtATimeResult);
+      Cal_BddFree(bddManager, oneAtATimeResult);
+      oneAtATimeResult = tempResult;
+    }
+    
+    nonSuperscalarResult = Cal_BddExists(bddManager, function);
+    
+    assert(Cal_BddIsEqual(bddManager, allTogetherResult, oneAtATimeResult));
+    assert(Cal_BddIsEqual(bddManager, allTogetherResult, nonSuperscalarResult));
+    Cal_BddFree(bddManager, oneAtATimeResult); 
+    Cal_BddFree(bddManager, allTogetherResult); 
+    Cal_BddFree(bddManager, nonSuperscalarResult);
+  }
+  fprintf(stdout, "Quantify Sanity Check Passed\n");
+  Cal_MemFree(assoc);
+  Cal_MemFree(varIdArray);
+  Cal_TempAssociationQuit(bddManager);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestRelProd(Cal_BddManager bddManager, Cal_Bdd
+                          *outputBddArray, int numFunctions, int
+                          bfZeroBFPlusDFOne, int cacheRelProdResultsFlag, int 
+                          cacheAndResultsFlag, int cacheOrResultsFlag)
+{
+  int i, j;
+  int numVars = Cal_BddVars(bddManager);
+  int numQuantifyVars = numVars/2;
+  int *varIdArray = Cal_MemAlloc(int, numQuantifyVars);
+  Cal_Bdd *assoc = Cal_MemAlloc(Cal_Bdd, numQuantifyVars+1);
+  Cal_Bdd function1, function2, result;
+  int assocId;
+  
+  for (i=0; i <= numQuantifyVars; i++){
+    assoc[i] = (Cal_Bdd) 0;
+  }
+  
+  elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION; i++){
+    function1 = outputBddArray[CalUtilRandom()%numFunctions];
+    function2 = outputBddArray[CalUtilRandom()%numFunctions]; 
+   GetRandomNumbers(1, numVars, numQuantifyVars,varIdArray);
+    for (j=0; j<numQuantifyVars; j++){
+      assoc[j] = Cal_BddManagerGetVarWithId(bddManager, varIdArray[j]);
+    }
+    assocId = Cal_AssociationInit(bddManager, assoc, 0);
+    Cal_AssociationSetCurrent(bddManager, assocId);
+    result = Cal_BddRelProd(bddManager, function1, function2);
+    Cal_BddFree(bddManager, result);
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "RELPROD", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_MemFree(assoc);
+  Cal_MemFree(varIdArray);
+  Cal_BddManagerGC(bddManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestSubstitute(Cal_BddManager bddManager, Cal_Bdd
+                             *outputBddArray, int numFunctions)
+{
+  int i, j;
+  int numVars = Cal_BddVars(bddManager);
+  int numQuantifyVars = ((numVars/2 > numFunctions/2) ? numFunctions/2
+                         : numVars/2);
+  int *varIdArray = Cal_MemAlloc(int, numQuantifyVars);
+  Cal_Bdd *assoc = Cal_MemAlloc(Cal_Bdd, 2*numQuantifyVars+1);
+  Cal_Bdd function, result;
+  
+  for (i=0; i <= 2*numQuantifyVars; i++){
+    assoc[i] = (Cal_Bdd) 0;
+  }
+  (void) elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION/5; i++){
+    function = outputBddArray[CalUtilRandom()%numFunctions];
+    GetRandomNumbers(1, numVars, numQuantifyVars,varIdArray);
+    for (j=0; j<numQuantifyVars; j++){
+      assoc[(j<<1)] = Cal_BddManagerGetVarWithId(bddManager,varIdArray[j]);
+    }
+    GetRandomNumbers(0, numFunctions-1, numQuantifyVars, varIdArray);
+    for (j=0; j<numQuantifyVars; j++){
+      assoc[(j<<1)+1] = outputBddArray[varIdArray[j]];
+    }
+    Cal_TempAssociationInit(bddManager, assoc, 1);
+    Cal_AssociationSetCurrent(bddManager, -1);
+    result = Cal_BddSubstitute(bddManager, function);
+    Cal_BddFree(bddManager, result);
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "SUBSTITUTE", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_MemFree(assoc);
+  Cal_MemFree(varIdArray);
+  Cal_TempAssociationQuit(bddManager);
+  Cal_BddManagerGC(bddManager);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performance test routine for quantify (all variables at the same
+  time).]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalPerformanceTestSwapVars(Cal_BddManager bddManager, Cal_Bdd
+                           *outputBddArray, int numFunctions) 
+{
+  int i;
+  int numVars = Cal_BddVars(bddManager);
+  Cal_Bdd function, result;
+  Cal_Bdd var1, var2;
+  
+  elapsedTime();
+  cpuTime();
+  pageFaults();
+  for (i=0; i<ITERATION; i++){
+    function = outputBddArray[CalUtilRandom()%numFunctions];
+    var1 = Cal_BddManagerGetVarWithId(bddManager,(Cal_BddId_t)(CalUtilRandom()%numVars)+1);
+    var2 = Cal_BddManagerGetVarWithId(bddManager,(Cal_BddId_t)(CalUtilRandom()%numVars)+1);
+    result = Cal_BddSwapVars(bddManager, function, var1,var2);
+    Cal_BddFree(bddManager, result);
+  }
+  fprintf(stdout, "%-20s%-10ld%-8.2f%-10ld\n", "SWAPVARS", elapsedTime(),
+          cpuTime(), pageFaults());
+  Cal_BddManagerGC(bddManager);
+}
+/**Function********************************************************************
+
+  Synopsis    [Computes the time.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static long
+elapsedTime(void)
+{
+  static long time_new, time_old;
+  struct timeval t;
+  static int flag = 0;
+  
+  gettimeofday(&t, NULL);
+  if (flag == 0){
+    time_old = time_new = t.tv_sec;
+    flag = 1;
+  }
+  else {
+    time_old = time_new;
+    time_new =  t.tv_sec;
+  }
+  return time_new-time_old;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the number of page faults.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+cpuTime(void)
+{
+#if HAVE_SYS_RESOURCE_H
+  static double timeNew, timeOld;
+  struct rusage rusage;
+  static int flag = 0;
+  
+  getrusage(RUSAGE_SELF, &rusage);
+  if (flag == 0){
+    timeOld = timeNew = rusage.ru_utime.tv_sec+
+        ((double)rusage.ru_utime.tv_usec)/1000000;
+    flag = 1;
+  }
+  else {
+    timeOld = timeNew;
+    timeNew = rusage.ru_utime.tv_sec+
+        ((float)rusage.ru_utime.tv_usec)/1000000;
+  }
+  return timeNew - timeOld;
+#else /* No sys/resource.h */
+  return 0;
+#endif
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the number of page faults.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static long
+pageFaults(void)
+{
+#if HAVE_SYS_RESOURCE_H
+  static long faultNew, faultOld;
+  struct rusage rusage;
+  static int flag = 0;
+  
+  getrusage(RUSAGE_SELF, &rusage);
+  if (flag == 0){
+    faultOld = faultNew = rusage.ru_majflt;
+    flag = 1;
+  }
+  else {
+    faultOld = faultNew;
+    faultNew = rusage.ru_majflt;
+  }
+  return faultNew - faultOld;
+#else /* Don't have sys/resource.h */
+  return 0;
+#endif
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generates "count" many random numbers ranging between
+  "lowerBound" and "upperBound".]
+
+  Description [The restriction is that count <= upperBound-lowerBound+1. The
+  size of the resultVector should be >= count.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+GetRandomNumbers(int lowerBound, int upperBound, int count, int *resultVector)
+{
+  int i,j, tempVector[2048], number;
+  int range = (upperBound - lowerBound + 1);
+
+  for (i=0; i<range; i++)  tempVector[i] = lowerBound+i;
+  for (i=0; i<count; i++){
+    number = (int)CalUtilRandom()% (range-i);
+    resultVector[i] = tempVector[number];
+    for (j=number; j < range-i; j++){
+      tempVector[j] = tempVector[j+1];
+    }
+  }
+  /*
+  fprintf(stdout,"%d\t%d\t%d\n", lowerBound, upperBound, count);
+  for (i=0; i<count; i++)  fprintf(stdout,"%d ", resultVector[i]);
+  fprintf(stdout, "\n");
+  */
+}
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calPipeline.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calPipeline.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calPipeline.c	(revision 8)
@@ -0,0 +1,497 @@
+/**CFile***********************************************************************
+
+  FileName    [calPipeline.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for creating and managing the pipelined BDD
+  operations.] 
+
+  Description [Eventually we would like to have this feature
+  transparent to the user.]
+
+  SeeAlso     [optional]
+
+  Author      [ Rajeev K. Ranjan   (rajeev@eecs.berkeley.edu)
+                Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+              ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calPipeline.c,v 1.1.1.3 1998/05/04 00:59:01 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Set depth of a BDD pipeline.]
+
+  Description [The "depth" determines the amount of dependency we
+  would allow in pipelined computation.]
+
+  SideEffects [None.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cal_PipelineSetDepth(Cal_BddManager bddManager, int depth)
+{
+  int i, j;
+  if(depth > 6){
+    CalBddWarningMessage("PipelineDepth can not exceed 6\n");
+    CalBddWarningMessage("setting PipelineDepth to 6\n");
+    depth = 6;
+  }
+  if(bddManager->maxDepth < depth){
+    int oldMaxDepth = bddManager->maxDepth;
+    bddManager->depth = bddManager->maxDepth = depth;
+    bddManager->reqQue = Cal_MemRealloc(CalHashTable_t **, bddManager->reqQue,
+                                 bddManager->maxDepth);
+    for(i = oldMaxDepth; i < bddManager->maxDepth; i++){
+      bddManager->reqQue[i] = Cal_MemAlloc(CalHashTable_t *, bddManager->maxNumVars+1);
+      for(j = 0; j < bddManager->numVars+1; j++){
+        bddManager->reqQue[i][j] =
+            CalHashTableInit(bddManager, j);
+      }
+    }
+  }
+  else{
+    bddManager->depth = depth;
+  }  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize a BDD pipeline.]
+
+  Description [All the operations for this pipeline must be of the
+  same kind.]
+
+  SideEffects [None.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cal_PipelineInit(Cal_BddManager bddManager, Cal_BddOp_t bddOp)
+{
+  CalBddPostProcessing(bddManager);
+  if(bddManager->pipelineState != READY){
+    CalBddWarningMessage("Pipeline cannot be initialized");
+    return 0;
+  }
+  else{
+    bddManager->pipelineState = CREATE;
+    switch(bddOp){
+    case CAL_AND :
+      bddManager->pipelineFn = CalOpAnd;
+      break;
+    case CAL_OR  :
+      bddManager->pipelineFn = CalOpOr;
+      break;
+    case CAL_XOR :
+      bddManager->pipelineFn = CalOpXor;
+      break;
+    default  :
+      CalBddWarningMessage("Unknown Bdd Operation type");
+      return 0;
+    }
+    return 1;
+  }  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create a provisional BDD in the pipeline.]
+
+  Description [The provisional BDD is automatically freed once the
+  pipeline is quitted.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Cal_Bdd
+Cal_PipelineCreateProvisionalBdd(Cal_BddManager bddManager, Cal_Bdd fUserBdd,
+                                 Cal_Bdd gUserBdd)
+{
+  int insertDepth, operandDepth;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t provisionalBdd, f, g;
+  Cal_BddId_t bddId;
+  Cal_Bdd userNode;
+  
+  insertDepth = 0;
+  
+  f = CalBddGetInternalBdd(bddManager, fUserBdd);
+  g = CalBddGetInternalBdd(bddManager, gUserBdd);
+  if(bddManager->pipelineState != CREATE){
+    CalBddWarningMessage("Provisional Bdd not created: Pipeline is not initialized");
+    return (Cal_Bdd) 0;
+  }
+  if(CalBddIsMarked(f)){
+    CalBddGetDepth(f, operandDepth);
+    if(insertDepth <= operandDepth){
+      insertDepth = operandDepth + 1;
+    }
+  }
+  if(CalBddIsMarked(g)){
+    CalBddGetDepth(g, operandDepth);
+    if(insertDepth <= operandDepth){
+      insertDepth = operandDepth + 1;
+    }
+  }
+  if (bddManager->pipelineDepth <= insertDepth){
+    bddManager->pipelineDepth = insertDepth + 1;
+  }
+  if (insertDepth >= MAX_INSERT_DEPTH){
+    CalBddWarningMessage("Provisional Bdd not created");
+    CalBddWarningMessage("Maximum pipeline depth is reached");
+    return (Cal_Bdd) 0;
+  }
+
+  CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], requestNode);
+  CalRequestNodePutF(requestNode, f);
+  CalRequestNodePutG(requestNode, g);
+  CalRequestNodeMark(requestNode);
+  CalRequestNodePutDepth(requestNode, insertDepth);
+  CalRequestNodePutNextRequestNode(requestNode,
+      bddManager->requestNodeListArray[insertDepth]);
+  bddManager->requestNodeListArray[insertDepth] = requestNode;
+
+  CalBddGetMinId2(bddManager, f, g, bddId);
+  CalBddPutBddId(provisionalBdd, bddId);
+  CalBddPutBddNode(provisionalBdd, (CalBddNode_t *)requestNode);
+
+  CalNodeManagerAllocNode(bddManager->nodeManagerArray[0], userNode);
+  CalBddNodePutThenBdd(userNode, provisionalBdd);
+  CalBddNodePutElseBdd(userNode, bddManager->bddOne);
+  CalBddNodePutNextBddNode(userNode,
+                           bddManager->userProvisionalNodeList);
+  bddManager->userProvisionalNodeList = userNode;
+  CalBddNodeIcrRefCount(userNode);
+  return userNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Executes a pipeline.]
+
+  Description [All the results are computed. User should update the
+  BDDs of interest. Eventually this feature would become transparent.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+Cal_PipelineExecute(Cal_BddManager bddManager)
+{
+  CalRequestNode_t **requestNodeListArray, *node, *nextNode;
+  int  i;
+  Cal_Bdd_t thenBdd;
+  int automaticDepthControlFlag = 0;
+  int pipelineDepth;
+  
+  if(bddManager->pipelineState != CREATE){
+    CalBddWarningMessage("Pipeline cannot be executed");
+    return 0;
+  }
+
+  /* Check if we need to control the depth value using some heuristic */
+  if (bddManager->depth == 0) automaticDepthControlFlag = 1;
+  
+  requestNodeListArray = bddManager->requestNodeListArray;
+  pipelineDepth = bddManager->pipelineDepth;
+  while(pipelineDepth){
+    if (automaticDepthControlFlag){
+      if (bddManager->numNodes < 10000) bddManager->depth = 4;
+      else if (bddManager->numNodes < 100000) bddManager->depth = 2;
+      else bddManager->depth = 1;
+    }
+    if(bddManager->depth > pipelineDepth){
+      bddManager->depth = pipelineDepth;
+    }
+    CalRequestNodeListArrayOp(bddManager, requestNodeListArray,
+                              bddManager->pipelineFn);
+    pipelineDepth -= bddManager->depth;
+
+    /* Lock the results, in case garbage collection needs to be
+       invoked */
+    for (i=0; i<bddManager->depth; i++){
+      for (node = requestNodeListArray[i]; node; node = nextNode){
+        nextNode = CalBddNodeGetNextBddNode(node);
+        CalBddNodeGetThenBdd(node, thenBdd);
+        CalBddIcrRefCount(thenBdd);
+      }
+    }
+    /* Save the current pipelineDepth */
+    bddManager->currentPipelineDepth = pipelineDepth;
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      /* Abort, may be we should clean up a little bit */
+      fprintf(stderr,"Bdd Overflow: Aborting\n");
+      return 0;
+    }
+    requestNodeListArray += bddManager->depth;
+  }
+  /* Need to decrement the reference counts */
+  for (i=0; i<bddManager->pipelineDepth; i++){
+    for (node=bddManager->requestNodeListArray[i]; node; node = nextNode){
+      nextNode = CalBddNodeGetNextBddNode(node);
+      CalBddNodeGetThenBdd(node, thenBdd);
+      CalBddDcrRefCount(thenBdd);
+    }
+  }
+  bddManager->pipelineState = UPDATE;
+  return 1;
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [Update a provisional Bdd obtained during pipelining.]
+
+  Description [The provisional BDD is automatically freed after
+  quitting pipeline.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Cal_Bdd
+Cal_PipelineUpdateProvisionalBdd(Cal_BddManager bddManager,
+                                 Cal_Bdd provisionalBdd) 
+{
+  Cal_Bdd_t calBdd = CalBddGetInternalBdd(bddManager, provisionalBdd);
+  if(bddManager->pipelineState != UPDATE){
+    CalBddWarningMessage("Provisional Bdd cannot be updated");
+    return (Cal_Bdd) 0;
+  }
+  CalBddGetThenBdd(calBdd, calBdd);
+  return CalBddGetExternalBdd(bddManager, calBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Returns 1, if the given user BDD contains
+  provisional BDD node.]
+
+  Description        [Returns 1, if the given user BDD contains
+  provisional BDD node.]
+
+  SideEffects        [None.]
+
+  SeeAlso            []
+
+******************************************************************************/
+int
+Cal_BddIsProvisional(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  Cal_Bdd_t internalBdd = CalBddGetInternalBdd(bddManager, userBdd);
+  return CalBddIsMarked(internalBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the pipeline freeing all resources.]
+
+  Description [The user must make sure to update all provisional BDDs
+  of interest before calling this routine.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cal_PipelineQuit(Cal_BddManager bddManager)
+{
+  CalRequestNode_t *requestNode, *next;
+  int i;
+
+  bddManager->pipelineState = READY;
+  for(i = 0; i < bddManager->pipelineDepth; i++){
+    for(requestNode = bddManager->requestNodeListArray[i], 
+        bddManager->requestNodeListArray[i] = Cal_Nil(CalRequestNode_t);
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = next){
+      next = CalRequestNodeGetNextRequestNode(requestNode);
+      CalNodeManagerFreeNode(bddManager->nodeManagerArray[0], requestNode);
+    }
+    bddManager->requestNodeListArray[i] = Cal_Nil(CalRequestNode_t);
+  }
+  bddManager->pipelineDepth = 0;
+  for (requestNode = bddManager->userProvisionalNodeList; requestNode;
+       requestNode = next){
+    next = CalRequestNodeGetNextRequestNode(requestNode);
+    CalNodeManagerFreeNode(bddManager->nodeManagerArray[0],
+                           requestNode);
+  }
+  bddManager->userProvisionalNodeList = Cal_Nil(CalRequestNode_t);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddReorderFixProvisionalNodes(Cal_BddManager_t *bddManager)
+{
+  CalRequestNode_t **requestNodeListArray =
+      bddManager->requestNodeListArray;
+  CalRequestNode_t *node, *nextNode;
+  int i;
+  Cal_Bdd_t thenBdd, elseBdd;
+  
+  for (i=0;
+       i<bddManager->pipelineDepth-bddManager->currentPipelineDepth;
+       i++){ 
+    for (node = *requestNodeListArray; node; node = nextNode){
+      nextNode = CalBddNodeGetNextBddNode(node);
+      Cal_Assert(CalBddNodeIsForwarded(node));
+      CalBddNodeGetThenBdd(node, thenBdd);
+      if (CalBddIsForwarded(thenBdd)) {
+        CalBddForward(thenBdd);
+      }
+      CalBddNodePutThenBdd(node, thenBdd);
+      Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+    }
+    requestNodeListArray++;
+  }
+  for (; i<bddManager->pipelineDepth; i++){
+    for (node = *requestNodeListArray; node; node = nextNode){
+      nextNode = CalBddNodeGetNextBddNode(node);
+      Cal_Assert(CalBddNodeIsForwarded(node) == 0);
+      CalBddNodeGetThenBdd(node, thenBdd);
+      if (CalBddIsForwarded(thenBdd)) {
+        CalBddForward(thenBdd);
+      }
+      CalBddNodePutThenBdd(node, thenBdd);
+      Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+      CalBddNodeGetElseBdd(node, elseBdd);
+      if (CalBddIsForwarded(elseBdd)) {
+        CalBddForward(elseBdd);
+      }
+      CalBddNodePutElseBdd(node, elseBdd);
+      Cal_Assert(CalBddIsForwarded(elseBdd) == 0);
+    }
+    requestNodeListArray++;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalCheckPipelineValidity(Cal_BddManager_t *bddManager)
+{
+  CalRequestNode_t **requestNodeListArray =
+      bddManager->requestNodeListArray;
+  CalRequestNode_t *node, *nextNode;
+  int i;
+  Cal_Bdd_t thenBdd, elseBdd;
+  
+  for (i=0;
+       i<bddManager->pipelineDepth-bddManager->currentPipelineDepth;
+       i++){ 
+    for (node = *requestNodeListArray; node; node = nextNode){
+      nextNode = CalBddNodeGetNextBddNode(node);
+      Cal_Assert(CalBddNodeIsForwarded(node));
+      CalBddNodeGetThenBdd(node, thenBdd);
+      Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+    }
+    requestNodeListArray++;
+  }
+  for (; i<bddManager->pipelineDepth; i++){
+    for (node = *requestNodeListArray; node; node = nextNode){
+      nextNode = CalBddNodeGetNextBddNode(node);
+      Cal_Assert(CalBddNodeIsForwarded(node) == 0); 
+      CalBddNodeGetThenBdd(node, thenBdd);
+      /*Cal_Assert(CalBddIsForwarded(thenBdd) == 0);*/
+      /* This is possible since the actual BDD of thenBdd could have been
+         computed and it is forwarded, however this node is not yet
+         updated with the result */
+      CalBddNodeGetElseBdd(node, elseBdd);
+      /*Cal_Assert(CalBddIsForwarded(elseBdd) == 0);*/
+    }
+    requestNodeListArray++;
+  }
+}
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/calBdd/calPrint.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calPrint.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calPrint.c	(revision 8)
@@ -0,0 +1,418 @@
+/**CFile***********************************************************************
+
+  FileName    [calPrint.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routine for printing a BDD.]
+
+  Description []
+
+  SeeAlso     [None]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu)
+               Originally written by David Long.
+               ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calPrint.c,v 1.2 1998/09/16 16:40:41 ravi Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static char defaultTerminalId[]="terminal XXXXXXXXXX XXXXXXXXXX";
+static char defaultVarName[]="var.XXXXXXXXXX";
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void Chars(char c, int n, FILE *fp);
+static void BddPrintTopVar(Cal_BddManager_t *bddManager, Cal_Bdd_t f, Cal_VarNamingFn_t VarNamingFn, Cal_Pointer_t env, FILE *fp);
+static void BddPrintBddStep(Cal_BddManager_t *bddManager, Cal_Bdd_t f, Cal_VarNamingFn_t VarNamingFn, Cal_TerminalIdFn_t TerminalIdFn, Cal_Pointer_t env, FILE *fp, CalHashTable_t* hashTable, int indentation);
+static char * BddTerminalId(Cal_BddManager_t *bddManager, Cal_Bdd_t f, Cal_TerminalIdFn_t TerminalIdFn, Cal_Pointer_t env);
+static void BddTerminalValueAux(Cal_BddManager_t *bddManager, Cal_Bdd_t f, CalAddress_t *value1, CalAddress_t *value2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Prints a BDD in the human readable form.]
+
+  Description [Prints a human-readable representation of the BDD f to
+  the file given by fp. The namingFn should be a pointer to a function
+  taking a bddManager, a BDD and the pointer given by env. This
+  function should return either a null pointer or a srting that is the
+  name of the supplied variable. If it returns a null pointer, a
+  default name is generated based on the index of the variable. It is
+  also legal for naminFN to e null; in this case, default names are
+  generated for all variables. The macro bddNamingFnNone is a null
+  pointer of suitable type. terminalIdFn should be apointer to a
+  function taking a bddManager and two longs. plus the pointer given
+  by the env. It should return either a null pointer. If it returns a
+  null pointer, or if terminalIdFn is null, then default names are
+  generated for the terminals. The macro bddTerminalIdFnNone is a null
+  pointer of suitable type.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+void
+Cal_BddPrintBdd(Cal_BddManager bddManager,
+                Cal_Bdd fUserBdd, Cal_VarNamingFn_t VarNamingFn,
+                Cal_TerminalIdFn_t TerminalIdFn,
+                Cal_Pointer_t env, FILE *fp)
+{
+  long next;
+  CalHashTable_t *hashTable;
+
+  Cal_Bdd_t f = CalBddGetInternalBdd(bddManager,fUserBdd);
+  CalBddMarkSharedNodes(bddManager, f);
+  hashTable = CalHashTableOneInit(bddManager, sizeof(long));
+  next = 0;
+  CalBddNumberSharedNodes(bddManager, f, hashTable, &next);
+  BddPrintBddStep(bddManager, f, VarNamingFn, TerminalIdFn, env, fp,
+                  hashTable, 0);
+  CalHashTableOneQuit(hashTable);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+char *
+CalBddVarName(Cal_BddManager_t *bddManager, Cal_Bdd_t v,
+           Cal_VarNamingFn_t VarNamingFn,  Cal_Pointer_t env)
+{
+  char *name;
+  if (VarNamingFn){
+    Cal_Bdd userV = CalBddGetExternalBdd(bddManager, v);
+    name = (*VarNamingFn)(bddManager, userV, env);
+    Cal_BddFree(bddManager, userV);
+  }
+ else
+   name=0;
+  if (!name){
+    sprintf(defaultVarName, "var.%d", CalBddGetBddIndex(bddManager, v));
+    name = defaultVarName;
+  }
+  return (name);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddNumberSharedNodes(Cal_BddManager_t *bddManager, Cal_Bdd_t f,
+                     CalHashTable_t *hashTable, long *next)
+{
+  Cal_Bdd_t thenBdd, elseBdd;
+  int mark;
+  
+  if (CalBddIsBddConst(f) || ((1 << CalBddTypeAux(bddManager, f)) &
+                           ((1 << CAL_BDD_TYPE_POSVAR) |
+                            (1 << CAL_BDD_TYPE_NEGVAR))))
+    return;
+  mark = CalBddGetMark(f);
+  if (mark == 0) return;
+  if (mark  == 2) {
+    CalHashTableOneInsert(hashTable, f, (char *)next);
+    ++*next;
+  }
+  CalBddPutMark(f, 0);
+  CalBddGetThenBdd(f, thenBdd);
+  CalBddGetElseBdd(f, elseBdd);
+  CalBddNumberSharedNodes(bddManager, thenBdd, hashTable, next);
+  CalBddNumberSharedNodes(bddManager, elseBdd, hashTable, next);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddMarkSharedNodes(Cal_BddManager_t *bddManager, Cal_Bdd_t f)
+{
+  int mark;
+  Cal_Bdd_t thenBdd, elseBdd;
+  
+  if (CalBddIsOutPos(f) == 0){
+    CalBddNot(f,f);
+  }
+  if (CalBddIsBddConst(f) || CalBddTypeAux(bddManager, f) ==
+      CAL_BDD_TYPE_POSVAR)
+    return; 
+  if ((mark = CalBddGetMark(f))){
+    if (mark == 1){
+      CalBddPutMark(f, 2);
+      return;
+    }
+  }
+  CalBddPutMark(f, 1);
+  CalBddGetThenBdd(f, thenBdd);
+  CalBddGetElseBdd(f, elseBdd);
+  CalBddMarkSharedNodes(bddManager, thenBdd);
+  CalBddMarkSharedNodes(bddManager, elseBdd);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+Chars(char c, int n,FILE *fp)
+{
+  int i;
+  for (i=0; i < n; ++i){
+    fputc(c, fp);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddPrintTopVar(Cal_BddManager_t *bddManager, Cal_Bdd_t f,
+               Cal_VarNamingFn_t VarNamingFn, Cal_Pointer_t env, FILE *fp)
+{
+  Cal_Bdd_t ifVar;
+  ifVar = CalBddIf(bddManager, f);
+  fputs(CalBddVarName(bddManager, ifVar, VarNamingFn, env), fp);  
+  fputc('\n', fp);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/static void
+BddPrintBddStep(Cal_BddManager_t *bddManager,
+                Cal_Bdd_t f, Cal_VarNamingFn_t VarNamingFn,
+                Cal_TerminalIdFn_t TerminalIdFn,
+                Cal_Pointer_t env, FILE *fp, CalHashTable_t* hashTable,
+                int indentation)
+{
+  int negated;
+  long *number;
+  Cal_Bdd_t fNot, thenBdd, elseBdd;
+  
+  Chars(' ', indentation, fp);
+  switch (CalBddTypeAux(bddManager, f)){
+      case CAL_BDD_TYPE_ZERO:
+      case CAL_BDD_TYPE_ONE:
+        fputs(BddTerminalId(bddManager, f, TerminalIdFn, env), fp);
+        fputc('\n', fp);
+        break;
+      case CAL_BDD_TYPE_NEGVAR:
+        fputc('!', fp);
+        /* fall through */
+      case CAL_BDD_TYPE_POSVAR:
+        BddPrintTopVar(bddManager, f, VarNamingFn, env, fp);
+        break;
+      case CAL_BDD_TYPE_NONTERMINAL:
+        CalBddNot(f, fNot);
+        if (CalHashTableOneLookup(hashTable, fNot, Cal_Nil(char *))){
+          f = fNot;
+          negated = 1;
+        }
+        else {
+          negated=0;
+        }
+        CalHashTableOneLookup(hashTable, f, (char **)&number);
+        if (number && *number < 0){
+          if (negated)
+            fputc('!', fp);
+          fprintf(fp, "subformula %d\n", (int)-*number-1);
+        }
+      else {
+        if (number){
+	      fprintf(fp, "%d: ", (int) *number);
+	      *number= -*number-1;
+	    }
+        fputs("if ", fp);
+        BddPrintTopVar(bddManager, f, VarNamingFn, env, fp);
+        CalBddGetThenBdd(f, thenBdd);
+        BddPrintBddStep(bddManager, thenBdd, VarNamingFn,
+                        TerminalIdFn, env, fp, hashTable, indentation+2);
+        Chars(' ', indentation, fp);
+        fputs("else if !", fp);
+        BddPrintTopVar(bddManager, f, VarNamingFn, env, fp);
+        CalBddGetElseBdd(f, elseBdd);
+        BddPrintBddStep(bddManager, elseBdd, VarNamingFn,
+                        TerminalIdFn, env, fp, hashTable, indentation+2); 
+        Chars(' ', indentation, fp);
+        fputs("endif ", fp);
+        BddPrintTopVar(bddManager, f, VarNamingFn, env, fp);
+      }
+        break;
+      default:
+        CalBddFatalMessage("BddPrintBddStep: unknown type returned by Cal_BddType"); 
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static char *
+BddTerminalId(Cal_BddManager_t *bddManager, Cal_Bdd_t f,
+              Cal_TerminalIdFn_t TerminalIdFn, Cal_Pointer_t env)
+{
+  char *id;
+  CalAddress_t  v1, v2;
+  BddTerminalValueAux(bddManager, f, &v1, &v2);
+  if (TerminalIdFn) id = (*TerminalIdFn)(bddManager, v1, v2, env);
+  else id=0;
+  if (!id){
+    if (CalBddIsBddOne(bddManager, f)) return ("1");
+    if (CalBddIsBddZero(bddManager, f)) return ("0");
+    sprintf(defaultTerminalId, "terminal %ld %ld", (long)v1, (long)v2);
+    id = defaultTerminalId;
+  }
+  return (id);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddTerminalValueAux(Cal_BddManager_t *bddManager, Cal_Bdd_t f,
+                    CalAddress_t *value1, CalAddress_t *value2)
+{
+  if (CalBddIsOutPos(f)){
+    *value1 = (CalAddress_t)CalBddGetThenBddNode(f);
+    *value2 = (CalAddress_t)CalBddGetElseBddNode(f);
+  }
+  else
+    (*bddManager->TransformFn)(bddManager,
+                               (CalAddress_t)CalBddGetThenBddNode(f),
+                               (CalAddress_t)CalBddGetElseBddNode(f),
+                                value1, value2, bddManager->transformEnv);  
+}
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calPrintProfile.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calPrintProfile.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calPrintProfile.c	(revision 8)
@@ -0,0 +1,334 @@
+/**CFile***********************************************************************
+
+  FileName    [calPrintProfile.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for printing various profiles for a BDD.]
+
+  Description [ ]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev Ranjan   (rajeev@eecs.berkeley.edu)
+               Originally written by David Long.
+              ] 
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calPrintProfile.c,v 1.1.1.3 1998/05/04 00:59:01 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static char profileWidth[] = "XXXXXXXXX";
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CalBddPrintProfileAux(Cal_BddManager_t * bddManager, long * levelCounts, Cal_VarNamingFn_t varNamingProc, char * env, int lineLength, FILE * fp);
+static void chars(char c, int n, FILE * fp);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Displays the node profile for f on fp. lineLength specifies 
+               the maximum line length.  varNamingFn is as in
+               Cal_BddPrintBdd.]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddPrintProfile(Cal_BddManager  bddManager,
+                    Cal_Bdd  fUserBdd,
+                    Cal_VarNamingFn_t varNamingProc,
+                    char * env,
+                    int  lineLength,
+                    FILE * fp)
+{
+  long *levelCounts;
+
+  if (CalBddPreProcessing(bddManager, 1, fUserBdd) == 0){
+	return;
+  }
+  levelCounts = Cal_MemAlloc(long, bddManager->numVars+1);
+  Cal_BddProfile(bddManager, fUserBdd, levelCounts, 1);
+  CalBddPrintProfileAux(bddManager, levelCounts, varNamingProc, env,
+                        lineLength, fp); 
+  Cal_MemFree(levelCounts);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Cal_BddPrintProfileMultiple is like Cal_BddPrintProfile except
+               it displays the profile for a set of BDDs]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddPrintProfileMultiple(
+  Cal_BddManager bddManager,
+  Cal_Bdd *userBdds,
+  Cal_VarNamingFn_t varNamingProc,
+  char * env,
+  int  lineLength,
+  FILE * fp)
+{
+  long *levelCounts;
+
+  if (CalBddArrayPreProcessing(bddManager, userBdds) == 0){
+	return;
+  }
+  levelCounts = Cal_MemAlloc(long, bddManager->numVars+1);
+  Cal_BddProfileMultiple(bddManager, userBdds, levelCounts, 1);
+  CalBddPrintProfileAux(bddManager, levelCounts, varNamingProc, env, lineLength, fp);
+  Cal_MemFree(levelCounts);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cal_BddPrintFunctionProfile is like Cal_BddPrintProfile except
+               it displays a function profile for f]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddPrintFunctionProfile(Cal_BddManager bddManager,
+                            Cal_Bdd  f,
+                            Cal_VarNamingFn_t varNamingProc,
+                            char * env,
+                            int  lineLength,
+                            FILE * fp)
+{
+  long *levelCounts;
+  if (CalBddPreProcessing(bddManager, 1, f)){
+	return;
+  }
+  levelCounts = Cal_MemAlloc(long, bddManager->numVars+1);
+  Cal_BddFunctionProfile(bddManager, f, levelCounts);
+  CalBddPrintProfileAux(bddManager, levelCounts, varNamingProc, env,
+                        lineLength, fp); 
+  Cal_MemFree(levelCounts);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cal_BddPrintFunctionProfileMultiple is like
+               Cal_BddPrintFunctionProfile except for multiple BDDs]
+
+  Description [optional]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+Cal_BddPrintFunctionProfileMultiple(Cal_BddManager bddManager,
+                                    Cal_Bdd *userBdds,
+                                    Cal_VarNamingFn_t varNamingProc,
+                                    char * env,
+                                    int  lineLength,
+                                    FILE * fp)
+{
+  long *levelCounts;
+  if (CalBddArrayPreProcessing(bddManager, userBdds) == 0){
+	return;
+  }
+  levelCounts = Cal_MemAlloc(long, bddManager->numVars+1);
+  Cal_BddFunctionProfileMultiple(bddManager, userBdds, levelCounts);
+  CalBddPrintProfileAux(bddManager, levelCounts, varNamingProc, env, lineLength, fp);
+  Cal_MemFree(levelCounts);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Prints a profile to the file given by fp.  The varNamingProc
+               is as in Cal_BddPrintBdd. lineLength gives the line width to scale
+               the profile to.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+CalBddPrintProfileAux(
+  Cal_BddManager_t * bddManager,
+  long * levelCounts,
+  Cal_VarNamingFn_t varNamingProc,
+  char * env,
+  int  lineLength,
+  FILE * fp)
+{
+  long i, n;
+  int l;
+  char *name;
+  int maxPrefixLen;
+  int maxProfileWidth;
+  int histogramColumn;
+  int histogramWidth;
+  int profileScale;
+  long total;
+
+  n = bddManager->numVars;
+  /* max_... initialized with values for leaf nodes */
+  maxPrefixLen = 5;
+  maxProfileWidth = levelCounts[n];
+  total = levelCounts[n];
+  for(i = 0; i < n; i++){
+    if(levelCounts[i]){
+      sprintf(profileWidth, "%ld", levelCounts[i]);
+      l = strlen(CalBddVarName(bddManager, 
+          bddManager->varBdds[bddManager->indexToId[i]],
+          varNamingProc, env)) + strlen((char *)profileWidth);
+      if(l > maxPrefixLen){
+        maxPrefixLen = l;
+      }
+      if(levelCounts[i] > maxProfileWidth){
+        maxProfileWidth = levelCounts[i];
+      }
+      total += levelCounts[i];
+    }
+  }
+  histogramColumn = maxPrefixLen+3;
+  histogramWidth = lineLength-histogramColumn-1;
+  if(histogramWidth < 20)
+    histogramWidth = 20;		/* Random minimum width */
+  if(histogramWidth >= maxProfileWidth){
+    profileScale = 1;
+  }
+  else{
+    profileScale = (maxProfileWidth+histogramWidth-1)/histogramWidth;
+  }
+  for(i = 0; i < n; ++i){
+    if(levelCounts[i]){
+      name = CalBddVarName(bddManager,
+          bddManager->varBdds[bddManager->indexToId[i]],
+          varNamingProc, env);
+      fputs(name, fp);
+      fputc(':', fp);
+      sprintf(profileWidth, "%ld", levelCounts[i]);
+      chars(' ', (int)(maxPrefixLen-strlen(name)-strlen(profileWidth)+1), fp);
+      fputs(profileWidth, fp);
+      fputc(' ', fp);
+      chars('#', levelCounts[i]/profileScale, fp);
+      fputc('\n', fp);
+    }
+  }
+  fputs("leaf:", fp);
+  sprintf(profileWidth, "%ld", levelCounts[n]);
+  chars(' ', (int)(maxPrefixLen-4-strlen(profileWidth)+1), fp);
+  fputs(profileWidth, fp);
+  fputc(' ', fp);
+  chars('#', levelCounts[n]/profileScale, fp);
+  fputc('\n', fp);
+  fprintf(fp, "Total: %ld\n", total);
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+chars(
+  char  c,
+  int  n,
+  FILE * fp)
+{
+  int i;
+
+  for(i = 0; i < n; ++i){
+    fputc(c, fp);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calQuant.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calQuant.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calQuant.c	(revision 8)
@@ -0,0 +1,1492 @@
+/**CFile***********************************************************************
+
+  FileName    [calQuant.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for existential/universal quantification and
+  relational product.]
+
+  Description []
+
+  SeeAlso     [None]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calQuant.c,v 1.1.1.4 1998/05/04 00:59:02 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DEFAULT_EXIST_HASH_TABLE_SIZE_INDEX 4
+#define DEFAULT_EXIST_HASH_TABLE_SIZE 16
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Cal_Bdd_t BddExistsStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, unsigned short opCode, CalAssociation_t *association);
+static Cal_Bdd_t BddRelProdStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t g, unsigned short opCode, CalAssociation_t *assoc);
+static Cal_Bdd_t BddDFStep(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t g, CalOpProc_t calOpProc, unsigned short opCode);
+static void HashTableApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t ** reqQueAtPipeDepth, CalOpProc_t calOpProc, unsigned long opCode);
+static void HashTableReduce(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t * uniqueTableForId);
+static void BddExistsApply(Cal_BddManager_t *bddManager, int quantifying, CalHashTable_t *existHashTable, CalHashTable_t **existHashTableArray, CalOpProc1_t calOpProc, unsigned short opCode, CalAssociation_t *assoc);
+static void BddExistsBFAux(Cal_BddManager_t *bddManager, int minIndex, CalHashTable_t **existHashTableArray, CalHashTable_t **orHashTableArray, CalOpProc1_t calOpProc, unsigned short opCode, CalAssociation_t *assoc);
+static void BddExistsReduce(Cal_BddManager_t *bddManager, CalHashTable_t *existHashTable, CalHashTable_t **existHashTableArray, CalHashTable_t **orHashTableArray, unsigned short opCode, CalAssociation_t *association);
+static Cal_Bdd_t BddExistsBFPlusDF(Cal_BddManager_t *bddManager, Cal_Bdd_t f, unsigned short opCode, CalAssociation_t *association);
+static void BddRelProdApply(Cal_BddManager_t *bddManager, int quantifying, CalHashTable_t *relProdHashTable, CalHashTable_t **relProdHashTableArray, CalHashTable_t **andHashTableArray, CalOpProc_t calOpProc, unsigned short opCode, CalAssociation_t *assoc);
+static void BddRelProdReduce(Cal_BddManager_t *bddManager, CalHashTable_t *relProdHashTable, CalHashTable_t **relProdHashTableArray, CalHashTable_t **andHashTableArray, CalHashTable_t **orHashTableArray, unsigned short opCode, CalAssociation_t *assoc);
+static void BddRelProdBFAux(Cal_BddManager_t *bddManager, int minIndex, CalHashTable_t **relProdHashTableArray, CalHashTable_t **andHashTableArray, CalHashTable_t **orHashTableArray, unsigned short opCode, CalAssociation_t *assoc);
+static Cal_Bdd_t BddRelProdBFPlusDF(Cal_BddManager_t * bddManager, Cal_Bdd_t f, Cal_Bdd_t g, unsigned short opCode, CalAssociation_t *association);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns the result of existentially quantifying some
+  variables from the given BDD.]
+
+  Description [Returns the BDD for f with all the variables that are
+  paired with something in the current variable association
+  existentially quantified out.]
+
+  SideEffects [None.]
+
+  SeeAlso     [Cal_BddRelProd]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddExists(Cal_BddManager bddManager, Cal_Bdd fUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+
+  if (CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    Cal_Bdd_t f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    CalAssociation_t *assoc = bddManager->currentAssociation;
+    unsigned short opCode;
+    
+    if (assoc->id == -1){
+      opCode = bddManager->tempOpCode--;
+    }
+    else {
+      opCode = CAL_OP_QUANT + assoc->id;
+    }
+    if (bddManager->numNodes <= CAL_LARGE_BDD){
+      /* If number of nodes is small, call depth first routine. */
+      result = BddExistsStep(bddManager, f, opCode, assoc);
+    }
+    else {
+      result = BddExistsBFPlusDF(bddManager, f, opCode, assoc);
+    }
+    userResult =  CalBddGetExternalBdd(bddManager, result);
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      Cal_BddFree(bddManager, userResult);
+      Cal_BddManagerGC(bddManager);
+      return (Cal_Bdd) 0;
+    }
+    return userResult;
+  }
+  return (Cal_Bdd) 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the result of taking the logical AND of the
+  argument BDDs and existentially quantifying some variables from the
+  product.] 
+
+  Description [Returns the BDD for the logical AND of f and g with all
+  the variables that are paired with something in the current variable
+  association existentially quantified out.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddRelProd(Cal_BddManager bddManager, Cal_Bdd fUserBdd, Cal_Bdd gUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+  
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, gUserBdd)){
+    Cal_Bdd_t f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    Cal_Bdd_t g = CalBddGetInternalBdd(bddManager, gUserBdd);
+    CalAssociation_t *assoc = bddManager->currentAssociation;
+    unsigned short opCode;
+    
+    if (bddManager->currentAssociation->id == -1){
+      opCode = bddManager->tempOpCode--;
+      bddManager->tempOpCode--;
+    }
+    else {
+      opCode = CAL_OP_REL_PROD + assoc->id;
+    }
+    if (bddManager->numNodes <= CAL_LARGE_BDD){
+      /* If number of nodes is small, call depth first routine. */
+      result = BddRelProdStep(bddManager, f, g, opCode, assoc);
+    }
+    else {
+      result = BddRelProdBFPlusDF(bddManager, f, g, opCode, assoc);
+    }
+    userResult =  CalBddGetExternalBdd(bddManager, result);
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      Cal_BddFree(bddManager, userResult);
+      Cal_BddManagerGC(bddManager);
+      return (Cal_Bdd) 0;
+    }
+    return userResult;
+  }
+  return (Cal_Bdd) 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the result of universally quantifying some
+  variables from the given BDD.]
+
+  Description [Returns the BDD for f with all the variables that are
+  paired with something in the current variable association
+  universally quantified out.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddForAll(Cal_BddManager bddManager, Cal_Bdd fUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+
+  if (CalBddPreProcessing(bddManager, 1, fUserBdd)){
+    Cal_Bdd_t f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    CalAssociation_t *assoc = bddManager->currentAssociation;
+    unsigned short opCode;
+
+    CalBddNot(f, f);
+    if (assoc->id == -1){
+      opCode = bddManager->tempOpCode--;
+    }
+    else {
+      opCode = CAL_OP_QUANT + assoc->id;
+    }
+    if (bddManager->numNodes <= CAL_LARGE_BDD){
+      /* If number of nodes is small, call depth first routine. */
+      result = BddExistsStep(bddManager, f, opCode, assoc);
+    }
+    else {
+      result = BddExistsBFPlusDF(bddManager, f, opCode, assoc);
+    }
+    CalBddNot(result, result);
+    userResult =  CalBddGetExternalBdd(bddManager, result);
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      Cal_BddFree(bddManager, userResult);
+      Cal_BddManagerGC(bddManager);
+      return (Cal_Bdd) 0;
+    }
+    return userResult;
+  }
+  return (Cal_Bdd) 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+  
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpExists(Cal_BddManager_t * bddManager, Cal_Bdd_t  f, Cal_Bdd_t *
+            resultBddPtr) 
+{
+  if (((int)bddManager->idToIndex[CalBddGetBddId(f)]) >
+      bddManager->currentAssociation->lastBddIndex){ 
+    *resultBddPtr = f;
+    return 1;
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpRelProd(Cal_BddManager_t * bddManager, Cal_Bdd_t  f, Cal_Bdd_t  g,
+             Cal_Bdd_t * resultBddPtr) 
+{
+  if (CalBddIsBddZero(bddManager, f) || CalBddIsBddZero(bddManager, g) ||
+      CalBddIsComplementEqual(f, g)){
+    *resultBddPtr = bddManager->bddZero;
+    return 1;
+  }
+  else if (CalBddIsBddOne(bddManager, f) && CalBddIsBddOne(bddManager, g)){
+    *resultBddPtr = bddManager->bddOne;
+    return 1;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddExistsStep(Cal_BddManager_t * bddManager, Cal_Bdd_t  f, unsigned
+              short opCode, CalAssociation_t *association)
+{
+  Cal_Bdd_t temp1, temp2;
+  Cal_Bdd_t f1, f2;
+  Cal_Bdd_t result;
+  Cal_BddId_t topId;
+  int quantifying;
+  
+  if (((int)CalBddGetBddIndex(bddManager, f)) > association->lastBddIndex){
+    return f;
+  }
+  if (CalCacheTableOneLookup(bddManager, f, opCode, &result)){
+    return result;
+  }
+
+  topId = CalBddGetBddId(f);
+  quantifying = (CalBddIsBddNull(bddManager,
+                                 association->varAssociation[topId]) ? 0 : 1);
+  CalBddGetCofactors(f, topId, f1, f2);
+  temp1 = BddExistsStep(bddManager, f1, opCode, association);
+  if (quantifying && CalBddIsEqual(temp1, bddManager->bddOne)){
+    result=temp1;
+  }
+  else {
+    temp2 = BddExistsStep(bddManager, f2, opCode, association);
+    if (quantifying){
+      CalBddNot(temp1, temp1);
+      CalBddNot(temp2, temp2);
+	  result = BddDFStep(bddManager, temp1, temp2, CalOpNand, CAL_OP_NAND);
+	}
+    else {
+      Cal_BddId_t id = CalBddGetBddId(f);
+      if (CalUniqueTableForIdFindOrAdd(bddManager, bddManager->uniqueTable[id],
+                                       temp1, temp2, &result) == 0){
+        CalBddIcrRefCount(temp1);
+        CalBddIcrRefCount(temp2);
+      }
+    }
+  } 
+  CalCacheTableOneInsert(bddManager, f, result, opCode, 0);
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddRelProdStep(Cal_BddManager_t * bddManager, Cal_Bdd_t  f, Cal_Bdd_t
+               g, unsigned short opCode, CalAssociation_t *assoc)
+{
+  Cal_BddId_t topId;
+  Cal_Bdd_t f1, f2, g1, g2;
+  Cal_Bdd_t temp1, temp2;
+  Cal_Bdd_t  result;
+  int quantifying;
+
+  if (CalBddIsBddConst(f) || CalBddIsBddConst(g)){
+    if (CalBddIsBddZero(bddManager, f) || CalBddIsBddZero(bddManager, g)){
+      return bddManager->bddZero;
+    }
+    if (assoc->id != -1){
+      opCode = CAL_OP_QUANT+assoc->id;
+    }
+    else{
+      opCode--;
+    }
+    if (CalBddIsBddOne(bddManager, f)){
+      return (BddExistsStep(bddManager, g, opCode, assoc));
+    }
+    return (BddExistsStep(bddManager, f, opCode, assoc));
+  }
+  if ((((int)CalBddGetBddIndex(bddManager, f)) > assoc->lastBddIndex) &&
+      (((int)CalBddGetBddIndex(bddManager, g)) > assoc->lastBddIndex)){
+    result = BddDFStep(bddManager, f, g, CalOpNand, CAL_OP_NAND);
+    CalBddNot(result, result);
+    return result;
+  }
+  if(CalOpRelProd(bddManager, f, g, &result) == 1){
+    return result;
+  }
+  CalBddNormalize(f, g);
+  if(CalCacheTableTwoLookup(bddManager, f, g, opCode, &result)){
+    return result;
+  }
+  CalBddGetMinId2(bddManager, f, g, topId);
+  
+  quantifying = (CalBddIsBddNull(bddManager, assoc->varAssociation[topId]) ? 0
+                 : 1);
+  CalBddGetCofactors(f, topId, f1, f2);
+  CalBddGetCofactors(g, topId, g1, g2);
+
+  temp1 = BddRelProdStep(bddManager, f1, g1, opCode, assoc);
+  if (quantifying && CalBddIsBddOne(bddManager, temp1)){
+    result=temp1;
+  }
+  else {
+    temp2 = BddRelProdStep(bddManager, f2, g2, opCode, assoc);
+    if (quantifying) {
+      CalBddNot(temp1, temp1);
+      CalBddNot(temp2, temp2);
+	  result = BddDFStep(bddManager, temp1, temp2, CalOpNand, CAL_OP_NAND);
+	  /*result = BddDFStep(bddManager, temp1, temp2, CalOpOr, CAL_OP_OR);*/
+	}
+    else {
+      if (CalUniqueTableForIdFindOrAdd(bddManager,
+                                       bddManager->uniqueTable[topId],
+                                       temp1, temp2, &result) == 0){
+        CalBddIcrRefCount(temp1);
+        CalBddIcrRefCount(temp2);
+      }
+    }
+  }
+  CalCacheTableTwoInsert(bddManager, f, g, result, opCode, 0);
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddDFStep(Cal_BddManager_t * bddManager, Cal_Bdd_t  f, Cal_Bdd_t g,
+          CalOpProc_t calOpProc, unsigned short opCode)
+{
+  Cal_BddId_t topId;
+  Cal_Bdd_t temp1, temp2, fx, fxbar, gx, gxbar;
+  Cal_Bdd_t  result;
+
+  if((*calOpProc)(bddManager, f, g, &result) == 1){
+    return result;
+  }
+  CalBddNormalize(f, g);
+  if(CalCacheTableTwoLookup(bddManager, f, g, opCode, &result)){
+    return result;
+  }
+  CalBddGetMinId2(bddManager, f, g, topId);
+  CalBddGetCofactors(f, topId, fx, fxbar);
+  CalBddGetCofactors(g, topId, gx, gxbar);
+  temp1 = BddDFStep(bddManager, fx, gx, calOpProc, opCode);
+  temp2 = BddDFStep(bddManager, fxbar, gxbar, calOpProc, opCode);
+
+  if (CalUniqueTableForIdFindOrAdd(bddManager,
+                                   bddManager->uniqueTable[topId],
+                                   temp1, temp2, &result) == 0){
+    CalBddIcrRefCount(temp1);
+    CalBddIcrRefCount(temp2);
+  }
+  CalCacheTableTwoInsert(bddManager, f, g, result, opCode, 0);
+  return (result);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+HashTableApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable,
+               CalHashTable_t ** reqQueAtPipeDepth, CalOpProc_t calOpProc,
+               unsigned long opCode)  
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t fx, gx, fxbar, gxbar, result;
+  Cal_BddId_t bddId;
+  
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetCofactors(bddManager, requestNode, fx, fxbar, gx, gxbar);
+      CalBddNormalize(fx, gx);
+      if((*calOpProc)(bddManager, fx, gx, &result) == 0){
+        if (CalCacheTableTwoLookup(bddManager, fx, gx, opCode, &result) == 0){
+          CalBddGetMinId2(bddManager, fx, gx, bddId);
+          CalHashTableFindOrAdd(reqQueAtPipeDepth[bddId], fx, gx, &result);
+          CalCacheTableTwoInsert(bddManager, fx, gx, result, opCode, 1);
+        }
+        else {
+          CalRequestIsForwardedTo(result);
+        }
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutThenRequest(requestNode, result);
+      CalBddNormalize(fxbar, gxbar);
+      if((*calOpProc)(bddManager, fxbar, gxbar, &result) == 0){
+        if (CalCacheTableTwoLookup(bddManager, fxbar, gxbar, opCode, &result)
+            == 0){ 
+          CalBddGetMinId2(bddManager, fxbar, gxbar, bddId);
+          CalHashTableFindOrAdd(reqQueAtPipeDepth[bddId], fxbar, gxbar,
+                                &result); 
+          CalCacheTableTwoInsert(bddManager, fxbar, gxbar, result,
+                                 opCode, 1);
+        }
+        else {
+          CalRequestIsForwardedTo(result);
+        }
+      }
+      CalBddIcrRefCount(result);
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+HashTableReduce(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable,
+                CalHashTable_t * uniqueTableForId)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  Cal_BddId_t currentBddId = uniqueTableForId->bddId;
+  CalNodeManager_t *nodeManager = uniqueTableForId->nodeManager;
+  CalRequestNode_t *requestNode, *next;
+  CalBddNode_t *bddNode, *endNode;
+  Cal_Bdd_t thenBdd, elseBdd, result;
+  Cal_BddRefCount_t refCount;
+
+  /*requestNodeList = hashTable->requestNodeList;*/
+  endNode = hashTable->endNode;
+  hashTable->numEntries = 0;
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = next){
+      next = CalRequestNodeGetNextRequestNode(requestNode);
+      /* Process the requestNode */
+      CalRequestNodeGetThenRequest(requestNode, thenBdd);
+      CalRequestNodeGetElseRequest(requestNode, elseBdd);
+      CalRequestIsForwardedTo(thenBdd);
+      CalRequestIsForwardedTo(elseBdd);
+      if(CalBddIsEqual(thenBdd, elseBdd)){
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddAddRefCount(thenBdd, refCount - 2);
+        CalRequestNodePutThenRequest(requestNode, thenBdd);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        /*
+        ** CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+        ** requestNodeList = requestNode;
+        */
+        /*CalRequestNodePutNextRequestNode(endNode, requestNode);*/
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+      else if(CalUniqueTableForIdLookup(bddManager, uniqueTableForId,
+          thenBdd, elseBdd, &result) == 1){
+        CalBddDcrRefCount(thenBdd);
+        CalBddDcrRefCount(elseBdd);
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddAddRefCount(result, refCount);
+        CalRequestNodePutThenRequest(requestNode, result);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        /*
+        ** CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+        ** requestNodeList = requestNode;
+        */
+        /*CalRequestNodePutNextRequestNode(endNode, requestNode);*/
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+      else if(CalBddIsOutPos(thenBdd)){
+        CalRequestNodePutThenRequest(requestNode, thenBdd);
+        CalRequestNodePutElseRequest(requestNode, elseBdd);
+        CalHashTableAddDirect(uniqueTableForId, requestNode);
+        bddManager->numNodes++;
+        bddManager->gcCheck--;
+      }
+      else{
+        CalNodeManagerAllocNode(nodeManager, bddNode);
+        CalBddNodePutThenBddId(bddNode, CalBddGetBddId(thenBdd));
+        CalBddNodePutThenBddNode(bddNode, CalBddGetBddNodeNot(thenBdd));
+        CalBddNodePutElseBddId(bddNode, CalBddGetBddId(elseBdd));
+        CalBddNodePutElseBddNode(bddNode, CalBddGetBddNodeNot(elseBdd));
+        /*
+        CalNodeManagerInitBddNode(nodeManager, thenBdd, elseBdd,
+                               Cal_Nil(CalBddNode_t), bddNode); 
+                               */
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddNodePutRefCount(bddNode, refCount);
+        CalHashTableAddDirect(uniqueTableForId, bddNode);
+        bddManager->numNodes++;
+        bddManager->gcCheck--;
+        CalRequestNodePutThenRequestId(requestNode, currentBddId);
+        CalRequestNodePutThenRequestNode(requestNode, CalBddNodeNot(bddNode));
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        /*
+        ** CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+        ** requestNodeList = requestNode;
+        */
+        /*CalRequestNodePutNextRequestNode(endNode, requestNode);*/
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+    }
+  }
+  /* hashTable->requestNodeList = requestNodeList; */
+  hashTable->endNode = endNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddExistsApply(Cal_BddManager_t *bddManager, int quantifying,
+               CalHashTable_t *existHashTable, CalHashTable_t
+               **existHashTableArray,  CalOpProc1_t calOpProc, 
+               unsigned short opCode, CalAssociation_t *assoc)  
+{
+  int i, numBins = existHashTable->numBins;
+  CalBddNode_t **bins = existHashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t f, fx, fxbar, result, resultBar;
+  int lastBddIndex = assoc->lastBddIndex; 
+  
+  if (quantifying){
+    for(i = 0; i < numBins; i++){
+      for(requestNode = bins[i];
+          requestNode != Cal_Nil(CalRequestNode_t);
+          requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+        CalRequestNodeGetF(requestNode, f);
+        CalBddGetThenBdd(f, fx);
+        CalBddGetElseBdd(f, fxbar);
+      
+        /*if(calOpProc(bddManager, fx, &result) == 0){*/
+        if (((int)bddManager->idToIndex[CalBddGetBddId(fx)]) <= lastBddIndex){
+          if (CalCacheTableOneLookup(bddManager, fx, opCode, &result)){ 
+            CalRequestIsForwardedTo(result);
+          }
+          else {
+            CalHashTableFindOrAdd(existHashTableArray[CalBddGetBddId(fx)], fx,
+                                  bddManager->bddOne, &result);
+            CalCacheTableOneInsert(bddManager, fx, result,
+                                   opCode, 1);
+          }
+        }
+        else {
+          result = fx;
+        }
+        CalRequestNodePutThenRequest(requestNode, result);
+        CalRequestNodePutElseRequest(requestNode, fxbar);
+      }
+    }
+  }
+  else {
+    for(i = 0; i < numBins; i++){
+      for(requestNode = bins[i];
+          requestNode != Cal_Nil(CalRequestNode_t);
+          requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+        CalRequestNodeGetF(requestNode, f);
+        CalBddGetThenBdd(f, fx);
+        CalBddGetElseBdd(f, fxbar);
+      
+        if (((int)bddManager->idToIndex[CalBddGetBddId(fx)]) <= lastBddIndex){
+          if (CalCacheTableOneLookup(bddManager, fx, opCode, &result)){ 
+            CalRequestIsForwardedTo(result);
+          }
+          else {
+            CalHashTableFindOrAdd(existHashTableArray[CalBddGetBddId(fx)], fx,
+                                  bddManager->bddOne, &result);
+            CalCacheTableOneInsert(bddManager, fx, result,
+                                   opCode, 1);
+          }
+        }
+        else {
+          result = fx;
+        }
+        CalRequestNodePutThenRequest(requestNode, result);
+        CalBddIcrRefCount(result);
+        /*if(calOpProc(bddManager, fxbar, &resultBar) == 0){*/
+        if (((int)bddManager->idToIndex[CalBddGetBddId(fxbar)]) <= lastBddIndex){
+          if (CalCacheTableOneLookup(bddManager, fxbar, opCode,
+                                       &resultBar)){
+            CalRequestIsForwardedTo(resultBar);
+          }
+          else {
+            CalHashTableFindOrAdd(existHashTableArray[CalBddGetBddId(fxbar)], fxbar,
+                                  bddManager->bddOne, &resultBar);
+            CalCacheTableOneInsert(bddManager, fxbar, resultBar,
+                                   opCode, 1); 
+          }
+        }
+        else{
+          resultBar = fxbar;
+        }
+        CalBddIcrRefCount(resultBar);
+        CalRequestNodePutElseRequest(requestNode, resultBar);
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void  
+BddExistsBFAux(Cal_BddManager_t *bddManager, int minIndex,
+               CalHashTable_t **existHashTableArray, CalHashTable_t
+               **orHashTableArray,  CalOpProc1_t calOpProc, unsigned
+               short opCode, CalAssociation_t *assoc)   
+{
+  int index;
+  Cal_BddId_t bddId;
+  int quantifying;
+  
+  /* Apply phase */
+  for (index = minIndex; index < bddManager->numVars; index++){
+    bddId = bddManager->indexToId[index];
+    if (existHashTableArray[bddId]->numEntries){
+      quantifying = (CalBddIsBddNull(bddManager,
+                                     assoc->varAssociation[bddId]) ? 0 : 1); 
+      BddExistsApply(bddManager, quantifying,
+                     existHashTableArray[bddId], existHashTableArray,
+                     calOpProc, opCode, assoc);    
+    }
+  }
+  
+  /* Reduce phase */
+  for (index = bddManager->numVars-1; index >= minIndex; index--){
+    bddId = bddManager->indexToId[index];
+    if (existHashTableArray[bddId]->numEntries){
+      quantifying = (CalBddIsBddNull(bddManager,
+                                     assoc->varAssociation[bddId]) ? 0 : 1); 
+      if (quantifying){
+        BddExistsReduce(bddManager, existHashTableArray[bddId],
+                        existHashTableArray, orHashTableArray,
+                        opCode, assoc);
+      } 
+      else {
+        HashTableReduce(bddManager, existHashTableArray[bddId],
+                        bddManager->uniqueTable[bddId]);
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddExistsReduce(Cal_BddManager_t *bddManager, CalHashTable_t
+                *existHashTable, CalHashTable_t **existHashTableArray,
+                CalHashTable_t **orHashTableArray, unsigned short
+                opCode, CalAssociation_t *association) 
+{
+  int i, numBins = existHashTable->numBins;
+  CalBddNode_t **bins = existHashTable->bins;
+  CalRequestNode_t *requestNode, *next, *requestNodeListAux;
+  CalBddNode_t *endNode;
+  
+  int bddIndex;
+  /*Cal_BddIndex_t minIndex, elseIndex;*/
+  int minIndex, elseIndex;
+  Cal_BddId_t bddId, minId;
+  Cal_Bdd_t thenBdd, elseBdd, result, orResult;
+  Cal_BddRefCount_t refCount;
+  int lastBddIndex = association->lastBddIndex; 
+  
+
+  /* For those nodes which get processed in the first pass */
+  /* requestNodeList = existHashTable->requestNodeList; */
+  endNode = existHashTable->endNode;
+
+  /* For the other ones. This list is merged with the requestNodeList
+   * after processing is complete.
+   */
+  requestNodeListAux = Cal_Nil(CalRequestNode_t);
+  existHashTable->numEntries = 0;
+  
+  minIndex = bddManager->numVars;
+  
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = next){
+      next = CalRequestNodeGetNextRequestNode(requestNode);
+      /* Process the requestNode */
+      CalRequestNodeGetThenRequest(requestNode, thenBdd);
+      CalRequestNodeGetElseRequest(requestNode, elseBdd);
+      CalRequestIsForwardedTo(thenBdd);
+      CalRequestNodePutThenRequest(requestNode, thenBdd);
+      if (CalBddIsBddOne(bddManager, thenBdd)){
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        /*
+        ** CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+        ** requestNodeList = requestNode;
+        */
+        /*CalRequestNodePutNextRequestNode(endNode, requestNode);*/
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+        continue;
+      }
+      
+      CalRequestNodePutNextRequestNode(requestNode, requestNodeListAux);
+      requestNodeListAux = requestNode;
+
+      /*if(CalOpExists(bddManager, elseBdd, &result) == 0){*/
+      if (((int)bddManager->idToIndex[CalBddGetBddId(elseBdd)]) <= lastBddIndex){
+        if (CalCacheTableOneLookup(bddManager, elseBdd, opCode,
+                                   &result)){  
+          CalRequestIsForwardedTo(result);
+        }
+        else{
+          CalHashTableFindOrAdd(existHashTableArray[CalBddGetBddId(elseBdd)], elseBdd,
+                                bddManager->bddOne, &result);
+          CalCacheTableOneInsert(bddManager, elseBdd, result,
+                                 opCode, 1);
+          if (minIndex > (elseIndex = CalBddGetBddIndex(bddManager,
+                                                        elseBdd))){ 
+            minIndex = elseIndex;
+          }
+        }
+      }
+      else{
+        result = elseBdd;
+      }
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+  
+  if (!requestNodeListAux){
+    /* requestNodeList = requestNodeList; */
+    existHashTable->endNode = endNode;
+    return;
+  }
+  
+  BddExistsBFAux(bddManager, minIndex, existHashTableArray,
+                 orHashTableArray,  CalOpExists, opCode, association); 
+  minIndex = bddManager->numVars;
+  for (requestNode = requestNodeListAux; requestNode; requestNode = next){
+    Cal_Bdd_t thenResult, elseResult;
+    Cal_BddIndex_t orResultIndex;
+    
+    next = CalRequestNodeGetNextRequestNode(requestNode);
+    CalRequestNodeGetThenRequest(requestNode, thenResult);
+    CalRequestNodeGetElseRequest(requestNode, elseResult);
+    CalRequestIsForwardedTo(elseResult);
+    if (CalOpOr(bddManager, thenResult, elseResult, &orResult) == 0){
+      CalBddNormalize(thenResult, elseResult);
+      CalBddNot(thenResult, thenResult);
+      CalBddNot(elseResult, elseResult);
+      if (CalCacheTableTwoLookup(bddManager, thenResult,elseResult,
+                                 CAL_OP_NAND, &orResult)){
+        CalRequestIsForwardedTo(orResult);
+      }
+      else {
+        CalBddGetMinIdAndMinIndex(bddManager, thenResult, elseResult,
+                                  minId, orResultIndex);
+        CalHashTableFindOrAdd(orHashTableArray[minId], thenResult, elseResult,
+                              &orResult);
+        CalCacheTableTwoInsert(bddManager, thenResult, elseResult, orResult,
+                               CAL_OP_NAND, 1);
+        if (minIndex > orResultIndex) minIndex = orResultIndex;
+      }
+    }
+    CalRequestNodePutThenRequest(requestNode, orResult);
+  }
+  
+
+  /* Call "OR" apply and reduce */
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    if(orHashTableArray[bddId]->numEntries){
+      HashTableApply(bddManager, orHashTableArray[bddId], orHashTableArray,
+                     CalOpNand, CAL_OP_NAND);
+    }
+  }
+  
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    CalHashTable_t *uniqueTableForId;
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    if(orHashTableArray[bddId]->numEntries){
+      HashTableReduce(bddManager, orHashTableArray[bddId], uniqueTableForId);
+    }
+  }
+  
+  for (requestNode = requestNodeListAux; requestNode; requestNode = next){
+    next = CalRequestNodeGetNextRequestNode(requestNode);
+    CalRequestNodeGetThenRequest(requestNode, result);
+    CalRequestIsForwardedTo(result);
+    CalBddNodeGetRefCount(requestNode, refCount);
+    CalBddAddRefCount(result, refCount);
+    CalRequestNodePutThenRequest(requestNode, result);
+    CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+    /*
+    ** CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+    ** requestNodeList = requestNode;
+    */
+    /*CalRequestNodePutNextRequestNode(endNode, requestNode);*/
+    endNode->nextBddNode = requestNode;
+    endNode = requestNode;
+  }
+  /*existHashTable->requestNodeList = requestNodeList;*/
+  existHashTable->endNode = endNode;
+  
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddExistsBFPlusDF(Cal_BddManager_t *bddManager, Cal_Bdd_t f, unsigned
+                  short opCode, CalAssociation_t *association)
+{
+  Cal_BddId_t fId = CalBddGetBddId(f);
+  Cal_BddIndex_t bddIndex;
+  Cal_BddId_t bddId;
+  
+  Cal_BddIndex_t fIndex = bddManager->idToIndex[fId];
+  CalHashTable_t **orHashTableArray = bddManager->reqQue[4];
+  CalHashTable_t **existHashTableArray = bddManager->reqQue[5];
+  Cal_Bdd_t result;
+  
+  if (CalOpExists(bddManager, f, &result) == 1){
+    return result;
+  }
+
+  if (CalCacheTableOneLookup(bddManager, f, opCode, &result)){
+    return result;
+  }
+  
+  /*
+   * Change the size of the exist hash table to min. size 
+   */
+  for (bddIndex = fIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    existHashTableArray[bddId]->sizeIndex =
+        DEFAULT_EXIST_HASH_TABLE_SIZE_INDEX;  
+    existHashTableArray[bddId]->numBins = DEFAULT_EXIST_HASH_TABLE_SIZE;
+    Cal_MemFree(existHashTableArray[bddId]->bins);
+    existHashTableArray[bddId]->bins = Cal_MemAlloc(CalBddNode_t*,
+                                             DEFAULT_EXIST_HASH_TABLE_SIZE);
+    memset((char *)existHashTableArray[bddId]->bins, 0,
+           existHashTableArray[bddId]->numBins*sizeof(CalBddNode_t*));
+  }
+  
+  CalHashTableFindOrAdd(existHashTableArray[fId], f, bddManager->bddOne,
+                        &result);  
+
+
+  BddExistsBFAux(bddManager, fIndex, existHashTableArray, orHashTableArray,
+                 CalOpExists, opCode, association);  
+
+  CalRequestIsForwardedTo(result);
+  
+  CalCacheTableTwoFixResultPointers(bddManager);
+  CalCacheTableOneInsert(bddManager, f, result, opCode, 0);
+  for (bddIndex = fIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(existHashTableArray[bddId]);
+    CalHashTableCleanUp(orHashTableArray[bddId]);
+  }
+  return result;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddRelProdApply(Cal_BddManager_t *bddManager, int quantifying, CalHashTable_t
+                *relProdHashTable, CalHashTable_t **relProdHashTableArray,
+                CalHashTable_t **andHashTableArray, CalOpProc_t
+                calOpProc, unsigned short opCode, CalAssociation_t *assoc)
+{
+  int i, numBins = relProdHashTable->numBins;
+  CalBddNode_t **bins = relProdHashTable->bins;
+  Cal_BddId_t minId;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t fx, fxbar, gx, gxbar, result, resultBar;
+  /*Cal_BddIndex_t minIndex;*/
+  int minIndex;
+  
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetCofactors(bddManager, requestNode, fx, fxbar, gx, gxbar);
+      CalBddNormalize(fx, gx);
+      CalBddGetMinIdAndMinIndex(bddManager, fx, gx, minId, minIndex);
+      if (minIndex > assoc->lastBddIndex){
+        if (CalOpAnd(bddManager, fx, gx, &result) == 0){
+          if (CalCacheTableTwoLookup(bddManager, fx, gx, CAL_OP_NAND,
+                                     &result)){  
+            CalRequestIsForwardedTo(result);
+          }
+          else{
+            CalHashTableFindOrAdd(andHashTableArray[minId], fx, gx, &result);
+            CalCacheTableTwoInsert(bddManager, fx, gx, result,
+                                   CAL_OP_NAND, 1);
+          }
+          CalBddNot(result, result);
+        }
+      }
+      else {
+        if(calOpProc(bddManager, fx, gx, &result) == 0){
+          if (CalCacheTableTwoLookup(bddManager, fx, gx, opCode,
+                                     &result)){      
+            CalRequestIsForwardedTo(result);
+          }
+          else {
+            CalHashTableFindOrAdd(relProdHashTableArray[minId], fx, gx,
+                                  &result);   
+            CalCacheTableTwoInsert(bddManager, fx, gx, result, opCode, 1); 
+          }
+        }
+      }
+      CalRequestNodePutThenRequest(requestNode, result);
+      if (quantifying){
+        Cal_Bdd_t elseRequest;
+        Cal_BddId_t elseRequestId;
+        CalBddNode_t *elseRequestNode;
+        
+        CalBddGetMinId2(bddManager, fxbar, gxbar, elseRequestId);
+        CalNodeManagerInitBddNode(bddManager->nodeManagerArray[elseRequestId],
+                                  fxbar, gxbar, Cal_Nil(CalBddNode_t),
+                                  elseRequestNode);
+        /*
+          CalNodeManagerAllocNode(bddManager->nodeManagerArray[elseRequestId],
+          elseRequestNode);  
+          CalRequestNodePutF(elseRequestNode, fxbar);
+          CalRequestNodePutG(elseRequestNode, gxbar);
+        */
+        CalRequestPutRequestId(elseRequest, elseRequestId);
+        CalRequestPutRequestNode(elseRequest, elseRequestNode);
+        CalRequestNodePutElseRequest(requestNode, elseRequest);
+      }
+      else {
+        CalBddIcrRefCount(result);
+        CalBddNormalize(fxbar, gxbar);
+        CalBddGetMinIdAndMinIndex(bddManager, fxbar, gxbar, minId, minIndex);
+        if (minIndex > assoc->lastBddIndex){
+          if (CalOpAnd(bddManager, fxbar, gxbar, &resultBar) == 0){
+            if( CalCacheTableTwoLookup(bddManager, fxbar, gxbar,
+                                       CAL_OP_NAND, &resultBar)){  
+              CalRequestIsForwardedTo(resultBar);
+            }
+            else{
+              CalHashTableFindOrAdd(andHashTableArray[minId], fxbar, gxbar,
+                                    &resultBar); 
+              CalCacheTableTwoInsert(bddManager, fxbar, gxbar, resultBar,
+                                     CAL_OP_NAND, 1); 
+            }
+            CalBddNot(resultBar, resultBar);
+          }
+        }
+        else {
+          if(calOpProc(bddManager, fxbar, gxbar, &resultBar) == 0){
+            if (CalCacheTableTwoLookup(bddManager, fxbar, gxbar, opCode,
+                                       &resultBar)){   
+              CalRequestIsForwardedTo(resultBar);
+            }
+            else { 
+              CalHashTableFindOrAdd(relProdHashTableArray[minId],
+                                    fxbar, gxbar, &resultBar);
+              CalCacheTableTwoInsert(bddManager, fxbar, gxbar,
+                                     resultBar, opCode, 1); 
+            }
+          }
+        }
+        CalBddIcrRefCount(resultBar);
+        CalRequestNodePutElseRequest(requestNode, resultBar);
+      }
+    }
+  }
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddRelProdReduce(Cal_BddManager_t *bddManager, CalHashTable_t
+                 *relProdHashTable, CalHashTable_t
+                 **relProdHashTableArray, CalHashTable_t
+                 **andHashTableArray, CalHashTable_t
+                 **orHashTableArray, unsigned short opCode,
+                 CalAssociation_t *assoc)  
+{
+  int i, numBins = relProdHashTable->numBins;
+  CalBddNode_t **bins = relProdHashTable->bins;
+  CalRequestNode_t *requestNode, *next, *requestNodeListAux;
+  CalBddNode_t  *elseRequestNode;
+  int bddIndex;
+  /*Cal_BddIndex_t minIndex;*/
+  int minIndex;
+  Cal_BddId_t bddId, minId, elseRequestId;
+  Cal_Bdd_t thenBdd, elseBdd, result, orResult;
+  Cal_BddRefCount_t refCount;
+  Cal_Bdd_t fxbar, gxbar;
+  CalBddNode_t *endNode;
+  
+
+  /* For those nodes which get processed in the first pass */
+  /*requestNodeList = relProdHashTable->requestNodeList;*/
+  endNode = relProdHashTable->endNode;
+  
+  /* For the other ones. This list is merged with the requestNodeList
+   * after processing is complete.
+   */
+  requestNodeListAux = Cal_Nil(CalRequestNode_t);
+  
+  minIndex = bddManager->numVars;
+  
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = next){
+      next = CalRequestNodeGetNextRequestNode(requestNode);
+      /* Process the requestNode */
+      CalRequestNodeGetThenRequest(requestNode, thenBdd);
+      CalRequestIsForwardedTo(thenBdd);
+      /*CalRequestNodePutThenRequest(requestNode, thenBdd);*/
+      CalRequestNodeGetElseRequest(requestNode, elseBdd);
+      CalRequestIsForwardedTo(elseBdd);
+      CalRequestGetF(elseBdd, fxbar);
+      CalRequestGetG(elseBdd, gxbar);
+      
+      /* Free the else request node because it is not needed */
+      elseRequestNode = CalRequestNodeGetElseRequestNode(requestNode);
+      elseRequestId = CalRequestNodeGetElseRequestId(requestNode);
+      CalNodeManagerFreeNode(bddManager->nodeManagerArray[elseRequestId],
+                             elseRequestNode);
+      if (CalBddIsBddOne(bddManager, thenBdd)){
+        CalRequestNodePutThenRequest(requestNode, bddManager->bddOne);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        /*
+        ** CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+        ** requestNodeList = requestNode;
+        */
+        /*CalRequestNodePutNextRequestNode(endNode, requestNode);*/
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+        continue;
+      }
+      
+      CalRequestNodePutNextRequestNode(requestNode, requestNodeListAux);
+      requestNodeListAux = requestNode;
+
+      CalBddGetMinIdAndMinIndex(bddManager, fxbar, gxbar, bddId, bddIndex);
+      CalBddNormalize(fxbar, gxbar);
+      if (bddIndex > assoc->lastBddIndex){
+        if (CalOpAnd(bddManager, fxbar, gxbar, &result) == 0){
+          if (CalCacheTableTwoLookup(bddManager, fxbar, gxbar,
+                                     CAL_OP_NAND, &result)){
+            CalRequestIsForwardedTo(result);
+          }
+          else {
+            CalHashTableFindOrAdd(andHashTableArray[bddId], fxbar,
+                                  gxbar, &result);
+            CalCacheTableTwoInsert(bddManager, fxbar, gxbar, result,
+                                   CAL_OP_NAND, 1);
+            if (minIndex > bddIndex) minIndex = bddIndex;
+          }
+          CalBddNot(result, result);
+        }
+      }
+      else {
+        if(CalOpRelProd(bddManager, fxbar, gxbar, &result) == 0){
+          if (CalCacheTableTwoLookup(bddManager, fxbar, gxbar, opCode,
+                                     &result)){  
+            CalRequestIsForwardedTo(result);
+          }
+          else {
+            CalHashTableFindOrAdd(relProdHashTableArray[bddId], fxbar, gxbar, 
+                                  &result);
+            CalCacheTableTwoInsert(bddManager, fxbar, gxbar, result,
+                                   opCode, 1); 
+            if (minIndex > bddIndex) minIndex = bddIndex;
+          }
+        }
+      }
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+
+  if (!requestNodeListAux){
+    /*relProdHashTable->requestNodeList = requestNodeList;*/
+    relProdHashTable->endNode = endNode;
+    return;
+  }
+  
+  BddRelProdBFAux(bddManager, minIndex, relProdHashTableArray,
+                  andHashTableArray, orHashTableArray, opCode, assoc);
+  
+  minIndex = bddManager->numVars;
+  for (requestNode = requestNodeListAux; requestNode; requestNode = next){
+    Cal_Bdd_t thenResult, elseResult;
+    Cal_BddIndex_t orResultIndex;
+    
+    next = CalRequestNodeGetNextRequestNode(requestNode);
+    CalRequestNodeGetThenRequest(requestNode, thenResult);
+    CalRequestNodeGetElseRequest(requestNode, elseResult);
+    CalRequestIsForwardedTo(elseResult);
+    CalRequestIsForwardedTo(thenResult);
+    CalBddNormalize(thenResult, elseResult);
+    if (CalOpOr(bddManager, thenResult, elseResult, &orResult) == 0){
+      CalBddNot(thenResult, thenResult);
+      CalBddNot(elseResult, elseResult);
+      if (CalCacheTableTwoLookup(bddManager, thenResult, elseResult,
+                                 CAL_OP_NAND, &orResult)){ 
+        CalRequestIsForwardedTo(orResult);
+      }
+      else {
+        CalBddGetMinIdAndMinIndex(bddManager, thenResult, elseResult,
+                                  minId, orResultIndex);
+        CalHashTableFindOrAdd(orHashTableArray[minId], thenResult, elseResult,
+                              &orResult);
+        CalCacheTableTwoInsert(bddManager, thenResult, elseResult, orResult,
+                                 CAL_OP_NAND, 1); 
+        if (minIndex > orResultIndex) minIndex = orResultIndex;
+      }
+    }
+    CalRequestNodePutThenRequest(requestNode, orResult);
+  }
+
+  /* Call "OR" apply and reduce */
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    if(orHashTableArray[bddId]->numEntries){
+        HashTableApply(bddManager, orHashTableArray[bddId], orHashTableArray,
+                       CalOpNand, CAL_OP_NAND); 
+    }
+  }
+  
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    CalHashTable_t *uniqueTableForId;
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    if(orHashTableArray[bddId]->numEntries){
+      HashTableReduce(bddManager, orHashTableArray[bddId], uniqueTableForId);
+    }
+  }
+  for (requestNode = requestNodeListAux; requestNode; requestNode = next){
+    next = CalRequestNodeGetNextRequestNode(requestNode);
+    CalRequestNodeGetThenRequest(requestNode, result);
+    CalRequestIsForwardedTo(result);
+    CalBddNodeGetRefCount(requestNode, refCount);
+    CalBddAddRefCount(result, refCount);
+    CalRequestNodePutThenRequest(requestNode, result);
+    CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+    /*
+    ** CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+    ** requestNodeList = requestNode;
+    */
+    /*CalRequestNodePutNextRequestNode(endNode, requestNode);*/
+    endNode->nextBddNode = requestNode;
+    endNode = requestNode;
+  }
+
+  /*relProdHashTable->requestNodeList = requestNodeList;*/
+  relProdHashTable->endNode = endNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddRelProdBFAux(Cal_BddManager_t *bddManager, int minIndex,
+                CalHashTable_t **relProdHashTableArray, CalHashTable_t
+                **andHashTableArray, CalHashTable_t
+                **orHashTableArray, unsigned short opCode,
+                CalAssociation_t *assoc)
+{
+  Cal_BddIndex_t bddIndex;
+  int quantifying;
+  int index;
+  Cal_BddId_t bddId;
+  CalHashTable_t *hashTable;
+  
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = andHashTableArray[bddId];
+    if(hashTable->numEntries){
+      HashTableApply(bddManager, hashTable, andHashTableArray, CalOpNand,
+                     CAL_OP_NAND); 
+    }
+    hashTable = relProdHashTableArray[bddId];
+    if(hashTable->numEntries){
+      quantifying = (CalBddIsBddNull(bddManager,
+                                     assoc->varAssociation[bddId]) ? 0 : 1); 
+      BddRelProdApply(bddManager, quantifying, hashTable,
+                      relProdHashTableArray, andHashTableArray,
+                      CalOpRelProd, opCode, assoc); 
+    }
+  }
+
+  /* Reduce phase */
+  for (index = bddManager->numVars-1; index >= minIndex; index--){
+    CalHashTable_t *uniqueTableForId;
+    bddId = bddManager->indexToId[index];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = andHashTableArray[bddId];
+    if(hashTable->numEntries){
+      HashTableReduce(bddManager, hashTable, uniqueTableForId);
+    }
+    if (relProdHashTableArray[bddId]->numEntries){
+      quantifying = (CalBddIsBddNull(bddManager,
+                                     assoc->varAssociation[bddId]) ? 0 : 1); 
+      if (quantifying){
+        BddRelProdReduce(bddManager, relProdHashTableArray[bddId],
+                         relProdHashTableArray, andHashTableArray,
+                         orHashTableArray, opCode, assoc); 
+      }
+      else {
+        HashTableReduce(bddManager, relProdHashTableArray[bddId],
+                        bddManager->uniqueTable[bddId]);
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddRelProdBFPlusDF(Cal_BddManager_t * bddManager, Cal_Bdd_t  f,
+                   Cal_Bdd_t  g, unsigned short opCode,
+                   CalAssociation_t *association)
+{
+  Cal_Bdd_t result;
+  /*Cal_BddIndex_t minIndex;*/
+  int  minIndex;
+  int bddIndex;
+  CalHashTable_t **andHashTableArray = bddManager->reqQue[3];
+  CalHashTable_t **relProdHashTableArray = bddManager->reqQue[4];
+  CalHashTable_t **orHashTableArray = bddManager->reqQue[5];
+  Cal_BddId_t bddId, minId;
+
+  if(CalOpRelProd(bddManager, f, g, &result) == 1){
+    return result;
+  }
+  CalBddNormalize(f, g);
+  if(CalCacheTableTwoLookup(bddManager, f, g, opCode, &result)){
+    return result;
+  }
+
+  CalBddGetMinIdAndMinIndex(bddManager, f, g, minId, minIndex);
+
+  /*
+   * Change the size of the exist hash table to min. size 
+   */
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    relProdHashTableArray[bddId]->sizeIndex =
+        DEFAULT_EXIST_HASH_TABLE_SIZE_INDEX;  
+    relProdHashTableArray[bddId]->numBins = DEFAULT_EXIST_HASH_TABLE_SIZE;
+    Cal_MemFree(relProdHashTableArray[bddId]->bins);
+    relProdHashTableArray[bddId]->bins = Cal_MemAlloc(CalBddNode_t*,
+                                             DEFAULT_EXIST_HASH_TABLE_SIZE);
+    memset((char *)relProdHashTableArray[bddId]->bins, 0,
+           relProdHashTableArray[bddId]->numBins*sizeof(CalBddNode_t*));
+  }
+
+  if (minIndex > association->lastBddIndex) {
+    if (CalOpAnd(bddManager, f, g, &result) == 0){
+      if (CalCacheTableTwoLookup(bddManager, f, g, CAL_OP_NAND, &result)
+          == 0){
+        CalHashTableFindOrAdd(andHashTableArray[minId], f, g, &result);
+      }
+      else{
+        CalCacheTableTwoInsert(bddManager, f, g, result, CAL_OP_NAND,
+                               1);
+      }
+      CalBddNot(result, result);
+    }
+  }
+  else {
+    CalHashTableFindOrAdd(relProdHashTableArray[minId], f, g, &result); 
+  }
+
+  BddRelProdBFAux(bddManager, minIndex, relProdHashTableArray,
+                  andHashTableArray, orHashTableArray, opCode, association); 
+  CalRequestIsForwardedTo(result);
+  CalCacheTableTwoFixResultPointers(bddManager);
+  CalCacheTableTwoInsert(bddManager, f, g, result, opCode, 0);
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(relProdHashTableArray[bddId]);
+    CalHashTableCleanUp(andHashTableArray[bddId]);
+    CalHashTableCleanUp(orHashTableArray[bddId]);
+  }
+  return result;
+}
+
Index: /vis_dev/glu-2.1/src/calBdd/calReduce.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calReduce.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calReduce.c	(revision 8)
@@ -0,0 +1,684 @@
+/**CFile***********************************************************************
+
+  FileName    [calReduce.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for optimizing a BDD with respect to a don't
+  care set (cofactor and restrict).]
+
+  Description []
+
+  SeeAlso     [None]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calReduce.c,v 1.3 2002/09/21 20:39:25 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Cal_Bdd_t BddReduceBF(Cal_BddManager_t * bddManager, CalOpProc_t calOpProc, Cal_Bdd_t f, Cal_Bdd_t c);
+static Cal_Bdd_t BddCofactorBF(Cal_BddManager_t * bddManager, CalOpProc_t calOpProc, Cal_Bdd_t f, Cal_Bdd_t c);
+static void HashTableReduceApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t ** reduceHashTableArray, CalHashTable_t ** orHashTableArray, CalOpProc_t calOpProc);
+static void HashTableCofactorApply(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t ** cofactorHashTableArray, CalOpProc_t calOpProc);
+static void HashTableCofactorReduce(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalHashTable_t * uniqueTableForId);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns the generalized cofactor of BDD f with respect
+  to BDD c.]
+
+  Description [Returns the generalized cofactor of BDD f with respect
+  to BDD c. The constrain operator given by Coudert et al (ICCAD90) is
+  used to find the generalized cofactor.]
+
+  SideEffects [None.]
+
+  SeeAlso     [Cal_BddReduce]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddCofactor(Cal_BddManager  bddManager, Cal_Bdd fUserBdd,
+                Cal_Bdd cUserBdd)
+{
+  Cal_Bdd_t result;
+  Cal_Bdd userResult;
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, cUserBdd)){
+    Cal_Bdd_t f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    Cal_Bdd_t c = CalBddGetInternalBdd(bddManager, cUserBdd);
+    result = BddCofactorBF(bddManager, CalOpCofactor, f, c);
+    userResult =  CalBddGetExternalBdd(bddManager, result);
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      Cal_BddFree(bddManager, userResult);
+      Cal_BddManagerGC(bddManager);
+      return (Cal_Bdd) 0;
+    }
+    return userResult;
+  }
+  return (Cal_Bdd) 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a BDD which agrees with f for all valuations
+  which satisfy c.]
+
+  Description [Returns a BDD which agrees with f for all valuations
+  which satisfy c. The result is usually smaller in terms of number of
+  BDD nodes than f. This operation is typically used in state space
+  searches to simplify the representation for the set of states wich
+  will be expanded at each step.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddCofactor]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddReduce(Cal_BddManager  bddManager, Cal_Bdd fUserBdd,
+              Cal_Bdd cUserBdd)
+{
+  if (CalBddPreProcessing(bddManager, 2, fUserBdd, cUserBdd)){
+    Cal_Bdd_t f = CalBddGetInternalBdd(bddManager, fUserBdd);
+    Cal_Bdd_t c = CalBddGetInternalBdd(bddManager, cUserBdd);
+    Cal_Bdd_t result;
+    Cal_Bdd userResult;
+
+    result = BddReduceBF(bddManager, CalOpCofactor, f, c);
+    userResult =  CalBddGetExternalBdd(bddManager, result);
+
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      Cal_BddFree(bddManager, userResult);
+      Cal_BddManagerGC(bddManager);
+      return (Cal_Bdd) 0;
+    }
+    if (Cal_BddSize(bddManager, userResult, 1) <
+        Cal_BddSize(bddManager, fUserBdd, 1)){
+      return userResult;
+    }
+    else{
+      Cal_BddFree(bddManager, userResult);
+      return Cal_BddIdentity(bddManager, fUserBdd);
+    }
+  }
+  return (Cal_Bdd) 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a minimal BDD whose function contains fMin and is
+  contained in fMax.]
+
+  Description [Returns a minimal BDD f which is contains fMin and is
+  contained in fMax ( fMin <= f <= fMax).
+  This operation is typically used in state space searches to simplify
+  the representation for the set of states wich will be expanded at
+  each step (Rk Rk-1' <= f <= Rk).] 
+
+  SideEffects [None]
+
+  SeeAlso     [Cal_BddReduce]
+
+******************************************************************************/
+Cal_Bdd
+Cal_BddBetween(Cal_BddManager  bddManager, Cal_Bdd fMinUserBdd,
+               Cal_Bdd fMaxUserBdd)
+{
+  if (CalBddPreProcessing(bddManager, 2, fMinUserBdd, fMaxUserBdd)){
+    Cal_Bdd_t fMin = CalBddGetInternalBdd(bddManager, fMinUserBdd);
+    Cal_Bdd_t fMax = CalBddGetInternalBdd(bddManager, fMaxUserBdd);
+    Cal_Bdd_t fMaxNot, careSet, result;
+    Cal_Bdd resultUserBdd;
+    long fMinSize, fMaxSize, resultSize;
+
+    CalBddNot(fMax, fMaxNot);
+    careSet = CalBddOpBF(bddManager, CalOpOr, fMin, fMaxNot);
+    result = BddReduceBF(bddManager, CalOpCofactor, fMin, careSet);
+    resultUserBdd =  CalBddGetExternalBdd(bddManager, result);
+    if (CalBddPostProcessing(bddManager) == CAL_BDD_OVERFLOWED){
+      Cal_BddFree(bddManager, resultUserBdd);
+      Cal_BddManagerGC(bddManager);
+      return (Cal_Bdd) 0;
+    }
+    fMinSize = Cal_BddSize(bddManager, fMinUserBdd, 1);
+    fMaxSize = Cal_BddSize(bddManager, fMaxUserBdd, 1);
+    resultSize = Cal_BddSize(bddManager, resultUserBdd, 1);
+    if (resultSize < fMinSize){
+      if (resultSize < fMaxSize){
+        return resultUserBdd;
+      }
+      else {
+        Cal_BddFree(bddManager, resultUserBdd);
+        return Cal_BddIdentity(bddManager, fMaxUserBdd);
+      }
+    }
+    Cal_BddFree(bddManager, resultUserBdd);
+    if (fMinSize < fMaxSize){
+      return Cal_BddIdentity(bddManager, fMinUserBdd);
+    }
+    else{
+      return Cal_BddIdentity(bddManager, fMaxUserBdd);
+    }
+  }
+  return (Cal_Bdd) 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpCofactor(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  f,
+  Cal_Bdd_t  c,
+  Cal_Bdd_t * resultBddPtr)
+{
+  if (CalBddIsBddConst(c)){
+    if (CalBddIsBddZero(bddManager, c)){
+      *resultBddPtr = bddManager->bddNull;
+    }
+    else {
+      *resultBddPtr = f;
+    }
+    return 1;
+  }
+  if (CalBddIsBddConst(f)){
+    *resultBddPtr = f;
+    return 1;
+  }
+  return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddReduceBF(
+  Cal_BddManager_t * bddManager,
+  CalOpProc_t calOpProc,
+  Cal_Bdd_t  f,
+  Cal_Bdd_t  c)
+{
+  Cal_Bdd_t result;
+  CalHashTable_t  *hashTable;
+  CalHashTable_t **orHashTableArray = bddManager->reqQue[0];
+  CalHashTable_t **reduceHashTableArray = bddManager->reqQue[1];
+  CalHashTable_t *uniqueTableForId;
+  
+  /*Cal_BddIndex_t minIndex;*/
+  int minIndex;
+  int bddIndex;
+  Cal_BddId_t bddId, minId;
+  
+  
+  if ((*calOpProc)(bddManager, f, c, &result) == 1){
+    return result;
+  }
+
+  CalBddGetMinIdAndMinIndex(bddManager, f, c, minId, minIndex);
+  CalHashTableFindOrAdd(reduceHashTableArray[minId], f, c, &result); 
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = reduceHashTableArray[bddId];
+    if(hashTable->numEntries){
+      HashTableReduceApply(bddManager, hashTable, reduceHashTableArray,
+                           orHashTableArray, CalOpCofactor);
+    }
+  }
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = reduceHashTableArray[bddId];
+    if(hashTable->numEntries){
+        HashTableCofactorReduce(bddManager, hashTable, uniqueTableForId);
+    }
+  }
+  CalRequestIsForwardedTo(result);
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(reduceHashTableArray[bddId]);
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd_t
+BddCofactorBF(Cal_BddManager_t * bddManager,
+              CalOpProc_t calOpProc,
+              Cal_Bdd_t  f,
+              Cal_Bdd_t  c)
+{
+  Cal_Bdd_t result;
+  CalHashTable_t  *hashTable;
+  CalHashTable_t **cofactorHashTableArray = bddManager->reqQue[0];
+  CalHashTable_t *uniqueTableForId;
+  
+/*Cal_BddIndex_t minIndex;*/
+  int minIndex;
+  int bddIndex;
+  Cal_BddId_t bddId, minId;
+  
+  if (CalBddIsBddZero(bddManager, c)){
+    CalBddWarningMessage("Bdd Cofactor Called with zero care set");
+    return bddManager->bddOne;
+  }
+  
+  if (calOpProc(bddManager, f, c, &result) == 1){
+    return result;
+  }
+
+  CalBddGetMinIdAndMinIndex(bddManager, f, c, minId, minIndex);
+  CalHashTableFindOrAdd(cofactorHashTableArray[minId], f, c, &result); 
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    hashTable = cofactorHashTableArray[bddId];
+    if(hashTable->numEntries){
+      HashTableCofactorApply(bddManager, hashTable, cofactorHashTableArray,
+                             calOpProc); 
+    }
+  }
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    hashTable = cofactorHashTableArray[bddId];
+    if(hashTable->numEntries){
+        HashTableCofactorReduce(bddManager, hashTable, uniqueTableForId);
+    }
+  }
+  CalRequestIsForwardedTo(result);
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(cofactorHashTableArray[bddId]);
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+HashTableReduceApply(Cal_BddManager_t * bddManager,
+                     CalHashTable_t * hashTable,
+                     CalHashTable_t ** reduceHashTableArray,
+                     CalHashTable_t ** orHashTableArray,
+                     CalOpProc_t calOpProc)
+{
+  int i, numBins = hashTable->numBins;
+  CalRequestNode_t *requestNode, *last, *nextRequestNode, *requestNodeList;
+  Cal_Bdd_t f, c, fx, cx, fxbar, cxbar, result, orResult;
+  Cal_BddId_t bddId, minId;
+  /*Cal_BddIndex_t minIndex;*/
+  int minIndex;
+  int bddIndex;
+  CalHashTable_t *orHashTable;
+  
+  requestNodeList = Cal_Nil(CalRequestNode_t);
+  for(i = 0; i < numBins; i++){
+    last = Cal_Nil(CalRequestNode_t);
+    for (requestNode =  hashTable->bins[i]; requestNode !=
+                                                Cal_Nil(CalRequestNode_t);
+         requestNode = nextRequestNode){
+      nextRequestNode = CalRequestNodeGetNextRequestNode(requestNode);  
+      CalRequestNodeGetF(requestNode, f);
+      CalRequestNodeGetG(requestNode, c);
+      CalBddGetMinId2(bddManager, f, c, minId);
+      CalBddGetCofactors(c, minId, cx, cxbar);
+      if (CalBddGetBddId(f) != minId){
+        if (CalOpOr(bddManager, cx, cxbar, &orResult) == 0){
+          CalBddNormalize(cx, cxbar);
+          CalBddGetMinId2(bddManager, cx, cxbar, minId);
+          CalHashTableFindOrAdd(orHashTableArray[minId], cx, cxbar, &orResult);
+        }
+        CalRequestNodePutElseRequest(requestNode, orResult);
+        if (last == Cal_Nil(CalRequestNode_t)){
+          hashTable->bins[i] = nextRequestNode;
+        }
+        else {
+          CalRequestNodePutNextRequestNode(last, nextRequestNode);
+        }
+        CalRequestNodePutNextRequestNode(requestNode, requestNodeList);
+        requestNodeList = requestNode;
+      }
+      else{
+        last = requestNode;
+        CalBddGetCofactors(f, minId, fx, fxbar);
+        if((*calOpProc)(bddManager, fx, cx, &result) == 0){
+          CalBddGetMinId2(bddManager, fx, cx, bddId);
+          CalHashTableFindOrAdd(reduceHashTableArray[bddId], fx, cx, &result);
+        }
+        if (CalBddIsBddNull(bddManager, result) == 0){
+          CalBddIcrRefCount(result);
+        }
+        CalRequestNodePutThenRequest(requestNode, result);
+        if((*calOpProc)(bddManager, fxbar, cxbar, &result) == 0){
+          CalBddGetMinId2(bddManager, fxbar, cxbar, bddId);
+          CalHashTableFindOrAdd(reduceHashTableArray[bddId], fxbar, cxbar,
+                                &result);
+        }
+        if (CalBddIsBddNull(bddManager, result) == 0){
+          CalBddIcrRefCount(result);
+        }
+        CalRequestNodePutElseRequest(requestNode, result);
+      }
+    }
+  }
+  minIndex = bddManager->idToIndex[hashTable->bddId];
+  for (bddIndex = minIndex; bddIndex < bddManager->numVars; bddIndex++){
+    bddId = bddManager->indexToId[bddIndex];
+    orHashTable = orHashTableArray[bddId];
+    if(orHashTable->numEntries){
+      CalHashTableApply(bddManager, orHashTable, orHashTableArray, CalOpOr);
+    }
+  }
+  
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    CalHashTable_t *uniqueTableForId;
+    bddId = bddManager->indexToId[bddIndex];
+    uniqueTableForId = bddManager->uniqueTable[bddId];
+    orHashTable = orHashTableArray[bddId];
+    if(orHashTable->numEntries){
+      CalHashTableReduce(bddManager, orHashTable, uniqueTableForId);
+    }
+  }
+  for (requestNode = requestNodeList; requestNode; requestNode =
+                                                       nextRequestNode){
+    nextRequestNode = CalRequestNodeGetNextRequestNode(requestNode);
+    CalRequestNodeGetElseRequest(requestNode, orResult);
+    CalRequestIsForwardedTo(orResult);
+    CalRequestNodeGetThenRequest(requestNode, f);
+    CalBddGetMinId2(bddManager, f, orResult, minId);
+    CalHashTableFindOrAdd(reduceHashTableArray[minId], f, orResult,
+                          &result);
+    CalRequestNodePutThenRequest(requestNode, result);
+    CalRequestNodePutElseRequest(requestNode, result);
+    CalBddAddRefCount(result, 2);
+    CalHashTableAddDirect(hashTable, requestNode);
+  }
+  
+  /* Clean up the orHashTableArray */
+  for(bddIndex = bddManager->numVars - 1; bddIndex >= minIndex; bddIndex--){
+    bddId = bddManager->indexToId[bddIndex];
+    CalHashTableCleanUp(orHashTableArray[bddId]);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+HashTableCofactorApply(Cal_BddManager_t * bddManager,
+                       CalHashTable_t * hashTable,
+                       CalHashTable_t ** cofactorHashTableArray,
+                       CalOpProc_t calOpProc)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  CalRequestNode_t *requestNode;
+  Cal_Bdd_t f, c, fx, cx, fxbar, cxbar, result;
+  Cal_BddId_t bddId, minId;
+
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i];
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = CalRequestNodeGetNextRequestNode(requestNode)){
+      CalRequestNodeGetF(requestNode, f);
+      CalRequestNodeGetG(requestNode, c);
+      CalBddGetMinId2(bddManager, f, c, minId);
+      CalBddGetCofactors(f, minId, fx, fxbar);
+      CalBddGetCofactors(c, minId, cx, cxbar);
+      if((*calOpProc)(bddManager, fx, cx, &result) == 0){
+        CalBddGetMinId2(bddManager, fx, cx, bddId);
+        CalHashTableFindOrAdd(cofactorHashTableArray[bddId], fx, cx, &result);
+      }
+      if (CalBddIsBddNull(bddManager, result) == 0){
+        CalBddIcrRefCount(result);
+      }
+      CalRequestNodePutThenRequest(requestNode, result);
+      if((*calOpProc)(bddManager, fxbar, cxbar, &result) == 0){
+        CalBddGetMinId2(bddManager, fxbar, cxbar, bddId);
+        CalHashTableFindOrAdd(cofactorHashTableArray[bddId], fxbar, cxbar,
+                              &result);
+      }
+      if (CalBddIsBddNull(bddManager, result) == 0){
+          CalBddIcrRefCount(result);
+      }
+      CalRequestNodePutElseRequest(requestNode, result);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+HashTableCofactorReduce(Cal_BddManager_t * bddManager,
+                        CalHashTable_t * hashTable,
+                        CalHashTable_t * uniqueTableForId)
+{
+  int i, numBins = hashTable->numBins;
+  CalBddNode_t **bins = hashTable->bins;
+  Cal_BddId_t currentBddId = uniqueTableForId->bddId;
+  CalNodeManager_t *nodeManager = uniqueTableForId->nodeManager;
+  CalRequestNode_t  *requestNode, *next, *endNode;
+  CalBddNode_t *bddNode;
+  Cal_Bdd_t thenBdd, elseBdd, result;
+  Cal_BddRefCount_t refCount;
+
+  endNode = hashTable->endNode;
+  for(i = 0; i < numBins; i++){
+    for(requestNode = bins[i], bins[i] = Cal_Nil(CalRequestNode_t);
+        requestNode != Cal_Nil(CalRequestNode_t);
+        requestNode = next){
+      next = CalRequestNodeGetNextRequestNode(requestNode);
+      /* Process the requestNode */
+      CalRequestNodeGetThenRequest(requestNode, thenBdd);
+      CalRequestNodeGetElseRequest(requestNode, elseBdd);
+      if (CalBddIsBddNull(bddManager, thenBdd)){
+        CalRequestIsForwardedTo(elseBdd);
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddAddRefCount(elseBdd, refCount - 1);
+        CalRequestNodePutThenRequest(requestNode, elseBdd);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+        continue;
+      }
+      else if (CalBddIsBddNull(bddManager, elseBdd)){
+        CalRequestIsForwardedTo(thenBdd);
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddAddRefCount(thenBdd, refCount - 1);
+        CalRequestNodePutThenRequest(requestNode, thenBdd);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+        continue;
+      }
+      CalRequestIsForwardedTo(thenBdd);
+      CalRequestIsForwardedTo(elseBdd);
+      if(CalBddIsEqual(thenBdd, elseBdd)){
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddAddRefCount(thenBdd, refCount - 2);
+        CalRequestNodePutThenRequest(requestNode, thenBdd);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+      else if(CalUniqueTableForIdLookup(bddManager, uniqueTableForId,
+          thenBdd, elseBdd, &result) == 1){
+        CalBddDcrRefCount(thenBdd);
+        CalBddDcrRefCount(elseBdd);
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddAddRefCount(result, refCount);
+        CalRequestNodePutThenRequest(requestNode, result);
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+      else if(CalBddIsOutPos(thenBdd)){
+        CalRequestNodePutThenRequest(requestNode, thenBdd);
+        CalRequestNodePutElseRequest(requestNode, elseBdd);
+        CalHashTableAddDirect(uniqueTableForId, requestNode);
+        bddManager->numNodes++;
+        bddManager->gcCheck--;
+      }
+      else{
+        CalNodeManagerAllocNode(nodeManager, bddNode);
+        CalBddNodePutThenBddId(bddNode, CalBddGetBddId(thenBdd));
+        CalBddNodePutThenBddNode(bddNode, CalBddGetBddNodeNot(thenBdd));
+        CalBddNodePutElseBddId(bddNode, CalBddGetBddId(elseBdd));
+        CalBddNodePutElseBddNode(bddNode, CalBddGetBddNodeNot(elseBdd));
+        CalBddNodeGetRefCount(requestNode, refCount);
+        CalBddNodePutRefCount(bddNode, refCount);
+        CalHashTableAddDirect(uniqueTableForId, bddNode);
+        bddManager->numNodes++;
+        bddManager->gcCheck--;
+        CalRequestNodePutThenRequestId(requestNode, currentBddId);
+        CalRequestNodePutThenRequestNode(requestNode, CalBddNodeNot(bddNode));
+        CalRequestNodePutElseRequestNode(requestNode, FORWARD_FLAG);
+        endNode->nextBddNode = requestNode;
+        endNode = requestNode;
+      }
+    }
+  }
+  hashTable->endNode = endNode;
+}
+  
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calReorderBF.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calReorderBF.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calReorderBF.c	(revision 8)
@@ -0,0 +1,1486 @@
+/**CFile***********************************************************************
+
+  FileName    [calReorderBF.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for dynamic reordering of variables.]
+
+  Description [This method dynamically reorders variables while
+  preserving their locality. This entails both memory and
+  computational overheads.  Conceptually and experimentally it has
+  been observed that these overheads lead to poorer performance
+  compared to the traditional reordering methods. For details, please
+  refer to the work by Rajeev K. Ranjan et al - "Dynamic variable
+  reordering in a breadth-first manipulation based package: Challenges
+  and Solutions"- Proceedings of ICCD'97.]
+
+  SeeAlso     [calReorderDF.c calReorderUtil.c]
+
+  Author      [Rajeev K. Ranjan   (rajeev@ic.eecs.berkeley.edu)
+               Wilsin Gosti (wilsin@ic.eecs.berkeley.edu)]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calReorderBF.c,v 1.3 2002/09/10 00:21:02 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void BddReorderFixForwardingNodes(Cal_BddManager bddManager, Cal_BddId_t id);
+static void BddReorderFixAndFreeForwardingNodes(Cal_BddManager bddManager, Cal_BddId_t id, int numLevels);
+static void BddReorderSwapVarIndex(Cal_BddManager_t * bddManager, int varIndex, int forwardCheckFlag);
+static int CofactorFixAndReclaimForwardedNodes(Cal_BddManager_t *bddManager, int cofactorCheckStartIndex, int cofactorCheckEndIndex, int reclaimStartIndex, int reclaimEndIndex);
+static void BddReorderFreeNodes(Cal_BddManager_t * bddManager, int varId);
+#ifdef _CAL_VERBOSE
+static void PrintBddProfileAfterReorder(Cal_BddManager_t *bddManager);
+#endif
+static void BddReorderVarSift(Cal_BddManager bddManager, double maxSizeFactor);
+static int BddReorderSiftToBestPos(Cal_BddManager_t * bddManager, int varStartIndex, double maxSizeFactor);
+static void BddSiftPerfromPhaseIV(Cal_BddManager_t *bddManager, int varStartIndex, int bestIndex, int bottomMostSwapIndex);
+static void BddReorderVarWindow(Cal_BddManager bddManager, char *levels);
+static int BddReorderWindow2(Cal_BddManager bddManager, long index, int directionFlag);
+static int BddReorderWindow3(Cal_BddManager bddManager, long index, int directionFlag);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddReorderAuxBF(Cal_BddManager_t * bddManager)
+{
+  Cal_Assert(CalCheckAllValidity(bddManager));
+  CalInitInteract(bddManager);
+#ifdef _CAL_QUANTIFY_
+  quantify_start_recording_data();
+#endif
+  if (bddManager->reorderTechnique == CAL_REORDER_WINDOW){
+    char *levels = Cal_MemAlloc(char, bddManager->numVars);
+    BddReorderVarWindow(bddManager, levels);
+    Cal_MemFree(levels);
+  }
+  else {
+    BddReorderVarSift(bddManager, bddManager->maxSiftingGrowth);
+  }
+#ifdef _CAL_QUANTIFY_
+  quantify_stop_recording_data();
+#endif
+  Cal_Assert(CalCheckAllValidity(bddManager));
+  Cal_MemFree(bddManager->interact);
+  bddManager->numReorderings++;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Fixes the forwarding nodes in a unique table.]
+
+  Description        [As opposed to CalBddReorderFixCofactors, which fixes
+  the cofactors of the non-forwarding nodes, this routine traverses
+  the list of forwarding nodes and removes the intermediate level of
+  forwarding. Number of levels should be 1 or 2.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReorderFixForwardingNodes(Cal_BddManager bddManager,
+                             Cal_BddId_t id) 
+{
+  CalHashTable_t *uniqueTableForId =
+      bddManager->uniqueTable[id];
+  CalBddNode_t *bddNode, *nextBddNode;
+  Cal_Bdd_t thenBdd;
+  
+  /* These are the forwarding nodes. */
+  CalBddNode_t *requestNodeList =
+      uniqueTableForId->startNode.nextBddNode;
+  for (bddNode = requestNodeList; bddNode; bddNode = nextBddNode){
+    nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+    CalBddNodeGetThenBdd(bddNode, thenBdd);
+    if (CalBddIsForwarded(thenBdd)) {
+      CalBddForward(thenBdd);
+      CalBddNodePutThenBdd(bddNode, thenBdd);
+    }
+    else {
+      /* there should not be anymore double forwarding */
+      break;
+    }
+    Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+  }
+  /* Adjust the list */
+  uniqueTableForId->endNode->nextBddNode =
+      uniqueTableForId->startNode.nextBddNode;
+  uniqueTableForId->startNode.nextBddNode = bddNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Traverses the forwarding node lists of index,
+  index+1 .. up to index+level. Frees the intermediate forwarding nodes.]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReorderFixAndFreeForwardingNodes(Cal_BddManager bddManager,
+                                    Cal_BddId_t id, int numLevels)
+{
+  CalHashTable_t *uniqueTableForId;
+  Cal_BddIndex_t index = bddManager->idToIndex[id];
+  CalBddNode_t *nextBddNode, *bddNode, *endNode;
+  Cal_Bdd_t thenBdd;
+  CalNodeManager_t *nodeManager;
+  int i;
+  
+  /* Fixing */
+  for (i=numLevels-1; i >= 0; i--){
+    uniqueTableForId =
+        bddManager->uniqueTable[bddManager->indexToId[index+i]];
+    for (bddNode = uniqueTableForId->startNode.nextBddNode; bddNode;
+         bddNode = nextBddNode){ 
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodeGetThenBdd(bddNode, thenBdd);
+      if (CalBddIsForwarded(thenBdd)){
+        do{
+          CalBddMark(thenBdd);
+          CalBddForward(thenBdd);
+        } while (CalBddIsForwarded(thenBdd));
+        CalBddNodePutThenBdd(bddNode, thenBdd); 
+      }
+      Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+    }
+  }
+  /* Freeing */
+  for (i=numLevels-1; i >= 0; i--){
+    uniqueTableForId =
+        bddManager->uniqueTable[bddManager->indexToId[index+i]];
+    endNode = &(uniqueTableForId->startNode);
+    for (bddNode = uniqueTableForId->startNode.nextBddNode; bddNode;
+         bddNode = nextBddNode){ 
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodeGetThenBdd(bddNode, thenBdd);
+      if (CalBddIsMarked(thenBdd)){
+        do{
+          /* Free the node */
+          nodeManager = bddManager->nodeManagerArray[CalBddGetBddId(thenBdd)];
+          CalNodeManagerFreeNode(nodeManager, CalBddGetBddNode(thenBdd));
+          bddManager->numForwardedNodes--;
+        } while (CalBddIsMarked(thenBdd));
+      }
+      else{
+        endNode->nextBddNode = bddNode;
+        endNode = bddNode;
+      }
+    }
+    uniqueTableForId->endNode = endNode;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [Traversesoptional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddReorderSwapVarIndex(Cal_BddManager_t * bddManager, int varIndex,
+                       int forwardCheckFlag)
+{
+  int thenVarIndex;
+  int elseVarIndex;
+  int varId;
+  int nextVarId;
+  int i;
+  int numBins;
+  int refCount;
+  int f0Found;
+  int f1Found;
+  CalHashTable_t *uniqueTableForId;
+  CalHashTable_t *nextUniqueTableForId;
+  CalBddNode_t **bins;
+  CalBddNode_t *bddNode, *startNode;
+  CalBddNode_t *nextBddNode, *processingNodeList;
+  CalBddNode_t *prevBddNode = Cal_Nil(CalBddNode_t);
+  Cal_Bdd_t newF;
+  Cal_Bdd_t f0;
+  Cal_Bdd_t f1;
+  Cal_Bdd_t newF0;
+  Cal_Bdd_t newF1;
+  Cal_Bdd_t f00;
+  Cal_Bdd_t f01;
+  Cal_Bdd_t f10;
+  Cal_Bdd_t f11;
+  CalAssociation_t *assoc;
+  
+  varId = bddManager->indexToId[varIndex];
+  nextVarId = bddManager->indexToId[varIndex + 1];
+  
+  if (CalTestInteract(bddManager, varId, nextVarId)){
+  bddManager->numSwaps++;
+#ifdef _CAL_VERBOSE
+  /*fprintf(stdout," %3d(%3d) going down,  %3d(%3d) going up\n",
+          varId, varIndex, nextVarId, varIndex+1);*/
+#endif
+  uniqueTableForId = bddManager->uniqueTable[varId];
+  nextUniqueTableForId = bddManager->uniqueTable[nextVarId];
+  
+  /*uniqueTableForId->requestNodeList = Cal_Nil(CalBddNode_t);*/
+  processingNodeList = Cal_Nil(CalBddNode_t);
+  numBins = uniqueTableForId->numBins;
+  bins = uniqueTableForId->bins;
+  if (forwardCheckFlag){
+    for(i = 0; i < numBins; ++i) {
+      prevBddNode = Cal_Nil(CalBddNode_t);
+      for(bddNode = bins[i];
+          bddNode != Cal_Nil(CalBddNode_t);
+          bddNode = nextBddNode) {
+        /*
+         * Process one bddNode at a time
+         */
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        /* The node should not be forwarded */
+        Cal_Assert(CalBddNodeIsForwarded(bddNode) == 0);
+        /*
+        ** We don't know for sure if the reference count of the node
+        ** could be 0. Let us use the assertion at this point.
+        */
+        Cal_Assert(CalBddNodeIsRefCountZero(bddNode) == 0);
+        /*
+        ** If ever the above assetion fails, or if we can convince
+        ** ourselves that the reference count could be zero, we need
+        ** to uncomment the following code.
+        */
+        /*
+        if (CalBddNodeIsRefCountZero(bddNode)){
+          thenBddNode = CAL_BDD_POINTER(CalBddNodeGetThenBddNode(bddNode));
+          elseBddNode = CAL_BDD_POINTER(CalBddNodeGetElseBddNode(bddNode));
+          CalBddNodeDcrRefCount(thenBddNode);
+          CalBddNodeDcrRefCount(elseBddNode);
+          if (prevBddNode){
+            CalBddNodePutNextBddNode(prevBddNode, nextBddNode);
+          }
+          else{
+            bins[i] = nextBddNode;
+          }
+          uniqueTableForId->numEntries--;
+          bddManager->numNodes--;
+          bddManager->numNodesFreed++;
+          CalNodeManagerFreeNode(uniqueTableForId->nodeManager, bddNode);
+          continue;
+        }
+        */
+        CalBddNodeGetElseBdd(bddNode, f0);
+        CalBddNodeGetThenBdd(bddNode, f1);
+        
+        if (CalBddIsForwarded(f1)) {
+          CalBddForward(f1);
+          CalBddNodePutThenBdd(bddNode, f1);
+        }
+        Cal_Assert(CalBddIsForwarded(f1) == 0);
+        
+        if (CalBddIsForwarded(f0)) {
+          CalBddForward(f0);
+          CalBddNodePutElseBdd(bddNode, f0); 
+        }
+        Cal_Assert(CalBddIsForwarded(f0) == 0);
+        /*
+        ** Get the index of f0 and f1 and create newF0 and newF1 if necessary
+        */
+        elseVarIndex = CalBddNodeGetElseBddIndex(bddManager, bddNode);
+        thenVarIndex = CalBddNodeGetThenBddIndex(bddManager, bddNode);
+        
+        if ((elseVarIndex > (varIndex + 1))
+            && (thenVarIndex > (varIndex + 1))) { 
+          prevBddNode = bddNode;
+          Cal_Assert(CalDoHash2(CalBddGetBddNode(f1),
+                                CalBddGetBddNode(f0), 
+                                uniqueTableForId) == i);
+          continue;
+        }
+  
+        /* This node is going to be forwared */
+        CalBddNodePutNextBddNode(bddNode, processingNodeList);
+        processingNodeList = bddNode;
+        
+        /* Update the unique table appropriately */
+        if (prevBddNode){
+          CalBddNodePutNextBddNode(prevBddNode, nextBddNode);
+        }
+        else{
+          bins[i] = nextBddNode;
+        } 
+        uniqueTableForId->numEntries--;
+        bddManager->numNodes--;
+      }
+    }
+  }
+  else{
+    for(i = 0; i < numBins; i++) {
+      prevBddNode = Cal_Nil(CalBddNode_t);
+      for(bddNode = bins[i];
+          bddNode != Cal_Nil(CalBddNode_t);
+          bddNode = nextBddNode) {
+        /*
+         * Process one bddNode at a time
+         */
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        /* The node should not be forwarded */
+        Cal_Assert(CalBddNodeIsForwarded(bddNode) == 0);
+
+        /*
+        ** We don't know for sure if the reference count of the node
+        ** could be 0. Let us use the assertion at this point.
+        */
+        Cal_Assert(CalBddNodeIsRefCountZero(bddNode) == 0);
+        /*
+        ** If ever the above assetion fails, or if we can convince
+        ** ourselves that the reference count could be zero, we need
+        ** to uncomment the following code.
+        */
+        /*
+        if (CalBddNodeIsRefCountZero(bddNode)){
+          thenBddNode = CAL_BDD_POINTER(CalBddNodeGetThenBddNode(bddNode));
+          elseBddNode = CAL_BDD_POINTER(CalBddNodeGetElseBddNode(bddNode));
+          CalBddNodeDcrRefCount(thenBddNode);
+          CalBddNodeDcrRefCount(elseBddNode);
+          if (prevBddNode){
+            CalBddNodePutNextBddNode(prevBddNode, nextBddNode);
+          }
+          else{
+            bins[i] = nextBddNode;
+          }
+          uniqueTableForId->numEntries--;
+          bddManager->numNodes--;
+          bddManager->numNodesFreed++;
+          CalNodeManagerFreeNode(uniqueTableForId->nodeManager, bddNode);
+          continue;
+        }
+        */
+        CalBddNodeGetThenBdd(bddNode, f1);
+        Cal_Assert(CalBddIsForwarded(f1) == 0);
+        CalBddNodeGetElseBdd(bddNode, f0);
+        Cal_Assert(CalBddIsForwarded(f0) == 0);
+        /*
+        ** Get the index of f0 and f1 and create newF0 and newF1 if necessary
+        */
+
+        elseVarIndex = CalBddNodeGetElseBddIndex(bddManager, bddNode);
+        thenVarIndex = CalBddNodeGetThenBddIndex(bddManager, bddNode);
+        
+        if ((elseVarIndex > (varIndex + 1))
+            && (thenVarIndex > (varIndex + 1))) { 
+          prevBddNode = bddNode;
+          continue;
+        }
+  
+        /* This node is going to be forwared */
+        CalBddNodePutNextBddNode(bddNode, processingNodeList);
+        processingNodeList = bddNode;
+        
+        /* Update the unique table appropriately */
+        if (prevBddNode){
+          CalBddNodePutNextBddNode(prevBddNode, nextBddNode);
+        }
+        else{
+          bins[i] = nextBddNode;
+        } 
+        uniqueTableForId->numEntries--;
+        bddManager->numNodes--;
+      }
+    }
+  }
+  bddNode = processingNodeList;
+  /*endNode = uniqueTableForId->endNode;*/
+  startNode = uniqueTableForId->startNode.nextBddNode;
+  while (bddNode != Cal_Nil(CalBddNode_t)) {
+    nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+
+    /*
+     * Get the index of f0 and f1 and create newF0 and newF1 if necessary
+     */
+
+    CalBddNodeGetElseBdd(bddNode, f0);
+    CalBddNodeGetThenBdd(bddNode, f1);
+    elseVarIndex = CalBddNodeGetElseBddIndex(bddManager, bddNode);
+    thenVarIndex = CalBddNodeGetThenBddIndex(bddManager, bddNode);
+
+    if (elseVarIndex > (varIndex + 1)) {
+      f00 = f0;
+      f01 = f0;
+      CalBddGetElseBdd(f1, f10);
+      CalBddGetThenBdd(f1, f11);
+    } else if (thenVarIndex > (varIndex + 1)) {
+      f10 = f1;
+      f11 = f1;
+      CalBddGetElseBdd(f0, f00);
+      CalBddGetThenBdd(f0, f01);
+    }else{
+      CalBddGetElseBdd(f1, f10);
+      CalBddGetThenBdd(f1, f11);
+      CalBddGetElseBdd(f0, f00);
+      CalBddGetThenBdd(f0, f01);
+    }
+    Cal_Assert(CalBddIsForwarded(f10) == 0);
+    Cal_Assert(CalBddIsForwarded(f11) == 0);
+    Cal_Assert(CalBddIsForwarded(f00) == 0);
+    Cal_Assert(CalBddIsForwarded(f01) == 0);
+
+    if (CalBddIsEqual(f10,f00)) {
+      newF0 = f00;
+      f0Found = 1;
+    }
+    else {
+      f0Found = CalUniqueTableForIdFindOrAdd(bddManager, uniqueTableForId, f10,
+                                             f00, &newF0);
+    }
+    CalBddIcrRefCount(newF0);
+    if (CalBddIsEqual(f11, f01)) {
+      newF1 = f01;
+      f1Found = 1;
+    }
+    else {
+      f1Found = CalUniqueTableForIdFindOrAdd(bddManager, uniqueTableForId, f11,
+                                             f01, &newF1);
+    }
+    CalBddIcrRefCount(newF1);
+
+    if (!f0Found){
+      CalBddIcrRefCount(f10);
+      CalBddIcrRefCount(f00);
+    }
+
+    if (!f1Found){
+      CalBddIcrRefCount(f11);
+      CalBddIcrRefCount(f01);
+    }
+
+    CalBddDcrRefCount(f0);
+    CalBddDcrRefCount(f1);
+    /*
+     * Create the new node for f. It cannot exist before, since at
+     * least one of newF0 and newF1 must be dependent on currentIndex.
+     * Otherwise, f00 == f10 and f01 == f11 (redundant nodes).
+     */
+    CalHashTableAddDirectAux(nextUniqueTableForId, newF1, newF0, &newF);
+    bddManager->numNodes++;
+    CalBddNodePutThenBdd(bddNode, newF);
+    CalBddNodePutElseBddNode(bddNode, FORWARD_FLAG);
+    bddManager->numForwardedNodes++;
+    CalBddNodeGetRefCount(bddNode, refCount);
+    CalBddAddRefCount(newF, refCount);
+    Cal_Assert(!CalBddIsRefCountZero(newF));
+    /* Put it in the forwarded list of the unique table */
+    /*
+    endNode->nextBddNode = bddNode;
+    endNode = bddNode;
+    */
+    bddNode->nextBddNode = startNode;
+    startNode = bddNode;
+    
+    bddNode = nextBddNode;
+  }
+  /*uniqueTableForId->endNode = endNode;*/
+  uniqueTableForId->startNode.nextBddNode = startNode;
+
+  BddReorderFreeNodes(bddManager, nextVarId);
+  
+  }
+  else{
+    bddManager->numTrivialSwaps++;
+  }
+  
+  CalFixupAssoc(bddManager, varId, nextVarId, bddManager->tempAssociation);
+  for(assoc = bddManager->associationList; assoc; assoc = assoc->next){
+    CalFixupAssoc(bddManager, varId, nextVarId, assoc);
+  }
+
+  bddManager->idToIndex[varId] = varIndex + 1;
+  bddManager->idToIndex[nextVarId] = varIndex;
+  bddManager->indexToId[varIndex] = nextVarId;
+  bddManager->indexToId[varIndex + 1] = varId;
+
+  Cal_Assert(CalCheckAssoc(bddManager));
+
+#ifdef _CAL_VERBOSE
+  /*fprintf(stdout,"Variable order after swap:\n");*/
+  for (i=0; i<bddManager->numVars; i++){
+    fprintf(stdout, "%3d ", bddManager->indexToId[i]);
+  }
+  fprintf(stdout, "%8d\n", bddManager->numNodes);
+#endif
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static int
+CofactorFixAndReclaimForwardedNodes(Cal_BddManager_t *bddManager, int
+                                       cofactorCheckStartIndex, int
+                                       cofactorCheckEndIndex, int
+                                       reclaimStartIndex, int reclaimEndIndex)
+{
+  int index, varId;
+  /* Clean up : Need to fix the cofactors of userBDDs and the
+     indices above the varStartIndex only. */
+  if (bddManager->pipelineState == CREATE){
+    /* There are some results computed in pipeline */
+    CalBddReorderFixProvisionalNodes(bddManager);
+  }
+  CalBddReorderFixUserBddPtrs(bddManager);
+  CalReorderAssociationFix(bddManager);
+  for (index = cofactorCheckStartIndex;
+       index <= cofactorCheckEndIndex; index++){ 
+    varId = bddManager->indexToId[index];
+    CalBddReorderFixCofactors(bddManager, varId);
+  }
+  CalBddReorderReclaimForwardedNodes(bddManager, reclaimStartIndex,
+                                     reclaimEndIndex);
+  Cal_Assert(CalCheckAllValidity(bddManager));
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddReorderFreeNodes(Cal_BddManager_t * bddManager, int varId)
+{
+  CalBddNode_t *prevNode, *bddNode, *nextBddNode;
+  CalBddNode_t *elseBddNode;
+  CalBddNode_t *thenBddNode;
+  CalHashTable_t *uniqueTableForId;
+  CalBddNode_t **bins;
+  int numBins;
+  int i;
+  long oldNumEntries, numNodesFreed;
+
+  uniqueTableForId = bddManager->uniqueTable[varId];
+  bins = uniqueTableForId->bins;
+  numBins = uniqueTableForId->numBins;
+  oldNumEntries = uniqueTableForId->numEntries;
+
+  if (bddManager->numPeakNodes < (bddManager->numNodes +
+                                  bddManager->numForwardedNodes)){
+    bddManager->numPeakNodes = bddManager->numNodes +
+        bddManager->numForwardedNodes ;
+  }
+  
+  for(i = 0; i < numBins; i++){
+    prevNode = NULL;
+    bddNode = bins[i];
+    while(bddNode != Cal_Nil(CalBddNode_t)){
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      Cal_Assert(CalBddNodeIsForwarded(bddNode) == 0);
+      if(CalBddNodeIsRefCountZero(bddNode)){
+        thenBddNode = CAL_BDD_POINTER(CalBddNodeGetThenBddNode(bddNode));
+        elseBddNode = CAL_BDD_POINTER(CalBddNodeGetElseBddNode(bddNode));
+        Cal_Assert(CalBddNodeIsForwarded(thenBddNode) == 0);
+        Cal_Assert(CalBddNodeIsForwarded(elseBddNode) == 0);
+        CalBddNodeDcrRefCount(thenBddNode);
+        CalBddNodeDcrRefCount(elseBddNode);
+        if (prevNode == NULL) {
+          bins[i] = nextBddNode;
+        } else {
+          CalBddNodePutNextBddNode(prevNode, nextBddNode);
+        }
+        CalNodeManagerFreeNode(uniqueTableForId->nodeManager, bddNode);
+        uniqueTableForId->numEntries--;
+      } else {
+        prevNode = bddNode;
+      }
+      bddNode = nextBddNode;
+    }
+  }
+  numNodesFreed = oldNumEntries - uniqueTableForId->numEntries;
+  bddManager->numNodes -= numNodesFreed;
+  bddManager->numNodesFreed += numNodesFreed;
+}
+
+#ifdef _CAL_VERBOSE
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+PrintBddProfileAfterReorder(Cal_BddManager_t *bddManager)
+{
+    int i, index, numBins, j;
+    CalHashTable_t *uniqueTableForId;
+    CalBddNode_t *bddNode, *nextBddNode;
+    char *levels = Cal_MemAlloc(char, bddManager->numVars+1);
+    CalBddNode_t *requestNodeList;
+    Cal_Bdd_t thenBdd, elseBdd;
+    
+  /* Now traverse all the nodes in order */
+    for (index = 0; index < bddManager->numVars; index++){
+      fprintf(stdout,"**** %3d ****\n", bddManager->indexToId[index]);  
+      uniqueTableForId = bddManager->uniqueTable[bddManager->indexToId[index]];
+      numBins = uniqueTableForId->numBins;
+      for (i=1; i<=bddManager->numVars; i++) {
+          levels[i] = 0;
+      }
+      j = 0;
+      for (i = 0; i < numBins; i++){
+          for (bddNode = uniqueTableForId->bins[i]; bddNode;
+               bddNode = nextBddNode){
+              nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+              CalBddNodeGetThenBdd(bddNode, thenBdd);
+              CalBddNodeGetElseBdd(bddNode, elseBdd);
+              if (CalBddIsForwarded(thenBdd) ||
+                  CalBddIsForwarded(elseBdd)){                       
+                j++;
+              }
+              if (CalBddIsForwarded(thenBdd)) {                      
+                  levels[CalBddGetThenBddId(thenBdd)]++;
+              }
+              if (CalBddIsForwarded(elseBdd)) {                      
+                  levels[CalBddGetThenBddId(elseBdd)]++;
+              }
+          }
+      }
+      fprintf(stdout,"\tCofactors (%3d): ", j);
+      for (i=1; i<=bddManager->numVars; i++){
+          if (levels[i]) {
+              fprintf(stdout,"%3d->%3d ", i, levels[i]);
+          }
+      }
+      fprintf(stdout,"\n");
+      for (i=1; i<=bddManager->numVars; i++) {
+          levels[i] = 0;
+      }
+      j = 0;
+      requestNodeList = uniqueTableForId->startNode.nextBddNode;
+      for (bddNode = requestNodeList; bddNode; bddNode = nextBddNode){
+          Cal_Assert(CalBddNodeIsForwarded(bddNode));
+          nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+          CalBddNodeGetThenBdd(bddNode, thenBdd);
+          Cal_Assert(!CalBddIsForwarded(thenBdd));
+          levels[CalBddGetBddId(thenBdd)]++;
+          j++;
+      }
+      fprintf(stdout,"\tForwarded nodes (%3d): ", j);
+      for (i=1; i<=bddManager->numVars; i++){
+          if (levels[i]) {
+              fprintf(stdout,"%3d->%3d ", i, levels[i]);
+          }
+      }
+      fprintf(stdout,"\n");
+    }
+    Cal_MemFree(levels);
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Reorder variables using "sift" algorithm.]
+
+  Description [Reorder variables using "sift" algorithm.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+BddReorderVarSift(Cal_BddManager bddManager, double maxSizeFactor)
+{
+  int i,j;
+  int mostNodesId = -1;
+  long mostNodes, varNodes;
+  int *idArray;
+  long numVarsShifted = 0;
+  bddManager->numSwaps = 0;
+  
+  idArray = Cal_MemAlloc(int, bddManager->numVars);
+  for (i = 0; i < bddManager->numVars; i++) {
+    idArray[i] = bddManager->indexToId[i];
+  }
+
+  while (i &&
+         (numVarsShifted <=
+          bddManager->maxNumVarsSiftedPerReordering) &&
+         (bddManager->numSwaps <=
+          bddManager->maxNumSwapsPerReordering)){ 
+    i--;
+    numVarsShifted++;
+/*
+ * Find var with the most number of nodes and do sifting on it.
+ * idArray is used to make sure that a var is not sifted more than
+ * once.
+ */
+    mostNodes = 0;
+    for (j = 0; j <= i; j++){
+      varNodes = bddManager->uniqueTable[idArray[j]]->numEntries;
+      if (varNodes > mostNodes) {
+        mostNodes = varNodes;
+        mostNodesId = j;
+      }
+    }
+ 
+    if (mostNodes <= 1) { /* I can put a different stopping criterion */
+      /*
+       * Most number of nodes among the vars not sifted yet is 0. Stop.
+       */
+      break;
+    }
+
+    BddReorderSiftToBestPos(bddManager,
+                            bddManager->idToIndex[idArray[mostNodesId]],
+                            maxSizeFactor); 
+    Cal_Assert(CalCheckAllValidity(bddManager));
+    idArray[mostNodesId] = idArray[i];
+  }
+
+  Cal_MemFree(idArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+BddReorderSiftToBestPos(Cal_BddManager_t * bddManager, int
+                        varStartIndex, double maxSizeFactor)
+{
+  long curSize;
+  long bestSize;
+  int bestIndex;
+  int varCurIndex;
+  int varId, i;
+  int lastIndex = bddManager->numVars - 1;
+  int numVars = bddManager->numVars;
+  long startSize = bddManager->numNodes;
+  long maxSize =  startSize * maxSizeFactor;
+  int origId = bddManager->indexToId[varStartIndex];
+
+  int topMostSwapIndex = 0; /* the variable has been swapped upto this
+                               index */
+  int bottomMostSwapIndex = lastIndex; /* the variable has been
+                                          swapped upto this index */
+
+  int swapFlag = 0; /* If a swap has taken place after last cleaning
+                       up */
+                       
+  
+  curSize = bestSize = bddManager->numNodes;
+  bestIndex = varStartIndex;
+
+#ifdef _CAL_VERBOSE
+  for (i=0; i<bddManager->numVars; i++){
+    fprintf(stdout, "%3d ", bddManager->indexToId[i]);
+  }
+  fprintf(stdout, "%8d\n", bddManager->numNodes);
+#endif
+  
+  /*
+  ** If varStartIndex > numVars/2, do: Down, Up, Down.
+  ** If varStartIndex < numVars/2, do: Up, Down, Up
+  ** Followed by a cleanup phase in either case.
+  */
+  
+  if (varStartIndex >= (numVars >> 1)){
+    /* Phase I: Downward swap, no forwarding check. */
+    varCurIndex = varStartIndex;
+    while (varCurIndex < lastIndex) {
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 0);
+      swapFlag = 1;
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                               varCurIndex-1,
+                                               varCurIndex+1,
+                                               varCurIndex+1); 
+        swapFlag = 0;
+      }
+      varCurIndex++;
+      curSize = bddManager->numNodes;
+      /*if (curSize > maxSize){*/
+      if (curSize >= (bestSize << 1)){
+        bottomMostSwapIndex = varCurIndex;
+        break;
+      }
+      if (curSize < bestSize) {
+        bestSize = curSize;
+        bestIndex = varCurIndex;
+      }
+    }
+    
+    /* Phase II : Two parts */
+    /*
+    ** Part One: Upward swap until varStartIndex. Fix cofactors and
+    ** fix double pointers. 
+    */
+    
+    while (varCurIndex > varStartIndex) {
+      varCurIndex--;
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 1);
+      swapFlag = 1;
+      varId = bddManager->indexToId[varCurIndex];
+      BddReorderFixForwardingNodes(bddManager, varId);
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                               varCurIndex-1,
+                                               varCurIndex,
+                                               bottomMostSwapIndex); 
+        swapFlag = 0;
+      }
+    }
+    curSize = startSize;
+    
+    /*
+    ** Part two: Upward swap all the way to the top. Fix cofactors.
+    */
+    while (varCurIndex > 0) {
+      varCurIndex--;
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 1);
+      swapFlag = 1;
+      curSize = bddManager->numNodes;
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                               varCurIndex-1,
+                                               varCurIndex,
+                                               bottomMostSwapIndex); 
+        swapFlag = 0;
+      }
+      if (curSize > maxSize){
+        topMostSwapIndex = varCurIndex;
+        break;
+      }
+      if (curSize <= bestSize) {
+        bestSize = curSize;
+        bestIndex = varCurIndex;
+      }
+    }
+
+    if (swapFlag){
+      /* Fix user BDD pointers and reclaim forwarding nodes */
+      if (bddManager->pipelineState == CREATE){
+        /* There are some results computed in pipeline */
+        CalBddReorderFixProvisionalNodes(bddManager);
+      }
+      CalBddReorderFixUserBddPtrs(bddManager);
+      CalReorderAssociationFix(bddManager);
+      
+      /* The upward swapping might have stopped short */
+      for (i = 0; i < topMostSwapIndex; i++){
+        varId = bddManager->indexToId[i];
+        CalBddReorderFixCofactors(bddManager, varId);
+      }
+      
+      CalBddReorderReclaimForwardedNodes(bddManager, topMostSwapIndex,
+                                         bottomMostSwapIndex);
+      swapFlag = 0;
+    }
+    
+    Cal_Assert(CalCheckAllValidity(bddManager));
+    
+    /* Phase III : Swap to the min position */
+
+    while (varCurIndex < bestIndex) {
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 0); 
+      swapFlag = 1;
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                               varCurIndex-1,
+                                               varCurIndex+1,
+                                               varCurIndex+1); 
+        swapFlag = 0;
+      }
+      varCurIndex++;
+    }
+  }
+  else{
+    /* Phase I: Upward swap, fix cofactors. */
+    varCurIndex = varStartIndex;
+    while (varCurIndex > 0) {
+      varCurIndex--;
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 1);
+      swapFlag = 1;
+      curSize = bddManager->numNodes;
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                               varCurIndex-1,
+                                               varCurIndex+1,
+                                               varStartIndex); 
+        swapFlag = 0;
+      }
+      if (curSize > maxSize){
+        topMostSwapIndex = varCurIndex;
+        break;
+      }
+      if (curSize < bestSize) {
+        bestSize = curSize;
+        bestIndex = varCurIndex;
+      }
+    }
+    
+    if (swapFlag){
+      /* Fix user BDD pointers and reclaim forwarding nodes */
+      if (bddManager->pipelineState == CREATE){
+        /* There are some results computed in pipeline */
+        CalBddReorderFixProvisionalNodes(bddManager);
+      }
+      CalBddReorderFixUserBddPtrs(bddManager);
+      CalReorderAssociationFix(bddManager);
+      /* The upward swapping might have stopped short */
+      for (i = 0; i < topMostSwapIndex; i++){
+        varId = bddManager->indexToId[i];
+        CalBddReorderFixCofactors(bddManager, varId);
+      }
+      CalBddReorderReclaimForwardedNodes(bddManager, topMostSwapIndex,
+                                         varStartIndex);
+      swapFlag = 0;
+    }
+    
+    Cal_Assert(CalCheckAllValidity(bddManager));
+
+    /* Phase II : Move all the way down : two parts */
+
+    /* Swap it to the original position, no cofactor fixing, fix
+       double pointers of the variable moving up.*/
+    while (varCurIndex < varStartIndex){
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 0);
+      swapFlag = 1;
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                               varCurIndex-1,
+                                               varCurIndex+1,
+                                               varCurIndex+1); 
+        swapFlag = 0;
+      }
+      varCurIndex++;
+    }
+    /* Swap to the bottom */
+    while (varCurIndex < lastIndex){
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 0);
+      swapFlag = 1;
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                               varCurIndex-1,
+                                               varCurIndex+1,
+                                               varCurIndex+1); 
+        swapFlag = 0;
+      }
+      varCurIndex++;
+      curSize = bddManager->numNodes;
+      /* if (curSize > maxSize){ */
+      if (curSize >= (bestSize << 1)){
+        bottomMostSwapIndex = varCurIndex;
+        break;
+      }
+      if (curSize <= bestSize) {
+        bestSize = curSize;
+        bestIndex = varCurIndex;
+      }
+    }
+
+    /* Phase III : Move up to the best position */
+    while (varCurIndex > bestIndex){
+      varCurIndex--;
+      BddReorderSwapVarIndex(bddManager, varCurIndex, 1);
+      swapFlag = 1;
+      varId = bddManager->indexToId[varCurIndex];
+      BddReorderFixForwardingNodes(bddManager, varId);
+      if (bddManager->numForwardedNodes > bddManager->maxForwardedNodes){
+        CofactorFixAndReclaimForwardedNodes(bddManager, 0, varCurIndex-1,
+                                               varCurIndex,
+                                               bottomMostSwapIndex); 
+        swapFlag = 0;
+      }
+    }
+  } /* End of else clause (varStartIndex < numVars/2) */
+
+#ifdef _CAL_VERBOSE
+  PrintBddProfileAfterReorder(bddManager);
+#endif
+  
+  if (CalBddIdNeedsRepacking(bddManager, origId)){
+    if (swapFlag){
+      if (varStartIndex >= (numVars >> 1)){
+        CalBddPackNodesAfterReorderForSingleId(bddManager, 0,
+                                               bestIndex, bestIndex); 
+      }
+      /*
+      else if (bestIndex >= (numVars >> 1)){
+        int i;
+        int nodeCounter = 0;
+        for (i=bestIndex; i<numVars; i++){
+          nodeCounter +=
+              bddManager->uniqueTable[bddManager->indexToId[i]]->numEntries;
+        }
+        if ((bddManager->numNodes - nodeCounter) >
+            bddManager->numForwardedNodes){
+            BddPackNodesAfterReorderForSingleId(bddManager, 1, bestIndex,
+                                                 bottomMostSwapIndex);
+        }
+        else {
+          BddSiftPerfromPhaseIV(bddManager, varStartIndex, bestIndex,
+                                bottomMostSwapIndex);
+          BddPackNodesAfterReorderForSingleId(bddManager, 0,
+                                                 bestIndex, bestIndex); 
+        }
+      }
+      */
+      else {
+        /* Clean up - phase IV */
+        BddSiftPerfromPhaseIV(bddManager, varStartIndex, bestIndex,
+                              bottomMostSwapIndex);
+        CalBddPackNodesAfterReorderForSingleId(bddManager, 0,
+                                               bestIndex, bestIndex); 
+      }
+    }
+    else {
+      CalBddPackNodesAfterReorderForSingleId(bddManager, 0, bestIndex,
+                                             bestIndex); 
+    }
+  }
+  else if (swapFlag) {
+    /* clean up - phase IV */
+    BddSiftPerfromPhaseIV(bddManager, varStartIndex, bestIndex,
+                          bottomMostSwapIndex);
+  }
+  Cal_Assert(CalCheckAllValidity(bddManager));
+  
+#ifdef _CAL_VERBOSE
+  printf("ID = %3d SI = %3d EI = %3d Nodes = %7d\n", origId,
+         varStartIndex, bestIndex, bddManager->numNodes);
+#endif
+  return bestIndex;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+BddSiftPerfromPhaseIV(Cal_BddManager_t *bddManager, int varStartIndex,
+                      int bestIndex, int bottomMostSwapIndex)
+{
+  int varCurIndex, varId;
+  
+
+/* We need to perform phase IV */
+  varCurIndex = bestIndex-1;
+  while (varCurIndex >= 0) {
+    varId = bddManager->indexToId[varCurIndex];
+    CalBddReorderFixCofactors(bddManager, varId);
+    varCurIndex--;
+  }
+  if (bddManager->pipelineState == CREATE){
+    /* There are some results computed in pipeline */
+    CalBddReorderFixProvisionalNodes(bddManager);
+  }
+  CalBddReorderFixUserBddPtrs(bddManager);
+  CalReorderAssociationFix(bddManager);
+  if (varStartIndex >= (bddManager->numVars >> 1)){
+    CalBddReorderReclaimForwardedNodes(bddManager, bestIndex, bestIndex);
+  }
+  else {
+    CalBddReorderReclaimForwardedNodes(bddManager, bestIndex,
+                                       bottomMostSwapIndex); 
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReorderVarWindow(Cal_BddManager bddManager, char *levels)
+{
+  long i;
+  int moved;
+  int anySwapped;
+  int even;
+  int lastIndex = bddManager->numVars-1;
+  
+#ifdef _CAL_VERBOSE
+  for (i=0; i<bddManager->numVars; i++){
+    fprintf(stdout, "%3d ", bddManager->indexToId[i]);
+  }
+  fprintf(stdout, "%8d\n", bddManager->numNodes);
+#endif
+  for (i=0; i < bddManager->numVars-1; i++) levels[i]=1;
+  even = 1;
+  do {
+    anySwapped=0;
+    if (even){
+      /*fprintf(stdout, "Downward Swap\n");*/
+      for (i=0; i < bddManager->numVars-1; i++){
+        if (levels[i]) {
+          if (i < bddManager->numVars-2) {
+            moved = BddReorderWindow3(bddManager, i, 0);
+            if (bddManager->numForwardedNodes >
+                bddManager->maxForwardedNodes){   
+              CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                                     i-1, 0, i+2);
+              CalBddPackNodesForMultipleIds(bddManager,
+                                         bddManager->indexToId[i], 3);
+            }
+          }
+          else {
+            moved = BddReorderWindow2(bddManager, i, 0);
+          }
+          if (moved){
+            if (i > 0) {
+              levels[i-1]=1;
+              if (i > 1) levels[i-2]=1;
+            }
+            levels[i]=1;
+            levels[i+1]=1;
+            if (i < bddManager->numVars-2) {
+              levels[i+2]=1;
+              if (i < bddManager->numVars-3) {
+                levels[i+3]=1;
+                if (i < bddManager->numVars-4) levels[i+4]=1;
+              }
+            }
+            anySwapped=1;
+          }
+          else {
+            levels[i]=0;
+          }
+        }
+      }
+      /* new code added */
+      for (i = bddManager->numVars-1; i >= 0; i--){
+        CalBddReorderFixCofactors(bddManager, bddManager->indexToId[i]);
+      }
+      CalBddReorderFixUserBddPtrs(bddManager);
+      if (bddManager->pipelineState == CREATE){
+        /* There are some results computed in pipeline */
+        CalBddReorderFixProvisionalNodes(bddManager);
+      }
+      CalReorderAssociationFix(bddManager);
+      CalBddReorderReclaimForwardedNodes(bddManager, 0, lastIndex);
+      /*even = 0;*/
+    }
+    else{
+      /*fprintf(stdout, "Upward Swap\n");*/
+      for (i=bddManager->numVars-1; i > 0; i--){
+          /*
+           * Fix the then and else cofactors. We need to fix it, even
+           * if this level is not supposed to be moved.
+           */
+        if (i > 1) {
+          CalBddReorderFixCofactors(bddManager,
+                                 bddManager->indexToId[i-2]); 
+        }
+        else {
+          CalBddReorderFixCofactors(bddManager,
+                                 bddManager->indexToId[i-1]); 
+        }
+        if (levels[i]) {
+          if (i > 1) {
+            moved = BddReorderWindow3(bddManager, i-2, 1);
+            if (bddManager->numForwardedNodes >
+                bddManager->maxForwardedNodes){ 
+              CofactorFixAndReclaimForwardedNodes(bddManager, 0,
+                                                  i-3, 0,
+                                                  lastIndex); 
+              CalBddPackNodesForMultipleIds(bddManager,
+                                            bddManager->indexToId[i-2], 3);
+            }
+          }
+          else {
+            moved = BddReorderWindow2(bddManager, i-1, 1);
+          }
+          if (moved){
+            if (i < bddManager->numVars-1) {
+              levels[i+1]=1;
+              if (i < bddManager->numVars-2) {
+                levels[i+2]=1;
+                if (i < bddManager->numVars-3) {
+                  levels[i+3]=1;
+                  if (i < bddManager->numVars-4) {
+                    levels[i+4]=1;
+                  }
+                }
+              }
+            }
+            levels[i]=1;
+            levels[i-1]=1;
+            if (i > 1) {
+              levels[i-2]=1;
+            }
+            anySwapped=1;
+          }
+          else {
+            levels[i]=0;
+          }
+        }
+      }
+      even = 1;
+      CalBddReorderFixUserBddPtrs(bddManager);
+      if (bddManager->pipelineState == CREATE){
+        /* There are some results computed in pipeline */
+        CalBddReorderFixProvisionalNodes(bddManager);
+      }
+      CalReorderAssociationFix(bddManager);
+      CalBddReorderReclaimForwardedNodes(bddManager, 0, lastIndex);
+    }
+  }
+  while (anySwapped);
+  if (!even){ /* Need to do pointer fixing */
+    for (i = bddManager->numVars-1; i >= 0; i--){
+      CalBddReorderFixCofactors(bddManager, bddManager->indexToId[i]);
+    }
+    CalBddReorderFixUserBddPtrs(bddManager);
+    if (bddManager->pipelineState == CREATE){
+      /* There are some results computed in pipeline */
+      CalBddReorderFixProvisionalNodes(bddManager);
+    }
+    CalReorderAssociationFix(bddManager);
+    CalBddReorderReclaimForwardedNodes(bddManager, 0, lastIndex);
+  }
+  Cal_Assert(CalCheckAllValidity(bddManager));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static int
+BddReorderWindow2(Cal_BddManager bddManager, long index, int directionFlag)
+{
+  long curSize, startSize;
+
+  startSize = bddManager->numNodes;
+  BddReorderSwapVarIndex(bddManager, index, 0);
+  curSize = bddManager->numNodes;
+  if (curSize > startSize){
+    BddReorderSwapVarIndex(bddManager, index, 0);
+  }
+  if (directionFlag){/* Upward window swap */
+    BddReorderFixAndFreeForwardingNodes(bddManager,
+                                        bddManager->indexToId[index],
+                                        bddManager->numVars-index); 
+  }
+  else{
+    BddReorderFixAndFreeForwardingNodes(bddManager,
+                                        bddManager->indexToId[index], 2);
+  }
+  Cal_Assert(CalCheckValidityOfNodesForWindow(bddManager, index, 2));
+  return (curSize < startSize);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static int
+BddReorderWindow3(Cal_BddManager bddManager, long index, int directionFlag)
+{
+  int best;
+  long curSize, bestSize;
+  long origSize = bddManager->numNodes;
+  
+  /* 1 2 3 */
+  best = 0;
+  bestSize = bddManager->numNodes;
+  BddReorderSwapVarIndex(bddManager, index, 0); 
+  /* 2 1 3 */
+  curSize = bddManager->numNodes;
+  if (curSize < bestSize){
+    best = 1;
+    bestSize = curSize;
+  }
+  BddReorderSwapVarIndex(bddManager, index+1, 0);
+  /* 2 3 1 */
+  curSize = bddManager->numNodes;
+  if (curSize < bestSize){
+    best = 2;
+    bestSize = curSize;
+  }
+  BddReorderSwapVarIndex(bddManager, index, 1);
+  /* 3 2 1 */
+  curSize = bddManager->numNodes;
+  if (curSize <= bestSize){
+    best = 3;
+    bestSize = curSize;
+  }
+  BddReorderSwapVarIndex(bddManager, index+1, 0);
+  /* 3 1 2 */
+  curSize = bddManager->numNodes;
+  if (curSize <= bestSize){
+    best = 4;
+    bestSize = curSize;
+  }
+  BddReorderSwapVarIndex(bddManager, index, 1);
+  /* 1 3 2 */
+  curSize = bddManager->numNodes;
+  if (curSize <= bestSize){
+    best = 5;
+    bestSize = curSize;
+  }
+  switch (best) {
+    case 0:
+      BddReorderSwapVarIndex(bddManager, index+1, 0);
+      break;
+    case 1:
+      BddReorderSwapVarIndex(bddManager, index+1, 0);
+      BddReorderSwapVarIndex(bddManager, index, 1);
+      break;
+    case 2:
+      BddReorderSwapVarIndex(bddManager, index, 0);
+      BddReorderSwapVarIndex(bddManager, index+1, 0);
+      BddReorderSwapVarIndex(bddManager, index, 1);
+      break;
+    case 3:
+      BddReorderSwapVarIndex(bddManager, index, 0);
+      BddReorderSwapVarIndex(bddManager, index+1, 0);
+      break;
+    case 4:
+      BddReorderSwapVarIndex(bddManager, index, 0);
+      break;
+    case 5:
+      break;
+  }
+  if ((best == 0) || (best == 3)){
+    CalBddReorderFixCofactors(bddManager, bddManager->indexToId[index]);
+  }
+  if (directionFlag){/* Upward window swap */
+    BddReorderFixAndFreeForwardingNodes(bddManager,
+                                        bddManager->indexToId[index],
+                                        bddManager->numVars-index); 
+  }
+  else{
+    BddReorderFixAndFreeForwardingNodes(bddManager,
+                                        bddManager->indexToId[index], 3);
+  }
+  Cal_Assert(CalCheckValidityOfNodesForWindow(bddManager, index, 3));
+  return ((best > 0) && (origSize > bestSize));
+}
+
Index: /vis_dev/glu-2.1/src/calBdd/calReorderDF.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calReorderDF.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calReorderDF.c	(revision 8)
@@ -0,0 +1,1584 @@
+/**CFile***********************************************************************
+
+  FileName    [calReorderDF.c]
+
+  PackageName [cal]
+
+  Synopsis    [Routines for dynamic reordering of variables.]
+
+  Description [This method is based on traditional dynamic reordering
+  technique found in depth-first based packages. The data structure is
+  first converted to conform to traditional one and then reordering is
+  performed. At the end the nodes are arranged back on the pages. The
+  computational overheads are in terms of converting the data
+  structure back and forth and the memory overhead due to the extra
+  space needed to arrange the nodes. This overhead can be eliminated
+  by proper implementation. For details, please refer to the work by
+  Rajeev K. Ranjan et al - "Dynamic variable reordering in a
+  breadth-first manipulation based package: Challenges and Solutions"-
+  Proceedings of ICCD'97.]
+
+  SeeAlso     [calReorderBF.c calReorderUtil.c]
+
+  Author      [Rajeev K. Ranjan   (rajeev@@ic. eecs.berkeley.edu)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static   CalNodeManager_t *nodeManager; 
+static   int freeListId;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+/* These macros are needed because we are dealing with a new data
+   structures of the BDD nodes */
+
+#define BddNodeIcrRefCount(f)                   \
+{                                               \
+  CalBddNode_t *_bddNode = CAL_BDD_POINTER(f);  \
+  if (_bddNode->elseBddId < CAL_MAX_REF_COUNT){ \
+    _bddNode->elseBddId++;                      \
+  }                                             \
+}
+
+#define BddNodeDcrRefCount(f) \
+{ \
+  CalBddNode_t *_bddNode = CAL_BDD_POINTER(f); \
+  if ((_bddNode->elseBddId < CAL_MAX_REF_COUNT) && (_bddNode->elseBddId)){ \
+    _bddNode->elseBddId--; \
+  } \
+  else if (_bddNode->elseBddId == 0){ \
+    CalBddWarningMessage("Trying to decrement reference count below zero"); \
+  } \
+}
+
+#define BddGetCofactors(bddManager, f, id, fThen, fElse)                \
+{                                                                       \
+  CalBddNode_t *_bddNode = CAL_BDD_POINTER(f);                          \
+  Cal_Assert(bddManager->idToIndex[_bddNode->thenBddId] <=              \
+             bddManager->idToIndex[id]);                                \
+  if (bddManager->idToIndex[_bddNode->thenBddId] ==                     \
+      bddManager->idToIndex[id]){                                       \
+    fThen = _bddNode->thenBddNode;                                      \
+    fElse = _bddNode->elseBddNode;                                      \
+  }                                                                     \
+  else{                                                                 \
+    fThen = fElse = f;                                                  \
+  }                                                                     \
+}
+
+#define BddNodeGetThenBddNode(bddNode)                    \
+((CalBddNode_t*) ((CalAddress_t)                          \
+                  (CAL_BDD_POINTER(bddNode)->thenBddNode) \
+                  ^ (CAL_TAG0(bddNode))))
+
+#define BddNodeGetElseBddNode(bddNode)                    \
+((CalBddNode_t*) ((CalAddress_t)                          \
+                  (CAL_BDD_POINTER(bddNode)->elseBddNode) \
+                  ^ (CAL_TAG0(bddNode))))
+  
+    
+    
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int UniqueTableForIdFindOrAdd(Cal_BddManager_t * bddManager, CalHashTable_t * hashTable, CalBddNode_t *thenBdd, CalBddNode_t *elseBdd, CalBddNode_t **bddPtr);
+static void HashTableAddDirect(CalHashTable_t * hashTable, CalBddNode_t *bddNode);
+static int HashTableFindOrAdd(Cal_BddManager_t *bddManager, CalHashTable_t *hashTable, CalBddNode_t *thenBdd, CalBddNode_t *elseBdd, CalBddNode_t **bddPtr);
+static void BddConvertDataStruct(Cal_BddManager_t *bddManager);
+static void BddConvertDataStructBack(Cal_BddManager_t *bddManager);
+static void BddReallocateNodes(Cal_BddManager_t *bddManager);
+static void BddExchangeAux(Cal_BddManager_t *bddManager, CalBddNode_t *f, int id, int nextId);
+static int CheckValidityOfNodes(Cal_BddManager_t *bddManager, long id);
+static void SweepVarTable(Cal_BddManager_t *bddManager, long id);
+static void BddExchange(Cal_BddManager_t *bddManager, long id);
+static void BddExchangeVarBlocks(Cal_BddManager_t *bddManager, Cal_Block parent, long blockIndex);
+static int BddReorderWindow2(Cal_BddManager_t *bddManager, Cal_Block block, long i);
+static int BddReorderWindow3(Cal_BddManager_t *bddManager, Cal_Block block, long i);
+static void BddReorderStableWindow3Aux(Cal_BddManager_t *bddManager, Cal_Block block, char *levels);
+static void BddReorderStableWindow3(Cal_BddManager_t *bddManager);
+static void BddSiftBlock(Cal_BddManager_t *bddManager, Cal_Block block, long startPosition, double maxSizeFactor);
+static void BddReorderSiftAux(Cal_BddManager_t *bddManager, Cal_Block block, Cal_Block *toSift, double maxSizeFactor);
+static void BddReorderSift(Cal_BddManager_t *bddManager, double maxSizeFactor);
+static int CeilLog2(int number);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddReorderAuxDF(Cal_BddManager_t *bddManager)
+{
+  CalHashTableGC(bddManager, bddManager->uniqueTable[0]);
+  /*Cal_BddManagerGC(bddManager);Cal_Assert(CalCheckAllValidity(bddManager));*/
+  /* If we want to check the validity, we need to garbage collect */
+  CalInitInteract(bddManager); /* Initialize the interaction matrix
+                                  before changing the data structure */
+  nodeManager = CalNodeManagerInit(bddManager->pageManager2);
+  freeListId = 1;
+#ifdef _CAL_QUANTIFY_
+  quantify_start_recording_data();
+#endif
+  BddConvertDataStruct(bddManager);
+  if (bddManager->reorderTechnique == CAL_REORDER_WINDOW){
+    BddReorderStableWindow3(bddManager);
+  }
+  else {
+    BddReorderSift(bddManager, bddManager->maxSiftingGrowth);
+  }
+  BddReallocateNodes(bddManager);
+  BddConvertDataStructBack(bddManager);
+#ifdef _CAL_QUANTIFY_
+  quantify_stop_recording_data();
+#endif
+  nodeManager->numPages = 0; /* Since these pages have already been
+                                freed */
+  CalNodeManagerQuit(nodeManager);
+  Cal_Assert(CalCheckAllValidity(bddManager));
+  Cal_MemFree(bddManager->interact);
+  bddManager->numReorderings++;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+static void
+NodeManagerAllocNode(Cal_BddManager_t *bddManager, CalBddNode_t **nodePtr) 
+{
+  /* First check the free list of bddManager */
+  if (nodeManager->freeNodeList){
+    *nodePtr = nodeManager->freeNodeList;
+    nodeManager->freeNodeList =
+        ((CalBddNode_t *)(*nodePtr))->nextBddNode;
+  }
+  else{
+    if (freeListId < bddManager->numVars){
+      /* Find the next id with free list */
+      for (; freeListId <= bddManager->numVars; freeListId++){
+        CalNodeManager_t *nodeManagerForId =
+            bddManager->nodeManagerArray[freeListId]; 
+        if (nodeManagerForId->freeNodeList){
+          *nodePtr = nodeManagerForId->freeNodeList;
+          nodeManagerForId->freeNodeList = (CalBddNode_t *)0;
+          nodeManager->freeNodeList =
+              ((CalBddNode_t *)(*nodePtr))->nextBddNode;
+          break;
+        }
+      }
+    }
+  }
+  if (!(*nodePtr)){
+    /* Create a new page */
+    CalBddNode_t *_freeNodeList, *_nextNode, *_node;                        
+    _freeNodeList =                                                         
+        (CalBddNode_t *)CalPageManagerAllocPage(nodeManager->pageManager);  
+    for(_node = _freeNodeList + NUM_NODES_PER_PAGE - 1, _nextNode =0;       
+        _node != _freeNodeList; _nextNode = _node--){                       
+      _node->nextBddNode = _nextNode;                                       
+    }                                                                       
+    nodeManager->freeNodeList = _freeNodeList + 1;                          
+    *nodePtr = _node;
+    if (nodeManager->numPages == nodeManager->maxNumPages){             
+      nodeManager->maxNumPages *= 2;                                      
+      nodeManager->pageList =                                            
+          Cal_MemRealloc(CalAddress_t *, nodeManager->pageList, 
+                         nodeManager->maxNumPages);                       
+    }                                                                       
+    nodeManager->pageList[nodeManager->numPages++] =
+        (CalAddress_t *)_freeNodeList;     
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [find or add in the unique table for id.]
+
+  Description [optional]
+
+  SideEffects [If a new BDD node is created (found == false), then the
+  numNodes field of the manager needs to be incremented.]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+UniqueTableForIdFindOrAdd(Cal_BddManager_t * bddManager,
+                          CalHashTable_t * hashTable,
+                          CalBddNode_t *thenBdd,
+                          CalBddNode_t *elseBdd,
+                          CalBddNode_t **bddPtr)
+{
+  int found = 0; 
+  if (thenBdd == elseBdd){
+    *bddPtr = thenBdd;
+    found = 1;
+  }
+  else if(CalBddNodeIsOutPos(thenBdd)){
+    found = HashTableFindOrAdd(bddManager, hashTable, thenBdd, elseBdd, bddPtr);
+  }
+  else{
+    found = HashTableFindOrAdd(bddManager, hashTable,
+                               CalBddNodeNot(thenBdd),
+                               CalBddNodeNot(elseBdd), bddPtr); 
+    *bddPtr = CalBddNodeNot(*bddPtr);
+  }
+  if (!found) bddManager->numNodes++;
+  return found;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Directly insert a BDD node in the hash table.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+HashTableAddDirect(CalHashTable_t * hashTable, CalBddNode_t *bddNode)
+{
+  int hashValue;
+  CalBddNode_t *thenBddNode, *elseBddNode;
+
+  hashTable->numEntries++;
+  if(hashTable->numEntries >= hashTable->maxCapacity){
+    CalHashTableRehash(hashTable, 1);
+  }
+  thenBddNode = bddNode->thenBddNode;
+  Cal_Assert(CalBddNodeIsOutPos(thenBddNode));
+  elseBddNode = bddNode->elseBddNode;
+  hashValue = CalDoHash2(thenBddNode, elseBddNode, hashTable);
+  bddNode->nextBddNode = hashTable->bins[hashValue];
+  hashTable->bins[hashValue] = bddNode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+HashTableFindOrAdd(Cal_BddManager_t *bddManager, CalHashTable_t
+                   *hashTable,  CalBddNode_t *thenBdd,
+                   CalBddNode_t *elseBdd, CalBddNode_t **bddPtr) 
+{
+  CalBddNode_t *ptr;
+  int hashValue;
+  
+  Cal_Assert(CalBddNodeIsOutPos(thenBdd));
+  hashValue = CalDoHash2(thenBdd, elseBdd, hashTable);
+  for (ptr = hashTable->bins[hashValue]; ptr; ptr = ptr->nextBddNode){
+    if ((ptr->thenBddNode == thenBdd) &&
+        (ptr->elseBddNode == elseBdd)){
+      *bddPtr = ptr;
+      return 1;
+    }
+  }
+  hashTable->numEntries++;
+  if(hashTable->numEntries > hashTable->maxCapacity){
+    CalHashTableRehash(hashTable,1);
+    hashValue = CalDoHash2(thenBdd, elseBdd, hashTable);
+  }
+
+  NodeManagerAllocNode(bddManager, &ptr);
+
+  ptr->thenBddNode = thenBdd;
+  ptr->elseBddNode = elseBdd;
+  ptr->nextBddNode = hashTable->bins[hashValue];
+  ptr->thenBddId = hashTable->bddId;
+  ptr->elseBddId = 0;
+  hashTable->bins[hashValue] = ptr;
+  *bddPtr = ptr;
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Changes the data structure of the bdd nodes.]
+
+  Description        [New data structure: thenBddId -> id 
+                                          elseBddId -> ref count]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddConvertDataStruct(Cal_BddManager_t *bddManager)
+{
+  CalBddNode_t *bddNode, *thenBddNode, *elseBddNode,
+      *next = Cal_Nil(CalBddNode_t); 
+  CalBddNode_t *last;
+  long numBins;
+  int i, refCount, id, index;
+  long oldNumEntries;
+  CalHashTable_t *uniqueTableForId;
+
+  if (bddManager->numPeakNodes < bddManager->numNodes){
+    bddManager->numPeakNodes = bddManager->numNodes;
+  }
+
+  for(index = 0; index < bddManager->numVars; index++){
+    id = bddManager->indexToId[index];
+    uniqueTableForId = bddManager->uniqueTable[id];
+    oldNumEntries = uniqueTableForId->numEntries;
+    numBins = uniqueTableForId->numBins;
+    for(i = 0; i < numBins; i++){
+      last = NULL;
+      bddNode = uniqueTableForId->bins[i];
+      while(bddNode != Cal_Nil(CalBddNode_t)){
+        next = CalBddNodeGetNextBddNode(bddNode);
+        CalBddNodeGetRefCount(bddNode, refCount);
+        thenBddNode = CalBddNodeGetThenBddNode(bddNode);
+        elseBddNode = CalBddNodeGetElseBddNode(bddNode);
+        if(refCount == 0){
+          if (last == NULL){
+            uniqueTableForId->bins[i] = next;
+          }
+          else{
+            last->nextBddNode = next;
+          }
+          CalBddNodeDcrRefCount(CAL_BDD_POINTER(thenBddNode));
+          CalBddNodeDcrRefCount(CAL_BDD_POINTER(elseBddNode));
+          CalNodeManagerFreeNode(nodeManager, bddNode);
+          uniqueTableForId->numEntries--;
+        }
+        else {
+          bddNode->thenBddId = id;
+          bddNode->elseBddId = refCount;
+          bddNode->nextBddNode = next;
+          bddNode->thenBddNode = thenBddNode;
+          bddNode->elseBddNode = elseBddNode;
+          last = bddNode; 
+        }
+        bddNode = next;
+      }
+    }
+    if ((uniqueTableForId->numBins > uniqueTableForId->numEntries) &&
+        (uniqueTableForId->sizeIndex > HASH_TABLE_DEFAULT_SIZE_INDEX)){
+      CalHashTableRehash(uniqueTableForId, 0);
+    }
+    bddManager->numNodes -= oldNumEntries - uniqueTableForId->numEntries;
+    bddManager->numNodesFreed += oldNumEntries - uniqueTableForId->numEntries;
+  }
+  id = 0;
+  uniqueTableForId = bddManager->uniqueTable[id];
+  numBins = uniqueTableForId->numBins;
+  for(i = 0; i < numBins; i++){
+    bddNode = uniqueTableForId->bins[i];
+    while(bddNode != Cal_Nil(CalBddNode_t)){
+      next = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodeGetRefCount(bddNode, refCount);
+      Cal_Assert(refCount);
+      thenBddNode = CalBddNodeGetThenBddNode(bddNode);
+      elseBddNode = CalBddNodeGetElseBddNode(bddNode);
+      bddNode->thenBddId = id;
+      bddNode->elseBddId = refCount;
+      bddNode->nextBddNode = next;
+      bddNode->thenBddNode = thenBddNode;
+      bddNode->elseBddNode = elseBddNode;
+      bddNode = next;
+    }
+  }
+  bddNode = bddManager->bddOne.bddNode;
+  CalBddNodeGetRefCount(bddNode, refCount);
+  Cal_Assert(refCount);
+  thenBddNode = CalBddNodeGetThenBddNode(bddNode);
+  elseBddNode = CalBddNodeGetElseBddNode(bddNode);
+  bddNode->thenBddId = id;
+  bddNode->elseBddId = refCount;
+  bddNode->nextBddNode = next;
+  bddNode->thenBddNode = thenBddNode;
+  bddNode->elseBddNode = elseBddNode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Changes the data structure of the bdd nodes to
+  the original one.]
+
+  Description        [Data structure conversion: thenBddId -> id 
+  elseBddId -> ref count]
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddConvertDataStructBack(Cal_BddManager_t *bddManager)
+{
+  Cal_Bdd_t thenBdd, elseBdd;
+  
+  CalBddNode_t *bddNode, *nextBddNode, **bins;
+  long numBins;
+  int i, id, index;
+  CalHashTable_t *uniqueTableForId;
+  uniqueTableForId = bddManager->uniqueTable[0];
+  numBins = uniqueTableForId->numBins;
+  bins = uniqueTableForId->bins;
+  for(i = 0; i < numBins; i++) {
+    for(bddNode = bins[i];
+        bddNode != Cal_Nil(CalBddNode_t);
+        bddNode = nextBddNode) {
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodePutRefCount(bddNode, bddNode->elseBddId);
+      bddNode->thenBddId = CAL_BDD_POINTER(bddNode->thenBddNode)->thenBddId;
+      bddNode->elseBddId = CAL_BDD_POINTER(bddNode->elseBddNode)->thenBddId;
+    }
+  }
+  for(index = 0; index < bddManager->numVars; index++){
+    id = bddManager->indexToId[index];
+    uniqueTableForId = bddManager->uniqueTable[id];
+    numBins = uniqueTableForId->numBins;
+    bins = uniqueTableForId->bins;
+    for(i = 0; i < numBins; i++) {
+      for(bddNode = bins[i];
+          bddNode != Cal_Nil(CalBddNode_t);
+          bddNode = nextBddNode) {
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        CalBddNodePutRefCount(bddNode, bddNode->elseBddId);
+        bddNode->thenBddId = CAL_BDD_POINTER(bddNode->thenBddNode)->thenBddId;
+        bddNode->elseBddId = CAL_BDD_POINTER(bddNode->elseBddNode)->thenBddId;
+      Cal_Assert(!CalBddNodeIsForwarded(bddNode));
+      Cal_Assert(!CalBddNodeIsRefCountZero(bddNode));
+      CalBddNodeGetThenBdd(bddNode, thenBdd);
+      CalBddNodeGetElseBdd(bddNode, elseBdd);
+      Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+      Cal_Assert(CalBddIsForwarded(elseBdd) == 0);
+      }
+    }
+  }
+  bddNode = bddManager->bddOne.bddNode;
+  CalBddNodePutRefCount(bddNode, bddNode->elseBddId);
+  bddNode->thenBddId = 0;
+  bddNode->elseBddId = 0;
+}
+
+#ifdef _FOO_
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReallocateNodesInPlace(Cal_BddManager_t *bddManager)
+{
+  Cal_Address_t  *pageSegment;
+  CalPageManager_t *pageManager;
+  CalHashTable_t *uniqueTable;
+  CalNodeManager_t *nodeManager;
+  int index, id, i, pageCounter, numUsefulSegments, segmentCounter;
+  
+  /* Initialize and set up few things */
+  pageManager = bddManager->pageManager;
+  uniqueTable = bddManager->uniqueTable;
+  for (id = 1; id <= bddManager->numVars; id++){
+    numPagesRequired =
+        uniqueTable[id]->numEntries/NUM_NODES_PER_PAGE+1;
+    nodeManager = uniqueTable[id]->nodeManager;
+    /* Clear out the page list of the node manager */
+    for (i=0; i<nodeManager->maxNumPages; i++){
+      nodeManager->pageList[i] = 0;
+    }
+    nodeManager->freeNodeList = (CalBddNode_t *)0;
+    nodeManager->numPages = numPagesRequired;
+    Cal_Assert(nodeManager->maxNumPages >= numPagesRequired);
+    for (i = 0; i<numPagesRequired; i++){
+      if (++pageCounter ==
+              pageManager->numPagesArray[segmentCounter]){
+        pageCounter = 0;
+        segmentCounter++;
+        pageSegment = pageManager->pageSegmentArray[segmentCounter];
+      }
+      nodeManager->pageList[i] = pageSegment[pageCounter];
+    }
+  }
+  numUsefulSegments = segmentCounter+1;
+  numUsefulPagesInLastSegment = pageCounter+1;
+  
+  /* Traverse all the nodes belonging in each page */
+  /* Put the destination addresses in the next pointer */
+  for (numSegment=0; numSegment < pageManager->numSegments; 
+       numSegment++){
+    for (numPage = 0, page = pageManager->pageSegmentArray[numSegment]; 
+         numPage < pageManager->numPagesArray[numSegment];
+         page += PAGE_SIZE, numPage++){
+      for (bddNode = (CalBddNode_t*) page, numNode = 0;
+           numNode < NUM_NODES_PER_PAGE; numNode++, bddNode += 1){
+        /* If the node is not useful, continue */
+        if (bddNode->elseBddId == 0) continue; 
+        /* Find out the destination address */
+        bddId = bddNode->thenBddId;
+        nodeCounter[bddId]++;
+        if (nodeCounter[bddId] == NUM_NODES_PER_PAGE){
+          pageCounter[bddId]++;
+          nodePointerArray[bddId] =
+              pageListArray[bddId][pageCounter[bddId]];
+          nodeCounter[bddId] = 0;
+        }
+        bddNode->nextBddNode = nodePointerArray[bddId];
+        nodePointerArray[bddId] += 1;
+      }
+    }
+  }
+  /* Traverse all the nodes belonging in each page */
+  /* Update the contents */
+  for (numSegment=0; numSegment < pageManager->totalNumSegments; 
+       numSegment++){
+    for (numPage = 0, page = pageManager->pageSegmentArray[numSegment]; 
+         numPage < pageManager->numPagesArray[numSegment];
+         page += PAGE_SIZE, numPage++){
+      for (bddNode = (CalBddNode_t*) page, numNode = 0;
+           numNode < NUM_NODES_PER_PAGE; numNode++, bddNode += 1){
+        /* If the node is not useful, continue */
+        if (bddNode->elseBddId == 0) continue; 
+        /* If the node has been visited, continue */
+        if ((CalAddress_t)bddNode->nextBddNode & 01) continue;
+        /* If the nodes is supposed to remain at the same place,
+           update the then and else pointers and continue */
+        if (((CalAddress_t) bddNode->nextBddNode &~01) ==
+            ((CalAddress_t) bddNode & ~01)){
+          CalBddNodeUpdatebddNode(bddNode);
+          continue;
+        }
+        origNode = bddNode; /* Remember the address */
+        /* Update the contents */
+        thenBddNode = bddNode->thenBddNode;
+        elseBddNode = bddNode->elseBddNode;
+        thenBddId = bddNode->thenBddId;
+        elseBddId = bddNode->elseBddId;
+        do{
+          thenBddNode = UpdateThenBddNode(thenBddNode);
+          elseBddNode = UpdateElseBddNode(elseBddNode);
+          destinationNode = bddNode->nextBddNode;
+          /* Mark the node visited */
+          bddNode->nextBddNode = (CalBddNode_t *)
+              ((CalAddress_t)bddNode->nextBddNode | 01);
+          thenBddNode2 = destinationNode->thenBddNode;
+          elseBddNode2 = destinationNode->elseBddNode;
+          thenBddId2 = destinationNode->thenBddId;
+          elseBddId2 = destinationNode->elseBddId;
+          destinationNode->thenBddNode = thenBddNode;
+          destinationNode->elseBddNode = elseBddNode;
+          destinationNode->thenBddId = thenBddId;
+          destinationNode->elseBddId = elseBddId;
+          bddNode = destinationNode;
+          thenBddNode = thenBddNode2;
+          elseBddNode = elseBddNode2;
+          thenBddId = thenBddId2;
+          elseBddId = elseBddId2;
+        } while ((elseBddId != 0) && (bddNode != origNode) &&
+                 !((CalAddress_t)(bddNode->nextBddNode) & 01));
+      }
+    }
+  }
+  /* Fix the handles to the nodes being moved */
+  for (id = 1; id <= bddManager->numVars; id++){
+    /* Fix the varBdd array */
+  }
+/* Need to update the handles to the nodes being moved */
+  if (bddManager->pipelineState == CREATE){
+    /* There are some results computed in pipeline */
+    CalBddReorderFixProvisionalNodesAfterReallocation(bddManager);
+  }
+  
+  /* Fix the user BDDs */
+  CalBddReorderFixUserBddPtrsAfterReallocation(bddManager);
+
+  /* Fix the association */
+  CalReorderAssociationFixAfterReallocation(bddManager);
+
+  Cal_Assert(CalCheckAssoc(bddManager));
+  
+
+  /* Update the next pointers */
+  /* Since the pages for the ids are distributed in the uniform
+     manner, we can scan the pages on id by id basis without any
+     disadvantage */
+  for (id = 1; id <= bddManager->numVars; id++){
+    nodeManager = uniqueTable[id]->nodeManager;
+    freeNodeList = Cal_Nil(CalBddNode_t);
+    for (i=0; i<nodeManager->numPages; i++){
+      page = nodeManager->pageList[i];
+      for (bddNode = (CalBddNode_t*) page, numNode = 0;
+           numNode < NUM_NODES_PER_PAGE; numNode++, bddNode += 1){
+        /* If the node is not useful, put it in the free list */
+        if ((bddNode->elseBddId == 0) || (bddNode->elseBddNode == 0)){
+          bddNode->nextBddNode = freeNodeList;
+          freeNodeList = bddNode;
+        }
+      }
+    }
+    nodeManager->freeNodeList = freeNodeList;
+  }
+  /* We should put the unused pages in the free page list */
+  pageSegment = pageManager->pageSegmentArray[numUsefulSegments-1];
+  for (pageCounter = numUsefulPagesInLastSegment;
+       pageCounter < pageSegment->numPages ; pageCounter++){
+    CalPageManagerFreePage(pageManager, pageSegment[pageCounter]);
+  }
+  /* We have to free up the unnecessary page segments;*/
+  for (i = numUsefulSegments; i < pageManager->numSegments; i++){
+    free(pageManager->pageSegmentArray[i]);
+    pageManager->pageSegmentArray[i] = 0;
+  }
+  pageManager->numSegments = numUsefulSegments;
+}
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalAlignCollisionChains(Cal_BddManager_t *bddManager)
+{
+  /* First find out the pages corresponding to each variable */
+  Cal_Address_t ***pageListArray = Cal_MemAlloc(Cal_Address_t **,
+                                                bddManager->numVars+1);
+  for (id = 1; id <= bddManager->numVars; id++){
+    nodeManager = bddManager->nodeManagerArray[id];
+    numPages = nodeManager->numPages;
+    pageListArray[id] = Cal_MemAlloc(Cal_Address_t *, numPages);
+    for (i=0; i<numPages; i++){
+      pageListArray[id][i] = nodeManager->pageList[i];
+    }
+  }
+    
+  /* Bottom up traversal */
+  for (index = bddManager->numVars-1; index >= 0; index--){
+    id = bddManager->indexToId[index];
+    uniqueTableForId = bddManager->uniqueTable[id];
+    nodeManager = uniqueTableForId->nodeManager;
+    /* Calculate the collision lengths */
+    collisionLengthArray = CalculateCollisionLength(uniqueTableForId);
+    /* Initialize the bins */
+    bins = uniqueTableForId->bins;
+    numBins = uniqueTableForId->numBins;
+    numNodes = 0;
+    pageNum = 0;
+    for (i=0; i<numBins; i++){
+      numNodes += collisionLengthArray[i];
+      if (numNodes < NUM_NODES_PER_PAGE){
+        nodePointer[i] += collisionLengthArray[i];
+      }
+      else if (numNodes == NUM_NODES_PER_PAGE){
+        nodePointer[i] = pageListArray[id][++pageNum];
+        numNodes = 0;
+      }
+      else {
+        /* put the rest of the nodes from this page in a free list */
+        nodePointer[i]->nextBddNode = nodeManager->freeNodeList;
+        nodeManager->freeNodeList = nodePointer;
+        nodePointer[i] = pageListArray[id][++pageNum]+collisionLengthArray[i];
+        numNodes = collisionLengthArray[i];
+      }
+    }
+  }
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReallocateNodes(Cal_BddManager_t *bddManager)
+{
+  int i;
+  int index;
+  CalNodeManager_t *nodeManager;
+  CalPageManager_t *pageManager;
+  int numSegments;
+  CalAddress_t **pageSegmentArray;
+  
+  pageManager = bddManager->pageManager2;
+  numSegments = pageManager->numSegments;
+  pageSegmentArray = pageManager->pageSegmentArray;
+  
+  /* Reinitialize the page manager */
+  pageManager->totalNumPages = 0;
+  pageManager->numSegments = 0;
+  pageManager->maxNumSegments = MAX_NUM_SEGMENTS;
+  pageManager->pageSegmentArray 
+      = Cal_MemAlloc(CalAddress_t *, pageManager->maxNumSegments);
+  pageManager->freePageList = Cal_Nil(CalAddress_t);
+  
+  /* Do a bottom up traversal */
+
+  for (index = bddManager->numVars-1; index >= 0; index--){
+    int id;
+    CalHashTable_t *uniqueTableForId;
+    int numPagesRequired, newSizeIndex;
+    CalBddNode_t *bddNode, *dupNode, *thenNode, *elseNode, **oldBins;
+    long hashValue, oldNumBins;
+    
+    id = bddManager->indexToId[index];
+    uniqueTableForId = bddManager->uniqueTable[id];
+    nodeManager = bddManager->nodeManagerArray[id];
+    oldBins = uniqueTableForId->bins;
+    oldNumBins = uniqueTableForId->numBins;
+    nodeManager->freeNodeList = Cal_Nil(CalBddNode_t);
+    nodeManager->numPages = 0;
+    numPagesRequired =
+        uniqueTableForId->numEntries/NUM_NODES_PER_PAGE;
+    nodeManager->maxNumPages =
+        2*(numPagesRequired ? numPagesRequired : 1);
+    Cal_MemFree(nodeManager->pageList);
+    nodeManager->pageList = Cal_MemAlloc(CalAddress_t *,
+                                         nodeManager->maxNumPages); 
+    /* Create the new set of bins */
+    newSizeIndex =
+        CeilLog2(uniqueTableForId->numEntries/HASH_TABLE_DEFAULT_MAX_DENSITY);
+    if (newSizeIndex < HASH_TABLE_DEFAULT_SIZE_INDEX){
+      newSizeIndex = HASH_TABLE_DEFAULT_SIZE_INDEX;
+    }
+    uniqueTableForId->sizeIndex = newSizeIndex;
+    uniqueTableForId->numBins =  TABLE_SIZE(uniqueTableForId->sizeIndex);
+    uniqueTableForId->maxCapacity =
+        uniqueTableForId->numBins * HASH_TABLE_DEFAULT_MAX_DENSITY; 
+    
+    uniqueTableForId->bins = Cal_MemAlloc(CalBddNode_t *,
+                                          uniqueTableForId->numBins); 
+    memset((char *)uniqueTableForId->bins, 0, 
+           uniqueTableForId->numBins*sizeof(CalBddNode_t *)); 
+    for (i=0; i<oldNumBins; i++){
+      for (bddNode = oldBins[i]; bddNode; bddNode = bddNode->nextBddNode){ 
+        CalNodeManagerAllocNode(nodeManager, dupNode);
+        thenNode = bddNode->thenBddNode;
+        CalBddNodeIsForwardedTo(thenNode);
+        Cal_Assert(thenNode);
+        Cal_Assert(!CalBddNodeIsForwarded(thenNode));
+        elseNode = bddNode->elseBddNode;
+        CalBddNodeIsForwardedTo(elseNode);
+        Cal_Assert(elseNode);
+        Cal_Assert(!CalBddNodeIsForwarded(CAL_BDD_POINTER(elseNode)));
+        Cal_Assert(bddManager->idToIndex[bddNode->thenBddId] <
+                   bddManager->idToIndex[thenNode->thenBddId]); 
+        Cal_Assert(bddManager->idToIndex[bddNode->thenBddId] <
+                   bddManager->idToIndex[CAL_BDD_POINTER(elseNode)->thenBddId]);
+        dupNode->thenBddNode = thenNode;
+        dupNode->elseBddNode = elseNode;
+        dupNode->thenBddId = bddNode->thenBddId;
+        dupNode->elseBddId = bddNode->elseBddId;
+        hashValue = CalDoHash2(thenNode, elseNode, uniqueTableForId);
+        dupNode->nextBddNode = uniqueTableForId->bins[hashValue];
+        uniqueTableForId->bins[hashValue] = dupNode;
+        bddNode->thenBddNode = dupNode;
+        bddNode->elseBddNode = (CalBddNode_t *)0;
+        bddNode->thenBddId = id;
+        Cal_Assert(bddManager->idToIndex[dupNode->thenBddId] <
+                   bddManager->idToIndex[thenNode->thenBddId]); 
+        Cal_Assert(bddManager->idToIndex[dupNode->thenBddId] <
+                   bddManager->idToIndex[CAL_BDD_POINTER(elseNode)->thenBddId]);
+      }
+    }
+    Cal_MemFree(oldBins);
+    CalBddIsForwardedTo(bddManager->varBdds[id]);
+  }
+
+  if (bddManager->pipelineState == CREATE){
+    /* There are some results computed in pipeline */
+    CalBddReorderFixProvisionalNodes(bddManager);
+  }
+  
+  /* Fix the user BDDs */
+  CalBddReorderFixUserBddPtrs(bddManager);
+
+  /* Fix the association */
+  CalReorderAssociationFix(bddManager);
+
+  Cal_Assert(CalCheckAssoc(bddManager));
+  
+  /* Free the page manager related stuff*/
+  for(i = 0; i < numSegments; i++){
+    free(pageSegmentArray[i]);
+  }
+  Cal_MemFree(pageSegmentArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddExchangeAux(Cal_BddManager_t *bddManager, CalBddNode_t *f,
+               int id, int nextId)
+{
+  CalBddNode_t *f0, *f1;
+  CalBddNode_t *f00, *f01, *f10, *f11;
+  CalBddNode_t *newF0, *newF1;
+  int f0Found, f1Found;
+  int fIndex;
+  
+  f0 = f->elseBddNode;
+  f1 = f->thenBddNode;
+
+  if (CAL_BDD_POINTER(f0)->thenBddId == nextId){
+    f00 = BddNodeGetElseBddNode(f0);
+    f01 = BddNodeGetThenBddNode(f0);
+  }
+  else {
+    f00 = f01 = f0;
+  }
+  if (CAL_BDD_POINTER(f1)->thenBddId == nextId){
+    f10 = BddNodeGetElseBddNode(f1);
+    f11 = BddNodeGetThenBddNode(f1);
+  }
+  else {
+    f10 = f11 = f1;
+  }
+  
+  if (f00 == f10){
+    newF0 = f00;
+    f0Found = 1;
+  }
+  else{
+    f0Found = UniqueTableForIdFindOrAdd(bddManager,
+                                        bddManager->uniqueTable[id], f10,
+                                        f00, &newF0);
+  }
+  BddNodeIcrRefCount(newF0);
+  if (f01 == f11){
+    newF1 = f11;
+    f1Found = 1;
+  }
+  else{
+    f1Found = UniqueTableForIdFindOrAdd(bddManager,
+                                        bddManager->uniqueTable[id], f11,
+                                        f01, &newF1);
+  }
+  BddNodeIcrRefCount(newF1);
+
+  f->thenBddId = nextId;
+  f->elseBddNode = newF0;
+  f->thenBddNode = newF1;
+
+  fIndex = bddManager->idToIndex[id];
+  Cal_Assert(fIndex <
+             bddManager->idToIndex[CAL_BDD_POINTER(f00)->thenBddId]);
+  Cal_Assert(fIndex <
+             bddManager->idToIndex[CAL_BDD_POINTER(f10)->thenBddId]);
+  Cal_Assert(fIndex <
+             bddManager->idToIndex[CAL_BDD_POINTER(f01)->thenBddId]);
+  Cal_Assert(fIndex <
+             bddManager->idToIndex[CAL_BDD_POINTER(f11)->thenBddId]);
+  Cal_Assert(CAL_BDD_POINTER(f00)->thenBddId != nextId);
+  Cal_Assert(CAL_BDD_POINTER(f01)->thenBddId != nextId);
+  Cal_Assert(CAL_BDD_POINTER(f10)->thenBddId != nextId);
+  Cal_Assert(CAL_BDD_POINTER(f11)->thenBddId != nextId);
+  
+  if (!f0Found){
+    BddNodeIcrRefCount(f00);
+    BddNodeIcrRefCount(f10);
+  }
+
+  if (!f1Found){
+    BddNodeIcrRefCount(f01);
+    BddNodeIcrRefCount(f11);
+  }
+
+  BddNodeDcrRefCount(f0);
+  BddNodeDcrRefCount(f1);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static int
+CheckValidityOfNodes(Cal_BddManager_t *bddManager, long id)
+{
+#ifndef NDEBUG
+  CalHashTable_t *table = bddManager->uniqueTable[id];
+  int i;
+  CalBddNode_t *bddNode;
+  int index = bddManager->idToIndex[id];
+  for(i = 0; i < table->numBins; ++i){
+    for (bddNode = table->bins[i]; bddNode; bddNode = bddNode->nextBddNode){
+      int thenIndex = bddManager->idToIndex[bddNode->thenBddNode->thenBddId];
+      int elseIndex =
+	bddManager->idToIndex[CAL_BDD_POINTER(bddNode->elseBddNode)->thenBddId]; 
+      assert((thenIndex > index) && (elseIndex > index));
+    }
+  }
+#endif
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+SweepVarTable(Cal_BddManager_t *bddManager, long id)
+{
+  CalHashTable_t *table = bddManager->uniqueTable[id];
+  long numNodesFreed, oldNumEntries;
+  CalBddNode_t **ptr, *bddNode;
+  int i;
+  
+  oldNumEntries = table->numEntries;
+  for(i = 0; i < table->numBins; ++i){
+    for (ptr = &table->bins[i], bddNode = *ptr; bddNode;
+         bddNode = *ptr){
+      if (bddNode->elseBddId == 0){
+        *ptr = bddNode->nextBddNode;
+        CalNodeManagerFreeNode(nodeManager, bddNode);
+        BddNodeDcrRefCount(bddNode->thenBddNode);
+        BddNodeDcrRefCount(bddNode->elseBddNode);
+        table->numEntries--;
+      }
+      else{
+        ptr = &bddNode->nextBddNode;
+      }
+    }
+  }
+  numNodesFreed = oldNumEntries - table->numEntries;
+  bddManager->numNodes -= numNodesFreed;
+  bddManager->numNodesFreed += numNodesFreed;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddExchange(Cal_BddManager_t *bddManager, long id)
+{
+  Cal_BddId_t  nextId;
+  CalBddNode_t **ptr, *bddNode, *nodeList;
+  CalHashTable_t *table, *nextTable;
+  Cal_BddIndex_t index, nextIndex;
+  int i;
+  CalBddNode_t  *f1, *f2;
+  CalAssociation_t *p;
+  CalNodeManager_t *nodeManager;
+  
+  index = bddManager->idToIndex[id];
+  nextIndex = index+1;
+  nextId = bddManager->indexToId[nextIndex];
+
+  if (CalTestInteract(bddManager, id, nextId)){
+    bddManager->numSwaps++;
+    nodeManager = bddManager->nodeManagerArray[id];
+    table = bddManager->uniqueTable[id];
+    nextTable = bddManager->uniqueTable[nextId];
+    nodeList = (CalBddNode_t*)0;
+    for(i = 0; i < table->numBins; i++){
+      for (ptr = &table->bins[i], bddNode = *ptr; bddNode;
+           bddNode = *ptr){
+        Cal_Assert(bddNode->elseBddId != 0);
+        f1 = bddNode->elseBddNode;
+        f2 = bddNode->thenBddNode;
+        if ((CAL_BDD_POINTER(f1)->thenBddId != nextId) &&
+            (CAL_BDD_POINTER(f2)->thenBddId != nextId)){ 
+          ptr = &bddNode->nextBddNode;
+        }
+        else{
+          *ptr = bddNode->nextBddNode;
+          bddNode->nextBddNode = nodeList;
+          nodeList = bddNode;
+        }
+      }
+    }
+    for (bddNode = nodeList; bddNode ; bddNode = nodeList){
+      BddExchangeAux(bddManager, bddNode, id, nextId);
+      nodeList = bddNode->nextBddNode;
+      HashTableAddDirect(nextTable, bddNode);
+      table->numEntries--;
+    }
+    SweepVarTable(bddManager, nextId);
+  }
+  else {
+    bddManager->numTrivialSwaps++;
+  }
+  
+  CalFixupAssoc(bddManager, id, nextId, bddManager->tempAssociation);
+  for(p = bddManager->associationList; p; p = p->next){
+    CalFixupAssoc(bddManager, id, nextId, p);
+  }
+
+  bddManager->idToIndex[id] = nextIndex;
+  bddManager->idToIndex[nextId] = index;
+  bddManager->indexToId[index] = nextId;
+  bddManager->indexToId[nextIndex] = id;
+
+  Cal_Assert(CheckValidityOfNodes(bddManager, id));
+  Cal_Assert(CheckValidityOfNodes(bddManager, nextId));
+  Cal_Assert(CalCheckAssoc(bddManager));
+#ifdef _CAL_VERBOSE
+  /*fprintf(stdout,"Variable order after swap:\n");*/
+  for (i=0; i<bddManager->numVars; i++){
+    fprintf(stdout, "%3d ", bddManager->indexToId[i]);
+  }
+  fprintf(stdout, "%8d\n", bddManager->numNodes);
+#endif
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddExchangeVarBlocks(Cal_BddManager_t *bddManager, Cal_Block parent,
+                     long blockIndex)
+{
+  Cal_Block b1, b2, temp;
+  long i, j, k, l, firstBlockWidth, secondBlockWidth;
+
+  b1 = parent->children[blockIndex];
+  b2 = parent->children[blockIndex+1];
+  /* This slides the blocks past each other in a kind of interleaving */
+  /* fashion. */
+  firstBlockWidth = b1->lastIndex - b1->firstIndex;
+  secondBlockWidth = b2->lastIndex - b2->firstIndex;
+  
+  for (i=0; i <= firstBlockWidth + secondBlockWidth; i++){
+    j = i - firstBlockWidth;
+    if (j < 0) j=0;
+    k = ((i > secondBlockWidth) ? secondBlockWidth : i);
+    while (j <= k) {
+	  l = b2->firstIndex + j - i + j;
+	  BddExchange(bddManager, bddManager->indexToId[l-1]);
+	  ++j;
+	}
+  }
+  CalBddBlockDelta(b1, secondBlockWidth+1);
+  CalBddBlockDelta(b2, -(firstBlockWidth+1));
+  temp = parent->children[blockIndex];
+  parent->children[blockIndex] = parent->children[blockIndex+1];
+  parent->children[blockIndex+1] = temp;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static int
+BddReorderWindow2(Cal_BddManager_t *bddManager, Cal_Block block, long i)
+{
+  long size, bestSize;
+
+  /* 1 2 */
+  bestSize = bddManager->numNodes;
+  BddExchangeVarBlocks(bddManager, block, i);
+  /* 2 1 */
+  size = bddManager->numNodes;
+  if (size < bestSize) return (1);
+  BddExchangeVarBlocks(bddManager, block, i);
+  return (0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static int
+BddReorderWindow3(Cal_BddManager_t *bddManager, Cal_Block block, long i)
+{
+  int best;
+  long size, bestSize;
+  long origSize;
+  
+  origSize = bddManager->numNodes;
+  best = 0;
+  /* 1 2 3 */
+  bestSize = bddManager->numNodes;
+  BddExchangeVarBlocks(bddManager, block, i);
+  /* 2 1 3 */
+  size=bddManager->numNodes;
+  if (size < bestSize) {
+    best=1;
+    bestSize=size;
+  }
+  BddExchangeVarBlocks(bddManager, block, i+1);
+  /* 2 3 1 */
+  size=bddManager->numNodes;
+  if (size < bestSize) {
+    best=2;
+    bestSize=size;
+  }
+  BddExchangeVarBlocks(bddManager, block, i);
+  /* 3 2 1 */
+  size=bddManager->numNodes;
+  if (size <= bestSize) {
+    best=3;
+    bestSize=size;
+  }
+  BddExchangeVarBlocks(bddManager, block, i+1);
+  /* 3 1 2 */
+  size=bddManager->numNodes;
+  if (size <= bestSize) {
+    best=4;
+    bestSize=size;
+  }
+  BddExchangeVarBlocks(bddManager, block, i);
+  /* 1 3 2 */
+  size=bddManager->numNodes;
+  if (size <= bestSize) {
+    best=5;
+    bestSize=size;
+  }
+  switch (best){
+      case 0:
+        BddExchangeVarBlocks(bddManager, block, i+1);
+        break;
+      case 1:
+        BddExchangeVarBlocks(bddManager, block, i+1);
+        BddExchangeVarBlocks(bddManager, block, i);
+        break;
+      case 2:
+        BddExchangeVarBlocks(bddManager, block, i+1);
+        BddExchangeVarBlocks(bddManager, block, i);
+        BddExchangeVarBlocks(bddManager, block, i+1);
+        break;
+      case 3:
+        BddExchangeVarBlocks(bddManager, block, i);
+        BddExchangeVarBlocks(bddManager, block, i+1);
+        break;
+      case 4:
+        BddExchangeVarBlocks(bddManager, block, i);
+        break;
+      case 5:
+        break;
+  }
+  return ((best > 0) && (origSize > bestSize));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReorderStableWindow3Aux(Cal_BddManager_t *bddManager, Cal_Block block,
+                           char *levels) 
+{
+  long i;
+  int moved;
+  int anySwapped;
+
+  if (block->reorderable) {
+    for (i=0; i < block->numChildren-1; ++i) levels[i]=1;
+    do {
+	  anySwapped=0;
+	  for (i=0; i < block->numChildren-1; i++){
+	    if (levels[i]){
+#ifdef _CAL_VERBOSE
+          fprintf(stdout,"Moving block %3d -- %3d\n",
+                  bddManager->indexToId[block->children[i]-> firstIndex],
+                  bddManager->indexToId[block->children[i]->lastIndex]);
+          fflush(stdout);
+          for (j=0; j<bddManager->numVars; j++){
+            fprintf(stdout, "%3d ", bddManager->indexToId[j]);
+          }
+          fprintf(stdout, "%8d\n", bddManager->numNodes);
+#endif
+          if (i < block->numChildren-2){
+            moved = BddReorderWindow3(bddManager, block, i);
+          }
+          else{
+            moved = BddReorderWindow2(bddManager, block, i);
+          }
+          if (moved){
+		    if (i > 0) {
+              levels[i-1]=1;
+              if (i > 1)
+                levels[i-2]=1;
+            }
+		    levels[i]=1;
+		    levels[i+1]=1;
+		    if (i < block->numChildren-2){
+              levels[i+2]=1;
+              if (i < block->numChildren-3) {
+			    levels[i+3]=1;
+			    if (i < block->numChildren-4) levels[i+4]=1;
+			  }
+            }
+		    anySwapped=1;
+          }
+          else levels[i]=0;
+        }
+      }
+    } while (anySwapped);
+  }
+  for (i=0; i < block->numChildren; ++i){
+    BddReorderStableWindow3Aux(bddManager, block->children[i], levels);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReorderStableWindow3(Cal_BddManager_t *bddManager)
+{
+  char *levels;
+  levels =  Cal_MemAlloc(char, bddManager->numVars);
+  bddManager->numSwaps = 0;
+  BddReorderStableWindow3Aux(bddManager, bddManager->superBlock, levels);
+  Cal_MemFree(levels);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddSiftBlock(Cal_BddManager_t *bddManager, Cal_Block block, long
+             startPosition, double maxSizeFactor)
+{
+  long startSize;
+  long bestSize;
+  long bestPosition;
+  long currentSize;
+  long currentPosition;
+  long maxSize;
+  
+  startSize = bddManager->numNodes;
+  bestSize = startSize;
+  bestPosition = startPosition;
+  currentSize = startSize;
+  currentPosition = startPosition;
+  maxSize = maxSizeFactor*startSize;
+  if (bddManager->nodeLimit && maxSize > bddManager->nodeLimit)
+    maxSize = bddManager->nodeLimit;
+
+  /* Need to do optimization here */
+  if (startPosition > (block->numChildren >> 1)){
+    while (currentPosition < block->numChildren-1 && currentSize <= maxSize){
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+      ++currentPosition;
+      currentSize = bddManager->numNodes;
+      if (currentSize < bestSize){
+        bestSize = currentSize;
+        bestPosition=currentPosition;
+      }
+    }
+    while (currentPosition != startPosition){
+      --currentPosition;
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+    }
+    currentSize = startSize;
+    while (currentPosition && currentSize <= maxSize){
+      --currentPosition;
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+      currentSize = bddManager->numNodes;
+      if (currentSize <= bestSize){
+        bestSize = currentSize;
+        bestPosition = currentPosition;
+      }
+    }
+    while (currentPosition != bestPosition){
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+      ++currentPosition;
+    }
+  }
+  else{
+    while (currentPosition && currentSize <= maxSize){
+      --currentPosition;
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+      currentSize = bddManager->numNodes;
+      if (currentSize < bestSize){
+        bestSize = currentSize;
+        bestPosition = currentPosition;
+      }
+    }
+    while (currentPosition != startPosition){
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+      ++currentPosition;
+    }
+    currentSize = startSize;
+    while (currentPosition < block->numChildren-1 && currentSize <= maxSize){
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+      currentSize = bddManager->numNodes;
+      ++currentPosition;
+      if (currentSize <= bestSize){
+        bestSize = currentSize;
+        bestPosition = currentPosition;
+      }
+    }
+    while (currentPosition != bestPosition){
+      --currentPosition;
+      BddExchangeVarBlocks(bddManager, block, currentPosition);
+    }
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorder variables using "sift" algorithm.]
+
+  Description [Reorder variables using "sift" algorithm.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+BddReorderSiftAux(Cal_BddManager_t *bddManager, Cal_Block block,
+                     Cal_Block *toSift, double maxSizeFactor) 
+{
+  long i, j, k;
+  long width;
+  long maxWidth;
+  long widest;
+  long numVarsShifted = 0;
+  bddManager->numSwaps = 0;
+  if (block->reorderable) {
+    for (i=0; i < block->numChildren; ++i){
+      toSift[i] = block->children[i];
+    }
+    while (i &&
+           (numVarsShifted <=
+            bddManager->maxNumVarsSiftedPerReordering) &&
+           (bddManager->numSwaps <=
+            bddManager->maxNumSwapsPerReordering)){ 
+	  i--;
+      numVarsShifted++;
+	  maxWidth = 0;
+	  widest = 0;
+	  for (j=0; j <= i; ++j) {
+        for (width=0, k=toSift[j]->firstIndex; k <= toSift[j]->lastIndex; ++k){
+          width +=
+              bddManager->uniqueTable[bddManager->indexToId[k]]->numEntries; 
+        }
+        width /= toSift[j]->lastIndex - toSift[j]->firstIndex+1;
+        if (width > maxWidth) {
+		  maxWidth = width;
+		  widest = j;
+		}
+      }
+	  if (maxWidth > 1) {
+        for (j=0; block->children[j] != toSift[widest]; ++j);
+#ifdef _CAL_VERBOSE
+        fprintf(stdout,"Moving block %3d -- %3d\n",
+                bddManager->indexToId[block->children[j]-> firstIndex],
+                bddManager->indexToId[block->children[j]->lastIndex]);
+        fflush(stdout);
+        for (l=0; l<bddManager->numVars; l++){
+          fprintf(stdout, "%3d ", bddManager->indexToId[l]);
+        }
+        fprintf(stdout, "%8d\n", bddManager->numNodes);
+#endif
+        BddSiftBlock(bddManager, block, j, maxSizeFactor);
+        toSift[widest] = toSift[i];
+      }
+	  else {
+        break;
+      }
+	}
+  }
+  for (i=0; i < block->numChildren; ++i)
+    BddReorderSiftAux(bddManager, block->children[i], toSift,
+                      maxSizeFactor);  
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+BddReorderSift(Cal_BddManager_t *bddManager, double maxSizeFactor)
+{
+  Cal_Block *toSift;
+
+  toSift = Cal_MemAlloc(Cal_Block, bddManager->numVars);
+  BddReorderSiftAux(bddManager, bddManager->superBlock, toSift,
+                       maxSizeFactor); 
+  Cal_MemFree(toSift);
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the smallest integer greater than or equal to log2 of a
+  number]
+
+  Description [Returns the smallest integer greater than or equal to log2 of a
+  number (The assumption is that the number is >= 1)]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CeilLog2(int  number)
+{
+  int num, count;
+  for (num=number, count=0; num > 1; num >>= 1, count++);
+  if ((1 << count) != number) count++;
+  return count;
+}
Index: /vis_dev/glu-2.1/src/calBdd/calReorderUtil.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calReorderUtil.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calReorderUtil.c	(revision 8)
@@ -0,0 +1,617 @@
+/**CFile***********************************************************************
+
+  FileName    [calReorderUtil.c]
+
+  PackageName [cal]
+
+  Synopsis    [Some utility routines used by both breadth-first and
+  depth-first reordering techniques.]
+
+  Description []
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan   (rajeev@ic.eecs.berkeley.edu)
+               Wilsin Gosti (wilsin@ic.eecs.berkeley.edu)]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calReorderUtil.c,v 1.3 2002/09/22 00:37:04 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddReorderFixUserBddPtrs(Cal_BddManager bddManager)
+{
+  CalHashTable_t *userBddUniqueTable = bddManager->uniqueTable[0];
+  int i;
+  int numBins;
+  int rehashFlag;
+  CalBddNode_t **bins;
+  CalBddNode_t *bddNode;
+  CalBddNode_t *nextBddNode;
+  CalBddNode_t *thenBddNode;
+  CalBddNode_t *elseBddNode;
+  Cal_Bdd_t internalBdd;
+
+  numBins = userBddUniqueTable->numBins;
+  bins = userBddUniqueTable->bins;
+
+  for(i = 0; i < numBins; i++) {
+    for(bddNode = bins[i];
+        bddNode != Cal_Nil(CalBddNode_t);
+        bddNode = nextBddNode) {
+      /*
+       * Process one bddNode at a time
+       */
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      rehashFlag = 0;
+
+      thenBddNode = CalBddNodeGetThenBddNode(bddNode);
+      elseBddNode = CalBddNodeGetElseBddNode(bddNode);
+      CalBddNodeGetThenBdd(bddNode, internalBdd);
+      if (CalBddIsForwarded(internalBdd)) {
+        CalBddForward(internalBdd);
+        CalBddNodePutThenBdd(bddNode, internalBdd);
+        rehashFlag = 1;
+      }
+      Cal_Assert(CalBddIsForwarded(internalBdd) == 0);
+      /*Cal_Assert(!CalBddIsRefCountZero(internalBdd));*/
+      /*
+       * Rehash if necessary
+       */
+      if (rehashFlag) {
+        CalUniqueTableForIdRehashNode(userBddUniqueTable, bddNode,
+                                      thenBddNode, elseBddNode);
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+int
+CalCheckAllValidity(Cal_BddManager bddManager)
+{
+  int id;
+  for(id = 0; id <= bddManager->numVars; id++){
+    CalCheckValidityOfNodesForId(bddManager, id);
+  }
+  CalCheckAssociationValidity(bddManager);
+  if (bddManager->pipelineState == CREATE){
+    CalCheckPipelineValidity(bddManager);
+  }
+  CalCheckRefCountValidity(bddManager);
+  CalCheckCacheTableValidity(bddManager);
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+int
+CalCheckValidityOfNodesForId(Cal_BddManager bddManager, int id)
+{
+  int i, numBins;
+  CalHashTable_t *uniqueTableForId;
+  CalBddNode_t *bddNode, *nextBddNode;
+  Cal_Bdd_t thenBdd, elseBdd;
+  
+  uniqueTableForId = bddManager->uniqueTable[id];
+  Cal_Assert(uniqueTableForId->startNode.nextBddNode == NULL);
+  numBins = uniqueTableForId->numBins;
+  for (i = 0; i < numBins; i++){
+    for (bddNode = uniqueTableForId->bins[i]; bddNode;
+         bddNode = nextBddNode){
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalCheckValidityOfANode(bddManager, bddNode, id);
+      CalBddNodeGetThenBdd(bddNode, thenBdd);
+      CalBddNodeGetElseBdd(bddNode, elseBdd);
+      Cal_Assert(CalDoHash2(CalBddGetBddNode(thenBdd),
+                            CalBddGetBddNode(elseBdd), 
+                            uniqueTableForId) == i);
+    }
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+int
+CalCheckValidityOfNodesForWindow(Cal_BddManager bddManager,
+                                 Cal_BddIndex_t index, int numLevels)
+{
+  int i, numBins, j;
+  CalHashTable_t *uniqueTableForId;
+  CalBddNode_t *bddNode, *nextBddNode;
+  Cal_Bdd_t thenBdd, elseBdd;
+
+  for (i = 0; i < numLevels; i++){
+    uniqueTableForId =
+        bddManager->uniqueTable[bddManager->indexToId[index+i]]; 
+    numBins = uniqueTableForId->numBins;
+    for (j = 0; j < numBins; j++){
+      for (bddNode = uniqueTableForId->bins[j]; bddNode;
+           bddNode = nextBddNode){
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        Cal_Assert(CalBddNodeIsForwarded(bddNode) == 0);
+        CalBddNodeGetThenBdd(bddNode, thenBdd);
+        CalBddNodeGetElseBdd(bddNode, elseBdd);
+        Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+        Cal_Assert(CalBddIsForwarded(elseBdd) == 0);
+        Cal_Assert(CalDoHash2(CalBddGetBddNode(thenBdd),
+                              CalBddGetBddNode(elseBdd), 
+                             uniqueTableForId) == j);
+      }
+    }
+    for (bddNode = uniqueTableForId->startNode.nextBddNode; bddNode;
+         bddNode = nextBddNode){ 
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodeGetThenBdd(bddNode, thenBdd);
+      Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+    }
+  }
+  return 1;
+}
+
+
+  
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+int
+CalCheckValidityOfANode(Cal_BddManager_t *bddManager, CalBddNode_t
+                     *bddNode, int id) 
+{
+  Cal_Bdd_t thenBdd, elseBdd, thenBdd_, elseBdd_, bdd;
+  if (id != 0){
+    /* id = 0 corresponds to the constants and the user BDDs */
+    Cal_Assert(bddManager->idToIndex[id] <
+               bddManager->idToIndex[bddNode->thenBddId]);   
+    Cal_Assert(bddManager->idToIndex[id] < 
+               bddManager->idToIndex[bddNode->elseBddId]);
+  }
+  Cal_Assert(!CalBddNodeIsForwarded(bddNode));
+  Cal_Assert(!CalBddNodeIsRefCountZero(bddNode));
+  CalBddNodeGetThenBdd(bddNode, thenBdd);
+  CalBddNodeGetElseBdd(bddNode, elseBdd);
+  Cal_Assert(CalBddIsForwarded(thenBdd) == 0);
+  Cal_Assert(CalBddIsForwarded(elseBdd) == 0);
+  Cal_Assert(!CalBddIsRefCountZero(thenBdd));
+  Cal_Assert(!CalBddIsRefCountZero(elseBdd));
+  /* Make sure that the then and else bdd nodes are part of the
+     respective unique tables */
+  if (bddNode->thenBddId != 0){
+    CalBddGetThenBdd(thenBdd, thenBdd_);
+    CalBddGetElseBdd(thenBdd, elseBdd_);
+    Cal_Assert(
+      CalUniqueTableForIdLookup(bddManager,
+                                bddManager->uniqueTable[bddNode->thenBddId],  
+                                thenBdd_, elseBdd_, &bdd));
+  }
+  if (bddNode->elseBddId != 0){
+    CalBddGetThenBdd(elseBdd, thenBdd_);
+    CalBddGetElseBdd(elseBdd, elseBdd_);
+    Cal_Assert(
+      CalUniqueTableForIdLookup(bddManager,
+                                bddManager->uniqueTable[bddNode->elseBddId],
+                                thenBdd_, elseBdd_, &bdd));
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalCheckRefCountValidity(Cal_BddManager_t *bddManager)
+{
+  int i, numBins, index;
+  CalHashTable_t *uniqueTableForId;
+  CalBddNode_t *bddNode, *nextBddNode;
+  Cal_Bdd_t thenBdd, elseBdd, internalBdd;
+  CalAssociation_t *assoc, *nextAssoc;
+  
+  /* First traverse the user BDDs */
+  uniqueTableForId = bddManager->uniqueTable[0];
+  numBins = uniqueTableForId->numBins;
+  for (i = 0; i < numBins; i++){
+    for (bddNode = uniqueTableForId->bins[i]; bddNode;
+         bddNode = nextBddNode){
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodeGetThenBdd(bddNode, internalBdd);
+      CalBddDcrRefCount(internalBdd);
+    }
+  }
+      /* Traverse the associations */
+  
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    for (i=1; i <= bddManager->numVars; i++){
+        if (CalBddGetBddId(assoc->varAssociation[i]) != CAL_BDD_NULL_ID){
+            CalBddDcrRefCount(assoc->varAssociation[i]);
+        }
+    }
+  }
+  /* temporary association */
+  assoc = bddManager->tempAssociation;
+  for (i=1; i <= bddManager->numVars; i++){
+      if (CalBddGetBddId(assoc->varAssociation[i]) != CAL_BDD_NULL_ID){
+          CalBddDcrRefCount(assoc->varAssociation[i]);
+      }
+  }
+
+  
+  /* Now traverse all the nodes in order */
+  for (index = 0; index < bddManager->numVars; index++){
+    uniqueTableForId = bddManager->uniqueTable[bddManager->indexToId[index]];
+    numBins = uniqueTableForId->numBins;
+    for (i = 0; i < numBins; i++){
+      for (bddNode = uniqueTableForId->bins[i]; bddNode;
+           bddNode = nextBddNode){
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        CalBddNodeGetThenBdd(bddNode, thenBdd);
+        CalBddNodeGetElseBdd(bddNode, elseBdd);
+        CalBddDcrRefCount(thenBdd);
+        CalBddDcrRefCount(elseBdd);
+      }
+    }
+  }
+
+  /* All the reference count must be zero  or max */
+  for (index = 0; index < bddManager->numVars; index++){
+    uniqueTableForId = bddManager->uniqueTable[bddManager->indexToId[index]];
+    numBins = uniqueTableForId->numBins;
+    for (i = 0; i < numBins; i++){
+      for (bddNode = uniqueTableForId->bins[i]; bddNode;
+           bddNode = nextBddNode){
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        /* If the pipeline execution is going on, the following
+           assertion will not hold */
+        if (bddManager->pipelineState != CREATE){
+          Cal_Assert(CalBddNodeIsRefCountZero(bddNode) ||
+                     CalBddNodeIsRefCountMax(bddNode));
+        }
+      }
+    }
+  }
+
+  /* Put back the ref count */
+  /* traverse all the nodes in order */
+  for (index = 0; index < bddManager->numVars; index++){
+    uniqueTableForId = bddManager->uniqueTable[bddManager->indexToId[index]];
+    numBins = uniqueTableForId->numBins;
+    for (i = 0; i < numBins; i++){
+      for (bddNode = uniqueTableForId->bins[i]; bddNode;
+           bddNode = nextBddNode){
+        nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+        CalBddNodeGetThenBdd(bddNode, thenBdd);
+        CalBddNodeGetElseBdd(bddNode, elseBdd);
+        CalBddIcrRefCount(thenBdd);
+        CalBddIcrRefCount(elseBdd);
+      }
+    }
+  }
+      /* Traverse the associations */
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    for (i=1; i <= bddManager->numVars; i++){
+        if (CalBddGetBddId(assoc->varAssociation[i]) != CAL_BDD_NULL_ID){
+            CalBddIcrRefCount(assoc->varAssociation[i]);
+        }
+    }
+  }
+  /* temporary association */
+  assoc = bddManager->tempAssociation;
+  for (i=1; i <= bddManager->numVars; i++){
+      if (CalBddGetBddId(assoc->varAssociation[i]) != CAL_BDD_NULL_ID){
+          CalBddIcrRefCount(assoc->varAssociation[i]);
+      }
+  }
+
+  /* Traverse the user BDDs */
+  uniqueTableForId = bddManager->uniqueTable[0];
+  numBins = uniqueTableForId->numBins;
+  for (i = 0; i < numBins; i++){
+    for (bddNode = uniqueTableForId->bins[i]; bddNode;
+         bddNode = nextBddNode){
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      CalBddNodeGetThenBdd(bddNode, internalBdd);
+      CalBddIcrRefCount(internalBdd);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+int
+CalCheckAssoc(Cal_BddManager_t *bddManager)
+{
+  CalAssociation_t *assoc, *nextAssoc;
+  int i;
+  int expectedLastBddIndex, bddIndex;
+
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    expectedLastBddIndex = -1;
+    for (i=1; i <= bddManager->numVars; i++){
+      if (CalBddIsBddNull(bddManager, assoc->varAssociation[i]) == 0){
+        bddIndex = bddManager->idToIndex[i];
+        if (expectedLastBddIndex < bddIndex){
+          expectedLastBddIndex = bddIndex;
+        }
+      }
+    }
+    Cal_Assert(expectedLastBddIndex == assoc->lastBddIndex);
+  }
+  /* fix temporary association */
+  assoc = bddManager->tempAssociation;
+  expectedLastBddIndex = -1;
+  for (i=1; i <= bddManager->numVars; i++){
+    if (CalBddIsBddNull(bddManager, assoc->varAssociation[i]) == 0){
+      bddIndex = bddManager->idToIndex[i];
+      if (expectedLastBddIndex < bddIndex){
+        expectedLastBddIndex = bddIndex;
+      }
+    }
+  }
+  Cal_Assert(expectedLastBddIndex == assoc->lastBddIndex);
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalFixupAssoc(Cal_BddManager_t *bddManager, long id1, long id2,
+           CalAssociation_t *assoc)
+{
+  if (assoc->lastBddIndex == -1) return;
+  /* Variable with id1 is moving down a spot. */
+  if ((CalBddIsBddNull(bddManager, assoc->varAssociation[id1]) == 0)
+      && (assoc->lastBddIndex == bddManager->idToIndex[id1])){
+    assoc->lastBddIndex++;
+  }
+  else if ((CalBddIsBddNull(bddManager, assoc->varAssociation[id1])) &&
+           (CalBddIsBddNull(bddManager, assoc->varAssociation[id2]) ==
+            0) && 
+  (assoc->lastBddIndex == bddManager->idToIndex[id2])){
+    assoc->lastBddIndex--;
+  }
+  Cal_Assert((assoc->lastBddIndex >= 0) && (assoc->lastBddIndex <=
+                                           CAL_BDD_CONST_INDEX));
+   
+}
+/**Function********************************************************************
+
+  Synopsis           [Fixes the cofactors of the nodes belonging to
+  the given index.]
+
+  Description        [This routine traverses the unique table and for
+  each node, looks at the then and else cofactors. If needed fixes the
+  cofactors.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddReorderFixCofactors(Cal_BddManager bddManager, Cal_BddId_t id)
+{
+  CalHashTable_t *uniqueTableForId =
+      bddManager->uniqueTable[id];
+  CalBddNode_t *bddNode, *nextBddNode, **bins, *thenBddNode, *elseBddNode;
+  Cal_Bdd_t f0, f1;
+  long numBins;
+  int i, rehashFlag;
+  
+  numBins = uniqueTableForId->numBins;
+  bins = uniqueTableForId->bins;
+
+  for(i = 0; i < numBins; i++) {
+    for(bddNode = bins[i];
+        bddNode != Cal_Nil(CalBddNode_t);
+        bddNode = nextBddNode) {
+      nextBddNode = CalBddNodeGetNextBddNode(bddNode);
+      /*
+       * Process one bddNode at a time
+       */
+      /*
+      ** Because we have kept all the forwarding nodes in the list,
+      ** this should not be a forwarding node.
+      */
+      Cal_Assert(CalBddNodeIsForwarded(bddNode) == 0);
+      Cal_Assert(CalBddNodeIsRefCountZero(bddNode) == 0);
+      thenBddNode = CalBddNodeGetThenBddNode(bddNode);
+      elseBddNode = CalBddNodeGetElseBddNode(bddNode);
+      rehashFlag = 0;
+      CalBddNodeGetThenBdd(bddNode, f1);
+      CalBddNodeGetElseBdd(bddNode, f0);
+      if (CalBddIsForwarded(f1)) {
+        CalBddForward(f1);
+        CalBddNodePutThenBdd(bddNode, f1);
+        rehashFlag = 1;
+      }
+      Cal_Assert(CalBddIsForwarded(f1) == 0);
+      if (CalBddIsForwarded(f0)) {
+        CalBddForward(f0);
+        CalBddNodePutElseBdd(bddNode, f0); 
+        rehashFlag = 1;
+      }
+      Cal_Assert(CalBddIsForwarded(f0) == 0);
+      /* Rehash if necessary */
+      if (rehashFlag) {
+        CalUniqueTableForIdRehashNode(uniqueTableForId, bddNode, thenBddNode,
+                                      elseBddNode);
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+CalBddReorderReclaimForwardedNodes(Cal_BddManager bddManager, int
+                                startIndex, int endIndex)
+{
+  Cal_BddIndex_t index;
+  Cal_BddId_t id;
+  CalHashTable_t *uniqueTableForId;
+  CalNodeManager_t *nodeManager;
+  
+  for(index = startIndex; index <= endIndex; index++){
+    id = bddManager->indexToId[index];
+    uniqueTableForId = bddManager->uniqueTable[id];
+    nodeManager = uniqueTableForId->nodeManager;
+    uniqueTableForId->endNode->nextBddNode = nodeManager->freeNodeList;
+    nodeManager->freeNodeList = uniqueTableForId->startNode.nextBddNode;
+    uniqueTableForId->endNode = &(uniqueTableForId->startNode);
+    uniqueTableForId->startNode.nextBddNode = NULL;
+  }
+  bddManager->numForwardedNodes = 0;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/calBdd/calTerminal.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calTerminal.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calTerminal.c	(revision 8)
@@ -0,0 +1,421 @@
+/**CFile***********************************************************************
+
+  FileName    [calTerminal.c]
+
+  PackageName [cal]
+
+  Synopsis    [Contains the terminal function for various BDD operations.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu) and
+               Jagesh V. Sanghavi (sanghavi@eecs.berkeley.edu]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calTerminal.c,v 1.1.1.2 1997/02/12 21:11:30 hsv Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpAnd(Cal_BddManager_t * bddManager,
+         Cal_Bdd_t  F,
+         Cal_Bdd_t  G,
+         Cal_Bdd_t * resultBddPtr)
+{
+  if(CalBddIsBddConst(F)){
+    if(CalBddIsBddOne(bddManager, F)){
+      *resultBddPtr = G;
+    }
+    else{
+      *resultBddPtr = F;
+    }
+    return 1;
+  }
+  else if(CalBddIsBddConst(G)){
+    if(CalBddIsBddOne(bddManager, G)){
+      *resultBddPtr = F;
+    }
+    else{
+      *resultBddPtr = G;
+    }
+    return 1;
+  }
+  else{
+    CalBddNode_t *bddNodeF, *bddNodeG;
+    bddNodeF = CalBddGetBddNode(F);
+    bddNodeG = CalBddGetBddNode(G);
+    if((CAL_BDD_POINTER(bddNodeF) == CAL_BDD_POINTER(bddNodeG))){
+      if((CalAddress_t)bddNodeF ^ (CalAddress_t)bddNodeG){
+        *resultBddPtr = CalBddZero(bddManager);
+      }
+      else{
+        *resultBddPtr = F;
+      }
+      return 1;
+    }
+    else{
+      return 0;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpNand(Cal_BddManager_t * bddManager,
+          Cal_Bdd_t  F,
+          Cal_Bdd_t  G,
+          Cal_Bdd_t * resultBddPtr)
+{
+  if(CalBddIsBddConst(F)){
+    if(CalBddIsBddOne(bddManager, F)){
+      CalBddNot(G, *resultBddPtr);
+    }
+    else{
+      CalBddNot(F, *resultBddPtr);
+    }
+    return 1;
+  }
+  else if(CalBddIsBddConst(G)){
+    if(CalBddIsBddOne(bddManager, G)){
+      CalBddNot(F, *resultBddPtr);
+    }
+    else{
+      CalBddNot(G, *resultBddPtr);
+    }
+    return 1;
+  }
+  else{
+    CalBddNode_t *bddNodeF, *bddNodeG;
+    bddNodeF = CalBddGetBddNode(F);
+    bddNodeG = CalBddGetBddNode(G);
+    if((CAL_BDD_POINTER(bddNodeF) == CAL_BDD_POINTER(bddNodeG))){
+      if((CalAddress_t)bddNodeF ^ (CalAddress_t)bddNodeG){
+        *resultBddPtr = CalBddOne(bddManager);
+      }
+      else{
+        CalBddNot(F, *resultBddPtr);
+      }
+      return 1;
+    }
+    else{
+      return 0;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpOr(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  F,
+  Cal_Bdd_t  G,
+  Cal_Bdd_t * resultBddPtr)
+{
+  if(CalBddIsBddConst(F)){
+    if(CalBddIsBddOne(bddManager, F)){
+      *resultBddPtr = F;
+    }
+    else{
+      *resultBddPtr = G;
+    }
+    return 1;
+  }
+  else if(CalBddIsBddConst(G)){
+    if(CalBddIsBddOne(bddManager, G)){
+      *resultBddPtr = G;
+    }
+    else{
+      *resultBddPtr = F;
+    }
+    return 1;
+  }
+  else{
+    CalBddNode_t *bddNodeF, *bddNodeG;
+    bddNodeF = CalBddGetBddNode(F);
+    bddNodeG = CalBddGetBddNode(G);
+    if((CAL_BDD_POINTER(bddNodeF) == CAL_BDD_POINTER(bddNodeG))){
+      if((CalAddress_t)bddNodeF ^ (CalAddress_t)bddNodeG){
+        *resultBddPtr = CalBddOne(bddManager);
+      }
+      else{
+        *resultBddPtr = F;
+      }
+      return 1;
+    }
+    else{
+      return 0;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalOpXor(
+  Cal_BddManager_t * bddManager,
+  Cal_Bdd_t  F,
+  Cal_Bdd_t  G,
+  Cal_Bdd_t * resultBddPtr)
+{
+  if(CalBddIsBddConst(F)){
+    if(CalBddIsBddOne(bddManager, F)){
+      CalBddNot(G, *resultBddPtr);
+    }
+    else{
+      *resultBddPtr = G;
+    }
+    return 1;
+  }
+  else if(CalBddIsBddConst(G)){
+    if(CalBddIsBddOne(bddManager, G)){
+      CalBddNot(F, *resultBddPtr);
+    }
+    else{
+      *resultBddPtr = F;
+    }
+    return 1;
+  }
+  else{
+    CalBddNode_t *bddNodeF, *bddNodeG;
+    bddNodeF = CalBddGetBddNode(F);
+    bddNodeG = CalBddGetBddNode(G);
+    if((CAL_BDD_POINTER(bddNodeF) == CAL_BDD_POINTER(bddNodeG))){
+      if((CalAddress_t)bddNodeF ^ (CalAddress_t)bddNodeG){
+        *resultBddPtr = CalBddOne(bddManager);
+      }
+      else{
+        *resultBddPtr = CalBddZero(bddManager);
+      }
+      return 1;
+    }
+    else{
+      return 0;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd_t
+CalOpITE(
+  Cal_BddManager_t *bddManager,
+  Cal_Bdd_t f,
+  Cal_Bdd_t g,
+  Cal_Bdd_t h,
+  CalHashTable_t **reqQueForITE)
+{
+  CalBddNode_t *bddNode1, *bddNode2;
+  int complementFlag = 0;
+
+  /*
+   * First phase: Make substitutions 
+   * ITE(F,F,H) = ITE(F,1,H)
+   * ITE(F,F',H) = ITE(F,0,H)
+   * ITE(F,G,F) = ITE(F,G,0)
+   * ITE(F,G,F') = ITE(F,G,1)
+   */
+  bddNode1 = CalBddGetBddNode(f);
+  bddNode2 = CalBddGetBddNode(g);
+  if((CAL_BDD_POINTER(bddNode1) == CAL_BDD_POINTER(bddNode2))){
+    if((CalAddress_t)bddNode1 ^ (CalAddress_t)bddNode2){
+      g = CalBddZero(bddManager);
+    }
+    else{
+      g = CalBddOne(bddManager);
+    }
+  }
+  bddNode2 = CalBddGetBddNode(h);
+  if((CAL_BDD_POINTER(bddNode1) == CAL_BDD_POINTER(bddNode2))){
+    if((CalAddress_t)bddNode1 ^ (CalAddress_t)bddNode2){
+      h = CalBddOne(bddManager);
+    }
+    else{
+      h = CalBddZero(bddManager);
+    }
+  }
+
+  /*
+   * Second phase: Fix the complement pointers.
+   * There are 3 possible cases:
+   * F +ve G -ve: ITE(F ,G',H ) = ITE(F ,G ,H')'
+   * F -ve H +ve: ITE(F',G ,H ) = ITE(F ,H ,G)
+   * F -ve H -ve: ITE(F',G ,H') = ITE(F ,H ,G')'
+   */
+  if(CalBddIsOutPos(f)){
+    if(!CalBddIsOutPos(g)){
+      CalBddNot(g, g);
+      CalBddNot(h, h);
+      complementFlag = 1;
+    }
+  }
+  else{
+    Cal_Bdd_t tmpBdd;
+    CalBddNot(f, f);
+    if(CalBddIsOutPos(h)){
+      tmpBdd = g;
+      g = h;
+      h = tmpBdd;
+    }
+    else{
+      tmpBdd = g;
+      CalBddNot(h, g);
+      CalBddNot(tmpBdd, h);
+      complementFlag = 1;
+    }
+  }
+
+  /*
+   * Third phase: Check for the terminal cases; create new request if needed
+   * ite(1,G,H) = G
+   * ite(0,G,H) = H (impossible by construction in second phase)
+   * ite(F,G,G) = G
+   * ite(F,1,0) = F
+   * ite(F,0,1) = F'(impossible by construction in second phase)
+   */
+  if(CalBddIsBddConst(f) || CalBddIsEqual(g, h)){
+    CalBddUpdatePhase(g, complementFlag);
+    return g;
+  }
+  else if(CalBddIsBddConst(g) && CalBddIsBddConst(h)){
+    CalBddUpdatePhase(f, complementFlag);
+    return f;
+  }
+  else{
+    Cal_BddId_t bddId;
+    Cal_Bdd_t result;
+    CalBddGetMinId3(bddManager, f, g, h, bddId);
+    CalHashTableThreeFindOrAdd(reqQueForITE[bddId], f, g, h, &result);
+    CalBddUpdatePhase(result, complementFlag);
+    return result;
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/calBdd/calTest.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calTest.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calTest.c	(revision 8)
@@ -0,0 +1,1804 @@
+/**CFile***********************************************************************
+
+  FileName    [calTest.c]
+
+  PackageName [cal]
+
+  Synopsis    [This file contains the test routines for the CAL package.]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan (rajeev@eecs.berkeley.edu)
+               Jagesh Sanghavi  (sanghavi@eecs.berkeley.edu)
+               Modified and extended from the original version written
+               by David Long. 
+              ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calTest.c,v 1.6 2002/08/28 19:26:39 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+#include "time.h"
+#include <signal.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define VARS 50
+#define TT_BITS 32              /* Size of tt in bits */
+#define MAX_TT_VARS 20
+#define ITERATIONS 50         /* Number of trials to run */
+#define BITS_PER_INT 32
+#define LG_BITS_PER_INT 5
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef unsigned long TruthTable_t;       /* "Truth table" */
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static Cal_BddManager bddManager;
+static Cal_Bdd vars[VARS];
+static TruthTable_t cofactorMasks[]=
+{
+  0xffff0000,
+  0xff00ff00,
+  0xf0f0f0f0,
+  0xcccccccc,
+  0xaaaaaaaa,
+};
+static int TT_VARS;
+static CalAddress_t asDoubleSpace[2];
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+#define EncodingToBdd(table) (Decode(0, (table)))
+
+#if HAVE_STDARG_H
+static void Error(char *op, Cal_BddManager bddManager, Cal_Bdd result, Cal_Bdd expected, ...);
+#else
+static void Error();
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static double asDouble(CalAddress_t v1, CalAddress_t v2);
+static void asAddress(double n, CalAddress_t * r1, CalAddress_t * r2);
+static char * terminalIdFn(Cal_BddManager bddManager, CalAddress_t v1, CalAddress_t v2, Cal_Pointer_t pointer);
+static void PrintBdd(Cal_BddManager bddManager, Cal_Bdd f);
+static void Error(char *op, Cal_BddManager bddManager, Cal_Bdd result, Cal_Bdd expected, ...);
+static TruthTable_t Cofactor(TruthTable_t table, int var, int value);
+static Cal_Bdd Decode(int var, TruthTable_t table);
+static void TestAnd(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestNand(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestOr(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestITE(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2, Cal_Bdd f3, TruthTable_t table3);
+static void TestXor(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestIdNot(Cal_BddManager bddManager, Cal_Bdd f, TruthTable_t table);
+static void TestCompose(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestSubstitute(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2, Cal_Bdd f3, TruthTable_t table3);
+static void TestVarSubstitute(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2, Cal_Bdd f3, TruthTable_t table3);
+static void TestSwapVars(Cal_BddManager bddManager, Cal_Bdd f, TruthTable_t table);
+static void TestMultiwayAnd(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2, Cal_Bdd f3, TruthTable_t table3);
+static void TestMultiwayOr(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2, Cal_Bdd f3, TruthTable_t table3);
+static void TestMultiwayLarge(Cal_BddManager bddManager, int numBdds);
+static void TestArrayOp(Cal_BddManager bddManager, int numBdds);
+static void TestInterImpl(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestQnt(Cal_BddManager bddManager, Cal_Bdd f, TruthTable_t table, int bfZeroBFPlusDFOne, int cacheExistsResultsFlag, int cacheOrResultsFlag);
+static void TestAssoc(Cal_BddManager bddManager, Cal_Bdd f, TruthTable_t table);
+static void TestRelProd(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2, int bfZeroBFPlusDFOne, int cacheRelProdResultsFlag, int cacheAndResultsFlag, int cacheOrResultsFlag);
+static void TestReduce(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestGenCof(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestSize(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2);
+static void TestSatisfy(Cal_BddManager bddManager, Cal_Bdd f, TruthTable_t table);
+static void TestPipeline(Cal_BddManager bddManager, Cal_Bdd f1, TruthTable_t table1, Cal_Bdd f2, TruthTable_t table2, Cal_Bdd f3, TruthTable_t table3);
+static void TestDump(Cal_BddManager bddManager, Cal_Bdd f);
+static void TestReorderBlock(Cal_BddManager bddManager, TruthTable_t table, Cal_Bdd f);
+static void TestReorder(Cal_BddManager bddManager, TruthTable_t table, Cal_Bdd f);
+static void handler(int ignored);
+static void RandomTests(int numVars, int iterations);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+#ifdef TEST
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+main(int  argc, char ** argv)
+{
+  int numVars, iterations;
+  if(argc < 2){
+    iterations = ITERATIONS;
+  }
+  else{
+    iterations = atoi(argv[1]);
+  }
+  if(argc < 3){
+    TT_VARS = 5;
+  }
+  else {
+    TT_VARS = atoi(argv[2]);
+  }
+  
+  CalUtilSRandom((long)1);
+  numVars = TT_VARS;
+  RandomTests(numVars, iterations);
+  return 0;
+}
+#endif
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+asDouble(
+  CalAddress_t  v1,
+  CalAddress_t  v2)
+{
+  asDoubleSpace[0] = v1;
+  asDoubleSpace[1] = v2;
+  return (*(double *)asDoubleSpace);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+asAddress(
+  double  n,
+  CalAddress_t * r1,
+  CalAddress_t * r2)
+{
+  (*(double *)asDoubleSpace)=n;
+  *r1 = asDoubleSpace[0];
+  *r2 = asDoubleSpace[1];
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static char *
+terminalIdFn(
+  Cal_BddManager bddManager,
+  CalAddress_t  v1,
+  CalAddress_t  v2,
+  Cal_Pointer_t  pointer)
+{
+  static char result[100];
+  sprintf(result, "%g", asDouble(v1, v2));
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+PrintBdd(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f)
+{
+  Cal_BddPrintBdd(bddManager, f, Cal_BddNamingFnNone, 
+		  (Cal_TerminalIdFn_t) terminalIdFn,
+                  (Cal_Pointer_t)0, stderr); 
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+#if HAVE_STDARG_H
+static void
+Error(char *op, Cal_BddManager bddManager, Cal_Bdd result,
+      Cal_Bdd expected, ...)
+{
+  va_list ap;
+  Cal_Bdd userBdd;
+  int i;
+
+  va_start(ap, expected);
+#else
+static void
+Error(va_alist)
+va_dcl
+{
+  va_list ap;
+  char *op;
+  Cal_BddManager_t *bddManager;
+  Cal_Bdd result, expected;
+  Cal_Bdd userBdd;
+  int i;
+  
+  va_start(ap);
+  op   = va_arg(ap, char *);
+  bddManager = va_arg(ap, Cal_BddManager_t *);
+  result = va_arg(ap, Cal_Bdd);
+  expected = va_arg(ap, Cal_Bdd);
+#endif
+
+  fprintf(stderr, "\nError: operation %s:\n", op);
+  i=0;
+  while (1) {
+    if ((userBdd = va_arg(ap, Cal_Bdd))){
+	  ++i;
+	  fprintf(stderr, "Argument %d:\n", i);
+	  Cal_BddFunctionPrint(bddManager, userBdd, "a");
+	}
+    else
+      break;
+  }
+  fprintf(stderr, "Expected result:\n");
+  Cal_BddFunctionPrint(bddManager, expected, "a");
+  fprintf(stderr, "Result:\n");
+  Cal_BddFunctionPrint(bddManager, result, "a");
+  va_end(ap);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static TruthTable_t
+Cofactor(TruthTable_t  table, int  var, int  value)
+{
+  int shift;
+  
+  shift = 1 << (TT_VARS-var-1);
+  if(value) {
+    table &= cofactorMasks[var];
+    table |= table >> shift;
+  }
+  else {
+    table &= ~cofactorMasks[var];
+    table |= table << shift;
+  }
+  return (table);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static Cal_Bdd
+Decode(int  var, TruthTable_t  table)
+{
+  Cal_Bdd temp1, temp2;
+  Cal_Bdd result;
+  Cal_Bdd left, right;
+  Cal_Bdd varBdd;
+
+  if(var == TT_VARS){
+    if(table & 0x1){
+      result = Cal_BddOne(bddManager);
+    }
+    else{
+      result = Cal_BddZero(bddManager);
+    }
+  }
+  else{
+    temp1 = Decode(var+1, table >> (1 << (TT_VARS-var-1)));
+    temp2 = Decode(var+1, table);
+    left = Cal_BddAnd(bddManager, vars[var], temp1);
+    varBdd = Cal_BddNot(bddManager, vars[var]);
+    right = Cal_BddAnd(bddManager, varBdd, temp2);
+    result = Cal_BddOr(bddManager, left, right);
+    /*
+    result = Cal_BddITE(bddManager, vars[var], temp1, temp2);
+    */
+    Cal_BddFree(bddManager, left);
+    Cal_BddFree(bddManager, right);
+    Cal_BddFree(bddManager, temp1);
+    Cal_BddFree(bddManager, temp2);
+    Cal_BddFree(bddManager, varBdd);
+  }
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestAnd(Cal_BddManager bddManager, Cal_Bdd  f1, TruthTable_t  table1,
+        Cal_Bdd  f2, TruthTable_t  table2)
+{
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  Cal_Bdd expected;
+
+  result = Cal_BddAnd(bddManager, f1, f2);
+  resulttable = table1 & table2;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("AND", bddManager, result, expected, f1, f2, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestNand(Cal_BddManager bddManager, Cal_Bdd  f1, TruthTable_t  table1,
+        Cal_Bdd  f2, TruthTable_t  table2)
+{
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  Cal_Bdd expected;
+
+  result = Cal_BddNand(bddManager, f1, f2);
+  resulttable = ~(table1 & table2);
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("NAND", bddManager, result, expected, f1, f2, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestOr(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2)
+{
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  Cal_Bdd expected;
+
+  result = Cal_BddOr(bddManager, f1, f2);
+  resulttable = table1 | table2;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("OR", bddManager,result, expected, f1, f2, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestITE(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2,
+  Cal_Bdd  f3,
+  TruthTable_t  table3)
+{
+  Cal_Bdd result;
+  TruthTable_t resultTable;
+  Cal_Bdd expected;
+
+  result = Cal_BddITE(bddManager, f1, f2, f3);
+  resultTable = (table1 & table2) | (~table1 & table3);
+  expected = EncodingToBdd(resultTable);
+  if(Cal_BddIsEqual(bddManager, result, expected) == 0){
+    Error("ITE", bddManager, result, expected, f1, f2, f3,
+          (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestXor(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2)
+{
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  Cal_Bdd expected;
+
+  result = Cal_BddXor(bddManager, f1, f2);
+  resulttable = table1 ^ table2;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("XOR", bddManager, result, expected, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestIdNot(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f,
+  TruthTable_t  table)
+{
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  Cal_Bdd expected;
+
+  result = Cal_BddNot(bddManager, f);
+  resulttable = ~table;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("Not", bddManager, result, expected, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+  result = Cal_BddIdentity(bddManager, f);
+  resulttable = table;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("Identity", bddManager, result, expected, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestCompose(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2)
+{
+  int var;
+  Cal_Bdd result, expected;
+  TruthTable_t resulttable;
+  
+
+  var = (int)(((long)CalUtilRandom())%TT_VARS);
+
+  result = Cal_BddCompose(bddManager, vars[var], vars[var], Cal_BddOne(bddManager));
+  if(!Cal_BddIsEqual(bddManager, result, Cal_BddOne(bddManager))){
+    Cal_BddFunctionPrint(bddManager, result, "Compose"); 
+  }
+
+  result = Cal_BddCompose(bddManager, vars[var], vars[var], Cal_BddZero(bddManager));
+  if(!Cal_BddIsEqual(bddManager, result, Cal_BddZero(bddManager))){
+    Cal_BddFunctionPrint(bddManager, result, "Compose"); 
+  }
+
+  result = Cal_BddCompose(bddManager, f1, vars[var], Cal_BddOne(bddManager));
+  resulttable = Cofactor(table1, var, 1);
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result,expected)){
+    Error("Restrict 1", bddManager, result, expected, f1, vars[var],
+          (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+
+  result = Cal_BddCompose(bddManager, f1, vars[var], Cal_BddZero(bddManager));
+  resulttable = Cofactor(table1, var, 0);
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("Restrict 0", bddManager, result, expected, f1, vars[var],
+          (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+
+  result = Cal_BddCompose(bddManager, f1, vars[var], f2);
+  resulttable = (table2 & Cofactor(table1, var, 1)) |
+      (~table2 & Cofactor(table1, var, 0));
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("Compose", bddManager, result, expected, f1, vars[var],
+          f2, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestSubstitute(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2,
+  Cal_Bdd  f3,
+  TruthTable_t  table3)
+{
+  int var1, var2;
+  Cal_Bdd associationInfo[6];
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  TruthTable_t temp1, temp2, temp3, temp4;
+  Cal_Bdd expected;
+  int assocId;
+  
+  var1 = (int)(((long)CalUtilRandom())%TT_VARS);
+  do{
+    var2 = (int)(((long)CalUtilRandom())%TT_VARS);
+  }while (var1 == var2);
+
+  associationInfo[0] = vars[var1];
+  associationInfo[1] = f2;
+  associationInfo[2] = vars[var2];
+  associationInfo[3] = f3;
+  associationInfo[4] = (Cal_Bdd) 0;
+  associationInfo[5] = (Cal_Bdd) 0;
+
+  assocId = Cal_AssociationInit(bddManager, associationInfo, 1);
+  Cal_AssociationSetCurrent(bddManager, assocId);
+
+  result = Cal_BddSubstitute(bddManager, f1);
+  temp1 = Cofactor(Cofactor(table1, var1, 1), var2, 1);
+  temp2 = Cofactor(Cofactor(table1, var1, 1), var2, 0);
+  temp3 = Cofactor(Cofactor(table1, var1, 0), var2, 1);
+  temp4 = Cofactor(Cofactor(table1, var1, 0), var2, 0);
+  resulttable = table2 & table3 & temp1;
+  resulttable |= table2 & ~table3 & temp2;
+  resulttable |= ~table2 & table3 & temp3;
+  resulttable |= ~table2 & ~table3 & temp4;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("substitute", bddManager, result, expected,
+        f1, vars[var1], f2, vars[var2], f3, (Cal_Bdd) 0);
+  }
+  /*Cal_AssociationQuit(bddManager, assocId);*/
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestVarSubstitute(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2,
+  Cal_Bdd  f3,
+  TruthTable_t  table3)
+{
+  int var1, var2, var3, var4;
+  Cal_Bdd associationInfo[6];
+  Cal_Bdd result1, result2;
+  TruthTable_t resulttable;
+  TruthTable_t temp1, temp2, temp3, temp4;
+  Cal_Bdd expected;
+  int assocId;
+  
+  var1 = (int)(((long)CalUtilRandom())%TT_VARS);
+  do{
+    var3 = (int)(((long)CalUtilRandom())%TT_VARS);
+  }while (var1 == var3);
+
+  var2 = (int)(((long)CalUtilRandom())%TT_VARS);
+  do{
+    var4 = (int)(((long)CalUtilRandom())%TT_VARS);
+  }while (var2 == var4);
+
+  /*
+  f1 = vars[0];
+  table1 = cofactorMasks[0];
+  */
+  associationInfo[0] = vars[var1];
+  associationInfo[1] = vars[var3];
+  associationInfo[2] = vars[var2];
+  associationInfo[3] = vars[var4];
+  associationInfo[4] = (Cal_Bdd) 0;
+  associationInfo[5] = (Cal_Bdd) 0;
+
+  assocId = Cal_AssociationInit(bddManager, associationInfo, 1);
+  Cal_AssociationSetCurrent(bddManager, assocId);
+
+  result1 = Cal_BddVarSubstitute(bddManager, f1);
+  result2 = Cal_BddSubstitute(bddManager, f1);
+  temp1 = Cofactor(Cofactor(table1, var2, 1), var1, 1);
+  temp2 = Cofactor(Cofactor(table1, var2, 1), var1, 0);
+  temp3 = Cofactor(Cofactor(table1, var2, 0), var1, 1);
+  temp4 = Cofactor(Cofactor(table1, var2, 0), var1, 0);
+  resulttable = cofactorMasks[var3] & cofactorMasks[var4] & temp1;
+  resulttable |= ~cofactorMasks[var3] & cofactorMasks[var4] & temp2;
+  resulttable |= cofactorMasks[var3] & ~cofactorMasks[var4] & temp3;
+  resulttable |= ~cofactorMasks[var3] & ~cofactorMasks[var4] & temp4;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result1, result2)){
+    Error("var substitute and substitute differ", bddManager, result1, result2,
+        f1, vars[var1], vars[var3], vars[var2], vars[var4],
+          (Cal_Bdd) 0); 
+  }
+  if(!Cal_BddIsEqual(bddManager, result1, expected)){
+    Error("var substitute", bddManager, result1, expected,
+        f1, vars[var1], vars[var3], vars[var2], vars[var4],
+          (Cal_Bdd) 0); 
+  }
+  /*Cal_AssociationQuit(bddManager, assocId);*/
+  Cal_BddFree(bddManager, result1);
+  Cal_BddFree(bddManager, result2);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestSwapVars(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f,
+  TruthTable_t  table)
+{
+  int var1, var2;
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  TruthTable_t temp1, temp2, temp3, temp4;
+  Cal_Bdd expected;
+
+  var1 = (int)(((long)CalUtilRandom())%TT_VARS);
+  var2 = (int)(((long)CalUtilRandom())%TT_VARS);
+  result = Cal_BddSwapVars(bddManager, f, vars[var1], vars[var2]);
+  temp1 = Cofactor(Cofactor(table, var1, 1), var2, 1);
+  temp2 = Cofactor(Cofactor(table, var1, 1), var2, 0);
+  temp3 = Cofactor(Cofactor(table, var1, 0), var2, 1);
+  temp4 = Cofactor(Cofactor(table, var1, 0), var2, 0);
+  resulttable = cofactorMasks[var2] & cofactorMasks[var1] & temp1;
+  resulttable |= cofactorMasks[var2] & ~cofactorMasks[var1] & temp2;
+  resulttable |= ~cofactorMasks[var2] & cofactorMasks[var1] & temp3;
+  resulttable |= ~cofactorMasks[var2] & ~cofactorMasks[var1] & temp4;
+  expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("swap variables", bddManager, result, expected, 
+        f, vars[var1], vars[var2], (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestMultiwayAnd(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2,
+  Cal_Bdd  f3,
+  TruthTable_t  table3)
+{
+	Cal_Bdd result;
+	TruthTable_t resulttable;
+	Cal_Bdd expected;
+	Cal_Bdd *calBddArray;
+
+    calBddArray = Cal_MemAlloc(Cal_Bdd, 4);
+    calBddArray[0] = f1;
+    calBddArray[1] = f2;
+    calBddArray[2] = f3;
+    calBddArray[3] = (Cal_Bdd) 0;
+	result = Cal_BddMultiwayAnd(bddManager, calBddArray);
+	resulttable = table1 & table2 & table3;
+	expected = EncodingToBdd(resulttable);
+    if(!Cal_BddIsEqual(bddManager, result, expected)){
+      Error("Multiway And", bddManager, result, expected,
+            (Cal_Bdd) 0);
+    }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+  Cal_MemFree(calBddArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestMultiwayOr(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2,
+  Cal_Bdd  f3,
+  TruthTable_t  table3)
+{
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  Cal_Bdd expected;
+  Cal_Bdd *calBddArray;
+  
+  calBddArray = Cal_MemAlloc(Cal_Bdd, 4);
+  calBddArray[0] = f1;
+  calBddArray[1] = f2;
+  calBddArray[2] = f3;
+  calBddArray[3] = (Cal_Bdd) 0;
+  result = Cal_BddMultiwayOr(bddManager, calBddArray);
+  resulttable = table1 | table2 | table3;
+	expected = EncodingToBdd(resulttable);
+  if(!Cal_BddIsEqual(bddManager, result, expected)){
+    Error("Multiway Or", bddManager, result, expected, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+  Cal_MemFree(calBddArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestMultiwayLarge(
+  Cal_BddManager bddManager,
+  int  numBdds)
+{
+  TruthTable_t table, andResulttable, orResulttable;
+  Cal_Bdd f, andResult, orResult, andExpected, orExpected;
+  int i;
+  Cal_Bdd *calBddArray;
+  
+  andResulttable = ~0x0;
+  orResulttable = 0x0;
+  calBddArray = Cal_MemAlloc(Cal_Bdd, numBdds+1);
+  for (i=0; i<numBdds; i++){
+    table = (TruthTable_t)CalUtilRandom();
+    f = EncodingToBdd(table);
+    calBddArray[i] = f;
+    andResulttable &= table;
+    orResulttable |= table;
+  }
+  calBddArray[numBdds] = (Cal_Bdd) 0;
+  andResult = Cal_BddMultiwayAnd(bddManager, calBddArray);
+  orResult = Cal_BddMultiwayOr(bddManager, calBddArray);
+  andExpected = EncodingToBdd(andResulttable);
+  orExpected = EncodingToBdd(orResulttable);
+  if(!Cal_BddIsEqual(bddManager, andResult, andExpected)){
+    Error("Multiway And", bddManager, andResult, andExpected,
+          (Cal_Bdd) 0);
+  }
+  if(!Cal_BddIsEqual(bddManager, orResult, orExpected)){
+    Error("Multiway Or", bddManager, andResult, andExpected,
+          (Cal_Bdd) 0);
+  }
+  for (i=0; i<numBdds; i++) Cal_BddFree(bddManager, calBddArray[i]);
+  Cal_MemFree(calBddArray);
+  Cal_BddFree(bddManager, andResult);
+  Cal_BddFree(bddManager, andExpected);
+  Cal_BddFree(bddManager, orResult);
+  Cal_BddFree(bddManager, orExpected);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestArrayOp(Cal_BddManager bddManager,  int  numBdds)
+{
+  TruthTable_t fTable, gTable;
+  Cal_Bdd f, g, *andExpectedArray, *orExpectedArray, *calBddArray;
+  Cal_Bdd *andResultArray, *orResultArray;
+  int i;
+  
+  calBddArray = Cal_MemAlloc(Cal_Bdd, 2*numBdds+1);
+  andExpectedArray = Cal_MemAlloc(Cal_Bdd, numBdds);
+  orExpectedArray = Cal_MemAlloc(Cal_Bdd, numBdds);
+  calBddArray[numBdds<<1] = (Cal_Bdd) 0;
+
+  for (i=0; i<numBdds; i++){
+    fTable = (TruthTable_t)CalUtilRandom();
+    gTable = (TruthTable_t)CalUtilRandom();
+    f = EncodingToBdd(fTable);
+    g = EncodingToBdd(gTable);
+    calBddArray[i<<1] = f;
+    calBddArray[(i<<1)+1] = g;
+    andExpectedArray[i] = EncodingToBdd(fTable & gTable);
+    orExpectedArray[i] = EncodingToBdd(fTable | gTable);
+  }
+  
+  andResultArray = Cal_BddPairwiseAnd(bddManager, calBddArray);
+  orResultArray = Cal_BddPairwiseOr(bddManager, calBddArray);
+
+  for (i=0; i<numBdds; i++){
+    if(!Cal_BddIsEqual(bddManager, andResultArray[i], andExpectedArray[i])){
+      Error("Array OR", bddManager, andResultArray[i], andExpectedArray[i],
+            (Cal_Bdd) 0);
+      break;
+    }
+  }
+
+  for (i=0; i<numBdds; i++){
+    if(!Cal_BddIsEqual(bddManager, orResultArray[i], orExpectedArray[i])){
+      Error("Array OR", bddManager, orResultArray[i], orExpectedArray[i],
+            (Cal_Bdd) 0);
+      break;
+    }
+  }
+  for (i=0; i<numBdds; i++){
+    Cal_BddFree(bddManager, calBddArray[i<<1]);
+    Cal_BddFree(bddManager, calBddArray[(i<<1)+1]);
+    Cal_BddFree(bddManager, andExpectedArray[i]);
+    Cal_BddFree(bddManager, orExpectedArray[i]);
+    Cal_BddFree(bddManager, andResultArray[i]);
+    Cal_BddFree(bddManager, orResultArray[i]);
+  }
+  Cal_MemFree(calBddArray);
+  Cal_MemFree(andExpectedArray);
+  Cal_MemFree(orExpectedArray);
+  Cal_MemFree(andResultArray);
+  Cal_MemFree(orResultArray);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestInterImpl(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2)
+{
+  Cal_Bdd result;
+  TruthTable_t resulttable;
+  Cal_Bdd expected;
+  Cal_Bdd impliesResult;
+
+  result = Cal_BddIntersects(bddManager, f1, f2);
+  resulttable = table1 & table2;
+  expected = EncodingToBdd(resulttable);
+  impliesResult = Cal_BddImplies(bddManager, result, expected);
+  if(Cal_BddIsBddZero(bddManager, impliesResult) == 0){
+    Error("intersection test", bddManager, result, expected, f1, f2,
+          (Cal_Bdd) 0); 
+  }
+  Cal_BddFree(bddManager, impliesResult);
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestQnt(Cal_BddManager bddManager, Cal_Bdd  f, TruthTable_t  table, int
+        bfZeroBFPlusDFOne, int cacheExistsResultsFlag, int cacheOrResultsFlag)
+{
+  int var1, var2;
+  Cal_Bdd assoc[3];
+  Cal_Bdd result, expected;
+  TruthTable_t  resultTable;
+  int associationId;
+  
+  var1= (int)(((long)CalUtilRandom())%TT_VARS);
+  do
+    var2= (int)(((long)CalUtilRandom())%TT_VARS);
+  while (var1 == var2);
+  assoc[0] = vars[var1];
+  assoc[1] = vars[var2];
+  assoc[2] = (Cal_Bdd) 0;
+  associationId = Cal_AssociationInit(bddManager, assoc, 0);
+  Cal_AssociationSetCurrent(bddManager, associationId);
+  result = Cal_BddExists(bddManager, f);
+  resultTable = Cofactor(table, var1, 1) | Cofactor(table, var1, 0);
+  resultTable = Cofactor(resultTable, var2, 1) | Cofactor(resultTable,
+                                                          var2, 0); 
+  expected = EncodingToBdd(resultTable);
+  if(Cal_BddIsEqual(bddManager, result, expected) == 0){
+    Error("quantification", bddManager, result, expected, f, vars[var1],
+          vars[var2], (Cal_Bdd) 0);
+  }
+  /*Cal_AssociationQuit(bddManager, associationId);*/
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestAssoc(Cal_BddManager bddManager, Cal_Bdd  f, TruthTable_t  table)
+{
+  Cal_Bdd assoc[3];
+  Cal_Bdd result, expected;
+  int associationId;
+  
+  assoc[0] = (Cal_Bdd) 0;
+  associationId = Cal_AssociationInit(bddManager, assoc, 0);
+  Cal_AssociationSetCurrent(bddManager, associationId);
+  result = Cal_BddExists(bddManager, f);
+  expected = Cal_BddIdentity(bddManager, f);
+  if(Cal_BddIsEqual(bddManager, result, expected) == 0){
+    Error("quantification", bddManager, result, expected, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestRelProd(Cal_BddManager bddManager, Cal_Bdd  f1, TruthTable_t
+            table1, Cal_Bdd  f2, TruthTable_t  table2, int bfZeroBFPlusDFOne,
+            int cacheRelProdResultsFlag, int cacheAndResultsFlag, int
+            cacheOrResultsFlag) 
+{
+  int var1, var2;
+  Cal_Bdd assoc[3];
+  Cal_Bdd result;
+  TruthTable_t resultTable;
+  Cal_Bdd expected;
+  int assocId;
+  
+  var1=(int)(((long)CalUtilRandom())%TT_VARS);
+  do
+    var2=(int)(((long)CalUtilRandom())%TT_VARS);
+  while (var1 == var2);
+  assoc[0] = vars[var1];
+  assoc[1] = vars[var2];
+  assoc[2] = (Cal_Bdd) 0;
+  assocId = Cal_AssociationInit(bddManager, assoc, 0);
+  Cal_AssociationSetCurrent(bddManager, assocId);
+  result = Cal_BddRelProd(bddManager, f1, f2);
+  table1 &= table2;
+  resultTable = Cofactor(table1, var1, 1) | Cofactor(table1, var1, 0);
+  resultTable = Cofactor(resultTable, var2, 1) | Cofactor(resultTable, var2, 0);
+  expected = EncodingToBdd(resultTable);
+  if(Cal_BddIsEqual(bddManager, result, expected) == 0){
+    Error("relational product", bddManager, result, expected, f1, f2,
+          vars[var1], vars[var2], (Cal_Bdd) 0);
+  }
+  /*Cal_AssociationQuit(bddManager, assocId);*/
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestReduce(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2)
+{
+  Cal_Bdd result;
+  Cal_Bdd temp1, temp2, temp3;
+
+  result = Cal_BddReduce(bddManager, f1, f2);
+  temp1 = Cal_BddXnor(bddManager, result, f1);
+  temp2 = Cal_BddNot(bddManager, f2);
+  temp3 = Cal_BddOr(bddManager, temp1, temp2);
+  if(Cal_BddIsBddOne(bddManager, temp3) == 0){
+    Error("d.c. comparison of reduce", bddManager, temp3,
+          Cal_BddOne(bddManager), f1, f2, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, temp1);
+  Cal_BddFree(bddManager, temp2);
+  Cal_BddFree(bddManager, temp3);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestGenCof(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2)
+{
+  int var1, var2;
+  Cal_Bdd result, temp1, temp2, temp3, expected;
+  TruthTable_t resultTable;
+
+  result = Cal_BddCofactor(bddManager, f1, f2);
+  temp1 = Cal_BddXnor(bddManager, result, f1);
+  temp2 = Cal_BddNot(bddManager, f2);
+  temp3 = Cal_BddOr(bddManager, temp1, temp2);
+  if (Cal_BddIsBddOne(bddManager, temp3) == 0){
+    Error("d.c. comparison of generalized cofactor", bddManager,
+          temp3, Cal_BddOne(bddManager), f1, f2, (Cal_Bdd) 0);
+  }
+
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, temp1);
+  Cal_BddFree(bddManager, temp2);
+  Cal_BddFree(bddManager, temp3);
+  var1=(int)(((long)CalUtilRandom())%TT_VARS);
+  do
+    var2=(int)(((long)CalUtilRandom())%TT_VARS);
+  while (var1 == var2);
+  temp1 = Cal_BddNot(bddManager, vars[var2]);
+  temp2 = Cal_BddAnd(bddManager, vars[var1], temp1);
+  Cal_BddFree(bddManager, temp1);
+  result = Cal_BddCofactor(bddManager, f1, temp2);
+  resultTable = Cofactor(Cofactor(table1, var1, 1), var2, 0);
+  expected = EncodingToBdd(resultTable);
+  if (Cal_BddIsEqual(bddManager, result, expected) == 0){
+    Error("generalized cofactor", bddManager, result, expected, f1,
+          temp2, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+  Cal_BddFree(bddManager, temp2);
+}
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestSize(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f1,
+  TruthTable_t  table1,
+  Cal_Bdd  f2,
+  TruthTable_t  table2)
+{
+  int i;
+  long size;
+  long profile[MAX_TT_VARS+1];
+  Cal_Bdd fs[3];
+
+  size = Cal_BddSize(bddManager, f1, 1);
+  Cal_BddProfile(bddManager, f1, profile, 1);
+  for(i = 0; i < TT_VARS+1; i++){
+    size -= profile[i];
+  }
+  if(size){
+    fprintf(stderr, "\nError: size count vs. profile sum:\n");
+    fprintf(stderr, "Argument:\n");
+    Cal_BddFunctionPrint(bddManager, f1, "f1");
+  }
+
+  size = Cal_BddSize(bddManager, f1, 0);
+  Cal_BddProfile(bddManager, f1, profile, 0);
+  for(i = 0; i < TT_VARS+1; i++){
+    size -= profile[i];
+  }
+  if(size){
+    fprintf(stderr, "\nError: no negout size count vs. profile sum:\n");
+    fprintf(stderr, "Argument:\n");
+    Cal_BddFunctionPrint(bddManager, f1, "f1");
+  }
+
+
+  fs[0] = f1;
+  fs[1] = f2;
+  fs[2] = (Cal_Bdd) 0;
+
+  size = Cal_BddSizeMultiple(bddManager, fs, 1);
+  Cal_BddProfileMultiple(bddManager, fs, profile, 1);
+  for(i = 0; i < TT_VARS+1; i++){
+    size -= profile[i];
+  }
+  if(size){
+    fprintf(stderr,"\nError: multiple size count vs. multiple profile sum:\n");
+    fprintf(stderr, "Argument 1:\n");
+    Cal_BddFunctionPrint(bddManager, f1, "f1");
+    fprintf(stderr, "Argument 2:\n");
+    Cal_BddFunctionPrint(bddManager, f2, "f2");
+  }
+
+  size = Cal_BddSizeMultiple(bddManager, fs, 0);
+  Cal_BddProfileMultiple(bddManager, fs, profile, 0);
+  for(i = 0; i < TT_VARS+1; i++){
+    size -= profile[i];
+  }
+  if(size){
+    fprintf(stderr,"\nError: multiple no negout size count vs. multiple profile sum:\n");
+    fprintf(stderr, "Argument 1:\n");
+    Cal_BddFunctionPrint(bddManager, f1, "f1");
+    fprintf(stderr, "Argument 2:\n");
+    Cal_BddFunctionPrint(bddManager, f2, "f2");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestSatisfy(
+  Cal_BddManager bddManager,
+  Cal_Bdd  f,
+  TruthTable_t  table)
+{
+  int var1, var2;
+  Cal_Bdd assoc[MAX_TT_VARS+1];
+  Cal_Bdd result;
+  Cal_Bdd temp1, temp2, temp3;
+  int assocId;
+  
+  if(Cal_BddIsBddZero(bddManager, f)){
+    return;
+  }
+  result = Cal_BddSatisfy(bddManager, f);
+  temp1 = Cal_BddNot(bddManager, f);
+  temp2 = Cal_BddIntersects(bddManager, temp1, result);
+  if(!Cal_BddIsBddZero(bddManager, temp2)){
+    Error("intersection of satisfy result with negated argument",
+        bddManager, temp2, Cal_BddZero(bddManager), f, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, temp1);
+  Cal_BddFree(bddManager, temp2);
+
+  var1 = (int)(((long)CalUtilRandom())%TT_VARS);
+  do{
+    var2 = (int)(((long)CalUtilRandom())%TT_VARS);
+  }while (var1 == var2);
+  assoc[0] = vars[var1];
+  assoc[1] = vars[var2];
+  assoc[2] = (Cal_Bdd) 0;
+  assocId = Cal_AssociationInit(bddManager, assoc, 0);
+  Cal_AssociationSetCurrent(bddManager, assocId);
+  temp1 = Cal_BddSatisfySupport(bddManager, result);
+  temp2 = Cal_BddNot(bddManager, result);
+  temp3 = Cal_BddIntersects(bddManager, temp2, temp1);
+  if(!Cal_BddIsBddZero(bddManager, temp3)){
+    Error("intersection of satisfy support result with negated argument",
+        bddManager, temp3, Cal_BddZero(bddManager), result,
+        (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, temp1);
+  Cal_BddFree(bddManager, temp2);
+  Cal_BddFree(bddManager, temp3);
+  temp1 = Cal_BddCompose(bddManager, f, vars[var1], Cal_BddZero(bddManager));
+  temp2 = Cal_BddCompose(bddManager, f, vars[var1], Cal_BddOne(bddManager));
+  if(Cal_BddSatisfyingFraction(bddManager, temp1) + 
+      Cal_BddSatisfyingFraction(bddManager, temp2) !=
+      2.0 * Cal_BddSatisfyingFraction(bddManager, f)){
+    fprintf(stderr, "\nError: operation satisfying fraction:\n");
+    fprintf(stderr, "Argument:\n");
+    Cal_BddFunctionPrint(bddManager, f, "f");
+    fprintf(stderr, "Cofactor on:\n");
+    Cal_BddFunctionPrint(bddManager, vars[var1], "var");
+  }
+  /*Cal_AssociationQuit(bddManager, assocId);*/
+  Cal_BddFree(bddManager, temp1);
+  Cal_BddFree(bddManager, temp2);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestPipeline(Cal_BddManager bddManager,
+             Cal_Bdd  f1,
+             TruthTable_t  table1,
+             Cal_Bdd  f2,
+             TruthTable_t  table2,
+             Cal_Bdd  f3,
+             TruthTable_t  table3)
+{
+  Cal_Bdd temp1, temp2, temp3, temp4, temp5, result, expected;
+  TruthTable_t table;
+
+  Cal_PipelineInit(bddManager, CAL_AND);
+  Cal_PipelineSetDepth(bddManager, 0);
+  temp1 = Cal_PipelineCreateProvisionalBdd(bddManager, f1, f2);
+  temp2 = Cal_PipelineCreateProvisionalBdd(bddManager, f1, f3);
+  temp3 = Cal_PipelineCreateProvisionalBdd(bddManager, f1, temp1);
+  temp4 = Cal_PipelineCreateProvisionalBdd(bddManager, f2, temp2);
+  temp5 = Cal_PipelineCreateProvisionalBdd(bddManager, temp3, temp4);
+  result = Cal_PipelineCreateProvisionalBdd(bddManager, temp4, temp5);
+  Cal_PipelineExecute(bddManager);
+  result = Cal_PipelineUpdateProvisionalBdd(bddManager, result);
+  Cal_PipelineQuit(bddManager);
+
+  table = table1 & table2 & table3;
+  expected = EncodingToBdd(table);
+
+  if (Cal_BddIsEqual(bddManager, result, expected) == 0){
+    Error("pipeline", bddManager, result, expected, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, result);
+  Cal_BddFree(bddManager, expected);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestDump(Cal_BddManager bddManager, Cal_Bdd f)
+{
+  FILE *fp;
+  int i, j;
+  Cal_Bdd dumpVars[MAX_TT_VARS];
+  Cal_Bdd temp, result;
+  int err;
+
+  if (!(fp=tmpfile()))
+    {
+      fprintf(stderr, "could not open temporary file\n");
+      exit(1);
+    }
+  for (i=0; i < TT_VARS; ++i)
+    dumpVars[i]=vars[i];
+  dumpVars[i]= (Cal_Bdd) 0;
+  for (i=0; i < TT_VARS-1; ++i)
+    {
+      j=i+(int)(((long)CalUtilRandom())%(TT_VARS-i));
+      temp=dumpVars[i];
+      dumpVars[i]=dumpVars[j];
+      dumpVars[j]=temp;
+    }
+  if (!Cal_BddDumpBdd(bddManager, f, dumpVars, fp))
+    {
+      fprintf(stderr, "Error: dump failure:\n");
+      fprintf(stderr, "Argument:\n");
+      PrintBdd(bddManager, f);
+      fclose(fp);
+      return;
+    }
+  rewind(fp);
+  if (!(result=Cal_BddUndumpBdd(bddManager, dumpVars, fp, &err)) || err)
+    {
+      fprintf(stderr, "Error: undump failure: code %d:\n", err);
+      fprintf(stderr, "Argument:\n");
+      PrintBdd(bddManager, f);
+      fclose(fp);
+      return;
+    }
+  fclose(fp);
+  if (result != f)
+    Error("dump/undump", bddManager, result, f, f, (Cal_Bdd) 0);
+  Cal_BddFree(bddManager, result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestReorderBlock(Cal_BddManager bddManager, TruthTable_t table, Cal_Bdd f)
+{
+  Cal_Bdd newFunction;
+  Cal_Block block1, block2, block3;
+  
+  /*if (CalUtilRandom()&0x1){*/
+  if (1){
+    fprintf(stdout, "Using Window\n");
+    Cal_BddDynamicReordering(bddManager, CAL_REORDER_WINDOW);
+  }
+  else{
+    fprintf(stdout, "Using Sift\n");
+    Cal_BddDynamicReordering(bddManager, CAL_REORDER_SIFT);
+  }
+  /* Create some blocks */
+  block1 = Cal_BddNewVarBlock(bddManager,
+                              vars[bddManager->indexToId[0]-1],
+                              4); 
+  block2 = Cal_BddNewVarBlock(bddManager,
+                              vars[bddManager->indexToId[4]-1],
+                              4);
+  block3 = Cal_BddNewVarBlock(bddManager,
+                              vars[bddManager->indexToId[8]-1],
+                              4);
+  Cal_BddVarBlockReorderable(bddManager, block2, 1);
+  Cal_BddReorder(bddManager);
+  newFunction = EncodingToBdd(table);
+  if (Cal_BddIsEqual(bddManager, f, newFunction) == 0){
+    Error("Reordering (window)", bddManager, newFunction, f, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, newFunction);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TestReorder(Cal_BddManager bddManager, TruthTable_t table, Cal_Bdd f)
+{
+  Cal_Bdd newFunction;
+  
+  if (CalUtilRandom()&0x1){
+    fprintf(stdout, "Using Window\n");
+    Cal_BddDynamicReordering(bddManager, CAL_REORDER_WINDOW);
+  }
+  else{
+    fprintf(stdout, "Using Sift\n");
+    Cal_BddDynamicReordering(bddManager, CAL_REORDER_SIFT);
+  }
+  if (CalUtilRandom()&0x1){
+    bddManager->reorderMethod = CAL_REORDER_METHOD_BF;
+  }
+  else{
+    bddManager->reorderMethod = CAL_REORDER_METHOD_DF;
+  }
+  Cal_BddReorder(bddManager);
+  newFunction = EncodingToBdd(table);
+  if (Cal_BddIsEqual(bddManager, f, newFunction) == 0){
+    Error("Reordering (window)", bddManager, newFunction, f, (Cal_Bdd) 0);
+  }
+  Cal_BddFree(bddManager, newFunction);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+handler(int ignored)
+{
+  printf("arthimetic exception ############\n");
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+RandomTests(int numVars, int  iterations)
+{
+  int i, seed;
+  TruthTable_t table1, table2, table3;
+  Cal_Bdd f1, f2, f3/*, f4*/;
+  CalAssociation_t *assoc, *nextAssoc;
+  /* Cal_Block block1, block2; */
+  
+  signal(SIGFPE, handler);
+  
+  printf("Random operation tests...\n");
+  bddManager  = Cal_BddManagerInit();
+  seed = 1;
+  /*
+  (void) time((time_t *)&seed);
+  */
+  CalUtilSRandom((long)seed);
+
+  for(i = 0; i < numVars; ++i){
+    vars[i] = Cal_BddManagerCreateNewVarLast(bddManager);
+  }
+  
+  /*
+  f1 = Cal_BddAnd(bddManager, vars[1], vars[2]);
+  f2 = Cal_BddAnd(bddManager, vars[1], vars[0]);
+  f3 = Cal_BddOr(bddManager, f1, f2);
+  Cal_BddFree(bddManager, f1);
+  Cal_BddFree(bddManager, f2);
+  Cal_BddDynamicReordering(bddManager, Cal_BddReorderSift);
+  fprintf(stdout,"Original function:\n");
+  Cal_BddFunctionPrint(bddManager, f3, "a");
+  Cal_BddReorderNew(bddManager);
+  f1 = Cal_BddAnd(bddManager, vars[1], vars[2]);
+  f2 = Cal_BddAnd(bddManager, vars[1], vars[0]);
+  f4 = Cal_BddOr(bddManager, f1, f2);
+  Cal_BddFree(bddManager, f1);
+  Cal_BddFree(bddManager, f2);
+  fprintf(stdout,"New function:\n");
+  Cal_BddFunctionPrint(bddManager, f4, "a");
+  Cal_Assert(Cal_BddIsEqual(bddManager, f3, f4));
+  Cal_BddFree(bddManager, f3);
+  Cal_BddFree(bddManager, f4);
+  */
+
+/*
+  block1 = Cal_BddNewVarBlock(bddManager,
+                              vars[0], 2);
+  block2 = Cal_BddNewVarBlock(bddManager, vars[3], 2);
+  Cal_BddVarBlockReorderable(bddManager, block2, 1);
+  */
+  for (i = 0; i < iterations; i++){
+    printf("Iteration %3d\n", i);
+    table1 = (TruthTable_t)CalUtilRandom();
+    table2 = (TruthTable_t)CalUtilRandom();
+    table3 = (TruthTable_t)CalUtilRandom();
+    f1 = EncodingToBdd(table1);
+    f2 = EncodingToBdd(table2);
+    f3 = EncodingToBdd(table3);
+
+    /* The following tests will fail if you do not use 5 variables */
+    if (numVars == 5){
+      TestGenCof(bddManager, f1, table1, f2, table2);
+      TestSubstitute(bddManager, f1, table1, f2, table2, f3, table3);
+      TestSwapVars(bddManager, f1, table1);
+      TestCompose(bddManager, f1, table1, f2, table2);
+      TestRelProd(bddManager, f1, table1, f2, table2, 0, 0, 0, 0);
+      TestQnt(bddManager, f1, table1, 1, 1, 1);
+      TestVarSubstitute(bddManager, f1, table1, f2, table2, f3,
+                        table3);
+    }
+    /* The following can be tested for larger number of variables */
+    TestAnd(bddManager,f1, table1, f2, table2);
+    TestIdNot(bddManager, f1, table1);
+    TestITE(bddManager, f1, table1, f2, table2, f3, table3);
+    TestNand(bddManager,f1, table1, f2, table2);
+    TestOr(bddManager, f1, table1, f2, table2);
+    TestXor(bddManager,f1, table1, f2, table2);
+    TestMultiwayOr(bddManager, f1, table1, f2, table2, f3, table3);
+    TestMultiwayAnd(bddManager, f1, table1, f2, table2, f3, table3);
+    TestArrayOp(bddManager, 10);
+    TestInterImpl(bddManager, f1, table1, f2, table2);
+    TestReduce(bddManager, f1, table1, f2, table2);
+    TestSize(bddManager, f1, table1, f2, table2);
+    TestSatisfy(bddManager, f1, table1);
+    TestAssoc(bddManager, f1, table1);
+    TestDump(bddManager, f1); 
+    TestPipeline(bddManager, f1, table1, f2, table2, f3, table3);
+    TestReorder(bddManager, table1, f1);
+    Cal_BddFree(bddManager, f1);
+    Cal_BddFree(bddManager, f2);
+    Cal_BddFree(bddManager, f3);
+  	if (i && (i % 10 == 0)) {
+      Cal_BddManagerGC(bddManager);
+      (void)CalPackNodes(bddManager);
+    }
+  }
+  for(i = 0; i < numVars; ++i){
+    Cal_BddFree(bddManager, vars[i]);
+  }
+  Cal_BddStats(bddManager, stdout);
+  for(assoc = bddManager->associationList;
+      assoc != Cal_Nil(CalAssociation_t); assoc = nextAssoc){
+    nextAssoc = assoc->next;
+    for (i=1; i <= bddManager->numVars; i++){
+      if (CalBddIsBddNull(bddManager, assoc->varAssociation[i]) == 0){
+        CalBddDcrRefCount(assoc->varAssociation[i]);
+        assoc->varAssociation[i] = bddManager->bddNull;
+        assoc->lastBddIndex = -1;
+      }
+    }
+  }
+  /* fix temporary association */
+  assoc = bddManager->tempAssociation;
+  for (i=1; i <= bddManager->numVars; i++){
+    if (CalBddIsBddNull(bddManager, assoc->varAssociation[i]) == 0){
+      CalBddDcrRefCount(assoc->varAssociation[i]);
+      assoc->varAssociation[i] = bddManager->bddNull;
+      assoc->lastBddIndex = -1;
+    }
+  }
+
+  Cal_BddManagerGC(bddManager);
+  Cal_BddStats(bddManager, stdout);
+  /*CalUniqueTablePrint(bddManager);*/
+  Cal_BddManagerQuit(bddManager);
+}
Index: /vis_dev/glu-2.1/src/calBdd/calTitle.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calTitle.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calTitle.html	(revision 8)
@@ -0,0 +1,17 @@
+<HTML>
+<HEAD><TITLE>The cal package: Title</TITLE></HEAD>
+<BODY>
+
+<TABLE BORDER WIDTH="100%">
+  <TR>
+    <TD ALIGN=center> <A HREF="calExt.html" TARGET="_top">
+        Programmer view</A> </TD>
+    <TD ALIGN=center> <A HREF="calAllByFunc.html" TARGET="_top">
+	Maintainer by function</A> </TD>
+    <TD ALIGN=center> <A HREF="calAllByFile.html" TARGET="_top">
+        Maintainer by file</A> </TD>
+  </TR>
+</TABLE>
+
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/calBdd/calUtil.c
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/calUtil.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/calUtil.c	(revision 8)
@@ -0,0 +1,698 @@
+/**CFile***********************************************************************
+
+  FileName    [calUtil.c]
+
+  PackageName [cal]
+
+  Synopsis    [Utility functions for the Cal package.]
+
+  Description [Utility functions used in the Cal package.]
+
+  SeeAlso     [optional]
+
+  Author      [Jagesh Sanghavi (sanghavi@eecs.berkeley.edu)
+               Rajeev K. Ranjan   (rajeev@eecs.berkeley.edu)
+              ]
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calUtil.c,v 1.4 2002/09/10 00:10:37 fabio Exp $]
+
+******************************************************************************/
+
+#include "calInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* Random generator constants. */
+#define CAL_MODULUS1 2147483563
+#define CAL_LEQA1 40014
+#define CAL_LEQQ1 53668
+#define CAL_LEQR1 12211
+#define CAL_MODULUS2 2147483399
+#define CAL_LEQA2 40692
+#define CAL_LEQQ2 52774
+#define CAL_LEQR2 3791
+#define CAL_STAB_SIZE 64
+#define CAL_STAB_DIV (1 + (CAL_MODULUS1 - 1) / CAL_STAB_SIZE)
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static long utilRand = 0;
+static long utilRand2;
+static long shuffleSelect;
+static long shuffleTable[CAL_STAB_SIZE];
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+void
+Cal_ImageDump(Cal_BddManager_t *bddManager, FILE *fp)
+{
+
+  CalPageManager_t *pageManager;
+  int i, j;
+  char *segment, c;
+  int count = NUM_PAGES_PER_SEGMENT * PAGE_SIZE;
+
+  pageManager = bddManager->pageManager1;
+  for(i = 0; i < pageManager->numSegments; i++){
+    segment = (char *) pageManager->pageSegmentArray[i];
+    for(j = 1; j <= count; j++){
+      c = segment[j];
+      fprintf(fp, "%c", j%64?c:'\n');
+    }
+  }
+  pageManager = bddManager->pageManager2;
+  for(i = 0; i < pageManager->numSegments; i++){
+    segment = (char *) pageManager->pageSegmentArray[i];
+    for(j = 1; j <= count; j++){
+      c = segment[j];
+      fprintf(fp, "%c", j%64?c:'\n');
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the function implemented by the argument BDD]
+
+  Description [Prints the function implemented by the argument BDD]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cal_BddFunctionPrint(Cal_BddManager bddManager, Cal_Bdd  userBdd,
+                     char *name)
+{
+  Cal_Bdd_t calBdd;
+  calBdd = CalBddGetInternalBdd(bddManager, userBdd);
+  CalBddFunctionPrint(bddManager, calBdd, name);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalUniqueTablePrint(Cal_BddManager_t *bddManager)
+{
+  int i;
+  for(i = 0; i <= bddManager->numVars; i++){
+    CalHashTablePrint(bddManager->uniqueTable[i]);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the function implemented by the argument BDD]
+
+  Description [Prints the function implemented by the argument BDD]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+CalBddFunctionPrint(Cal_BddManager_t * bddManager,
+                    Cal_Bdd_t  calBdd,
+                    char * name)
+{
+  Cal_Bdd_t T,E;
+  Cal_BddId_t id;
+  char c;
+  static int level;
+
+  if(level == 0)printf("%s = ",name);
+  level++;
+  printf("( ");
+  if(CalBddIsBddZero(bddManager, calBdd)){
+    printf("0 ");
+  }
+  else if(CalBddIsBddOne(bddManager, calBdd)){
+    printf("1 ");
+  }
+  else{
+    id = CalBddGetBddId(calBdd);
+    c = (char)((int)'a' + id - 1);
+    printf("%c ", c);
+    CalBddGetCofactors(calBdd, id, T, E);
+    CalBddFunctionPrint(bddManager, T, " ");
+    printf("+ %c' ", c);
+    CalBddFunctionPrint(bddManager, E, " ");
+  }
+  level--;
+  printf(") ");
+  if(level == 0)printf("\n");
+}
+
+/**Function********************************************************************
+  
+  Synopsis    [required]
+  
+  Description [optional]
+  
+  SideEffects [required]
+  
+  SeeAlso     [optional]
+  
+******************************************************************************/
+#if HAVE_STDARG_H
+int
+CalBddPreProcessing(Cal_BddManager_t *bddManager, int count, ...)
+{
+  int allValid;
+  va_list ap;
+  Cal_Bdd fUserBdd;
+  Cal_Bdd_t f;
+  
+  va_start(ap, count);
+#else
+#  if HAVE_VARARGS_H
+int
+CalBddPreProcessing(va_alist)
+va_dcl
+{
+  int allValid;
+  va_list ap;
+  Cal_Bdd *fUserBdd;
+  int count;
+  Cal_BddManager_t *bddManager;
+  Cal_Bdd_t f;
+  
+  va_start(ap);
+  bddManager = va_arg(ap, Cal_BddManager_t *);
+  count = va_arg(ap, int);
+#  endif
+#endif  
+
+  allValid=1;
+  while (count){
+    fUserBdd = va_arg(ap, Cal_Bdd);
+	if (fUserBdd == 0){
+	  allValid=0;
+    }
+	else {
+      f = CalBddGetInternalBdd(bddManager, fUserBdd);
+      if (CalBddIsRefCountZero(f)){
+        CalBddFatalMessage("Bdd With Zero Reference Count Used.");
+      }
+    }
+    --count;
+  }
+  if (allValid) {
+    CalBddPostProcessing(bddManager);
+  }
+  va_end(ap);
+  return (allValid);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+CalBddPostProcessing(Cal_BddManager_t *bddManager)
+{
+  if (bddManager->gcCheck > 0) return CAL_BDD_OK;
+  bddManager->gcCheck = CAL_GC_CHECK;
+  if(bddManager->numNodes > bddManager->uniqueTableGCLimit){
+    long origNodes = bddManager->numNodes;
+    Cal_BddManagerGC(bddManager);
+    if ((bddManager->numNodes > bddManager->reorderingThreshold) &&
+        (3*bddManager->numNodes > 2* bddManager->uniqueTableGCLimit) &&
+        (bddManager->dynamicReorderingEnableFlag) &&
+        (bddManager->reorderTechnique != CAL_REORDER_NONE)){
+      CalCacheTableTwoFlush(bddManager->cacheTable);
+      if (bddManager->reorderMethod == CAL_REORDER_METHOD_BF){
+        CalBddReorderAuxBF(bddManager);
+      }
+      else{
+        CalBddReorderAuxDF(bddManager);
+      }
+    }
+    else {
+      /* Check if we should repack */
+      Cal_Assert(CalCheckAllValidity(bddManager));
+      if (bddManager->numNodes <
+          bddManager->repackAfterGCThreshold*origNodes){
+        CalRepackNodesAfterGC(bddManager);
+      }
+      Cal_Assert(CalCheckAllValidity(bddManager));
+    }
+    Cal_BddManagerSetGCLimit(bddManager);
+    if (bddManager->nodeLimit && (bddManager->numNodes >
+                                  bddManager->nodeLimit)){ 
+      CalBddWarningMessage("Overflow: Node Limit Exceeded");
+      bddManager->overflow = 1;
+      return CAL_BDD_OVERFLOWED;
+    }
+    /*
+     * Check to see if the cache table needs to be rehashed.
+     */
+    CalCacheTableRehash(bddManager);
+  }
+  return CAL_BDD_OK;
+}
+
+/**Function********************************************************************
+  
+  Synopsis    [required]
+  
+  Description [optional]
+  
+  SideEffects [required]
+  
+  SeeAlso     [optional]
+  
+******************************************************************************/
+int
+CalBddArrayPreProcessing(Cal_BddManager_t *bddManager, Cal_Bdd *userBddArray) 
+{
+  int i = 0;
+  Cal_Bdd userBdd;
+  while ((userBdd = userBddArray[i++])){
+    if (CalBddPreProcessing(bddManager, 1, userBdd) == 0){
+      return 0;
+    }
+  }
+  return 1;
+}
+    
+                       
+/**Function********************************************************************
+
+  Name        [CalBddFatalMessage]
+
+  Synopsis    [Prints fatal message and exits.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd_t
+CalBddGetInternalBdd(Cal_BddManager bddManager, Cal_Bdd userBdd)
+{
+  Cal_Bdd_t resultBdd;
+  if (CalBddNodeIsOutPos(userBdd)){
+    CalBddNodeGetThenBdd(userBdd, resultBdd);
+  }
+  else {
+    Cal_Bdd userBddNot = CalBddNodeNot(userBdd);
+    Cal_Bdd_t internalBdd;
+	CalBddNodeGetThenBdd(userBddNot,internalBdd);
+    CalBddNot(internalBdd, resultBdd);
+  }
+  return resultBdd;
+}
+
+/**Function********************************************************************
+
+  Name        [CalBddFatalMessage]
+
+  Synopsis    [Prints fatal message and exits.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+Cal_Bdd
+CalBddGetExternalBdd(Cal_BddManager_t *bddManager, Cal_Bdd_t internalBdd)
+{
+  CalHashTable_t *hashTableForUserBdd = bddManager->uniqueTable[0];
+  Cal_Bdd_t resultBdd;
+  int found;
+  
+  if(CalBddIsOutPos(internalBdd)){
+    found = CalHashTableFindOrAdd(hashTableForUserBdd, internalBdd,
+                          bddManager->bddOne, &resultBdd);
+  }
+  else {
+    Cal_Bdd_t internalBddNot;
+    CalBddNot(internalBdd, internalBddNot);
+    found = CalHashTableFindOrAdd(hashTableForUserBdd, internalBddNot,
+                          bddManager->bddOne, &resultBdd);
+    CalBddNot(resultBdd, resultBdd);
+  }
+  if (found == 0){
+    CalBddIcrRefCount(internalBdd);
+  }
+  CalBddIcrRefCount(resultBdd);
+  return CalBddGetBddNode(resultBdd);
+}
+
+
+/**Function********************************************************************
+
+  Name        [CalBddFatalMessage]
+
+  Synopsis    [Prints fatal message and exits.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddFatalMessage(char *string)
+{
+  (void) fprintf(stderr,"Fatal: %s\n", string);
+  exit(-1);
+}
+/**Function********************************************************************
+
+  Name        [CalBddWarningMessage]
+
+  Synopsis    [Prints warning message.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddWarningMessage(char *string)
+{
+  (void) fprintf(stderr,"Warning: %s\n", string);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalBddNodePrint(CalBddNode_t *bddNode)
+{
+  int refCount;
+  CalBddNodeGetRefCount(bddNode, refCount);
+  printf("Node (%lx) thenBdd(%2d %lx)  elseBdd(%2d %lx) ref_count (%d) next (%lx)\n",
+         (CalAddress_t)bddNode,
+         CalBddNodeGetThenBddId(bddNode),
+         (CalAddress_t) CalBddNodeGetThenBddNode(bddNode), 
+         CalBddNodeGetElseBddId(bddNode),
+         (CalAddress_t) CalBddNodeGetElseBddNode(bddNode),
+         refCount, (CalAddress_t)bddNode->nextBddNode);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+
+void
+CalBddPrint(Cal_Bdd_t calBdd)
+{
+  printf("Id(%2d) node(%lx) ",
+      CalBddGetBddId(calBdd), (CalAddress_t) CalBddGetBddNode(calBdd));
+  printf("thenBdd(%2d %lx)  elseBdd(%2d %lx)\n",
+         CalBddGetThenBddId(calBdd),
+         (CalAddress_t) CalBddGetThenBddNode(calBdd), 
+         CalBddGetElseBddId(calBdd),
+         (CalAddress_t) CalBddGetElseBddNode(calBdd));
+}
+
+#ifdef TEST_CALBDDNODE
+main(int argc, char **argv)
+{
+  CalBddNode_t *bddNode, *thenBddNode, *elseBddNode;
+
+  bddNode = Cal_MemAlloc(CalBddNode_t, 1);
+  thenBddNode = Cal_MemAlloc(CalBddNode_t, 1);
+  elseBddNode = Cal_MemAlloc(CalBddNode_t, 1);
+
+  CalBddNodePutThenBddId(bddNode, 1);
+  CalBddNodePutThenBddNode(bddNode, thenBddNode);
+  CalBddNodePutElseBddId(bddNode, 2);
+  CalBddNodePutElseBddNode(bddNode, elseBddNode);
+
+  printf("then( 1 %x) else( 2 %x)\n", thenBddNode, elseBddNode);
+  CalBddNodePrint(bddNode);
+}
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a hash table.]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTablePrint(CalHashTable_t *hashTable)
+{
+  int i;
+  CalBddNode_t *ptr;
+  Cal_Bdd_t calBdd, T, E;
+  int refCount, firstFlag;
+
+  printf("HashTable bddId(%d) entries(%ld) bins(%ld) capacity(%ld)\n",
+         hashTable->bddId, hashTable->numEntries, hashTable->numBins,
+         hashTable->maxCapacity);
+  for(i = 0; i < hashTable->numBins; i++){
+    ptr = hashTable->bins[i];
+    firstFlag = 1;
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      CalBddPutBddNode(calBdd, ptr);
+      CalBddNodeGetThenBdd(ptr, T);
+      CalBddNodeGetElseBdd(ptr, E);
+      if (firstFlag){
+        printf("\tbin = (%d) ", i);
+        firstFlag = 0;
+      }
+      printf("\t\tbddNode(%lx) ", (CalAddress_t)ptr);
+      printf("thenId(%d) ", CalBddGetBddId(T)); 
+      printf("thenBddNode(%lx) ", (CalAddress_t) CalBddGetBddNode(T));
+      printf("elseId(%d) ", CalBddGetBddId(E)); 
+      printf("elseBddNode(%lx) ", (unsigned long)CalBddGetBddNode(E));
+      CalBddGetRefCount(calBdd, refCount);
+      printf("refCount(%d)\n", refCount);
+      ptr = CalBddNodeGetNextBddNode(ptr);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CalHashTableOnePrint(CalHashTable_t *hashTable, int flag)
+{
+  int i;
+  CalBddNode_t *ptr, *node;
+  Cal_Bdd_t keyBdd;
+
+  printf("*************************************************\n");
+  for(i = 0; i < hashTable->numBins; i++){
+    ptr = hashTable->bins[i];
+    while(ptr != Cal_Nil(CalBddNode_t)){
+      CalBddNodeGetThenBdd(ptr, keyBdd);
+      node = CalBddNodeGetElseBddNode(ptr);
+      if(flag == 1){
+        printf("Key(%d %lx) Value(%f)\n", 
+            CalBddGetBddId(keyBdd), (CalAddress_t)CalBddGetBddNode(keyBdd), *(double *)node); 
+      }
+      else{
+        printf("Key(%d %lx) Value(%d)\n",
+            CalBddGetBddId(keyBdd), (CalAddress_t)CalBddGetBddNode(keyBdd),  *(int *)node); 
+      }
+      ptr = CalBddNodeGetNextBddNode(ptr);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initializer for the portable random number generator.]
+
+  Description [Initializer for the portable number generator based on
+  ran2 in "Numerical Recipes in C." The input is the seed for the
+  generator. If it is negative, its absolute value is taken as seed.
+  If it is 0, then 1 is taken as seed. The initialized sets up the two
+  recurrences used to generate a long-period stream, and sets up the
+  shuffle table.]
+
+  SideEffects [None]
+
+  SeeAlso     [CalUtilRandom]
+
+******************************************************************************/
+void
+CalUtilSRandom(long seed)
+{
+    int i;
+
+    if (seed < 0)       utilRand = -seed;
+    else if (seed == 0) utilRand = 1;
+    else                utilRand = seed;
+    utilRand2 = utilRand;
+    /* Load the shuffle table (after 11 warm-ups). */
+    for (i = 0; i < CAL_STAB_SIZE + 11; i++) {
+	long int w;
+	w = utilRand / CAL_LEQQ1;
+	utilRand = CAL_LEQA1 * (utilRand - w * CAL_LEQQ1) - w * CAL_LEQR1;
+	utilRand += (utilRand < 0) * CAL_MODULUS1;
+	shuffleTable[i % CAL_STAB_SIZE] = utilRand;
+    }
+    shuffleSelect = shuffleTable[1 % CAL_STAB_SIZE];
+} /* end of CalUtilSRandom */
+
+/**Function********************************************************************
+
+  Synopsis    [Portable random number generator.]
+
+  Description [Portable number generator based on ran2 from "Numerical
+  Recipes in C." It is a long period (> 2 * 10^18) random number generator
+  of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly
+  distributed between 0 and 2147483561 (inclusive of the endpoint values).
+  The random generator can be explicitly initialized by calling
+  CalUtilSRandom. If no explicit initialization is performed, then the
+  seed 1 is assumed.]
+
+  SideEffects []
+
+  SeeAlso     [CalUtilSRandom]
+
+******************************************************************************/
+long
+CalUtilRandom(void)
+{
+    int i;	/* index in the shuffle table */
+    long int w; /* work variable */
+
+    /* utilRand == 0 if the geneartor has not been initialized yet. */
+    if (utilRand == 0) CalUtilSRandom((long)1);
+
+    /* Compute utilRand = (utilRand * CAL_LEQA1) % CAL_MODULUS1 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = utilRand / CAL_LEQQ1;
+    utilRand   = CAL_LEQA1 * (utilRand - w * CAL_LEQQ1) - w * CAL_LEQR1;
+    utilRand  += (utilRand < 0) * CAL_MODULUS1;
+
+    /* Compute utilRand2 = (utilRand2 * CAL_LEQA2) % CAL_MODULUS2 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = utilRand2 / CAL_LEQQ2;
+    utilRand2  = CAL_LEQA2 * (utilRand2 - w * CAL_LEQQ2) - w * CAL_LEQR2;
+    utilRand2 += (utilRand2 < 0) * CAL_MODULUS2;
+
+    /* utilRand is shuffled with the Bays-Durham algorithm.
+    ** shuffleSelect and utilRand2 are combined to generate the output.
+    */
+
+    /* Pick one element from the shuffle table; "i" will be in the range
+    ** from 0 to CAL_STAB_SIZE-1.
+    */
+    i = shuffleSelect / CAL_STAB_DIV;
+    /* Mix the element of the shuffle table with the current iterate of
+    ** the second sub-generator, and replace the chosen element of the
+    ** shuffle table with the current iterate of the first sub-generator.
+    */
+    shuffleSelect   = shuffleTable[i] - utilRand2;
+    shuffleTable[i] = utilRand;
+    shuffleSelect  += (shuffleSelect < 1) * (CAL_MODULUS1 - 1);
+    /* Since shuffleSelect != 0, and we want to be able to return 0,
+    ** here we subtract 1 before returning.
+    */
+    return(shuffleSelect - 1);
+
+} /* end of CalUtilRandom */
+
+
Index: /vis_dev/glu-2.1/src/calBdd/credit.html
===================================================================
--- /vis_dev/glu-2.1/src/calBdd/credit.html	(revision 8)
+++ /vis_dev/glu-2.1/src/calBdd/credit.html	(revision 8)
@@ -0,0 +1,15 @@
+<HTML>
+<HEAD><TITLE>Credit</TITLE></HEAD>
+<BODY>
+<TABLE BORDER WIDTH="100%">
+  <TR>
+    <TD ALIGN=center> <A HREF="commands.html" TARGET="_top">
+        Command Documentation</A> </TD>
+    <TD ALIGN=center> <A HREF="packages.html" TARGET="_top">
+	Package Documentation</A> </TD>
+    <TD ALIGN=center> Generated by <A HREF="http://www.eecs.berkeley.edu/~sedwards/ext" TARGET="_top">
+        <B>the Ext system</B></A> </TD>
+  </TD>
+</TABLE>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/calPort/calPort.c
===================================================================
--- /vis_dev/glu-2.1/src/calPort/calPort.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calPort/calPort.c	(revision 8)
@@ -0,0 +1,3716 @@
+/**CFile***********************************************************************
+
+  FileName    [calPort.c]
+
+  PackageName [cal_port]
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "calPortInt.h"
+#ifndef	EPD_MAX_BIN
+#include "epd.h" 
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void InvalidType(FILE *file, char *field, char *expected);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Function to construct a bdd_t.]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+bdd_t *
+bdd_construct_bdd_t(bdd_manager *mgr, bdd_node *fn)
+{
+  bdd_t *result;
+  if (!fn){
+	fail("bdd_construct_bdd_t: possible memory overflow");
+  }
+  result = Cal_MemAlloc(bdd_t, 1);
+  result->bddManager = (Cal_BddManager_t *) mgr;
+  result->calBdd = (Cal_Bdd) fn;
+  result->free = 0;
+  return result;
+}
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_package_type_t
+bdd_get_package_name(void)
+{
+  return CAL;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+void
+bdd_end(void *manager)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  void *hooks;
+  hooks = Cal_BddManagerGetHooks(mgr);
+  Cal_MemFree(hooks); 
+  Cal_BddManagerQuit(mgr);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_manager *
+bdd_start(int nvariables)
+{
+  Cal_BddManager mgr;
+  int i;
+  bdd_external_hooks *hooks;
+  
+  mgr = Cal_BddManagerInit();
+  for (i = 0; i < nvariables; i++) {
+	(void) Cal_BddManagerCreateNewVarLast(mgr);
+  }
+  hooks = Cal_MemAlloc(bdd_external_hooks, 1);
+  hooks->mdd = hooks->network = hooks->undef1 = (char *) 0;
+  Cal_BddManagerSetHooks(mgr, (void *)hooks);
+  return (bdd_manager *)mgr;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_create_variable(bdd_manager *manager)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  return bdd_construct_bdd_t(mgr, Cal_BddManagerCreateNewVarLast(mgr));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_create_variable_after(bdd_manager *manager, bdd_variableId afterId)
+{
+  Cal_Bdd afterVar;
+  bdd_t 	*result;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  afterVar = Cal_BddManagerGetVarWithId(mgr, afterId + 1);
+  result =  bdd_construct_bdd_t(mgr,
+                                Cal_BddManagerCreateNewVarAfter(mgr,
+                                                                afterVar));  
+  
+  /* No need to free after_var, since single variable BDDs are never garbage collected */
+  
+  return result;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_get_variable(bdd_manager *manager, bdd_variableId varId)
+{
+  Cal_Bdd varBdd;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  varBdd = Cal_BddManagerGetVarWithId(mgr, varId + 1);
+  if (!varBdd){
+	fprintf(stderr,"bdd_get_variable: Variable has not been created");
+    exit(-1);
+  }
+  return bdd_construct_bdd_t(mgr, varBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_dup(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddIdentity(f->bddManager, f->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+void
+bdd_free(bdd_t *f)
+{
+  if (f == NIL(bdd_t)) {
+	fail("bdd_free: trying to free a NIL bdd_t");			
+  }
+  if (f->free){
+    fail("bdd_free: Trying to free a freed bdd_t");
+  }
+  Cal_BddFree(f->bddManager, f->calBdd);
+  f->calBdd = (Cal_Bdd) 0;
+  f->bddManager = NIL(Cal_BddManager_t);
+  f->free = 1;
+  Cal_MemFree(f);  
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_node *
+bdd_get_node(bdd_t *f, boolean *isComplemented)
+{
+  *isComplemented = CAL_TAG0(f->calBdd);
+  return (f->calBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_and(bdd_t *f,bdd_t *g, boolean f_phase, boolean g_phase)
+{
+  Cal_Bdd temp1, temp2;
+  bdd_t *result;
+  Cal_BddManager mgr;
+  
+  mgr = f->bddManager;
+  temp1 = ((f_phase == TRUE) ? Cal_BddIdentity(mgr, f->calBdd) :
+           Cal_BddNot(mgr, f->calBdd)); 
+  temp2 = ((g_phase == TRUE) ? Cal_BddIdentity(mgr, g->calBdd) :
+           Cal_BddNot(mgr, g->calBdd));
+  result = bdd_construct_bdd_t(mgr, Cal_BddAnd(mgr, temp1, temp2));
+  Cal_BddFree(mgr, temp1);
+  Cal_BddFree(mgr, temp2);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [AND of BDDs with limit on nodes created]
+
+  Description        [AND of BDDs with limit on nodes created.  This function
+  is not supported by the CAL package.  We fall back to the standard AND.]
+
+  SideEffects        [required]
+
+  SeeAlso            [bdd_and]
+******************************************************************************/
+bdd_t *
+bdd_and_with_limit(bdd_t *f, bdd_t *g, boolean f_phase, boolean g_phase, unsigned int limit)
+{
+  return bdd_and(f, g, f_phase, g_phase);
+}
+
+bdd_t *
+bdd_and_array(bdd_t *f, array_t *g_array, boolean f_phase, boolean g_phase)
+{
+  Cal_Bdd temp1, temp2, result;
+  bdd_t *g;
+  Cal_BddManager mgr;
+  int i;
+
+  mgr = f->bddManager;
+  result = ((f_phase == TRUE) ? Cal_BddIdentity(mgr, f->calBdd) :
+            Cal_BddNot(mgr, f->calBdd)); 
+
+  for (i = 0; i < array_n(g_array); i++) {
+    g = array_fetch(bdd_t *, g_array, i);
+    temp1 = result;
+    temp2 = ((g_phase == TRUE) ? Cal_BddIdentity(mgr, g->calBdd) :
+             Cal_BddNot(mgr, g->calBdd));
+    result = Cal_BddAnd(mgr, temp1, temp2);
+    Cal_BddFree(mgr, temp1);
+    Cal_BddFree(mgr, temp2);
+    if (result == NULL)
+      return(NULL);
+  }
+
+  return(bdd_construct_bdd_t(mgr, result));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_multiway_and(bdd_manager *manager, array_t *bddArray)
+{
+  int i;
+  Cal_Bdd *calBddArray;
+  bdd_t *operand, *result;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  
+  calBddArray = Cal_MemAlloc(Cal_Bdd, array_n(bddArray)+1);
+  for (i=0; i<array_n(bddArray); i++){
+    operand = array_fetch(bdd_t*, bddArray, i);
+    calBddArray[i] = operand->calBdd;
+  }
+  calBddArray[i] = (Cal_Bdd)0;
+  result = bdd_construct_bdd_t(mgr,
+                               Cal_BddMultiwayAnd(mgr, calBddArray));
+  Cal_MemFree(calBddArray);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_multiway_or(bdd_manager *manager, array_t *bddArray)
+{
+  int i;
+  Cal_Bdd *calBddArray;
+  bdd_t *operand, *result;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  
+  calBddArray = Cal_MemAlloc(Cal_Bdd, array_n(bddArray)+1);
+  for (i=0; i<array_n(bddArray); i++){
+    operand = array_fetch(bdd_t*, bddArray, i);
+    calBddArray[i] = operand->calBdd;
+  }
+  calBddArray[i] = (Cal_Bdd)0;
+  result = bdd_construct_bdd_t(mgr,
+                               Cal_BddMultiwayOr(mgr, calBddArray));
+  Cal_MemFree(calBddArray);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_multiway_xor(bdd_manager *manager, array_t *bddArray)
+{
+  int i;
+  Cal_Bdd *calBddArray;
+  bdd_t *operand, *result;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  
+  calBddArray = Cal_MemAlloc(Cal_Bdd, array_n(bddArray)+1);
+  for (i=0; i<array_n(bddArray); i++){
+    operand = array_fetch(bdd_t*, bddArray, i);
+    calBddArray[i] = operand->calBdd;
+  }
+  calBddArray[i] = (Cal_Bdd)0;
+  result = bdd_construct_bdd_t(mgr,
+                               Cal_BddMultiwayXor(mgr, calBddArray));
+  Cal_MemFree(calBddArray);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+array_t *
+bdd_pairwise_and(bdd_manager *manager, array_t *bddArray1,
+                 array_t *bddArray2) 
+{
+  int i;
+  array_t *resultArray;
+  Cal_Bdd *calBddArray, *calBddResultArray;
+  bdd_t *operand;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  
+  if (array_n(bddArray1) != array_n(bddArray2)){
+    fprintf(stderr, "bdd_pairwise_and: Arrays of different lengths.\n");
+    return NIL(array_t);
+  }
+  calBddArray = Cal_MemAlloc(Cal_Bdd, 2*array_n(bddArray1)+1);
+  for (i=0; i<array_n(bddArray1); i++){
+    operand = array_fetch(bdd_t*, bddArray1, i);
+    calBddArray[i<<1] = operand->calBdd;
+    operand = array_fetch(bdd_t*, bddArray2, i);
+    calBddArray[(i<<1)+1] = operand->calBdd;
+  }
+  calBddArray[i<<1] = (Cal_Bdd)0;
+  calBddResultArray = Cal_BddPairwiseAnd(mgr, calBddArray);
+  resultArray = array_alloc(bdd_t*, 0);
+  for (i=0; i<array_n(bddArray1); i++){
+    array_insert_last(bdd_t *, resultArray, 
+                      bdd_construct_bdd_t(mgr, calBddResultArray[i]));
+  }
+  Cal_MemFree(calBddArray);
+  Cal_MemFree(calBddResultArray);
+  return resultArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+array_t *
+bdd_pairwise_or(bdd_manager *manager, array_t *bddArray1,
+                array_t *bddArray2) 
+{
+  int i;
+  array_t *resultArray;
+  Cal_Bdd *calBddArray, *calBddResultArray;
+  bdd_t *operand;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  
+  if (array_n(bddArray1) != array_n(bddArray2)){
+    fprintf(stderr, "bdd_pairwise_or: Arrays of different lengths.\n");
+    return NIL(array_t);
+  }
+  calBddArray = Cal_MemAlloc(Cal_Bdd, 2*array_n(bddArray1)+1);
+  for (i=0; i<array_n(bddArray1); i++){
+    operand = array_fetch(bdd_t*, bddArray1, i);
+    calBddArray[i<<1] = operand->calBdd;
+    operand = array_fetch(bdd_t*, bddArray2, i);
+    calBddArray[(i<<1)+1] = operand->calBdd;
+  }
+  calBddArray[i<<1] = (Cal_Bdd)0;
+  calBddResultArray = Cal_BddPairwiseOr(mgr, calBddArray);
+  resultArray = array_alloc(bdd_t*, 0);
+  for (i=0; i<array_n(bddArray1); i++){
+    array_insert_last(bdd_t *, resultArray, 
+                      bdd_construct_bdd_t(mgr, calBddResultArray[i]));
+  }
+  Cal_MemFree(calBddArray);
+  Cal_MemFree(calBddResultArray);
+  return resultArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+array_t *
+bdd_pairwise_xor(bdd_manager *manager, array_t *bddArray1,
+                 array_t *bddArray2) 
+{
+  int i;
+  array_t *resultArray;
+  Cal_Bdd *calBddArray, *calBddResultArray;
+  bdd_t *operand;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  
+  if (array_n(bddArray1) != array_n(bddArray2)){
+    fprintf(stderr, "bdd_pairwise_xor: Arrays of different lengths.\n");
+    return NIL(array_t);
+  }
+  calBddArray = Cal_MemAlloc(Cal_Bdd, 2*array_n(bddArray1)+1);
+  for (i=0; i<array_n(bddArray1); i++){
+    operand = array_fetch(bdd_t*, bddArray1, i);
+    calBddArray[i<<1] = operand->calBdd;
+    operand = array_fetch(bdd_t*, bddArray2, i);
+    calBddArray[(i<<1)+1] = operand->calBdd;
+  }
+  calBddArray[i<<1] = (Cal_Bdd)0;
+  calBddResultArray = Cal_BddPairwiseXor(mgr, calBddArray);
+  resultArray = array_alloc(bdd_t*, 0);
+  for (i=0; i<array_n(bddArray1); i++){
+    array_insert_last(bdd_t *, resultArray, 
+                      bdd_construct_bdd_t(mgr, calBddResultArray[i]));
+  }
+  Cal_MemFree(calBddArray);
+  Cal_MemFree(calBddResultArray);
+  return resultArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_and_smooth(bdd_t *f, bdd_t *g, array_t *smoothingVars)
+{
+  int num_vars, i;
+  bdd_t *fn, *result;
+  Cal_Bdd *assoc;
+  Cal_BddManager mgr;
+  int assocId;
+  
+  num_vars = array_n(smoothingVars);
+  if (num_vars == 0) {
+    fprintf(stderr,"bdd_and_smooth: no smoothing variables");
+    return bdd_and(f, g, 1, 1);
+  }
+  mgr = f->bddManager;
+  assoc = Cal_MemAlloc(Cal_Bdd, num_vars+1);
+  for (i = 0; i < num_vars; i++) {
+	fn = array_fetch(bdd_t *, smoothingVars, i);
+	assoc[i] = fn->calBdd;
+  }
+  assoc[num_vars] = 0;
+  assocId = Cal_AssociationInit(mgr, assoc, 0);
+  Cal_AssociationSetCurrent(mgr, assocId);
+  result = bdd_construct_bdd_t(mgr, Cal_BddRelProd(mgr, f->calBdd, g->calBdd));
+  Cal_MemFree(assoc);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [Unsupported: Fall back to standard and_smooth]
+
+  SideEffects        [required]
+
+  SeeAlso            [bdd_and_smooth]
+
+******************************************************************************/
+bdd_t *
+bdd_and_smooth_with_limit(bdd_t *f, bdd_t *g, array_t *smoothingVars, unsigned int limit)
+{
+  return bdd_and_smooth(f, g, smoothingVars);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_between(bdd_t *fMin, bdd_t *fMax)
+{
+  return bdd_construct_bdd_t(fMin->bddManager,
+                             Cal_BddBetween(fMin->bddManager,
+                                            fMin->calBdd,
+                                            fMax->calBdd));
+}
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_cofactor(bdd_t *f,bdd_t *g)
+{
+  return bdd_construct_bdd_t(f->bddManager,
+                             Cal_BddCofactor(f->bddManager,
+                                             f->calBdd,
+                                             g->calBdd));  
+}
+
+bdd_t *
+bdd_cofactor_array(bdd_t *f, array_t *bddArray)
+{
+  bdd_t *operand;
+  Cal_Bdd result, temp;
+  int i;
+
+  result = Cal_BddIdentity(f->bddManager, f->calBdd);
+
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = Cal_BddCofactor(f->bddManager, result, operand->calBdd);
+    if (temp == NULL) {
+      Cal_BddFree(f->bddManager, result);
+      return(NULL);
+    }
+    Cal_BddFree(f->bddManager, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(f->bddManager, result));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_compose(bdd_t *f,bdd_t *v,bdd_t *g)
+{
+  return bdd_construct_bdd_t(f->bddManager,
+                             Cal_BddCompose(f->bddManager,
+                                            f->calBdd,
+                                            v->calBdd,
+                                            g->calBdd)); 
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_consensus(bdd_t *f, array_t *quantifyingVars)
+{
+  int num_vars, i;
+  bdd_t *fn, *result;
+  Cal_Bdd *assoc;
+  Cal_BddManager mgr;
+  
+  num_vars = array_n(quantifyingVars);
+  if (num_vars == 0) {
+    fprintf(stderr, "bdd_consensus: no smoothing variables");
+    return f;
+  }
+  mgr = f->bddManager;
+  assoc = Cal_MemAlloc(Cal_Bdd, num_vars+1);
+  for (i = 0; i < num_vars; i++) {
+	fn = array_fetch(bdd_t *, quantifyingVars, i);
+	assoc[i] = fn->calBdd;
+  }
+  assoc[num_vars] = 0;
+  Cal_TempAssociationInit(mgr, assoc, 0);
+  Cal_AssociationSetCurrent(mgr, -1);
+  result = bdd_construct_bdd_t(mgr, Cal_BddForAll(mgr, f->calBdd));
+  Cal_MemFree(assoc);
+  Cal_TempAssociationQuit(mgr);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_cproject(bdd_t *f,array_t *quantifyingVars)
+{
+  return NIL(bdd_t);
+  
+  /*
+  int num_vars, i;
+  bdd_t *fn, *result;
+  Cal_Bdd_t*assoc;
+  Cal_BddManager mgr;
+  
+  if (f == NIL(bdd_t))
+	fail ("bdd_cproject: invalid BDD");
+  
+  num_vars = array_n(quantifying_vars);
+  if (num_vars <= 0) {
+      printf("Warning: bdd_cproject: no projection variables\n");
+      result = bdd_dup(f);
+  }
+  else {
+    assoc = Cal_MemAlloc(Cal_Bdd_t, num_vars+1);
+    for (i = 0; i < num_vars; i++) {
+      fn = array_fetch(bdd_t *, quantifying_vars, i);
+      assoc[i] = fn->calBdd;
+    }
+    assoc[num_vars] = (struct bdd_ *) 0;
+    mgr = f->bddManager;
+    cmu_bdd_temp_assoc(mgr, assoc, 0);
+    (void) cmu_bdd_assoc(mgr, -1); 
+    result = bdd_construct_bdd_t(mgr, cmu_bdd_project(mgr, f->calBdd));
+    Cal_MemFree(assoc);
+  }
+  return result;
+  */
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_else(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddElse(f->bddManager, f->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_ite(bdd_t *i,bdd_t *t,bdd_t *e,boolean i_phase,
+        boolean t_phase,boolean e_phase) 
+{
+  Cal_Bdd temp1, temp2, temp3;
+  bdd_t *result;
+  Cal_BddManager mgr;
+  
+  mgr = i->bddManager;
+  temp1 = (i_phase ? Cal_BddIdentity(mgr, i->calBdd) : Cal_BddNot(mgr, i->calBdd));
+  temp2 = (t_phase ? Cal_BddIdentity(mgr, t->calBdd) : Cal_BddNot(mgr, t->calBdd));
+  temp3 = (e_phase ? Cal_BddIdentity(mgr, e->calBdd) : Cal_BddNot(mgr, e->calBdd));
+  result = bdd_construct_bdd_t(mgr, Cal_BddITE(mgr, temp1, temp2, temp3));
+  Cal_BddFree(mgr, temp1);
+  Cal_BddFree(mgr, temp2);
+  Cal_BddFree(mgr, temp3);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_minimize(bdd_t *f, bdd_t *c)
+{
+  return bdd_construct_bdd_t(f->bddManager,
+                             Cal_BddReduce(f->bddManager,
+                                           f->calBdd, c->calBdd));
+}
+
+bdd_t *
+bdd_minimize_array(bdd_t *f, array_t *bddArray)
+{
+  bdd_t *operand;
+  Cal_Bdd result, temp;
+  int i;
+
+  result = Cal_BddIdentity(f->bddManager, f->calBdd);
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = Cal_BddReduce(f->bddManager, result, operand->calBdd);
+    if (temp == NULL) {
+      Cal_BddFree(f->bddManager, result);
+      return(NULL);
+    }
+    Cal_BddFree(f->bddManager, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(f->bddManager, result));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_not(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddNot(f->bddManager, f->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_one(bdd_manager *manager)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  return bdd_construct_bdd_t(mgr, Cal_BddOne(mgr));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_or(bdd_t *f, bdd_t *g, boolean f_phase, boolean g_phase)
+{
+  Cal_Bdd temp1, temp2;
+  bdd_t *result;
+  Cal_BddManager mgr;
+
+  mgr = f->bddManager;
+  temp1 = (f_phase ? Cal_BddIdentity(mgr, f->calBdd) : Cal_BddNot(mgr, f->calBdd));
+  temp2 = (g_phase ? Cal_BddIdentity(mgr, g->calBdd) : Cal_BddNot(mgr, g->calBdd));
+  result = bdd_construct_bdd_t(mgr, Cal_BddOr(mgr, temp1, temp2));
+  Cal_BddFree(mgr, temp1);
+  Cal_BddFree(mgr, temp2);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_smooth(bdd_t *f, array_t *smoothingVars)
+{
+  int numVars, i;
+  bdd_t *fn, *result;
+  Cal_Bdd *assoc;
+  Cal_BddManager mgr;
+  int assocId;
+
+  numVars = array_n(smoothingVars);
+  if (numVars == 0) {
+	fprintf(stderr,"bdd_smooth: no smoothing variables");
+    return f;
+  }
+  mgr = f->bddManager;
+  assoc = Cal_MemAlloc(Cal_Bdd, numVars+1);
+  for (i = 0; i < numVars; i++) {
+	fn = array_fetch(bdd_t *, smoothingVars, i);
+	assoc[i] = fn->calBdd;
+  }
+  assoc[numVars] = 0;
+  assocId = Cal_AssociationInit(mgr, assoc, 0);
+  (void) Cal_AssociationSetCurrent(mgr, assocId);  /* set the temp
+                                                 association as the
+                                                 current association
+                                                 */ 
+  result = bdd_construct_bdd_t(mgr, Cal_BddExists(mgr, f->calBdd));
+  Cal_MemFree(assoc);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_substitute(bdd_t *f, array_t *old_array, array_t *new_array)
+{
+  int num_old_vars, num_new_vars, i;
+  bdd_t *fn_old, *fn_new, *result;
+  Cal_Bdd *assoc;
+  Cal_BddManager mgr;
+  int assocId;
+
+  num_old_vars = array_n(old_array);
+  num_new_vars = array_n(new_array);
+  if (num_old_vars != num_new_vars) {
+	fprintf(stderr,"bdd_substitute: mismatch of number of new and old variables"); 
+    exit(-1);
+  }
+  mgr = f->bddManager;
+  assoc = Cal_MemAlloc(Cal_Bdd, 2*num_old_vars+1);
+  for (i = 0; i < num_old_vars; i++) {
+	fn_old = array_fetch(bdd_t *, old_array, i);
+	fn_new = array_fetch(bdd_t *, new_array, i);
+	assoc[2*i]   = fn_old->calBdd;
+	assoc[2*i+1] = fn_new->calBdd;
+  }
+  assoc[2*num_old_vars] = 0;
+  assocId = Cal_AssociationInit(mgr, assoc, 1);
+  (void) Cal_AssociationSetCurrent(mgr, assocId);  
+  result = bdd_construct_bdd_t(mgr, Cal_BddSubstitute(mgr, f->calBdd));
+  Cal_MemFree(assoc);
+  Cal_TempAssociationQuit(mgr);
+  return result;
+}
+
+array_t *
+bdd_substitute_array(array_t *f_array, array_t *old_array, array_t *new_array)
+{
+  int	i;
+  bdd_t	*f, *new_;
+  array_t *substitute_array = array_alloc(bdd_t *, 0);
+
+  arrayForEachItem(bdd_t *, f_array, i, f) {
+    new_ = bdd_substitute(f, old_array, new_array);
+    array_insert_last(bdd_t *, substitute_array, new_);
+  }
+  return(substitute_array);
+}
+
+/**Function********************************************************************
+ 
+  Synopsis           [Returns the pointer of the BDD.]
+ 
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+ 
+******************************************************************************/
+void *
+bdd_pointer(bdd_t *f)
+{
+    return((void *)f->calBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_then(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddThen(f->bddManager, f->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_top_var(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddIf(f->bddManager, f->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_xnor(bdd_t *f,bdd_t *g)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddXnor(f->bddManager, f->calBdd, g->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_xor(bdd_t *f,bdd_t *g)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddXor(f->bddManager, f->calBdd, g->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_zero(bdd_manager *manager)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  return bdd_construct_bdd_t(mgr, Cal_BddZero(mgr));
+}
+
+/*
+Queries about BDD Formulas ----------------------------------------------------
+*/
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+boolean
+bdd_equal(bdd_t *f,bdd_t *g)
+{
+  return Cal_BddIsEqual(f->bddManager, f->calBdd, g->calBdd);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+boolean
+bdd_equal_mod_care_set(bdd_t *f, bdd_t *g, bdd_t *CareSet)
+{
+  bdd_t	*diffBdd;
+  boolean result;
+
+  if (bdd_equal(f, g))
+    return 1;
+
+  diffBdd = bdd_xor(f, g);
+
+  result = bdd_leq(diffBdd, CareSet, 1, 0);
+  bdd_free(diffBdd);
+
+  return(result);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_intersects(bdd_t *f,bdd_t *g)
+{
+  return bdd_construct_bdd_t(f->bddManager, Cal_BddIntersects(f->bddManager,
+                                                       f->calBdd,
+                                                       g->calBdd)); 
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_closest_cube(bdd_t *f,bdd_t *g,int *dist)
+{
+  return NIL(bdd_t); 
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+boolean
+bdd_is_tautology(bdd_t *f, boolean phase)
+{
+  return ((phase == TRUE) ? Cal_BddIsBddOne(f->bddManager, f->calBdd):
+          Cal_BddIsBddZero(f->bddManager, f->calBdd));
+  
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+boolean
+bdd_leq(bdd_t *f, bdd_t *g, boolean f_phase, boolean g_phase)
+{
+  Cal_Bdd temp1, temp2, impliesFn;
+  Cal_BddManager mgr;
+  boolean resultValue;
+  
+  mgr = f->bddManager;
+  temp1 = (f_phase ? Cal_BddIdentity(mgr, f->calBdd) : Cal_BddNot(mgr, f->calBdd));
+  temp2 = (g_phase ? Cal_BddIdentity(mgr, g->calBdd) : Cal_BddNot(mgr, g->calBdd));
+  impliesFn = Cal_BddImplies(mgr, temp1, temp2); /* returns a minterm
+                                                     of temp1*!temp2
+                                                     */ 
+  resultValue = Cal_BddIsBddZero(mgr, impliesFn);
+  Cal_BddFree(mgr, temp1);
+  Cal_BddFree(mgr, temp2);
+  Cal_BddFree(mgr, impliesFn);
+  return resultValue;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+boolean
+bdd_lequal_mod_care_set(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase,
+  bdd_t *careSet)
+{
+  bdd_t *temp;
+  boolean result;
+
+  if (bdd_leq(f, g, f_phase, g_phase))
+    return 1;
+
+  temp = bdd_and(f, careSet, f_phase, 1);
+
+  result = bdd_leq(temp, g, 1, g_phase);
+  bdd_free(temp);
+
+  return(result);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+boolean
+bdd_leq_array(bdd_t *f, array_t *g_array, boolean f_phase, boolean g_phase)
+{
+  int	i;
+  bdd_t	*g;
+  boolean result;
+
+  arrayForEachItem(bdd_t *, g_array, i, g) {
+    result = bdd_leq(f, g, f_phase, g_phase);
+    if (g_phase) {
+      if (!result)
+	return(0);
+    } else {
+      if (result)
+	return(1);
+    }
+  }
+  if (g_phase)
+    return(1);
+  else
+    return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+double 
+bdd_count_onset(bdd_t *f, array_t *var_array)
+{
+  int numVars;
+  double fraction;
+  numVars = array_n(var_array);
+  fraction = Cal_BddSatisfyingFraction(f->bddManager, f->calBdd);
+  return (fraction * pow((double) 2, (double) numVars));
+}
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms in the on set.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_epd_count_onset(
+  bdd_t *f,
+  array_t *var_array /* of bdd_t *'s */,
+  EpDouble *epd)
+{
+  double nMinterms;
+
+  nMinterms = bdd_count_onset(f, var_array);
+  EpdConvert(nMinterms, epd);
+  return 0;
+} /* end of bdd_epd_count_onset */
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+int
+bdd_get_free(bdd_t *f)
+{
+    return (f->free);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_manager *
+bdd_get_manager(bdd_t *f)
+{
+    return (bdd_manager *) (f->bddManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+var_set_t *
+bdd_get_support(bdd_t *f)
+{
+  Cal_Bdd *support, var;
+  Cal_BddManager mgr;
+  long num_vars;
+  var_set_t *result;
+  int id, i;
+  
+  mgr = f->bddManager;
+  num_vars = Cal_BddVars(mgr);
+  result = var_set_new((int) num_vars);
+  support = Cal_MemAlloc(Cal_Bdd, (num_vars+1) * sizeof(Cal_Bdd));
+  for (i = 0; i <= num_vars; ++i) {
+	support[i] = 0; 
+  }
+  
+  (void) Cal_BddSupport(mgr, f->calBdd, support);
+  for (i = 0; i < num_vars; ++i) {
+	var = support[i]; 
+	if (var) {
+      id = (int) (Cal_BddGetIfId(mgr, var) - 1);
+      var_set_set_elt(result, id);
+    }
+  }
+  
+  Cal_MemFree(support);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a BDD is a support of f.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_is_support_var(bdd_t *f, bdd_t *var)
+{
+    return(bdd_is_support_var_id(f, bdd_top_var_id(var)));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a BDD index is a support of f.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_is_support_var_id(bdd_t *f, int index)
+{
+  Cal_Bdd *support, var;
+  Cal_BddManager mgr;
+  long num_vars;
+  int id, i;
+  
+  mgr = f->bddManager;
+  num_vars = Cal_BddVars(mgr);
+  support = Cal_MemAlloc(Cal_Bdd, (num_vars+1) * sizeof(Cal_Bdd));
+  for (i = 0; i <= num_vars; ++i) {
+    support[i] = 0; 
+  }
+  
+  (void) Cal_BddSupport(mgr, f->calBdd, support);
+  for (i = 0; i < num_vars; ++i) {
+    var = support[i]; 
+    if (var) {
+      id = (int) (Cal_BddGetIfId(mgr, var) - 1);
+      if (id == index) {
+	Cal_MemFree(support);
+	return 1;
+      }
+    }
+  }
+  
+  Cal_MemFree(support);
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+array_t *
+bdd_get_varids(array_t *var_array)
+{
+  int i;
+  bdd_t *var;
+  array_t *result;
+  bdd_variableId varId;
+  
+  result = array_alloc(bdd_variableId, 0);
+  for (i = 0; i < array_n(var_array); i++) {
+    var = array_fetch(bdd_t *, var_array, i);
+    varId = (int) bdd_top_var_id(var);
+    array_insert_last(bdd_variableId, result, varId);
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+unsigned int 
+bdd_num_vars(bdd_manager *manager)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  return (Cal_BddVars(mgr));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+void
+bdd_print(bdd_t *f)
+{
+  Cal_BddPrintBdd(f->bddManager, f->calBdd, Cal_BddNamingFnNone,
+                  Cal_BddTerminalIdFnNone, (Cal_Pointer_t) 0, (FILE *)stdout); 
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+void
+bdd_print_stats(bdd_manager *manager, FILE *file)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  Cal_BddManagerGC(mgr);
+  Cal_BddStats(mgr, file);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+int
+bdd_size(bdd_t *f)
+{
+  return ((int) Cal_BddSize(f->bddManager, f->calBdd, 1));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the number of nodes of a BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_node_size(bdd_node *f)
+{
+    return(0);
+
+} /* end of bdd_node_size */
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+long
+bdd_size_multiple(array_t *bdd_array)
+{
+  long result;
+  Cal_Bdd *vector_bdd;
+  bdd_t *f;
+  int i;
+  Cal_BddManager mgr;
+  
+  if ((bdd_array == NIL(array_t)) || (array_n(bdd_array) == 0))
+    return 0;
+  
+  f = array_fetch(bdd_t*, bdd_array, 0);
+  mgr = f->bddManager;
+  vector_bdd = Cal_MemAlloc(Cal_Bdd, array_n(bdd_array)+1);
+  for(i=0; i<array_n(bdd_array);i++){
+    f = array_fetch(bdd_t*, bdd_array, i);
+    vector_bdd[i] = f->calBdd;
+  }
+  vector_bdd[array_n(bdd_array)] = 0;
+  result =  Cal_BddSizeMultiple(mgr, vector_bdd,1);
+  Cal_MemFree(vector_bdd);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_variableId
+bdd_top_var_id(bdd_t *f)
+{
+  return ((bdd_variableId) (Cal_BddGetIfId(f->bddManager, f->calBdd) - 1));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_external_hooks *
+bdd_get_external_hooks(bdd_manager *manager)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  return (bdd_external_hooks *) Cal_BddManagerGetHooks(mgr);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+void
+bdd_set_gc_mode(bdd_manager *manager,boolean no_gc)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  Cal_BddSetGCMode(mgr, (int) no_gc);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+void 
+bdd_dynamic_reordering(bdd_manager *manager, bdd_reorder_type_t
+                       algorithm_type, bdd_reorder_verbosity_t verbosity)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+    switch(algorithm_type) {
+      case BDD_REORDER_SIFT:
+        Cal_BddDynamicReordering(mgr, CAL_REORDER_SIFT);
+      break;
+      case BDD_REORDER_WINDOW:
+        Cal_BddDynamicReordering(mgr, CAL_REORDER_WINDOW);
+      break;
+      case BDD_REORDER_NONE:
+        Cal_BddDynamicReordering(mgr, CAL_REORDER_NONE);
+      break;
+      default:
+        fprintf(stderr,"CAL: bdd_dynamic_reordering: unknown algorithm type\n");
+        fprintf(stderr,"Using SIFT method instead\n");
+        Cal_BddDynamicReordering(mgr, CAL_REORDER_SIFT);
+    }
+  
+}
+
+void 
+bdd_dynamic_reordering_zdd(bdd_manager *manager, bdd_reorder_type_t
+                       algorithm_type, bdd_reorder_verbosity_t verbosity)
+{
+    return;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+void 
+bdd_reorder(bdd_manager *manager)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  Cal_BddReorder(mgr);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_variableId
+bdd_get_id_from_level(bdd_manager *manager, long level)
+{
+  Cal_Bdd fn;
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  fn = Cal_BddManagerGetVarWithIndex(mgr, level);
+  if (!fn){
+    /* variable should always be found, since they are created at bdd_start */
+    fprintf(stderr, "bdd_get_id_from_level: assumption violated");
+    exit(-1);
+  }
+  return ((bdd_variableId)(Cal_BddGetIfId(mgr, fn) - 1 ));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+long
+bdd_top_var_level(bdd_manager *manager, bdd_t *fn)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  return (long)Cal_BddGetIfIndex(mgr, fn->calBdd);
+}
+
+/*
+ */
+/**Function********************************************************************
+
+  Synopsis           [Return TRUE if f is a cube, else return FALSE.]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+boolean
+bdd_is_cube(bdd_t *f)
+{
+  Cal_BddManager mgr;
+  if (f == NIL(bdd_t)) {
+    fail("bdd_is_cube: invalid BDD");
+  }
+  if(f->free) fail ("Freed Bdd passed to bdd_is_cube");
+  mgr = f->bddManager;
+  return ((boolean)Cal_BddIsCube(mgr, f->calBdd));
+}
+
+/**Function********************************************************************
+
+  Synopsis           []
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_block *
+bdd_new_var_block(bdd_t *f, long length)
+{
+	return (bdd_block *) Cal_BddNewVarBlock(f->bddManager, f->calBdd, length);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Return TRUE if f is a cube, else return FALSE.]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_t *
+bdd_var_with_index(bdd_manager *manager, int index)
+{
+  Cal_BddManager mgr = (Cal_BddManager) manager;
+  return bdd_construct_bdd_t(mgr,
+                             Cal_BddManagerGetVarWithIndex(mgr,
+                                                           index)); 
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the internal parameters of the package to the given values.]
+
+  Description [The CAL package has a set of parameters that can be assigned
+  different values. This function receives a table which maps strings to
+  values and sets the parameters represented by the strings to the pertinent
+  values. Some basic type checking is done. It returns 1 if everything is
+  correct and 0 otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_set_parameters(
+  bdd_manager *mgr,
+  avl_tree *valueTable,
+  FILE *file)
+{
+  /* int reorderMethod; */
+  st_table *newValueTable;
+  st_generator *stgen;
+  avl_generator *avlgen;
+  char *paramName;
+  char *paramValue;
+  Cal_BddManager bddManager = (Cal_BddManager)mgr;
+  
+
+  /* Build a new table with the parameter names but with
+  ** the prefix removed. */
+  newValueTable = st_init_table(st_ptrcmp, st_ptrhash);
+  avl_foreach_item(valueTable, avlgen, AVL_FORWARD, (char **)&paramName, 
+                   (char **)&paramValue) {
+    if (strncmp(paramName, "BDD.", 4) == 0) {
+      st_insert(newValueTable, (char *)&paramName[4],
+                (char *)paramValue);
+    }
+  }
+  
+  st_foreach_item(newValueTable, stgen, &paramName, &paramValue) {
+    unsigned int uvalue;
+    double value;
+    char *invalidChar;
+    
+    invalidChar = NIL(char);
+    
+    if (strcmp(paramName, "Node limit") == 0) {
+      uvalue = (unsigned int) strtol(paramValue, &invalidChar, 10);
+      /* RB an unsigned will never be < 0 */
+      if (*invalidChar /*|| uvalue < 0*/) {
+	InvalidType(file, "Node limit", "unsigned integer");
+      }
+      else {
+	bddManager->nodeLimit = uvalue;
+      }
+    }
+    else if (strcmp(paramName, "Garbage collection enabled") == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	bddManager->gcMode = 1;
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	bddManager->gcMode = 0;
+      }
+      else {
+	InvalidType(file, "Garbage collection enabled", "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, 
+		    "Maximum number of variables sifted per reordering") == 0) {
+      uvalue = (unsigned int) strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar /*|| uvalue < 0*/) {
+	InvalidType(file, "Maximum number of variables sifted per reordering",
+		    "unsigned integer");
+      }
+      else {
+	bddManager->maxNumVarsSiftedPerReordering = uvalue;
+      }
+    }
+    else if (strcmp(paramName,
+		    "Maximum number of variable swaps per reordering") == 0) {
+      uvalue = (unsigned int) strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar /*|| uvalue < 0*/) {
+	InvalidType(file, "Maximum number of variable swaps per reordering", 
+		    "unsigned integer");
+      }
+      else {
+	bddManager->maxNumSwapsPerReordering = uvalue;
+      }
+    }
+    else if (strcmp(paramName, 
+		    "Maximum growth while sifting a variable") == 0) {
+      value = strtod(paramValue, &invalidChar);
+      if (*invalidChar) {
+	InvalidType(file, "Maximum growth while sifting a variable",
+		    "real");
+      }
+      else {
+	bddManager->maxSiftingGrowth = value;
+      }
+    }
+    else if (strcmp(paramName, "Dynamic reordering of BDDs enabled") == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	bddManager->dynamicReorderingEnableFlag = 1;
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	bddManager->dynamicReorderingEnableFlag = 0;
+      }
+      else {
+	InvalidType(file, "Dynamic reordering of BDDs enabled",
+		    "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, "Use old reordering")
+	     == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	bddManager->reorderMethod = CAL_REORDER_METHOD_BF;
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	bddManager->reorderMethod = CAL_REORDER_METHOD_DF;
+      }
+      else {
+	InvalidType(file, "Dynamic reordering of BDDs enabled",
+		    "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, "Dynamic reordering threshold") == 0) {
+      uvalue = (unsigned int) strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar /*|| uvalue < 0*/) {
+        InvalidType(file, "Dynamic reordering threshold", "unsigned integer");
+      }
+      else {
+        bddManager->reorderingThreshold = uvalue;
+      }
+    }
+    else if (strcmp(paramName, "Repacking after GC threshold")
+	     == 0) {
+      value = strtod(paramValue, &invalidChar);
+      if (*invalidChar || value < 0) {
+        InvalidType(file, "Repacking after GC threshold", "unsigned real");
+      }
+      else {
+        bddManager->repackAfterGCThreshold = value;
+      }
+    }
+    else if (strcmp(paramName, "Table repacking threshold")
+	     == 0) {
+      value = strtod(paramValue, &invalidChar);
+      if (*invalidChar || value < 0) {
+        InvalidType(file, "Table repacking threshold", "unsigned real");
+      }
+      else {
+        bddManager->tableRepackThreshold = value;
+      }
+    }
+    else {
+      (void) fprintf(file, "Warning: Parameter %s not recognized.",
+                     paramName);
+      (void) fprintf(file, " Ignored.\n");
+    }
+  } /* end of st_foreach_item */
+  
+  /* Clean up. */
+  st_free_table(newValueTable);
+  
+  return(1);
+  
+} /* end of bdd_set_parameters */
+
+/**Function********************************************************************
+
+  Synopsis    [Dummy functions defined in bdd.h]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_compact(bdd_t *f, bdd_t *g)
+{
+    return 0;
+}
+
+bdd_t *
+bdd_squeeze(bdd_t *f, bdd_t *g)
+{
+    return 0;
+}
+bdd_t *
+bdd_clipping_and_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars	/* of bdd_t *'s */,
+  int maxDepth,
+  int over)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_hb(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_sp(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  int hardlimit)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_ua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  int safe,
+  double quality)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_remap_ua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  double quality)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_biased_rua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  bdd_t *bias,
+  int numVars,
+  int threshold,
+  double quality,
+  double quality1)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_compress(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold)
+{
+  return NIL(bdd_t);
+}
+
+int
+bdd_gen_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t ***conjArray)
+{
+  return 0;
+}
+
+int
+bdd_var_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t ***conjArray)
+{
+  return 0;
+}
+
+int 
+bdd_approx_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t ***conjArray)
+{
+  return 0;
+}
+
+int
+bdd_add_hook(
+  bdd_manager *mgr,
+  int (*procedure)(bdd_manager *, char *, void *),
+  bdd_hook_type_t whichHook)
+{
+  return 0;
+}
+
+int
+bdd_remove_hook(
+  bdd_manager *mgr,
+  int (*procedure)(bdd_manager *, char *, void *),
+  bdd_hook_type_t whichHook)
+{
+  return 0;
+}
+
+int
+bdd_enable_reordering_reporting(bdd_manager *mgr)
+{
+  return 0;
+}
+int
+bdd_disable_reordering_reporting(bdd_manager *mgr)
+{
+  return 0;
+}
+
+bdd_reorder_verbosity_t 
+bdd_reordering_reporting(bdd_manager *mgr)
+{
+  return BDD_REORDER_VERBOSITY_DEFAULT;
+}
+
+int 
+bdd_print_apa_minterm(
+  FILE *fp,
+  bdd_t *f,
+  int nvars,
+  int precision)
+{
+  return 0;
+}
+
+int 
+bdd_apa_compare_ratios(
+  int nvars,
+  bdd_t *f1,
+  bdd_t *f2,
+  int f1Num,
+  int f2Num)
+{
+  return 0;
+}
+
+int
+bdd_iter_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t  ***conjArray)
+{
+  return 0;
+}
+
+int
+bdd_reordering_status(
+  bdd_manager *mgr,
+  bdd_reorder_type_t *method)
+{
+  return 0;
+}
+
+int
+bdd_read_node_count(bdd_manager *mgr)
+{
+  return 0;
+}
+
+double
+bdd_correlation(bdd_t *f, bdd_t *g)
+{
+    return 0.0;
+}
+
+
+bdd_t *
+bdd_pick_one_minterm(bdd_t *f, array_t *varsArray)
+{
+    return NIL(bdd_t);
+}
+
+array_t *
+bdd_bdd_pick_arbitrary_minterms(
+  bdd_t *f,
+  array_t *varsArray,
+  int n,
+  int k)
+{
+    return NIL(array_t);
+}
+
+
+int
+bdd_reordering_zdd_status(
+  bdd_manager *mgr,
+  bdd_reorder_type_t *method)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_bdd_to_add(
+  bdd_manager *mgr,
+  bdd_node *fn)
+{
+  return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_add_permute(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  int *permut)
+{
+  return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_permute(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  int *permut)
+{
+  return NIL(bdd_node);
+}
+
+
+void
+bdd_ref(bdd_node *fn)
+{
+  return ;
+}
+
+
+void
+bdd_recursive_deref(bdd_manager *mgr, bdd_node *f)
+{
+  return;
+}
+
+
+bdd_node *
+bdd_add_exist_abstract(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *vars)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_apply(
+  bdd_manager *mgr,
+  bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **),
+  bdd_node *fn1,
+  bdd_node *fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_nonsim_compose(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node **vector)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_residue(
+  bdd_manager *mgr,
+  int n,
+  int m,
+  int options,
+  int top)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node **vector)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_times(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_check_zero_ref(bdd_manager *mgr)
+{
+  return 0;
+}
+
+
+void
+bdd_dynamic_reordering_disable(bdd_manager *mgr)
+{
+  return;
+}
+
+void
+bdd_dynamic_reordering_zdd_disable(bdd_manager *mgr)
+{
+  return;
+}
+
+
+bdd_node *
+bdd_add_xnor(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_shuffle_heap(
+  bdd_manager *mgr,
+  int *permut)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_add_compose(
+  bdd_manager *mgr,
+  bdd_node *fn1,
+  bdd_node *fn2,
+  int var)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_ith_var(
+  bdd_manager *mgr,
+  int i)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_get_level_from_id(
+  bdd_manager *mgr,
+  int id)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_bdd_exist_abstract(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *cube)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_equal_sup_norm(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *gn,
+  BDD_VALUE_TYPE tolerance,
+  int pr)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_read_logic_zero(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_ith_var(
+  bdd_manager *mgr,
+  int i)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_divide(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_constrain(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *c)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_restrict(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *c)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_hamming(
+  bdd_manager *mgr,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  int nVars)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_ite(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *h)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_find_max(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+
+int
+bdd_bdd_pick_one_cube(
+  bdd_manager *mgr,
+  bdd_node *node,
+  char *string)
+{
+    return 0;
+}
+
+
+bdd_node *
+bdd_add_swap_variables(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  bdd_node **y,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_swap_variables(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  bdd_node **y,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_or(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_t *
+bdd_compute_cube(
+  bdd_manager *mgr,
+  array_t *vars)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_compute_cube_with_phase(
+  bdd_manager *mgr,
+  array_t *vars,
+  array_t *phase)
+{
+  return NIL(bdd_t);
+}
+
+
+bdd_node *
+bdd_bdd_compute_cube(
+  bdd_manager *mgr,
+  bdd_node **vars,
+  int *phase,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_indices_to_cube(
+  bdd_manager *mgr,
+  int *idArray,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_and(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_matrix_multiply(
+  bdd_manager *mgr,
+  bdd_node *A,
+  bdd_node *B,
+  bdd_node **z,
+  int nz)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_compute_cube(
+  bdd_manager *mgr,
+  bdd_node **vars,
+  int *phase,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_const(
+  bdd_manager *mgr,
+  BDD_VALUE_TYPE c)
+{
+    return NIL(bdd_node);
+}
+
+
+double
+bdd_count_minterm(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int n)
+{
+    return 0;
+}
+
+
+bdd_node *
+bdd_add_bdd_threshold(
+  bdd_manager *mgr,
+  bdd_node *f,
+  BDD_VALUE_TYPE value)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_bdd_strict_threshold(
+  bdd_manager *mgr,
+  bdd_node *f,
+  BDD_VALUE_TYPE value)
+{
+    return NIL(bdd_node);
+}
+
+BDD_VALUE_TYPE
+bdd_read_epsilon(bdd_manager *mgr)
+{
+    return 0;
+}
+
+bdd_node *
+bdd_read_one(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_pick_one_minterm(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vars,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_read_zero(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_new_var(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_and_abstract(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *cube)
+{
+    return NIL(bdd_node);
+}
+
+void
+bdd_deref(bdd_node *f)
+{
+    return;
+}
+
+bdd_node *
+bdd_add_plus(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_read_reorderings(bdd_manager *mgr)
+{
+    return 0;
+}
+
+int
+bdd_read_next_reordering(bdd_manager *mgr)
+{
+    return 0;
+}
+
+void
+bdd_set_next_reordering(bdd_manager *mgr, int next)
+{
+}
+
+bdd_node *
+bdd_bdd_xnor(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vector)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_extract_node_as_is(bdd_t *fn)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_zdd_get_node(
+  bdd_manager *mgr,
+  int id,
+  bdd_node *g,
+  bdd_node *h)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_product(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_product_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_union(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return(NIL(bdd_node));
+}
+
+
+bdd_node *
+bdd_zdd_weak_div(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_weak_div_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_isop_recur(
+  bdd_manager *mgr,
+  bdd_node *L,
+  bdd_node *U,
+  bdd_node **zdd_I)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_isop(
+  bdd_manager *mgr,
+  bdd_node *L,
+  bdd_node *U,
+  bdd_node **zdd_I)
+{
+    return NIL(bdd_node);
+}
+
+int
+bdd_zdd_get_cofactors3(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int v,
+  bdd_node **f1,
+  bdd_node **f0,
+  bdd_node **fd)
+{
+    return 0;
+}
+
+bdd_node *
+bdd_bdd_and_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+     return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_unique_inter(
+  bdd_manager *mgr,
+  int v,
+  bdd_node *f,
+  bdd_node *g)
+{
+     return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_unique_inter_ivo(
+  bdd_manager *mgr,
+  int v,
+  bdd_node *f,
+  bdd_node *g)
+{
+     return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_zdd_diff(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_diff_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+} 
+
+int
+bdd_num_zdd_vars(bdd_manager *mgr)
+{
+    return -1;
+}
+
+bdd_node *
+bdd_regular(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+int
+bdd_is_constant(bdd_node *f)
+{
+    return 0;
+}
+
+int
+bdd_is_complement(bdd_node *f)
+{
+    return 0;
+}
+
+bdd_node *
+bdd_bdd_T(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_E(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_not_bdd_node(bdd_node *f)
+{
+    return NIL(bdd_node);
+} 
+
+void
+bdd_recursive_deref_zdd(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+    return;
+} 
+
+int
+bdd_zdd_count(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+    return 0;
+}
+
+int
+bdd_read_zdd_level(
+  bdd_manager *mgr,
+  int index)
+{
+    return -1;
+} 
+
+int
+bdd_zdd_vars_from_bdd_vars(
+  bdd_manager *mgr,
+  int multiplicity)
+{
+   return 0;
+} 
+
+void
+bdd_zdd_realign_enable(bdd_manager *mgr)
+{
+    return;
+} 
+
+void
+bdd_zdd_realign_disable(bdd_manager *mgr)
+{
+    return;
+} 
+
+int
+bdd_zdd_realignment_enabled(bdd_manager *mgr)
+{
+    return 0;
+} 
+
+void
+bdd_realign_enable(bdd_manager *mgr)
+{
+    return;
+} 
+
+void
+bdd_realign_disable(bdd_manager *mgr)
+{
+    return;
+} 
+
+int
+bdd_realignment_enabled(bdd_manager *mgr)
+{
+    return 0;
+} 
+
+int
+bdd_node_read_index(bdd_node *f)
+{
+    return -1;
+}
+
+bdd_node *
+bdd_read_next(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+void
+bdd_set_next(bdd_node *f, bdd_node *g)
+{
+    return;
+}
+
+int
+bdd_read_reordered_field(bdd_manager *mgr)
+{
+    return -1;
+}
+
+void
+bdd_set_reordered_field(bdd_manager *mgr, int n)
+{
+    return;
+}
+
+bdd_node *
+bdd_add_apply_recur(
+  bdd_manager *mgr,
+  bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **),
+  bdd_node *fn1,
+  bdd_node *fn2)
+{
+    return NIL(bdd_node);
+}
+
+
+BDD_VALUE_TYPE
+bdd_add_value(bdd_node *f)
+{
+    return 0.0; 
+}
+
+int
+bdd_print_minterm(bdd_t *f)
+{
+  return 0;
+}
+
+
+bdd_t *
+bdd_xor_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars)
+{
+    return NIL(bdd_t);
+}
+
+
+bdd_node *
+bdd_read_plus_infinity(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_read_plus_infinity */
+
+
+
+bdd_node *
+bdd_priority_select(
+  bdd_manager *mgr,
+  bdd_node *R,
+  bdd_node  **x,
+  bdd_node **y,
+  bdd_node **z,
+  bdd_node *Pi,
+  int n,
+  bdd_node  *(*Pifunc)(bdd_manager *, int, bdd_node **, bdd_node **, bdd_node **))
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_priority_select */
+
+
+void
+bdd_set_background(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+    return;
+ 
+} /* end of bdd_set_background */
+
+
+bdd_node *
+bdd_read_background(bdd_manager *mgr)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_read_background */
+
+
+bdd_node *
+bdd_bdd_cofactor(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_cofactor */
+
+
+bdd_node *
+bdd_bdd_ite(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *h)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_ite */
+
+
+bdd_node *
+bdd_add_minus(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_add_plus */
+
+
+bdd_node *
+bdd_dxygtdxz(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y,
+  bdd_node **z)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_dxygtdxz */
+
+
+bdd_node *
+bdd_bdd_univ_abstract(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *vars)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_univ_abstract */
+
+
+bdd_node *
+bdd_bdd_cprojection(
+  bdd_manager *mgr,
+  bdd_node *R,
+  bdd_node *Y)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_cprojection */
+
+bdd_node *
+bdd_xeqy(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_xeqy */
+
+bdd_node *
+bdd_add_roundoff(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int N)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_add_roundoff */
+
+bdd_node *
+bdd_xgty(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_xgty */
+
+bdd_node *
+bdd_add_cmpl(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_add_cmpl */
+
+bdd_node *
+bdd_split_set(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  int n,
+  double m)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_split_set */
+
+
+int
+bdd_debug_check(bdd_manager *mgr)
+{
+    return -1;
+
+} /* end of bdd_debug_check */
+
+bdd_node *
+bdd_bdd_xor(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+void 
+bdd_dump_blif(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  char *model,
+  FILE *fp)
+{
+  return;
+}
+
+void 
+bdd_dump_blif_body(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  FILE *fp)
+{
+  return;
+}
+
+void 
+bdd_dump_dot(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  FILE *fp)
+{
+  return;
+}
+
+bdd_node *
+bdd_make_bdd_from_zdd_cover(bdd_manager *mgr, bdd_node *node)
+{
+    return(NIL(bdd_node));
+}
+
+bdd_node *
+bdd_zdd_complement(bdd_manager *mgr, bdd_node *node)
+{
+    return(NIL(bdd_node));
+}
+
+bdd_node *
+bdd_bdd_vector_support(
+  bdd_manager *mgr,
+  bdd_node **F,
+  int n)
+{
+  return NIL(bdd_node);
+}
+
+int
+bdd_bdd_vector_support_size(
+  bdd_manager *mgr,
+  bdd_node **F,
+  int n)
+{
+  return -1;
+}
+
+
+int
+bdd_bdd_support_size(
+  bdd_manager *mgr,
+  bdd_node *F)
+{
+  return -1;
+}
+
+bdd_node *
+bdd_bdd_support(
+  bdd_manager *mgr,
+  bdd_node *F)
+{
+  return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_add_general_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vectorOn,
+  bdd_node **vectorOff)
+{
+  return NIL(bdd_node);
+}
+
+int
+bdd_bdd_leq(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+  return -1;
+} 
+
+bdd_node *
+bdd_bdd_boolean_diff(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int x)
+{
+  return NIL(bdd_node);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two bdds are same.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_ptrcmp(bdd_t *f, bdd_t *g)
+{
+  if (f->calBdd == g->calBdd)
+    return(0);
+  else
+    return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash value of a bdd.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_ptrhash(bdd_t *f, int size)
+{
+  int hash;
+
+  hash = (int)((unsigned long)f->calBdd >> 2) % size;
+  return(hash);
+}
+
+bdd_t *
+bdd_subset_with_mask_vars(
+  bdd_t *f,
+  array_t *varsArray,
+  array_t *maskVarsArray)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_and_smooth_with_cube(
+  bdd_t *f,
+  bdd_t *g,
+  bdd_t *cube)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_smooth_with_cube(bdd_t *f, bdd_t *cube)
+{
+  int i;
+  bdd_t *var, *res;
+  array_t *smoothingVars;
+  var_set_t *supportVarSet;
+
+  smoothingVars = array_alloc(bdd_t *, 0);
+  supportVarSet = bdd_get_support(f);
+  for (i = 0; i < supportVarSet->n_elts; i++) {
+    if (var_set_get_elt(supportVarSet, i) == 1) {
+      var = bdd_var_with_index(f->bddManager, i);
+      array_insert_last(bdd_t *, smoothingVars, var);
+    }
+  }
+  var_set_free(supportVarSet);
+
+  res = bdd_smooth(f, smoothingVars);
+
+  for (i = 0; i < array_n(smoothingVars); i++) {
+    var = array_fetch(bdd_t *, smoothingVars, i);
+    bdd_free(var);
+  }
+  array_free(smoothingVars);
+  return res;
+}
+
+bdd_t *
+bdd_substitute_with_permut(bdd_t *f, int *permut)
+{
+  return NIL(bdd_t);
+}
+
+array_t *
+bdd_substitute_array_with_permut(array_t *f_array, int *permut)
+{
+  return NIL(array_t);
+}
+
+bdd_t *
+bdd_vector_compose(
+  bdd_t *f,
+  array_t *varArray,
+  array_t *funcArray)
+{
+  return NIL(bdd_t);
+}
+
+double *
+bdd_cof_minterm(bdd_t *f)
+{
+  return(NIL(double));
+}
+
+int
+bdd_var_is_dependent(
+  bdd_t *f,
+  bdd_t *var)
+{
+  return(0);
+}
+
+array_t *
+bdd_find_essential(bdd_t *f)
+{
+  return(NIL(array_t));
+}
+
+bdd_t *
+bdd_find_essential_cube(bdd_t *f)
+{
+  return(NIL(bdd_t));
+}
+
+int
+bdd_estimate_cofactor(
+  bdd_t *f,
+  bdd_t *var,
+  int phase)
+{
+  return(0);
+}
+
+long
+bdd_read_peak_memory(bdd_manager *mgr)
+{
+  return(0);
+}
+
+int
+bdd_read_peak_live_node(bdd_manager *mgr)
+{
+  return(0);
+}
+
+int
+bdd_set_pi_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_set_ps_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_set_ns_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_is_pi_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_is_ps_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_is_ns_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_set_pair_index(
+  bdd_manager *mgr,
+  int index,
+  int pairIndex)
+{
+    return(0);
+}
+
+int
+bdd_read_pair_index(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_set_var_to_be_grouped(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_set_var_hard_group(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_reset_var_to_be_grouped(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_is_var_to_be_grouped(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_is_var_hard_group(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_is_var_to_be_ungrouped(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_set_var_to_be_ungrouped(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_bind_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_unbind_var(
+  bdd_manager *mgr,
+  int index)
+{
+    return(0);
+}
+
+int
+bdd_is_lazy_sift(bdd_manager *mgr)
+{
+    return(0);
+}
+
+void
+bdd_discard_all_var_groups(bdd_manager *mgr)
+{
+    return;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Function to print a warning that an illegal value was read.]
+
+  SideEffects        []
+
+  SeeAlso            [bdd_set_parameters]
+
+******************************************************************************/
+static void
+InvalidType(
+  FILE *file,
+  char *field,
+  char *expected)
+{
+    (void) fprintf(file, "Warning: In parameter \"%s\"\n", field);
+    (void) fprintf(file, "Illegal type detected. %s expected\n", expected);
+
+} /* end of InvalidType */
Index: /vis_dev/glu-2.1/src/calPort/calPort.make
===================================================================
--- /vis_dev/glu-2.1/src/calPort/calPort.make	(revision 8)
+++ /vis_dev/glu-2.1/src/calPort/calPort.make	(revision 8)
@@ -0,0 +1,4 @@
+CSRC_cal += calPort.c calPortIter.c
+HEADERS_cal += calPortInt.h
+
+DEPENDENCYFILES = $(CSRC_cal)
Index: /vis_dev/glu-2.1/src/calPort/calPortInt.h
===================================================================
--- /vis_dev/glu-2.1/src/calPort/calPortInt.h	(revision 8)
+++ /vis_dev/glu-2.1/src/calPort/calPortInt.h	(revision 8)
@@ -0,0 +1,85 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [calPortInt.h]
+
+  PackageName [cal]
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: calPortInt.h,v 1.2 2002/08/25 05:30:11 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CAL_PORT_INT_H
+#define _CAL_PORT_INT_H
+#include "util.h"  
+#include "array.h"
+#include "st.h"
+#include "avl.h"
+#include "var_set.h"
+#include "bdd.h"
+#include "calInt.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+struct bdd_t {
+  Cal_Bdd calBdd;
+  Cal_BddManager_t *bddManager; 
+  int free;
+};
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+#endif 
+
Index: /vis_dev/glu-2.1/src/calPort/calPortIter.c
===================================================================
--- /vis_dev/glu-2.1/src/calPort/calPortIter.c	(revision 8)
+++ /vis_dev/glu-2.1/src/calPort/calPortIter.c	(revision 8)
@@ -0,0 +1,667 @@
+/**CFile***********************************************************************
+
+  FileName    [calPortIter.c]
+
+  PackageName [calPort]
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan. Modified from the CMU port package
+  written by Tom Shiple.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "calPortInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct CalBddGenStruct CalBddGen_t;
+/*
+ * Traversal of BDD Formulas
+ */
+
+typedef enum {
+    bdd_gen_cubes,
+    bdd_gen_nodes
+} bdd_gen_type;
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+struct CalBddGenStruct {
+  Cal_BddManager manager;
+  bdd_gen_status status;
+  bdd_gen_type type;
+  union {
+	struct {
+      array_t *cube;	/* of bdd_literal */
+	} cubes;
+	struct {
+      st_table *visited;	/* of bdd_node* */
+	} nodes;
+  } gen;	
+  struct {
+	int sp;
+	CalBddNode_t **nodeStack;
+    int *idStack;
+  } stack;
+  CalBddNode_t *node;
+};
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static void pop_node_stack(CalBddGen_t *gen);
+static void push_node_stack(Cal_Bdd_t f, CalBddGen_t *gen);
+static void pop_cube_stack(CalBddGen_t *gen);
+static void push_cube_stack(Cal_Bdd_t f, CalBddGen_t *gen);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/*
+ *    Defines an iterator on the onset of a BDD.  Two routines are
+ *    provided: bdd_first_cube, which extracts one cube from a BDD and
+ *    returns a bdd_gen structure containing the information necessary to
+ *    continue the enumeration; and bdd_next_cube, which returns 1 if
+ *     another cube was 
+ *    found, and 0 otherwise. A cube is represented
+ *    as an array of bdd_literal (which are integers in {0, 1, 2}),
+ *    where 0 represents 
+ *    negated literal, 1 for literal, and 2 for don't care.  Returns a
+ *    disjoint 
+ *    cover.  A third routine is there to clean up. 
+ */
+
+bdd_gen_status
+bdd_gen_read_status(bdd_gen *gen)
+{
+  return ((CalBddGen_t *)gen)->status;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [bdd_first_cube - return the first cube of the function.
+  A generator is returned that will iterate over the rest. Return the
+  generator. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+bdd_gen *
+bdd_first_cube(bdd_t *fn,array_t **cube)
+{
+  Cal_BddManager_t *manager;
+  CalBddGen_t *gen;
+  int i;
+  long numVars;
+  Cal_Bdd function;
+  Cal_Bdd_t calBdd;
+  
+  if (fn == NIL(bdd_t)) {
+	CalBddFatalMessage("bdd_first_cube: invalid BDD");
+  }
+
+  manager = fn->bddManager;
+  function = fn->calBdd;
+  
+  /*
+   *    Allocate a new generator structure and fill it in; the stack and the 
+   *    cube will be used, but the visited table and the node will not be used.
+   */
+  gen = ALLOC(CalBddGen_t, 1);
+  
+    /*
+     *    first - init all the members to a rational value for cube iteration
+     */
+  gen->manager = manager;
+  gen->status = bdd_EMPTY;
+  gen->type = bdd_gen_cubes;
+  gen->gen.cubes.cube = NIL(array_t);
+  gen->stack.sp = 0;
+  gen->stack.nodeStack = NIL(CalBddNode_t *);
+  gen->stack.idStack = NIL(int);
+  gen->node = NIL(CalBddNode_t);
+  
+  numVars = Cal_BddVars(manager);
+  gen->gen.cubes.cube = array_alloc(bdd_literal, numVars);
+    
+  /*
+   * Initialize each literal to 2 (don't care).
+   */
+  for (i = 0; i < numVars; i++) {
+    array_insert(bdd_literal, gen->gen.cubes.cube, i, 2);
+  }
+  
+  /*
+   * The stack size will never exceed the number of variables in the BDD, since
+   * the longest possible path from root to constant 1 is the number
+   * of variables in the BDD.
+   */
+  gen->stack.sp = 0;
+  gen->stack.nodeStack = ALLOC(CalBddNode_t *, numVars);
+  gen->stack.idStack = ALLOC(int, numVars);
+
+  /*
+   * Clear out the stack so that in bdd_gen_free, we can decrement the
+   * ref count of those nodes still on the stack.
+   */
+  for (i = 0; i < numVars; i++) {
+	gen->stack.nodeStack[i] = NIL(CalBddNode_t);
+	gen->stack.idStack[i] = -1;
+  }
+  
+  if (Cal_BddIsBddZero(manager, function)){
+	/*
+	 *    All done, for this was but the zero constant ...
+	 *    We are enumerating the onset, (which is vacuous).
+     *    gen->status initialized to bdd_EMPTY above, so this
+     *    appears to be redundant.
+	 */
+	gen->status = bdd_EMPTY;
+  } else {
+	/*
+	 *    Get to work enumerating the onset.  Get the first cube.  Note that
+     *    if fn is just the constant 1, push_cube_stack will properly
+     *    handle this. 
+	 *    Get a new pointer to fn->node beforehand: this increments 
+	 *    the reference count of fn->node; this is necessary, because
+     *    when fn->node 
+	 *    is popped from the stack at the very end, it's ref count is
+     *    decremented. 
+	 */
+	gen->status = bdd_NONEMPTY;
+    calBdd = CalBddGetInternalBdd(manager, function);
+    push_cube_stack(calBdd, gen);
+  }
+  *cube = gen->gen.cubes.cube;
+  return (bdd_gen *)(gen);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [bdd_next_cube - get the next cube on the generator.
+  Returns {TRUE, FALSE} when {more, no more}.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+boolean
+bdd_next_cube(bdd_gen *gen_, array_t **cube)
+{
+  CalBddGen_t *gen = (CalBddGen_t *) gen_;
+  pop_cube_stack(gen);
+  if (gen->status == bdd_EMPTY) {
+    return (FALSE);
+  }
+  *cube = gen->gen.cubes.cube;
+  return (TRUE);
+}
+
+bdd_gen *
+bdd_first_disjoint_cube(bdd_t *fn,array_t **cube)
+{
+  return(bdd_first_cube(fn,cube));
+}
+
+boolean
+bdd_next_disjoint_cube(bdd_gen *gen_, array_t **cube)
+{
+  return(bdd_next_cube(gen_,cube));
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [bdd_first_node - enumerates all bdd_node in fn. 
+  Return the generator.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+bdd_gen *
+bdd_first_node(bdd_t *fn, bdd_node **node)
+{
+  Cal_BddManager_t *manager;
+  CalBddGen_t *gen;
+  long numVars;
+  int i;
+  Cal_Bdd_t calBdd;
+  Cal_Bdd function;
+  
+  if (fn == NIL(bdd_t)) {
+	CalBddFatalMessage("bdd_first_node: invalid BDD");
+  }
+  
+  manager = fn->bddManager;
+  function = fn->calBdd;
+  
+  /*
+   *    Allocate a new generator structure and fill it in; the
+   *    visited table will be used, as will the stack, but the
+   *    cube array will not be used.
+   */
+  gen = ALLOC(CalBddGen_t, 1);
+  
+  /*
+   *    first - init all the members to a rational value for node iteration.
+   */
+  gen->manager = manager;
+  gen->status = bdd_NONEMPTY;
+  gen->type = bdd_gen_nodes;
+  gen->gen.nodes.visited = NIL(st_table);
+  gen->stack.sp = 0;
+  gen->stack.nodeStack = NIL(CalBddNode_t *);
+  gen->stack.idStack = NIL(int);
+  gen->node = NIL(CalBddNode_t);
+  
+  /* 
+   * Set up the hash table for visited nodes.  Every time we visit a node,
+   * we insert it into the table.
+   */
+  gen->gen.nodes.visited = st_init_table(st_ptrcmp, st_ptrhash);
+  
+  /*
+   * The stack size will never exceed the number of variables in the BDD, since
+   * the longest possible path from root to constant 1 is the number
+   * of variables in the BDD.
+   */
+  gen->stack.sp = 0;
+  numVars = Cal_BddVars(manager);
+  gen->stack.nodeStack = ALLOC(CalBddNode_t *, numVars);
+  gen->stack.idStack = ALLOC(int, numVars);
+  /*
+   * Clear out the stack so that in bdd_gen_free, we can decrement the
+   * ref count of those nodes still on the stack.
+   */
+  for (i = 0; i < numVars; i++) {
+	gen->stack.nodeStack[i] = NIL(CalBddNode_t);
+	gen->stack.idStack[i] = -1;
+  }
+  
+  /*
+   * Get the first node.  Get a new pointer to fn->node beforehand:
+   * this increments 
+   * the reference count of fn->node; this is necessary, because when fn->node
+   * is popped from the stack at the very end, it's ref count is decremented.
+   */
+  calBdd = CalBddGetInternalBdd(manager, function);
+  push_node_stack(calBdd, gen);
+  gen->status = bdd_NONEMPTY;
+  
+  *node = (bdd_node *)gen->node;	/* return the node */
+  return (bdd_gen *)(gen);	/* and the new generator */
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [bdd_next_node - get the next node in the BDD.
+  Return {TRUE, FALSE} when {more, no more}. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+boolean
+bdd_next_node(bdd_gen *gen_,bdd_node **node)
+{
+  CalBddGen_t *gen = (CalBddGen_t *) gen_;
+  pop_node_stack(gen);
+  if (gen->status == bdd_EMPTY) {
+	return (FALSE);
+  }
+  *node = (bdd_node *) gen->node;
+  return (TRUE);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [bdd_gen_free - frees up the space used by the generator.
+  Return an int so that it is easier to fit in a foreach macro.
+  Return 0 (to make it easy to put in expressions). ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+int
+bdd_gen_free(bdd_gen *gen_)
+{
+  CalBddGen_t *gen = (CalBddGen_t *) gen_;
+  st_table *visited_table;
+
+  switch (gen->type) {
+    case bdd_gen_cubes:
+      array_free(gen->gen.cubes.cube);
+      gen->gen.cubes.cube = NIL(array_t);
+      break;
+    case bdd_gen_nodes:
+      visited_table = gen->gen.nodes.visited;
+      st_free_table(visited_table);
+      visited_table = NIL(st_table);
+      break;
+  }
+  FREE(gen->stack.nodeStack);
+  FREE(gen->stack.idStack);
+  FREE(gen);
+  return (0);	/* make it return some sort of an int */
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/*
+ *    Invariants:
+ *
+ *    gen->stack.stack contains nodes that remain to be explored.
+ *
+ *    For a cube generator,
+ *        gen->gen.cubes.cube reflects the choices made to reach node
+ *        at top of the stack. 
+ *    For a node generator,
+ *        gen->gen.nodes.visited reflects the nodes already visited in
+ *         the BDD dag. 
+ */
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [push_cube_stack - push a cube onto the stack to
+  visit. Return nothing, just do it. 
+  The BDD is traversed using depth-first search, with the ELSE branch
+  searched before the THEN branch. 
+  Caution: If you are creating new BDD's while iterating through the
+  cubes, and a garbage collection happens to be performed during this
+  process, then the BDD generator will get lost and an error will result. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+push_cube_stack(Cal_Bdd_t f, CalBddGen_t *gen)
+{
+  bdd_variableId topId;
+  Cal_Bdd_t f0, f1;
+  Cal_BddManager_t *manager;
+
+  manager = gen->manager;
+  
+  if (CalBddIsBddOne(manager, f)){
+    return;
+  }
+
+  topId = f.bddId-1;
+  CalBddGetElseBdd(f, f0);
+  CalBddGetThenBdd(f, f1);
+
+  if (CalBddIsBddZero(manager, f1)){ 
+/*
+ *    No choice: take the 0 branch.  Since there is only one branch to 
+ *    explore from f, there is no need to push f onto the stack, because
+ *    after exploring this branch we are done with f.  A consequence of 
+ *    this is that there will be no f to pop either.  Same goes for the
+ *    next case.  Decrement the ref count of f and of the branch leading
+ *    to zero, since we will no longer need to access these nodes.
+ */
+    array_insert(bdd_literal, gen->gen.cubes.cube, topId, 0);
+	push_cube_stack(f0, gen);
+  }
+  else if (CalBddIsBddZero(manager, f0)){
+	/*
+	 *    No choice: take the 1 branch
+	 */
+	array_insert(bdd_literal, gen->gen.cubes.cube, topId, 1);
+	push_cube_stack(f1, gen);
+  } else {
+    /*
+     * In this case, we must explore both branches of f.  We always choose
+     * to explore the 0 branch first.  We must push f on the stack, so that
+     * we can later pop it and explore its 1 branch. Decrement the ref count 
+     * of f1 since we will no longer need to access this node.  Note that 
+     * the parent of f1 was bdd_freed above or in pop_cube_stack.
+     */
+    gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
+    gen->stack.idStack[gen->stack.sp++] = f.bddId;
+    array_insert(bdd_literal, gen->gen.cubes.cube, topId, 0);
+    push_cube_stack(f0, gen);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+pop_cube_stack(CalBddGen_t *gen)
+{
+  CalBddNode_t *fNode;
+  int fId, fIndex, i;
+  Cal_Bdd_t f1, f;
+  Cal_BddManager_t *manager;
+  
+  manager = gen->manager;
+  if (gen->stack.sp == 0) {
+    /*
+     * Stack is empty.  Have already explored both the 0 and 1 branches of 
+     * the root of the BDD.
+     */
+	gen->status = bdd_EMPTY;
+  } else {
+    /*
+     * Explore the 1 branch of the node at the top of the stack (since it is
+     * on the stack, this means we have already explored the 0 branch).  We 
+     * permanently pop the top node, and bdd_free it, since there are
+     * no more edges left to explore. 
+     */
+	fNode = gen->stack.nodeStack[--gen->stack.sp];
+	fId = gen->stack.idStack[gen->stack.sp];
+	gen->stack.nodeStack[gen->stack.sp] = NIL(CalBddNode_t); /* overwrite */
+                                                         /* with NIL */
+	gen->stack.idStack[gen->stack.sp] = -1;
+	array_insert(bdd_literal, gen->gen.cubes.cube, fId-1, 1);
+    fIndex = manager->idToIndex[fId];
+	for (i = fIndex + 1; i < array_n(gen->gen.cubes.cube); i++) {
+      array_insert(bdd_literal, gen->gen.cubes.cube,
+                   manager->indexToId[i]-1, 2); 
+	}
+    f.bddNode = fNode;
+    f.bddId = fId;
+    CalBddGetThenBdd(f, f1);
+	push_cube_stack(f1, gen);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [push_node_stack - push a node onto the stack.
+  The same as push_cube_stack but for enumerating nodes instead of cubes.
+  The BDD is traversed using depth-first search, with the ELSE branch
+  searched before the THEN branch, and a node returned only after its
+  children have been returned.  Note that the returned bdd_node
+  pointer has the complement bit zeroed out.
+  Caution: If you are creating new BDD's while iterating through the
+  nodes, and a garbage collection happens to be performed during this
+  process, then the BDD generator will get lost and an error will result. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+static void
+push_node_stack(Cal_Bdd_t f, CalBddGen_t *gen)
+{
+  Cal_Bdd_t f0, f1;
+  bdd_node *reg_f, *reg_f0, *reg_f1;
+
+  reg_f = (CalBddNode_t *) CAL_BDD_POINTER(f.bddNode);  /* use of calInt.h */
+  if (st_is_member(gen->gen.nodes.visited, (char *) reg_f)){
+    /* 
+     * Already been visited.
+     */
+	return;
+  }
+  
+  if (CalBddIsBddConst(f)){
+    /*
+     * If f is the constant node and it has not been visited yet, then
+     * put it in the visited table and set the gen->node pointer.
+     * There is no need to put it in the stack because 
+     * the constant node does not have any branches, and there is no
+     * need to free f because constant nodes have a saturated
+     * reference count. 
+     */
+	st_insert(gen->gen.nodes.visited, (char *) reg_f, NIL(char));
+	gen->node = (CalBddNode_t *) reg_f;
+  } else {
+    /*
+     * f has not been marked as visited.  We don't know yet if any of
+     * its branches remain to be explored.  First get its branches.
+     */
+    CalBddGetElseBdd(f, f0);
+    CalBddGetThenBdd(f, f1);
+
+	reg_f0 = (CalBddNode_t *) CAL_BDD_POINTER(f0.bddNode);
+	reg_f1 = (CalBddNode_t *) CAL_BDD_POINTER(f1.bddNode);
+
+	if (st_is_member(gen->gen.nodes.visited, (char *) reg_f0) == 0){
+      /* 
+       * The 0 child has not been visited, so explore the 0 branch.
+       * First push f on the stack.  Bdd_free f1 since we will not
+       * need to access this exact pointer any more.
+       */
+      gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
+      gen->stack.idStack[gen->stack.sp++] = f.bddId;
+      push_node_stack(f0, gen);
+	} else{
+      if (st_is_member(gen->gen.nodes.visited, (char *) reg_f1) == 0){
+        /* 
+         * The 0 child has been visited, but the 1 child has not been
+         * visited, so explore the 1 branch.  First push f on the
+         * stack. 
+         */
+        gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
+        gen->stack.idStack[gen->stack.sp++] = f.bddId;
+        push_node_stack(f1, gen);
+      } else {
+        /*
+         * Both the 0 and 1 children have been visited. Thus we are done
+         * exploring from f.   
+         * Mark f as visited (put it in the visited table), and set the
+         * gen->node pointer. 
+         */
+        st_insert(gen->gen.nodes.visited, (char *) reg_f, NIL(char));
+        gen->node = (CalBddNode_t *) reg_f;
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+
+static void
+pop_node_stack(CalBddGen_t *gen)
+{
+  CalBddNode_t *fNode;
+  int fId;
+  Cal_Bdd_t calBdd;
+  
+  if (gen->stack.sp == 0) {
+    gen->status = bdd_EMPTY;
+    return;
+  }
+  fNode = gen->stack.nodeStack[--gen->stack.sp]; 
+  fId = gen->stack.idStack[gen->stack.sp];
+  gen->stack.nodeStack[gen->stack.sp] = NIL(CalBddNode_t);
+  gen->stack.idStack[gen->stack.sp] = -1;
+  calBdd.bddNode = fNode;
+  calBdd.bddId = fId;
+  push_node_stack(calBdd, gen);
+}
+
Index: /vis_dev/glu-2.1/src/cmuBdd/bdd.3
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bdd.3	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bdd.3	(revision 8)
@@ -0,0 +1,2001 @@
+.\" BDD library man page
+.TH BDD 3 "11 June 1993"
+.SH NAME
+bdd \- a binary decision diagram (BDD) package
+.SH SYNOPSIS
+.B #include <bdduser.h>
+.SH DESCRIPTION
+The
+.B libbdd
+library provides a set of routines for manipulating binary decision
+diagrams (BDDs).  Some support is also provided for multi-terminal
+BDDs (MTBDDs).  Programs designed to be used with the library should
+use the
+.B -lbdd -lmem
+options to
+.B cc
+when linking.
+.SH "LIST OF FUNCTIONS"
+.nf
+.ta 3in
+\fIName\fP	\fIFunction\fP
+bdd_init	Initialize the library
+bdd_quit	Finish using the library
+bdd_new_var_first	Create a variable first in the order
+bdd_new_var_last	Create a variable last in the order
+bdd_new_var_before	Create a variable before an existing one
+bdd_new_var_after	Create a variable after an existing one
+bdd_var_with_index	Obtain an existing variable
+bdd_var_with_id	Obtain an existing variable
+bdd_one	Constant TRUE
+bdd_zero	Constant FALSE
+bdd_and	Logical AND
+bdd_nand	Logical NAND
+bdd_or	Logical OR
+bdd_nor	Logical NOR
+bdd_xor	Logical XOR
+bdd_xnor	Logical XNOR
+bdd_identity	Logical identity
+bdd_not	Logical NOT
+bdd_ite	Logical IF-THEN-ELSE
+bdd_if	Get the variable of the top node in a BDD
+bdd_then	Get the THEN branch of the top node in a BDD
+bdd_else	Get the ELSE branch of the top node in a BDD
+bdd_if_index	Get the index of the top variable in a BDD
+bdd_if_id	Get a unique ID number for the top variable
+bdd_intersects	Check intersection
+bdd_implies	Check boolean implication
+bdd_new_assoc	Make a new variable association
+bdd_free_assoc	Free a variable association
+bdd_temp_assoc	Set the temporary variable association
+bdd_augment_temp_assoc	Set the temporary variable association
+bdd_assoc	Set the current variable association
+bdd_exists	Existential quantification
+bdd_forall	Universal quantification
+bdd_rel_prod	Relational product
+bdd_compose	Substitute for a variable
+bdd_substitute	Substitute for a set of variables
+bdd_reduce	Simplify given a constraint
+bdd_cofactor	Generalized cofactor
+bdd_depends_on	Determine if a BDD depends on a variable
+bdd_support	Find the support of a BDD
+bdd_satisfy	Find a satisfying assignment
+bdd_satisfy_support	Find a satisfying assignment
+bdd_satisfying_fraction	Fraction of valuations satisfying a BDD
+bdd_swap_vars	Swap two variables in a BDD
+bdd_apply2	Generic apply routine
+bdd_apply1	Generic apply routine
+bdd_size	Number of nodes in a BDD
+bdd_size_multiple	Number of nodes in multiple BDDs
+bdd_profile	Node profile of a BDD
+bdd_profile_multiple	Node profile of multiple BDDs
+bdd_function_profile	Function profile of a BDD
+bdd_function_profile_multiple	Function profile of multiple BDDs
+bdd_print_bdd	Print a BDD in human-readable form
+bdd_print_profile	Print a node profile of a BDD
+bdd_print_profile_multiple	Print a profile of multiple BDDs
+bdd_print_function_profile	Print a function profile of a BDD
+bdd_dump_bdd	Write a BDD to a file
+bdd_undump_bdd	Load a BDD from a file
+bdd_type	Classify a BDD
+bdd_free	Decrease the reference count of a BDD
+bdd_unfree	Increase the reference count of a BDD
+bdd_clear_refs	Set all BDD reference counts to zero
+bdd_gc	Garbage collect unused BDD nodes
+bdd_total_size	Total number of BDD nodes in use
+bdd_vars	Total number of variables in existence
+bdd_cache_ratio	Get/set operation result cache size
+bdd_node_limit	Get/set the number of BDD nodes allowed
+bdd_overflow	Get/clear overflow flag
+bdd_overflow_closure	Set a closure to invoke on overflow
+bdd_abort_closure	Used to abort operations in progress
+bdd_stats	Print statistics
+bdd_dynamic_reordering	Specify dynamic reordering technique
+bdd_reorder	Invoke dynamic reordering
+bdd_new_var_block	Create variable block
+bdd_var_block_reorderable	Set block reorderability
+mtbdd_free_terminal_closure	Called when freeing an MTBDD terminal
+mtbdd_get_terminal	Get an MTBDD terminal node
+mtbdd_terminal_value	Get the value of an MTBDD terminal node
+mtbdd_ite	IF-THEN-ELSE operation for MTBDDs
+mtbdd_equal	Equality operation for MTBDDs
+mtbdd_transform	Applies the current transform to an MTBDD
+mtbdd_transform_closure	Called to set the MTBDD transform
+mtbdd_one_data	Sets the MTBDD data value for TRUE
+.fi
+.SH "BASIC CONCEPTS"
+For a general overview of BDDs, see the original article by Bryant
+[1].
+
+Almost all of the BDD library routines require a BDD manager as one of
+their arguments.  A BDD manager is a structure which holds various
+variables used by the BDD routines.  The type
+.B bdd_manager
+is a pointer to this structure.  BDDs themselves are also represented
+internally as structures.  The type
+.B bdd
+is a pointer to one of these structures.
+
+There is a global ordering on the boolean variables which may appear
+in a BDD.  The variable at the root of a BDD is earlier in the
+ordering than all other variables in the BDD.  Each variable has an
+index which represents its position in the ordering;
+.I v1
+appears before
+.I v2
+in the ordering if and only if the index for
+.I v1
+is less than the ordering for \fIv2\fR.  Each variable is also
+assigned a unique ID number that is invariant.  Since variables can be
+created at any position within the order, this is not true for the
+index.  Also, the library supports dynamic variable reordering.  With
+dynamic variable reordering, variables may be shuffled around in the
+middle of an operation in order to reduce the number of BDD nodes in
+use.
+
+Some routines such as
+.B bdd_substitute
+require a mapping from variables to BDDs to operate.  This mapping is
+supplied in the form of a variable association which is a set of
+pairs.  The first element of each pair is the variable, and the second
+element is the BDD that the variable is associated with.  Multiple
+associations may exist at any one time.  Other routines such as
+.B bdd_exists
+require sets of variables.  Sets of variables are represented by
+variable associations where only the fact that a variable is
+associated with some BDD is significant.  There is one association,
+called the temporary variable association, which is special in two
+ways.  First, this association always exists.  Second, results are not
+cached across calls when this association is used.  The temporary
+association is intended for when an association will not be reused.
+The advantage of using it is that setting the temporary association
+does not require scanning the result cache to flush out-of-date
+results.
+
+The results returned by the library represent canonical forms and may
+be checked for equivalence using the standard C comparison operators.
+For example:
+
+.nf
+{
+  bdd_manager bddm;
+  bdd f;
+  ...
+  if (f == bdd_one(bddm))  /* Tautology check */
+    ...
+}
+.fi
+
+For checking for relations such as boolean implication, use
+.B bdd_intersects
+and \fBbdd_implies\fR.
+
+Multi-terminal BDDs are like BDDs, except an MTBDD may have more than
+just the constants TRUE and FALSE at the leaves.  Passing an MTBDD to
+a routine expecting a BDD will give undefined results, except where
+noted below.  MTBDDs are built up using
+.B mtbdd_get_terminal
+and \fBmtbdd_ite\fR.
+.SH "STORAGE MANAGEMENT"
+Each BDD node has an associated reference count which records the
+number of references to the BDD (internal and external).  Whenever a
+BDD is returned from a function, the reference count for its top node
+is incremented.  (If the BDD did not exist before, the reference count
+will be 1.)  Each time a garbage collection occurs, either internally
+or because of a call to \fBbdd_gc\fR, all nodes which are not
+referenced are reclaimed.  The reference count of a BDD may be
+decremented by calling \fBbdd_free\fR.  This should be done whenever
+possible for maximum space efficiency.  You may also specify a limit
+for the total number of BDD nodes using \fBbdd_node_limit\fR.  If it
+is not possible to complete an operation without exceeding this limit,
+the operation is aborted and (by default) a null pointer is returned.
+Whenever this happens, the reference counts of all nodes are restored
+to what they were before the operation.  If a null pointer is passed
+to a routine, the routine simply returns null.  Thus, it is not
+necessary to check for overflows after each operation.  There is also
+an internal flag that indicates whether any operation has caused an
+overflow.  It may be read and reset by \fBbdd_overflow\fR.
+Optionally, a user-defined closure may be invoked when an overflow
+occurs; see \fBbdd_overflow_closure\fR.  Also see \fBbdd_free\fR,
+\fBbdd_unfree\fR, \fBbdd_clear_refs\fR, \fBbdd_node_limit\fR and
+\fBbdd_gc\fR.  The library also includes high-performance replacements
+for
+.B malloc
+and \fBfree\fR.  See the discussion at the end of the section on
+adding new routines.
+.SH "DETAILED DESCRIPTION"
+.B bdd_manager
+.br
+.B bdd_init()
+.in +4
+Creates and initializes a new BDD manager.  Multiple BDD managers may
+exist at any time.
+.LP
+.B void
+.br
+.B bdd_quit(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Deallocates the BDD manager given by
+.B bddm
+and all the storage associated with it.
+.LP
+.B bdd
+.br
+.B bdd_new_var_first(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Creates a new variable at the start of the BDD variable ordering and
+returns the BDD for it.
+.LP
+.B bdd
+.br
+.B bdd_new_var_last(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Creates a new variable at the end of the BDD variable ordering and
+returns the BDD for it.
+.LP
+.B bdd
+.br
+.B bdd_new_var_before(bddm, var)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd var;
+.in +4
+Creates a new variable which is before
+.B var
+in the BDD variable ordering and returns the BDD for the new variable.
+.LP
+.B bdd
+.br
+.B bdd_new_var_after(bddm, var)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd var;
+.in +4
+Creates a new variable which is after
+.B var
+in the BDD variable ordering and returns the BDD for the new variable.
+.LP
+.B bdd
+.br
+.B bdd_var_with_index(bddm, i)
+.br
+.B bdd_manager bddm;
+.br
+.B long i;
+.in +4
+If a variable with index
+.B i
+has been created, returns the BDD for the variable.  If no such
+variable exists, returns null.  See also \fBbdd_if_index\fR.
+.LP
+.B bdd
+.br
+.B bdd_var_with_id(bddm, i)
+.br
+.B bdd_manager bddm;
+.br
+.B long i;
+.in +4
+If a variable with ID
+.B i
+has been created, returns the BDD for the variable.  If no such
+variable has been created, returns null.  See also \fBbdd_if_id\fR.
+.LP
+.B bdd
+.br
+.B bdd_one(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Returns the BDD for the constant TRUE.
+.LP
+.B bdd
+.br
+.B bdd_zero(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Returns the BDD for the constant FALSE.
+.LP
+.B bdd
+.br
+.B bdd_and(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns the BDD for the logical AND of
+.B f
+and \fBg\fR.
+.LP
+.B bdd
+.br
+.B bdd_nand(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns the BDD for the logical NAND of
+.B f
+and \fBg\fR.
+.LP
+.B bdd
+.br
+.B bdd_or(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns the BDD for the logical OR of
+.B f
+and \fBg\fR.
+.LP
+.B bdd
+.br
+.B bdd_nor(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns the BDD for the logical NOR of
+.B f
+and \fBg\fR.
+.LP
+.B bdd
+.br
+.B bdd_xor(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns the BDD for the logical XOR of
+.B f
+and \fBg\fR.
+.LP
+.B bdd
+.br
+.B bdd_xnor(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns the BDD for the logical XNOR of
+.B f
+and \fBg\fR.
+.LP
+.B bdd
+.br
+.B bdd_identity(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for \fBf\fR.  The only real effect of this function is
+to increase the reference count of \fBf\fR.  Also works with MTBDDs.
+.LP
+.B bdd
+.br
+.B bdd_not(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for the logical NOT of \fBf\fR.
+.LP
+.B bdd
+.br
+.B bdd_ite(bddm, f, g, h)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g, h;
+.in +4
+Returns the BDD for the logical operation IF
+.B f
+THEN
+.B g
+ELSE \fBh\fR.
+.LP
+.B bdd
+.br
+.B bdd_if(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for the variable which labels the root of the BDD
+given by \fBf\fR.  Also works with MTBDDs.  The result is undefined if
+.B f
+is one of the constants TRUE or FALSE or an MTBDD terminal node.
+.LP
+.B bdd
+.br
+.B bdd_then(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for the THEN branch of the root of the BDD given by
+\fBf\fR.  Also works with MTBDDs.  The result is undefined if
+.B f
+is one of the constants TRUE or FALSE or an MTBDD terminal node.
+.LP
+.B bdd
+.br
+.B bdd_else(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for the ELSE branch of the root of the BDD given by
+\fBf\fR.  Also works with MTBDDs.  The result is undefined if
+.B f
+is one of the constants TRUE or FALSE or an MTBDD terminal node.
+.LP
+.B long
+.br
+.B bdd_if_index(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the index of the variable which labels the root of the BDD
+given by \fBf\fR.  Also works with MTBDDs.  The result is undefined if
+.B f
+is one of the constants TRUE or FALSE or an MTBDD terminal node.  The
+variable at the start of variable ordering has index 0, the next has
+index 1, etc.  Note that creating new variables may change the index
+of existing variables.  Dynamic reordering may also change the index
+of variables.
+.LP
+.B long
+.br
+.B bdd_if_id(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns a unique ID number for the variable which labels the root of
+the BDD given by \fBf\fR.  Also works with MTBDDs.  The result is
+undefined if
+.B f
+is one of the constants TRUE or FALSE or an MTBDD terminal node.  The
+ID for a variable is fixed at the time the variable is created and
+never changes after that.
+.LP
+.B bdd
+.br
+.B bdd_intersects(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Computes a BDD that implies the conjunction of
+.B f
+and \fBg\fR.  If the conjunction is not FALSE, then the BDD returned
+will not be FALSE.  Also, the function tries to construct as few new
+nodes as possible.  This routine is intended for cases where you need
+to test for a FALSE conjunction, and, when it the conjunction is not
+FALSE, to obtain just one valuation satisfying both
+.B f
+and \fBg\fR.  A non-FALSE result from
+.B bdd_intersects
+can be passed directly to a routine like \fBbdd_satisfy_support\fR.
+.LP
+.B bdd
+.br
+.B bdd_implies(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+This is equivalent to calling
+.B bdd_intersects
+with
+.B f
+and NOT \fBg\fR.
+.LP
+.B int
+.br
+.B bdd_new_assoc(bddm, assoc, pairs)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd *assoc;
+.br
+.B int pairs;
+.in +4
+Creates or finds a variable association.  The association is specified
+by
+.B assoc
+and should be a null-terminated array of BDDs.  If
+.B pairs
+is 0, the array is assumed to be an array of variables.  In this case,
+each variable is paired with the BDD for TRUE.  Such an association
+may essentially be viewed as specifying a set of variables for use
+with routines such as \fBbdd_exists\fR.  If
+.B pairs
+is nonzero, then the even numbered array elements should be variables
+and the odd numbered elements should be the BDDs which they are mapped
+to.  In both cases, the return value is an integer identifier for this
+association.  Note: if the given association is equivalent to one
+which already exists, the same identifier is used for both, and the
+reference count of the association is increased by one.
+.LP
+.B void
+.br
+.B bdd_free_assoc(bddm, id)
+.br
+.B bdd_manager bddm;
+.br
+.B int id;
+.in +4
+Decrements the reference count of the variable association with
+identifier \fBid\fR, and frees it if the reference count becomes zero.
+.LP
+.B void
+.br
+.B bdd_temp_assoc(bddm, assoc, pairs)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd *assoc;
+.br
+.B int pairs;
+.in +4
+Sets the temporary variable association.  The arguments
+.B assoc
+and
+.B pairs
+are as in \fBbdd_new_assoc\fR.
+.LP
+.B void
+.br
+.B bdd_augment_temp_assoc(bddm, assoc, pairs)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd *assoc;
+.br
+.B int pairs;
+.in +4
+Add to the temporary variable association.  The arguments
+.B assoc
+and
+.B pairs
+are as in \fBbdd_new_assoc\fR.  Any existing associations are
+overwritten.  This is mainly used when doing things like substituting
+for all variables in a BDD.  It isn't necessary to clear out the
+temporary association in such cases, so you can save a little time by
+using this routine.
+.LP
+.B int
+.br
+.B bdd_assoc(bddm, id)
+.br
+.B bdd_manager bddm;
+.br
+.B int id;
+.in +4
+Sets the current variable association to the one identified by
+\fBid\fR.  The identifier for the old current association is returned.
+The temporary variable association has identifier -1.
+.LP
+.B bdd
+.br
+.B bdd_exists(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for
+.B f
+with all the variables that are paired with something in the current
+variable association existentially quantified out.
+.LP
+.B bdd
+.br
+.B bdd_forall(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for
+.B f
+with all the variables that are paired with something in the current
+variable association universally quantified out.
+.LP
+.B bdd
+.br
+.B bdd_rel_prod(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns the BDD for the logical AND of
+.B f
+and
+.B g
+with all the variables that are paired with something in the current
+variable association existentially quantified out.  If
+.B f
+and
+.B g
+are viewed as boolean relations, this operation corresponds to
+relational product.  This routine is generally much more efficient
+than doing the operations separately.
+.LP
+.B bdd
+.br
+.B bdd_compose(bddm, f, g, h)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g, h;
+.in +4
+Returns the BDD for the substitution of
+.B h
+for the variable
+.B g
+in \fBf\fR.  When
+.B h
+does not depend on \fBg\fR, the operation may be viewed as composition
+of boolean functions.  If
+.B h
+does depend on \fBg\fR, it corresponds to instantaneous substitution
+in a boolean formula.
+.LP
+.B bdd
+.br
+.B bdd_substitute(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the BDD for
+.B f
+under a substitution defined by the current variable association.
+Each variable is replaced by its associated BDD.  The substitution is
+effectively simultaneous.
+.LP
+.B bdd
+.br
+.B bdd_reduce(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns a BDD which agrees with
+.B f
+for all valuations which satisfy \fBg\fR.  The result is usually
+smaller in terms of number of BDD nodes than \fBf\fR.  This operation
+is typically used in state space searches to simplify the
+representation for the set of states which will be expanded at each
+step.
+.LP
+.B bdd
+.br
+.B bdd_cofactor(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f, g;
+.in +4
+Returns a BDD for the generalized cofactor of
+.B f
+by \fBg\fR.  The BDD indicated by
+.B g
+should not be the constant FALSE.  For some properties of this
+operation, see Touati
+.I et al.
+[2].
+.LP
+.B int
+.br
+.B bdd_depends_on(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B bdd g;
+.in +4
+Returns 1 if the BDD or MTBDD
+.B f
+depends on the variable given by the BDD \fBg\fR, and returns 0
+otherwise.
+.LP
+.B void
+.br
+.B bdd_support(bddm, f, support)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B bdd *support;
+.in +4
+Stores the support of
+.B f
+as a null-terminated sequence of variables in \fBsupport\fR.  Works
+for MTBDDs also.
+.LP
+.B bdd
+.br
+.B bdd_satisfy(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns a BDD which is not false, implies \fBf\fR, and has at most one
+BDD node at each level.  The BDD indicated by
+.B f
+should not be the constant FALSE.
+.LP
+.B bdd
+.br
+.B bdd_satisfy_support(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns a BDD which is not false, implies \fBf\fR, has at most one
+BDD node at each level, and has a node labeled with each variable
+which is paired with something in the current variable association.
+If
+.B f
+is the constant FALSE, the result is undefined.
+.LP
+.B double
+.br
+.B bdd_satisfying_fraction(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns the fraction of valuations which satisfy \fBf\fR.  If
+.B f
+is a function of 
+.I n
+variables, then 2 to the power
+.I n
+times this fraction is the number of valuations which satisfy \fBf\fR.
+.LP
+.B bdd
+.br
+.B bdd_swap_vars(bddm, f, g, h)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B bdd g;
+.br
+.B bdd h;
+.in +4
+Returns the BDD for
+.B f
+with
+.B g
+substituted for
+.B h
+and
+.B h
+substituted for \fBg\fR.  The substitution is effectively
+simultaneous.
+.LP
+.B bdd
+.br
+.B bdd_apply2(bddm, terminal_fn, f, g, env)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd (*terminal_fn)();
+.br
+.B bdd f;
+.br
+.B bdd g;
+.br
+.B pointer env;
+.in +4
+This is a generic two-argument operation.  The behavior of the
+operation on terminal values is given by \fBterminal_fn\fR.  It should
+take as arguments: the BDD manager, pointers to two BDDs (the
+arguments for the call), and the pointer given by \fBenv\fR.  If the
+value of the call can be determined immediately from the arguments, it
+should return that value.  Otherwise, it should return a null pointer.
+In this case, it may also use the BDD pointers that it received to
+alter the arguments to the call.  A typical use for this ability is to
+put the arguments in a canonical order for commutative operations.
+The function should not alter the reference counts of either the
+arguments or the returned value.  Also, the returned value (if
+non-null) has its temporary reference count incremented once
+automatically.  If your function always returns one of the arguments
+or TRUE or FALSE, this is the right thing and you don't have to worry
+about it.  If you want to call other routines to determine the return
+value, you should read the section on adding new routines below.
+Works with MTBDDs.
+.LP
+.B bdd
+.br
+.B bdd_apply1(bddm, terminal_fn, f, env)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd (*terminal_fn)();
+.br
+.B bdd f;
+.br
+.B pointer env;
+.in +4
+This is a generic one-argument operation.  It is basically like
+\fBbdd_apply2\fR, except that
+.B terminal_fn
+takes a single BDD pointer argument instead of the pair of pointers in
+the two-argument case.  Works with MTBDDs.
+.LP
+.B long
+.br
+.B bdd_size(bddm, f, negout)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B int negout;
+.in +4
+Returns the number of nodes in \fBf\fR.  The parameter
+.B negout
+is a flag indicating whether negative output pointers should be
+considered.  The library uses this type of pointer flag internally,
+so if the flag is nonzero, the actual number of nodes used is
+returned.  If the flag is zero, the return value is the number of
+nodes which would be needed to represent
+.B f
+using a basic BDD.  Works for MTBDDs too.
+.LP
+.B long
+.br
+.B bdd_size_multiple(bddm, fs, negout)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd *fs;
+.br
+.B int negout;
+.in +4
+Returns the number of nodes in the set of BDDs or MTBDDs given by
+\fBfs\fR, which should be a null-terminated array.  Nodes which are
+shared among the BDDs are only counted once.  The parameter
+.B negout
+is as in \fBbdd_size\fR.
+.LP
+.B void
+.br
+.B bdd_profile(bddm, f, level_counts, negout)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B long *level_counts;
+.br
+.B int negout;
+.in +4
+Returns the ``node profile'' of \fBf\fR, i.e., the number of nodes at
+each level in \fBf\fR.  The parameter
+.B level_counts
+should be an array of longs of size one plus the number of variables
+in existence (see \fBbdd_vars\fR).  On return, this array holds the
+profile; the \fIi\fRth entry is the number of nodes labeled with the
+variable of index \fIi\fR.  The last entry corresponds to the nodes
+for TRUE and FALSE.  The parameter
+.B negout
+is as in \fBbdd_size\fR.  Works for MTBDDs too; in this case, the
+last entry corresponds to the MTBDD terminal nodes.
+.LP
+.B void
+.br
+.B bdd_profile_multiple(bddm, fs, level_counts, negout)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd* fs;
+.br
+.B long *level_counts;
+.br
+.B int negout;
+.in +4
+Returns the ``node profile'' of the set of BDDs or MTBDDs given by
+\fBfs\fR, which should be a null-terminated array.  The parameters
+\fBlevel_counts\fR and
+.B negout
+are as in \fBbdd_profile\fR.
+.LP
+.B void
+.br
+.B bdd_function_profile(bddm, f, func_counts)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B long *func_counts;
+.in +4
+Returns the ``function profile'' of \fBf\fR, i.e., the number of
+functions at or below each level in \fBf\fR.  The parameter
+.B func_counts
+should be an array of longs of size one plus the number of variables
+in existence (see \fBbdd_vars\fR).  On return, this array holds the
+profile.  The \fIi\fRth entry corresponds to the number of functions
+which can be obtained by restricting those variables of index less
+than \fIi\fR, provided that
+.B f
+has at least one node labeled with the variable of index \fIi\fR.  If
+.B f
+has no nodes labeled with the variable of index \fIi\fR, then the
+\fIi\fRth entry of the profile is 0.  Works for MTBDDs also.
+.LP
+.B void
+.br
+.B bdd_function_profile_multiple(bddm, fs, func_counts)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd *fs;
+.br
+.B long *func_counts;
+.in +4
+Returns the ``function profile'' of the set of BDDs or MTBDDs given by
+\fBfs\fR, which should be a null-terminated array.  The parameter
+.B func_counts
+is as in \fBbdd_function_profile\fR.
+.LP
+.B void
+.br
+.B bdd_print_bdd(bddm, f, naming_fn, terminal_id_fn, env, fp)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B char *(*naming_fn)();
+.br
+.B char *(*terminal_id_fn)();
+.br
+.B pointer env;
+.br
+.B FILE *fp;
+.in +4
+Prints a human-readable representation of the BDD or MTBDD
+.B f
+to the file given by \fBfp\fR.  The
+.B naming_fn
+should be a pointer to a function taking a \fBbdd_manager\fR, a
+.B bdd
+and the pointer given by \fBenv\fR.  This function should return
+either a null pointer or a string that is the name of the supplied
+variable.  If it returns a null pointer, a default name is generated
+based on the index of the variable.  It is also legal for
+.B naming_fn
+to be null; in this case, default names are generated for all variables.
+The macro
+.B bdd_naming_fn_none
+is a null pointer of suitable type.
+.B terminal_id_fn
+should be a pointer to a function taking a
+.B bdd_manager
+and two longs, plus the pointer given by \fBenv\fR.  It should
+return either a null pointer or a string representing the MTBDD
+terminal represented by the given value.  If it returns a null
+pointer, or if
+.B terminal_id_fn
+is null, then default names are generated for the terminals.
+The macro
+.B bdd_terminal_id_fn_none
+is a null pointer of suitable type.
+.LP
+.B void
+.br
+.B bdd_print_profile(bddm, f, naming_fn, env, width, fp)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B char *(*naming_fn)();
+.br
+.B pointer env;
+.br
+.B int width;
+.br
+.B FILE *fp;
+.in +4
+Prints a node profile of a BDD in histogram form.  The argument
+.B naming_fn
+should be as described in \fBbdd_print_bdd\fR.  The width of the
+output stream is specified by \fBwidth\fR.  This is used to determine
+how to scale the histogram.
+.LP
+.B void
+.br
+.B bdd_print_profile_multiple(bddm, fs, naming_fn, env, width, fp)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd *fs;
+.br
+.B char *(*naming_fn)();
+.br
+.B pointer env;
+.br
+.B int width;
+.br
+.B FILE *fp;
+.in +4
+Prints a node profile of a set of BDDs, which should be given as a
+null-terminated array.  The other arguments are as in
+\fBbdd_print_profile\fR.
+.LP
+.B void
+.br
+.B bdd_print_function_profile(bddm, f, naming_fn, env, width, fp)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B char *(*naming_fn)();
+.br
+.B pointer env;
+.br
+.B int width;
+.br
+.B FILE *fp;
+.in +4
+Prints a function profile of a BDD in histogram form.  The arguments
+are the same as those to \fBbdd_print_profile\fR.
+.LP
+.B int
+.br
+.B bdd_dump_bdd(bddm, f, vars, fp)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B bdd *vars;
+.br
+.B FILE *fp;
+.in +4
+Writes an encoded description of the BDD or MTBDD
+.B f
+to the file given by \fBfp\fR.  The argument
+.B vars
+should be a null-terminated array of variables that include the
+support of \fBf\fR.  These variables need not be in order of
+increasing index.  The function returns a nonzero value if
+.B f
+was written to the file successfully.
+.LP
+.B bdd
+.br
+.B bdd_undump_bdd(bddm, vars, fp, error)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd *vars;
+.br
+.B FILE *fp;
+.br
+.B int *error;
+.in +4
+Loads an encoded description of a BDD or MTBDD from the file given by
+\fBfp\fR.  The argument
+.B vars
+should be a null-terminated array of variables that will become the
+support of the BDD.  As in \fBbdd_dump_bdd\fR, these need not be in
+order of increasing index.  If the same array of variables is used in
+dumping and undumping, the BDD returned will be equal to the one that
+was dumped.  More generally, if the array
+.B v1
+is used when dumping, and the array
+.B v2
+is used when undumping, the BDD returned will be equal to the original
+BDD with the \fIi\fRth variable in
+.B v2
+substituted for the \fIi\fRth variable in
+.B v1
+for all \fIi\fR.  Null is returned if the operation fails for some
+reason (node limit reached, I/O error, invalid file format, etc.).
+In this case, an error code is stored in \fBerror\fR.  The code will
+be one of the following.
+.nf
+.ta 3in
+\fIValue\fR	\fIMeaning\fR
+BDD_UNDUMP_FORMAT	Invalid file format
+BDD_UNDUMP_OVERFLOW	Node limit exceeded
+BDD_UNDUMP_IOERROR	File I/O error
+BDD_UNDUMP_EOF	Unexpected EOF
+.fi
+.LP
+.B int
+.br
+.B bdd_type(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Returns an integer classifying the BDD or MTBDD \fBf\fR.  The possible
+return values and their meanings are as follows.
+.nf
+.ta 3in
+\fIValue\fR	\fIMeaning\fR
+BDD_TYPE_OVERFLOW	\fBf\fR is a null pointer
+BDD_TYPE_ZERO	\fBf\fR is the constant FALSE
+BDD_TYPE_ONE	\fBf\fR is the constant TRUE
+BDD_TYPE_CONSTANT	\fBf\fR is an MTBDD constant
+BDD_TYPE_POSVAR	\fBf\fR is a variable
+BDD_TYPE_NEGVAR	\fBf\fR is the negation of a variable
+BDD_TYPE_NONTERMINAL	\fBf\fR is not one of the above
+.fi
+.LP
+.B void
+.br
+.B bdd_free(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Decreases the reference count of
+.B f
+by one.  When the reference count of a BDD or MTBDD node reaches 0,
+the node and any of its children that are not otherwise referenced may
+eventually be garbage collected and reused.  Intermediate results and
+unused BDDs and MTBDDs should be freed whenever possible.  For
+example:
+
+.nf
+bdd
+f_or_g_and_h(bddm, f, g, h)
+     bdd_manager bddm;
+     bdd f, g, h;
+{
+  bdd temp, result;
+  temp=bdd_and(bddm, g, h);
+  result=bdd_or(bddm, f, temp);
+  bdd_free(bddm, temp);    /* Free intermediate */
+  return (result);
+}
+.fi
+.LP
+.B void
+.br
+.B bdd_unfree(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Increases the reference count of
+.B f
+by one.  This is usually used in conjunction with
+\fBbdd_clear_refs\fR.  Works with MTBDDs.
+.LP
+.B void
+.br
+.B bdd_clear_refs(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Sets the reference counts of all BDD and MTBDD nodes (except for the
+node for TRUE/FALSE) to 0.  Calling this routine and then immediately
+calling
+.B bdd_unfree
+on a set of BDDs has the effect of disposing of all BDDs except those
+in the set.
+.LP
+.B void
+.br
+.B bdd_gc(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Forces a BDD garbage collection; all nodes not reachable from a node
+with a nonzero reference count are disposed of.  (Garbage collections
+also occur internally at various times.)
+.LP
+.B long
+.br
+.B bdd_total_size(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Returns the number of BDD and MTBDD nodes in existence (including
+those which are eligible for garbage collection).
+.LP
+.B long
+.br
+.B bdd_vars(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Returns the number of variables in existence.
+.LP
+.B int
+.br
+.B bdd_cache_ratio(bddm, ratio)
+.br
+.B bdd_manager bddm;
+.br
+.B int ratio;
+.in +4
+Sets the BDD operation cache size ratio to
+.B ratio
+and returns the old cache size ratio.  The number of cache entries is
+constrained to be (roughly) less than the cache size ratio divided by
+16 times the number of BDD nodes in existence.  The default size ratio
+is 4, which gives about 1 cache entry per 4 BDD nodes.  The amount of
+memory required per node will be about 17+(\fBratio\fR/16)*20 bytes on
+a machine with 32-bit words.
+.LP
+.B void
+.br
+.B bdd_node_limit(bddm, limit)
+.br
+.B bdd_manager bddm;
+.br
+.B long limit;
+.in +4
+Sets the number of allowed BDD nodes to
+.B limit
+and returns the old limit.  A value of 0 specifies no limit.  If in
+the course of an operation, the number of nodes reaches the limit, an
+internal garbage collection takes place.  If this does not free enough
+nodes to continue, the operation is aborted and a null value is
+returned.  When dynamic reordering is used to shift around large
+variable block, this limit may be exceeded during reordering.
+.LP
+.B int
+.br
+.B bdd_overflow(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Returns 1 if any operation has caused an overflow in the number of
+nodes, and 0 otherwise.  Calling this routine clears the internal
+overflow flag, so subsequent calls will return 0 until the next
+overflow occurs.
+.LP
+.B void
+.br
+.B bdd_overflow_closure(bddm, overflow_fn, overflow_env)
+.br
+.B bdd_manager bddm;
+.br
+.B void (*overflow_fn)();
+.br
+.B pointer overflow_env;
+.in +4
+Sets the closure to invoke when an overflow occurs.  The function
+given by
+.B overflow_fn
+will be invoked as the last stage in the cleanup after the overflow.
+The function is passed the BDD manager and the pointer given by
+\fBoverflow_env\fR.  Typically, the function will jump to a
+user-provided error recovery routine.
+.LP
+.B void
+.br
+.B bdd_abort_closure(bddm, abort_fn, abort_env)
+.br
+.B bdd_manager bddm;
+.br
+.B void (*abort_fn)();
+.br
+.B pointer abort_env;
+.in +4
+Sets a closure to invoke when the next node creation is attempted.
+All temporary results will be cleaned up just before the function
+given by
+.B abort_fn
+is called.  The function is passed the BDD manager and the pointer
+given by \fBabort_env\fR.  Typically, the function will jump to a
+user-provided error recovery routine.  This functionality is intended
+to be used to cleanly interrupt BDD operations.  Typically,
+.B bdd_abort_closure
+will be called within a signal handler.
+.LP
+.B void
+.br
+.B bdd_stats(bddm, fp)
+.br
+.B bdd_manager bddm;
+.br
+.B FILE *fp;
+.in +4
+Prints some statistics to the file given by \fBfp\fR.
+.LP
+.B void
+.br
+.B bdd_dynamic_reordering(bddm, reorder_fn)
+.br
+.B bdd_manager bddm;
+.br
+.B void (*reorder_fn)();
+.in +4
+Selects the method for dynamic reordering.  When dynamic reordering is
+being used, the library may attempt to rearrange the BDD variable
+ordering in the midst of an operation so as to reduce the number of
+nodes in use.  There are currently two available reordering methods.
+The first, \fBbdd_reorder_stable_window3\fR, permutes the variables
+within windows of three adjacent variables so as to minimize the
+overall BDD size.  This process is repeated until no more reduction in
+size occurs.  The second method, \fBbdd_reorder_sift\fR, moves each
+variable throughout the order to find an optimal position for that
+variable (assuming all other variables are fixed).  This generally
+achieves greater size reductions than the window-based method, but is
+slower.  The
+.B reorder_fn
+may also be
+.B bdd_reorder_none
+(an appropriately cast null pointer), in which case dynamic reordering
+is turned off.  Also see the discussion on variable blocks in
+\fBbdd_new_var_block\fR.
+.LP
+.B void
+.br
+.B bdd_reorder(bddm)
+.br
+.B bdd_manager bddm;
+.in +4
+Invoke the current dynamic reordering method.
+.LP
+.B block
+.br
+.B bdd_new_var_block(bddm, v, n)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd v;
+.br
+.B long n;
+.in +4
+Groups the variable
+.B v
+and the \fBn\fR-1 variables after it in the ordering into a single
+block for purposes of dynamic reordering.  The purpose of blocks is to
+provide control over the possible orders that dynamic reordering will
+consider.  In general, the variable blocks form a hierarchy.  For
+example, a block consisting of the variables with indexes 0 through 3
+might be made up of two sub-blocks, one for the variables with index 0
+and 1, and one for the variables with index 2 and 3.  When dynamic
+reordering is invoked, it is actually applied to each block within the
+hierarchy.  Reordering a block involves shuffling around the
+sub-blocks within it.  Thus, dynamic reordering actually moves groups
+of variables rather than single variables.  If you know that a group
+of variables should be together in the ordering, you should collect
+them together into a block.  As an example, in BDD-based sequential
+verification algorithms, the variables representing the current state
+and next state of a state-holding element should generally be adjacent
+in a good ordering.  By grouping these variables into a block, we can
+ensure that only orderings with this property are considered.  After a
+block has been reordered, each sub-block within it is recursively
+reordered as well.  You can also specify that certain blocks should
+not be reordered (see
+.B bdd_var_block_reorderable
+below).
+.LP
+.B void
+.br
+.B bdd_var_block_reorderable(bddm, b, reorderable)
+.br
+.B bdd_manager bddm;
+.br
+.B block b;
+.br
+.B int reorderable;
+.in +4
+If
+.B reorderable
+is non-zero, turns on reordering for the given block, otherwise turns
+it off.  By default, blocks are not reorderable.  As an example,
+suppose we are building the BDDs representing a circuit with distinct
+control and data path.  In such a case, we typically want to have the
+control variables at the top of the ordering.  For the data path, we
+probably want to have the variables for each bit slice grouped
+together, and we want the bit slices to be ordered from
+most-significant to least-significant.  However, we want to allow
+reordering within the control part and within each slice.  To do this,
+we create the variables in the following order: control variables
+first, down to LSB slice variables.  Then we create separate variable
+blocks for the control part and for each slice.  We then turn on
+reordering for these blocks.  Next, we create a block containing all
+of the variables, and we leave reordering off for this block.  When
+dynamic reordering is invoked, it will rearrange the control variables
+and the variables within each slice, but will not move the control
+variables or the slices in relation to each other.
+.LP
+.B void
+.br
+.B bdd_free_terminal_closure(bddm, free_terminal_fn, free_terminal_env)
+.br
+.B bdd_manager bddm;
+.br
+.B void (*free_terminal_fn)();
+.br
+.B pointer free_terminal_env;
+.in +4
+Sets a closure to invoke when freeing an MTBDD terminal node.  The
+function receives the BDD manager, two longs representing the value of
+the terminal, and the pointer given by \fBfree_terminal_env\fR.  If
+you using the terminal value to hold pointers to other data
+structures, you can set up this routine to free those structures.
+.LP
+.B bdd
+.br
+.B mtbdd_get_terminal(bddm, value1, value2)
+.br
+.B bdd_manager bddm;
+.br
+.B long value1;
+.br
+.B long value2;
+.in +4
+Creates an MTBDD terminal node corresponding to the value given by
+.B value1
+and \fBvalue2\fR.  If a terminal node with the value already exists,
+its reference count is increased.  See also
+\fBbdd_free_terminal_closure\fR.
+.LP
+.B void
+.br
+.B mtbdd_terminal_value(bddm, f, value1, value2)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B long *value1;
+.br
+.B long *value2;
+.in +4
+.B f
+should be an MTBDD terminal node.  The value of the node is stored in
+.B value1
+and \fBvalue2\fR.
+.LP
+.B bdd
+.br
+.B mtbdd_ite(bddm, f, g, h)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B bdd g;
+.br
+.B bdd h;
+.in +4
+.B f
+should be a BDD and
+.B g
+and
+.B h
+should be MTBDDs.  Returns the MTBDD for the operation IF
+.B f
+THEN
+.B g
+ELSE \fBh\fR.
+.LP
+.B bdd
+.br
+.B mtbdd_substitute(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Does the analog of
+.B bdd_substitute
+for the MTBDD \fBf\fR.  The elements in the variable association must
+be BDDs.
+.LP
+.B bdd
+.br
+.B mtbdd_equal(bddm, f, g)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.br
+.B bdd g;
+.in +4
+Returns the BDD which is true for those valuations on which the MTBDDs
+.B f
+and
+.B g
+are equal.  That is, this is the analog of a logical XNOR for MTBDDs.
+.LP
+.B bdd
+.br
+.B mtbdd_transform(bddm, f)
+.br
+.B bdd_manager bddm;
+.br
+.B bdd f;
+.in +4
+Conceptually applies the user-defined transform to all terminals of
+the specified MTBDD.  (This is actually done by just flipping the
+pointer flag, so this routine is really a macro for \fBbdd_not\fR.)
+See \fBmtbdd_transform_closure\fR.
+.LP
+.B void
+.br
+.B mtbdd_transform_closure(bddm, canonical_fn, transform_fn, env)
+.br
+.B bdd_manager bddm;
+.br
+.B int (*canonical_fn)();
+.br
+.B void (*transform_fn)();
+.br
+.B pointer env;
+.in +4
+Sets the MTBDD terminal transformation closure.  Currently in the
+library, the pointer representing a boolean function and the pointer
+representing the negation of that function are identical except for
+the low-order bit.  Complementing a function is done by simply
+toggling that bit.  The MTBDD terminal transformation allows this
+mechanism to be extended to MTBDDs.  Whenever a terminal is created,
+.B canonical_fn
+will be called.  It is passed the BDD manager, two longs representing
+the terminal being created, and the pointer given by \fBenv\fR.  The
+function should return zero if the value is already canonical, and a
+non-zero result if it needs to be transformed.  If the value needs to
+be transformed, then
+.B transform_fn
+will be called, with the BDD manager, two longs representing the value
+to be transformed, pointers to two longs to hold the result, and the
+pointer given by \fBenv\fR.  The actual terminal node that is created
+will contain the transformed value.  The original terminal requested
+will be represented by a pointer to this node, with the low-order bit
+of the pointer set.  Also see \fBmtbdd_one_data\fR.  If you are going
+to call this function, you should do it before creating any MTBDD
+terminals.
+.LP
+.B void
+.br
+.B mtbdd_one_data(bddm, value1, value2)
+.br
+.B bdd_manager bddm;
+.br
+.B long value1;
+.br
+.B long value2;
+.in +4
+If you are planning to use MTBDDs that contain TRUE and FALSE as well
+as other values, you may need to use this function to set the MTBDD
+value for the node representing TRUE.  In this case, also keep in mind
+that the when the transformation function is applied to this value, it
+should yield the value that you want for FALSE.  Also, the value for
+TRUE should be regarding as canonical, i.e., TRUE must be represented
+by a pointer with the low-order bit cleared.  As an example, suppose
+that we are planning to use MTBDDs to represent spectral transforms of
+boolean functions [4].  In this case, the MTBDD terminal values will
+conceptually be integers.  Further, it is convenient for TRUE to be
+represented by the value -1, and FALSE to be represented by +1.  We
+will represent terminal values using two longs, with the first long
+representing the most-significant part of the integer.  We will also
+assume a 2's complement representation, so TRUE should be represented
+by the data values -1 and -1.  Since the value for FALSE is the
+negation of that for TRUE, we will have our transform function
+represent integer negation.  Also, since we want the value for TRUE to
+be canonical, we will regard nonnegative values as canonical.  Thus,
+we define
+
+.nf
+int
+canonical_fn(bddm, value1, value2, env)
+     bdd_manager bddm;
+     long value1;
+     long value2;
+     pointer env;
+{
+  return (value1 > 0 || (!value1 && value2 > 0));
+}
+
+void
+transform_fn(bddm, value1, value2, result1, result2, env)
+     bdd_manager bddm;
+     long value1;
+     long value2;
+     long *result1;
+     long *result2;
+     pointer env;
+{
+  if (!value2)
+    /* Will be a carry when taking 2's complement of value2.  Thus, */
+    /* take 2's complement of high part. */
+    value1= -value1;
+  else
+    {
+      value2= -value2;
+      value1= ~value1;
+    }
+  *result1=value1;
+  *result2=value2;
+}
+.fi
+
+We then call
+.B mtbdd_transform_closure
+to register these functions, and use
+
+.nf
+bdd_one_data(bddm, -1l, -1l);
+.fi
+
+to set the value for TRUE to -1.  (The default canonical checking and
+transformation functions and the default MTBDD values for TRUE and
+FALSE are actually as given in this example.)  If you are going to
+call \fBbdd_one_data\fR, you should do it before creating any MTBDD
+terminals.
+.SH "ADDING NEW ROUTINES"
+If you want to add new routines to the library, you would be
+well-advised to look at some of the existing ones to get a feel for
+how they operate.  Good ones include \fBbdd_ite\fR (the basic logical
+operation) and \fBbdd_exists\fR (a routine using variable
+associations).  Some basic points are explained below.  To get the
+declarations of the internal library data structures and routines, you
+should
+.B #include <bddint.h>
+instead of using \fBbdduser.h\fR.  You will probably want to study
+this file to become familiar with the data structures.
+
+Pointers to BDD nodes and cache entries are tagged using the low three
+bits of the pointer.  Because of this, all structures must be aligned
+on eight byte boundaries.  The storage allocation routines guarantee
+this alignment.  The tag field of a tagged pointer is extracted with
+the
+.B TAG
+macro.  The
+.B POINTER
+macro masks off the tag to get the actual pointer.  If the pointer is
+a pointer to a BDD node, you can use
+.B BDD_POINTER
+instead; this just casts the result to a
+.B bdd
+after masking off the tag.  The tag can be set using \fBSET_TAG\fR, and
+individual tag bits can be manipulated with \fBTAG0\fR,
+.B FLIP_TAG0
+and \fBSET_TAG0\fR for tag bit 0, and the analogous macros for tag
+bits 1 and 2.  More commonly, slightly higher level macros are used
+for manipulating tags.  For BDD nodes, there is only one tag bit that
+is actually used.  When it is set, it indicates the pointer should be
+interpreted as representing the complement of the node that it points
+to.  (Or for MTBDDs, that it should be interpreted as transformed
+using the user-definable transformation function).  There are macros
+for testing, clearing, and flipping the negation flag.
+
+Before using the macros below on a pointer \fBf\fR, you need to use
+\fBBDD_SETUP(f)\fR.  This actually declares a new variable to hold the
+masked pointer \fBBDD_POINTER(f)\fR.  Hence, it needs to be placed at
+some point where a variable declaration could legally go.  If you
+change \fBf\fR, you can reset this internal variable using
+\fBBDD_RESET\fR.
+
+BDD pointers are generally manipulated using the following macros.
+Below, ``node'' refers to the node referenced by the pointer.
+.LP
+.B BDD_IS_CONST
+.in +4
+Tests if the node represents the constant TRUE or FALSE or an MTBDD
+terminal node.
+.LP
+.B BDD_INDEX
+.in +4
+Returns the index of the node, or
+.B BDD_MAX_INDEX
+if given a constant node.
+.LP
+.B BDD_INDEXINDEX
+.in +4
+Returns the index index of a node.  This field is the value returned
+by \fBbdd_if_id\fR and is invariant; when you create a new variable,
+the index of old nodes may change, but the index index stays the same.
+When you call \fBbdd_find\fR, you pass the desired index index of the
+new node, not the index.
+.LP
+.B BDD_NOT
+.in +4
+Flips the negation flag on a pointer.
+.LP
+.B BDD_THEN, BDD_ELSE
+.in +4
+Return the THEN and ELSE pointers of a node, taking proper account of
+pointer flags.  These are used for doing Shannon expansions on a node.
+.LP
+.B BDD_TOP_VAR2
+Takes a \fBbdd_manager\fR, a variable that can hold an index index,
+and two \fBbdd\fRs.  Sets the index index variable to the index index
+of the variable with the lowest index among the variables at the roots
+of the BDDs.  This index index can then be used with...
+.LP
+.B BDD_COFACTOR
+Takes an index index, a BDD, and two variables of type \fBbdd\fR, and
+sets the two variables either to the original BDD or to the cofactors
+of the original BDD with respect to its top variable, depending on
+whether the index index of the first BDD matches that specified.  You
+can do a Shannon expansion on the top variable of two BDDs by using
+.B BDD_TOP_VAR2
+to get the index index of the highest variable and then using
+.B BDD_COFACTOR
+to take the appropriate cofactors.
+.LP
+.B BDD_MARK
+.in +4
+Accesses the mark field of a node.  This expands to a l-value, so you
+can set the mark with this as well.  (But see BDD_TEMP_REFS below.)
+.LP
+.B BDD_ONE, BDD_ZERO
+.in +4
+Take a BDD manager and give back the BDDs for TRUE and FALSE.
+.LP
+.B BDD_REFS
+.in +4
+Accesses the reference count field of a node.
+.LP
+.B BDD_INCREFS, BDD_DECREFS
+.in +4
+Increment and decrement the reference count.
+.LP
+.B BDD_TEMP_REFS
+.in +4
+Accesses the temporary reference count field of a node.  The temporary
+reference count and the mark actually share storage, so you can't use
+both at once!  That is, unless you are very clever, you can't write a
+routine that builds temporary nodes and uses the marks.
+.LP
+.B BDD_TEMP_INCREFS, BDD_TEMP_DECREFS
+.in +4
+Increment and decrement the temporary reference count.
+.LP
+
+New BDD nodes are created using \fBbdd_find\fR.  This routine takes a
+BDD manager, an index index, and two subBDDs as arguments.  New MTBDD
+terminals can be created with \fBbdd_find_terminal\fR.  The result
+cache is manipulated using the
+.B bdd_lookup_in_cache
+and
+.B bdd_insert_in_cache
+routines.  There are different versions of these routines depending on
+exactly what is being cached.  The basic ones are
+\fBbdd_lookup_in_cache31\fR and \fBbdd_insert_in_cache31\fR.
+The first of these takes a cache entry type (CACHE_TYPE_ITE,
+CACHE_TYPE_TWO, etc.), three arguments of unspecified type (passed as
+longs), and a pointer to an unspecified type of result (a pointer to a
+long).  It returns a nonzero result if the lookup succeeds.  The
+corresponding insert routine is similar except that the result is
+passed in as a long, and nothing is returned.  There are similar
+functions that are for routines that take two arguments and return two
+results (or a single double-word result), or for routines that take
+one argument and return three results.  There are also macros such as
+\fBbdd_lookup_in_cache2\fR that are wrappers for things like
+two-argument functions, etc.  In general, some action must be taken
+when results are returned from the cache, when entries are purged from
+the cache, when entries are garbage collected, and when a variable
+association ID is reclaimed.  For the built-in cache entry types,
+these actions are done automatically.  For example, when a BDD is
+returned from an entry with CACHE_TYPE_TWO, the temporary reference
+count of the BDD is incremented.  Some of the entry types are
+available for customization.  The actions to take for these entry
+types are specified by calling \fBbdd_cache_functions\fR.  This
+function takes a BDD manager, an integer between 1 and 3 specifying
+the number of arguments you want to cache on, and four function
+pointers.  When returning a result, purging an entry, garbage
+collecting, or reclaiming an association ID, these functions are
+called.  The first three functions are passed the BDD manager and the
+entry.  (The tag bits will have already been masked off the entry
+pointer.)  The last receives these plus the association ID being freed
+(cast to a pointer).  The garbage collection function should return a
+nonzero result if the entry should be garbage collected.  If the entry
+contains some BDD nodes, they should be tested with \fBBDD_IS_USED\fR.
+The function called when an association ID is reclaimed should return
+a nonzero result if the entry should be flushed from the cache.  This
+function and the purge function and return functions may be null,
+specifying that no action need be taken.  \fBbdd_cache_functions\fR
+returns an integer that represents a tag to use with the cache
+insertion and lookup routines, or -1 if there are no more free tags
+available.  The routine \fBbdd_free_cache_tag\fR makes a tag available
+again.
+
+Routines that build new BDD nodes must take into account the
+possibility of running into the node limit.  The package is set up to
+make this easy if you use the following strategy.  Organize your
+routine as a top-level (user-callable) procedure and an internal
+procedure for performing the actual computation.  The top-level
+procedure should check its arguments before calling the internal
+routine.  The
+.B bdd_check_arguments
+function can be used to test for null arguments (indicating a prior
+overflow) or arguments with a zero reference count (indicating a bug).
+It should also use the
+.B FIREWALL
+macro to set up an overflow trap.  The internal routine should use
+temporary reference counts to keep track of the nodes it is using.
+When a node is returned from the internal routine, increment its
+temporary reference count once.  (You don't have to do this for the
+constants or for variables, since they can't be garbage collected.)
+When you pass a node to \fBbdd_find\fR, its temporary reference count
+is decremented once automatically, and its reference count is
+incremented.  Also, the result of \fBbdd_find\fR has its temporary
+reference count incremented once automatically.  Hence, if you your
+routine has the standard organization (Shannon's expansion followed by
+\fBbdd_find\fR on the subresults), you usually don't have to worry
+about incrementing or decrementing the reference counts yourself.  If
+you don't use a subresult, or if you want a subresult to stick around
+after calling \fBbdd_find\fR, you'll have to do the appropriate
+twiddling.  When the internal routine finally returns, you should have
+a BDD with a single temporary reference count.  Use
+.B RETURN_BDD
+to convert this temporary reference count to an external one and
+return the result to the user.  If you follow this strategy, you won't
+have to deal with overflow; when the node limit is reached,
+\fBbdd_find\fR will try garbage collecting, and if that doesn't work,
+will call the overflow trap set up by \fBFIREWALL\fR.  The overflow
+trap handler will automatically zero all temporary reference counts
+and return a null pointer to the user.  Note: if you want to call
+other routines, such as the IF-THEN-ELSE routine, within your internal
+procedure, you should call the internal procedure for the routine.
+That way, the overflow handler will give control back to the user
+if the routine you are calling causes an overflow.
+
+A typical routine looks like:
+
+.nf
+bdd
+foo_step(bddm, f, g)
+     bdd_manager bddm;
+     bdd f, g;
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+  
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (<terminal case>)
+    {
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (bdd_lookup_in_cache2(bddm, <op>, f, g, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=foo_step(bddm, f1, g1);
+  temp2=foo_step(bddm, f2, g2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache2(bddm, <op>, f, g, result);
+  return (result);
+}
+
+bdd
+foo(bddm, f, g)
+     bdd_manager bddm;
+     bdd f, g;
+{
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(foo_step(bddm, f, g));
+    }
+  return ((bdd)0);
+}
+.fi
+
+In the case of dynamic variable reordering, the same abort mechanism
+is used.  After reordering, all reference counts are reset to their
+original values and the operation is retried.  This is handled
+automatically by the FIREWALL macro.  (The operation is aborted since
+after reordering, the implicit ordering represented in the C
+subroutine call stack may be different from the new variable order.
+Reordering occurs before freeing the temporaries, since we want to
+minimize the aggregate size of the operands plus the result that is
+being constructed.)
+
+Storage can be allocated through a number of mechanisms.  The routines
+\fBmem_get_block\fR, \fBmem_free_block\fR, and \fBmem_resize_block\fR
+are generally used for large single items.  For smaller uniformly
+sized items, you probably should use a record manager.
+.B mem_new_rec_mgr
+will return a record manager that handles blocks of a given size.
+Use
+.B mem_new_rec
+and
+.B mem_free_rec
+to obtain and free individual records.  Finally,
+.B mem_free_rec_mgr
+will dispose of the record manager and all of its associated records.
+These routines are documented in more detail in the storage management
+library man page.  If your structures are at most 64 bytes in size,
+you can use the macros
+.B BDD_NEW_REC
+and \fBBDD_FREE_REC\fR.  These obtain records from the internal BDD
+record managers.
+.SH "PORTABILITY NOTES"
+Since pointer tagging is heavily used, you'll have major problems if
+you can't cast back and forth between pointers and longs without
+losing something.  The low-level storage management routines are
+fairly UNIX specific; they call
+.B sbrk
+directly.  If you don't have something similar, you may have to
+rewrite them.  The storage management routines also need to be able to
+move and clear blocks of memory whose size is given by a long.  You
+may have to fiddle with these, especially if you have a machine where
+int and long are different.  If you encounter portability problems,
+let me know; maybe the next release will be able to accommodate your
+machine.
+.SH "SEE ALSO"
+mem(3)
+.SH BUGS
+Surely you're joking.
+.SH REFERENCES
+[1] R. E. Bryant.  Graph Based Algorithms for Boolean Function
+Manipulation.  \fIIEEE Transactions on Computers\fR, C-35(8):677-691,
+August 1986.
+.LP
+[2] H. J. Touati, H. Savoj, B. Lin, R. K. Brayton, and A.
+Sangiovanni-Vincentelli.  Implicit State Enumeration of Finite State
+Machines using BDD's.  In \fIProceedings of the 1990 IEEE
+International Conference on Computer-Aided Design\fR, November, 1990.
+.LP
+[3] K. S. Brace, R. L. Rudell, and R. E. Bryant.  Efficient
+Implementation of a BDD Package.  In \fIProceedings of the 27th
+ACM/IEEE Design Automation Conference\fR, June, 1990.
+.LP
+[4] E. M. Clarke, K. L. McMillan, X. Zhao, M. Fujita, and J. C.-Y.
+Yang.  Spectral Transforms for Large Boolean Functions with
+Applications to Technology Mapping.  In \fIProceedings of the 30th
+ACM/IEEE Design Automation Conference\fR, June, 1993.
+.SH AUTHOR
+David E. Long
+.br
+long@research.att.com
Index: /vis_dev/glu-2.1/src/cmuBdd/bdd.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bdd.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bdd.c	(revision 8)
@@ -0,0 +1,1097 @@
+/* Basic BDD routines */
+
+
+#include "bddint.h"
+
+
+/* cmu_bdd_one(bddm) gives the BDD for true. */
+
+bdd
+cmu_bdd_one(cmu_bdd_manager bddm)
+{
+  return (BDD_ONE(bddm));
+}
+
+
+/* cmu_bdd_zero(bddm) gives the BDD for false. */
+
+bdd
+cmu_bdd_zero(cmu_bdd_manager bddm)
+{
+  return (BDD_ZERO(bddm));
+}
+
+
+bdd
+bdd_make_external(bdd f)
+{
+  BDD_SETUP(f);
+  BDD_INCREFS(f);
+  BDD_TEMP_DECREFS(f);
+  return (f);
+}
+
+
+long
+bdd_find_block(block b, long index)
+{
+  long i, j, k;
+
+  i=0;
+  j=b->num_children-1;
+  while (i <= j)
+    {
+      k=(i+j)/2;
+      if (b->children[k]->first_index <= index && b->children[k]->last_index >= index)
+	return (k);
+      if (b->children[k]->first_index > index)
+	j=k-1;
+      else
+	i=k+1;
+    }
+  return (i);
+}
+
+
+void
+bdd_block_delta(block b, long delta)
+{
+  long i;
+
+  b->first_index+=delta;
+  b->last_index+=delta;
+  for (i=0; i < b->num_children; ++i)
+    bdd_block_delta(b->children[i], delta);
+}
+
+
+static
+block
+shift_block(cmu_bdd_manager bddm, block b, long index)
+{
+  long i, j;
+  block p;
+
+  if (b->first_index >= index)
+    {
+      bdd_block_delta(b, 1l);
+      return (b);
+    }
+  if (b->last_index < index)
+    return (b);
+  b->last_index++;
+  i=bdd_find_block(b, index);
+  if (i == b->num_children || b->children[i]->first_index == index)
+    {
+      b->children=(block *)mem_resize_block((pointer)b->children, (SIZE_T)(sizeof(block)*(b->num_children+1)));
+      for (j=b->num_children-1; j >= i; --j)
+	b->children[j+1]=shift_block(bddm, b->children[j], index);
+      b->num_children++;
+      p=(block)BDD_NEW_REC(bddm, sizeof(struct block_));
+      p->reorderable=0;
+      p->first_index=index;
+      p->last_index=index;
+      p->num_children=0;
+      p->children=0;
+      b->children[i]=p;
+    }
+  else
+    while (i < b->num_children)
+      {
+	shift_block(bddm, b->children[i], index);
+	++i;
+      }
+  return (b);
+}
+
+
+/* bdd_new_var(bddm, index) creates a new variable with the */
+/* specified index.  Existing variables with greater or equal index */
+/* have their index incremented. */
+
+static
+bdd
+bdd_new_var(cmu_bdd_manager bddm, bdd_index_type index)
+{
+  long i;
+  long temp;
+  long oldmax;
+  assoc_list p;
+  bdd var;
+
+  if (bddm->vars == BDD_MAX_INDEXINDEX)
+    cmu_bdd_fatal("bdd_new_var: no more indexes");
+  if (index > bddm->vars)
+    cmu_bdd_fatal("bdd_new_var: index out of range");
+  if (bddm->vars == bddm->maxvars)
+    {
+      /* Expand indexing tables and variable associations. */
+      oldmax=bddm->maxvars;
+      temp=bddm->maxvars*2;
+      if (temp > BDD_MAX_INDEXINDEX-1)
+	temp=BDD_MAX_INDEXINDEX-1;
+      bddm->maxvars=temp;
+      bddm->variables=(bdd *)mem_resize_block((pointer)bddm->variables,
+					      (SIZE_T)((bddm->maxvars+1)*sizeof(bdd)));
+      bddm->indexes=(bdd_index_type *)mem_resize_block((pointer)bddm->indexes,
+						       (SIZE_T)((bddm->maxvars+1)*sizeof(bdd_index_type)));
+      bddm->indexindexes=
+	(bdd_indexindex_type *)mem_resize_block((pointer)bddm->indexindexes,
+						(SIZE_T)(bddm->maxvars*sizeof(bdd_indexindex_type)));
+      bddm->unique_table.tables=
+	(var_table *)mem_resize_block((pointer)bddm->unique_table.tables,
+				      (SIZE_T)((bddm->maxvars+1)*sizeof(var_table)));
+      /* Variable associations are padded with nulls in case new variables */
+      /* are created. */
+      for (p=bddm->assocs; p; p=p->next)
+	{
+	  p->va.assoc=(bdd *)mem_resize_block((pointer)p->va.assoc, (SIZE_T)((bddm->maxvars+1)*sizeof(bdd)));
+	  for (i=oldmax; i < bddm->maxvars; ++i)
+	    p->va.assoc[i+1]=0;
+	}
+      bddm->temp_assoc.assoc=(bdd *)mem_resize_block((pointer)bddm->temp_assoc.assoc, (SIZE_T)((bddm->maxvars+1)*sizeof(bdd)));
+      for (i=oldmax; i < bddm->maxvars; ++i)
+	bddm->temp_assoc.assoc[i+1]=0;
+    }
+  /* Shift index of following variables. */
+  if (index != bddm->vars)
+    for (i=0; i < bddm->vars; ++i)
+      if (bddm->indexes[i+1] >= index)
+	bddm->indexes[i+1]++;
+  for (p=bddm->assocs; p; p=p->next)
+    if (p->va.last >= index)
+      p->va.last++;
+  if (bddm->temp_assoc.last >= index)
+    bddm->temp_assoc.last++;
+  /* Shift indexindex values. */
+  for (i=bddm->vars; i > index; --i)
+    bddm->indexindexes[i]=bddm->indexindexes[i-1];
+  /* Make a new variable table. */
+  bddm->vars++;
+  bddm->unique_table.tables[bddm->vars]=bdd_new_var_table(bddm);
+  /* Create the variable. */
+  var=bdd_find_aux(bddm, (bdd_indexindex_type)bddm->vars, (INT_PTR)BDD_ONE(bddm), (INT_PTR)BDD_ZERO(bddm));
+  var->refs=BDD_MAX_REFS;
+  /* Record everything. */
+  bddm->variables[bddm->vars]=var;
+  bddm->indexes[bddm->vars]=index;
+  bddm->indexindexes[index]=bddm->vars;
+  /* Make a new variable block containing the variable. */
+  shift_block(bddm, bddm->super_block, (long)index);
+  return (var);
+}
+
+
+/* cmu_bdd_new_var_first(bddm) returns the BDD for a new variable at the */
+/* start of the variable order. */
+
+bdd
+cmu_bdd_new_var_first(cmu_bdd_manager bddm)
+{
+  return (bdd_new_var(bddm, (bdd_index_type)0));
+}
+
+
+/* cmu_bdd_new_var_last(bddm) returns the BDD for a new variable at the */
+/* end of the variable order. */
+
+bdd
+cmu_bdd_new_var_last(cmu_bdd_manager bddm)
+{
+  return (bdd_new_var(bddm, (bdd_index_type)bddm->vars));
+}
+
+
+/* cmu_bdd_new_var_before(bddm, var) returns the BDD for a new variable */
+/* before the specified one in the variable order. */
+
+bdd
+cmu_bdd_new_var_before(cmu_bdd_manager bddm, bdd var)
+{
+  if (bdd_check_arguments(1, var))
+    {
+      BDD_SETUP(var);
+      if (cmu_bdd_type_aux(bddm, var) != BDD_TYPE_POSVAR)
+	{
+	  cmu_bdd_warning("cmu_bdd_new_var_before: argument is not a positive variable");
+	  if (BDD_IS_CONST(var))
+	    return (cmu_bdd_new_var_last(bddm));
+	}
+      return (bdd_new_var(bddm, BDD_INDEX(bddm, var)));
+    }
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_new_var_after(bddm, var) returns the BDD for a new variable */
+/* after the specified one in the variable order. */
+
+bdd
+cmu_bdd_new_var_after(cmu_bdd_manager bddm, bdd var)
+{
+  if (bdd_check_arguments(1, var))
+    {
+      BDD_SETUP(var);
+      if (cmu_bdd_type_aux(bddm, var) != BDD_TYPE_POSVAR)
+	{
+	  cmu_bdd_warning("cmu_bdd_new_var_after: argument is not a positive variable");
+	  if (BDD_IS_CONST(var))
+	    return (cmu_bdd_new_var_last(bddm));
+	}
+      return (bdd_new_var(bddm, BDD_INDEX(bddm, var)+1));
+    }
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_var_with_index(bddm, index) returns the variable with the */
+/* specified index, or null if there is no such variable. */
+
+bdd
+cmu_bdd_var_with_index(cmu_bdd_manager bddm, long index)
+{
+  if (index < 0 || index >= bddm->vars)
+    return ((bdd)0);
+  return (bddm->variables[bddm->indexindexes[index]]);
+}
+
+
+/* cmu_bdd_var_with_id(bddm, id) returns the variable with the specified */
+/* id, or null if there is no such variable. */
+
+bdd
+cmu_bdd_var_with_id(cmu_bdd_manager bddm, long indexindex)
+{
+  if (indexindex <= 0 || indexindex > bddm->vars)
+    return ((bdd)0);
+  return (bddm->variables[indexindex]);
+}
+
+
+static
+bdd
+cmu_bdd_and_step(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (BDD_IS_CONST(f))
+    {
+      if (f == BDD_ZERO(bddm))
+	return (f);
+      BDD_TEMP_INCREFS(g);
+      return (g);
+    }
+  /* f is not constant. */
+  if (BDD_IS_CONST(g))
+    {
+      if (g == BDD_ZERO(bddm))
+	return (g);
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  /* f and g are not constant. */
+  if (BDD_SAME_OR_NEGATIONS(f, g))
+    {
+      if (f == g)
+	{
+	  BDD_TEMP_INCREFS(f);
+	  return (f);
+	}
+      return (BDD_ZERO(bddm));
+    }
+  /* f and g are not constant and are not equal or negations. */
+  if (BDD_OUT_OF_ORDER(f, g))
+    BDD_SWAP(f, g);
+  if (bdd_lookup_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)BDD_ZERO(bddm), (INT_PTR *)&result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=cmu_bdd_and_step(bddm, f1, g1);
+  temp2=cmu_bdd_and_step(bddm, f2, g2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)BDD_ZERO(bddm), (INT_PTR)result);
+  return (result);
+}
+
+
+static
+bdd
+cmu_bdd_xnor_step(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  int outneg;
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (BDD_IS_CONST(f))
+    {
+      BDD_TEMP_INCREFS(g);
+      if (f == BDD_ONE(bddm))
+	return (g);
+      return (BDD_NOT(g));
+    }
+  if (BDD_IS_CONST(g))
+    {
+      BDD_TEMP_INCREFS(f);
+      if (g == BDD_ONE(bddm))
+	return (f);
+      return (BDD_NOT(f));
+    }
+  /* f and g are not constant. */
+  if (BDD_SAME_OR_NEGATIONS(f, g))
+    {
+      if (f == g)
+	return (BDD_ONE(bddm));
+      return (BDD_ZERO(bddm));
+    }
+  /* f and g are not constant, not same, not negations. */
+  if (BDD_OUT_OF_ORDER(f, g))
+    BDD_SWAP(f, g);
+  if (BDD_IS_OUTPOS(g))
+    outneg=0;
+  else
+    {
+      outneg=1;
+      g=BDD_NOT(g);
+    }
+  /* g is an uncomplemented output pointer. */
+  if (bdd_lookup_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)BDD_NOT(g), (INT_PTR *)&result))
+    return (outneg ? BDD_NOT(result) : result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=cmu_bdd_xnor_step(bddm, f1, g1);
+  temp2=cmu_bdd_xnor_step(bddm, f2, g2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)BDD_NOT(g), (INT_PTR)result);
+  return (outneg ? BDD_NOT(result) : result);
+}
+
+
+bdd
+cmu_bdd_ite_step(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  int outneg;
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd h1, h2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  BDD_SETUP(h);
+  if (BDD_IS_CONST(f))
+    {
+      if (f == BDD_ONE(bddm))
+	{
+	  BDD_TEMP_INCREFS(g);
+	  return (g);
+	}
+      BDD_TEMP_INCREFS(h);
+      return (h);
+    }
+  /* f is not constant. */
+  if (BDD_SAME_OR_NEGATIONS(f, g))
+    {
+      if (f == g)
+	g=BDD_ONE(bddm);
+      else
+	g=BDD_ZERO(bddm);
+      BDD_RESET(g);
+    }
+  if (BDD_SAME_OR_NEGATIONS(f, h))
+    {
+      if (f == h)
+	h=BDD_ZERO(bddm);
+      else
+	h=BDD_ONE(bddm);
+      BDD_RESET(h);
+    }
+  if (BDD_IS_CONST(g))
+    {
+      if (BDD_IS_CONST(h))
+	{
+	  if (g == h)
+	    return (g);
+	  BDD_TEMP_INCREFS(f);
+	  if (g == BDD_ONE(bddm))
+	    return (f);
+	  return (BDD_NOT(f));
+	}
+      if (g == BDD_ZERO(bddm))
+	return (cmu_bdd_and_step(bddm, BDD_NOT(f), h));
+      return (BDD_NOT(cmu_bdd_and_step(bddm, BDD_NOT(f), BDD_NOT(h))));
+    }
+  else if (BDD_SAME_OR_NEGATIONS(g, h))
+    {
+      if (g == h)
+	{
+	  BDD_TEMP_INCREFS(g);
+	  return (g);
+	}
+      return (cmu_bdd_xnor_step(bddm, f, g));
+    }
+  else if (BDD_IS_CONST(h))
+    {
+    if (h == BDD_ZERO(bddm))
+      return (cmu_bdd_and_step(bddm, f, g));
+    else
+      return (BDD_NOT(cmu_bdd_and_step(bddm, f, BDD_NOT(g))));
+    }
+  /* No special cases; it's a real if-then-else. */
+  if (!BDD_IS_OUTPOS(f))
+    {
+      f=BDD_NOT(f);
+      BDD_SWAP(g, h);
+    }
+  /* f is now an uncomplemented output pointer. */
+  if (BDD_IS_OUTPOS(g))
+    outneg=0;
+  else
+    {
+      outneg=1;
+      g=BDD_NOT(g);
+      h=BDD_NOT(h);
+    }
+  /* g is now an uncomplemented output pointer. */
+  if (bdd_lookup_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)h, (INT_PTR *)&result))
+    return (outneg ? BDD_NOT(result) : result);
+  BDD_TOP_VAR3(top_indexindex, bddm, f, g, h);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  BDD_COFACTOR(top_indexindex, h, h1, h2);
+  temp1=cmu_bdd_ite_step(bddm, f1, g1, h1);
+  temp2=cmu_bdd_ite_step(bddm, f2, g2, h2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)h, (INT_PTR)result);
+  return (outneg ? BDD_NOT(result) : result);
+}
+
+
+/* cmu_bdd_ite(bddm, f, g, h) returns the BDD for "if f then g else h". */
+
+bdd
+cmu_bdd_ite(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  if (bdd_check_arguments(3, f, g, h))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(cmu_bdd_ite_step(bddm, f, g, h));
+    }
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_and(bddm, f, g) returns the BDD for "f and g". */
+
+bdd
+cmu_bdd_and(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  return (cmu_bdd_ite(bddm, f, g, BDD_ZERO(bddm)));
+}
+
+
+/* cmu_bdd_nand(bddm, f, g) returns the BDD for "f nand g". */
+
+bdd
+cmu_bdd_nand(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  bdd temp;
+
+  if ((temp=cmu_bdd_and(bddm, f, g)))
+    return (BDD_NOT(temp));
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_or(bddm, f, g) returns the BDD for "f or g". */
+
+bdd
+cmu_bdd_or(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  return (cmu_bdd_ite(bddm, f, BDD_ONE(bddm), g));
+}
+
+
+/* cmu_bdd_nor(bddm, f, g) returns the BDD for "f nor g". */
+
+bdd
+cmu_bdd_nor(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  bdd temp;
+
+  if ((temp=cmu_bdd_or(bddm, f, g)))
+    return (BDD_NOT(temp));
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_xor(bddm, f, g) returns the BDD for "f xor g". */
+
+bdd
+cmu_bdd_xor(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  return (cmu_bdd_ite(bddm, f, BDD_NOT(g), g));
+}
+
+
+/* cmu_bdd_xnor(bddm, f, g) returns the BDD for "f xnor g". */
+
+bdd
+cmu_bdd_xnor(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  bdd temp;
+
+  if ((temp=cmu_bdd_xor(bddm, f, g)))
+    return (BDD_NOT(temp));
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_identity(bddm, f) returns the BDD for f.  (The only effect is */
+/* to increase the reference count for f.) */
+
+bdd
+cmu_bdd_identity(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      BDD_INCREFS(f);
+    }
+  return (f);
+}
+
+
+/* cmu_bdd_not(bddm, f) returns the BDD for "not f". */
+
+bdd
+cmu_bdd_not(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      BDD_INCREFS(f);
+      return (BDD_NOT(f));
+    }
+  return ((bdd)0);
+}
+ 
+
+/* cmu_bdd_if(bddm, f) returns the BDD for the variable at the top of f. */
+
+bdd
+cmu_bdd_if(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      if (BDD_IS_CONST(f))
+	{
+	  cmu_bdd_warning("cmu_bdd_if: argument is a constant");
+	  return (f);
+	}
+      FIREWALL(bddm);
+      RETURN_BDD(BDD_IF(bddm, f));
+    }
+  return (f);
+}
+
+
+/* cmu_bdd_if_index(bddm, f) returns the index for the variable at the top */
+/* of f. */
+
+long
+cmu_bdd_if_index(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      if (BDD_IS_CONST(f))
+	return (-1l);
+      return ((long)BDD_INDEX(bddm, f));
+    }
+  return (-1l);
+}
+
+
+/* cmu_bdd_if_id(bddm, f) returns a unique identifier for the variable at */
+/* the top of f. */
+
+long
+cmu_bdd_if_id(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      if (BDD_IS_CONST(f))
+	return (-1l);
+      return ((long)BDD_INDEXINDEX(f));
+    }
+  return (-1l);
+}
+
+
+/* cmu_bdd_then(bddm, f) returns the BDD for the "then" pointer of f. */
+
+bdd
+cmu_bdd_then(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      if (BDD_IS_CONST(f))
+	{
+	  cmu_bdd_warning("cmu_bdd_then: argument is a constant");
+	  return (f);
+	}
+      f=BDD_THEN(f);
+      BDD_RESET(f);
+      BDD_INCREFS(f);
+    }
+  return (f);
+}
+ 
+
+/* cmu_bdd_else(bddm, f) returns the BDD for the "else" pointer of f. */
+
+bdd
+cmu_bdd_else(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      if (BDD_IS_CONST(f))
+	{
+	  cmu_bdd_warning("cmu_bdd_else: argument is a constant");
+	  return (f);
+	}
+      f=BDD_ELSE(f);
+      BDD_RESET(f);
+      BDD_INCREFS(f);
+    }
+  return (f);
+}
+
+
+static
+bdd
+cmu_bdd_intersects_step(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (BDD_IS_CONST(f))
+    {
+      if (f == BDD_ZERO(bddm))
+	return (f);
+      BDD_TEMP_INCREFS(g);
+      return (g);
+    }
+  /* f is not constant. */
+  if (BDD_IS_CONST(g))
+    {
+      if (g == BDD_ZERO(bddm))
+	return (g);
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  /* f and g are not constant. */
+  if (BDD_SAME_OR_NEGATIONS(f, g))
+    {
+      if (f == g)
+	{
+	  BDD_TEMP_INCREFS(f);
+	  return (f);
+	}
+      return (BDD_ZERO(bddm));
+    }
+  /* f and g are not constant and are not equal or negations. */
+  if (BDD_OUT_OF_ORDER(f, g))
+    BDD_SWAP(f, g);
+  if (bdd_lookup_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)BDD_ZERO(bddm), (INT_PTR *)&temp))
+    return (temp);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp=cmu_bdd_intersects_step(bddm, f1, g1);
+  if (temp != BDD_ZERO(bddm))
+    return (bdd_find(bddm, top_indexindex, temp, BDD_ZERO(bddm)));
+  temp=bdd_find(bddm, top_indexindex, BDD_ZERO(bddm), cmu_bdd_intersects_step(bddm, f2, g2));
+  if (temp == BDD_ZERO(bddm))
+    bdd_insert_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)BDD_ZERO(bddm), (INT_PTR)temp);
+  return (temp);
+}
+
+
+/* cmu_bdd_intersects(bddm, f, g) returns a BDD contained in "f and g", */
+/* while building as few nodes as possible.  The idea is that it */
+/* gives us a fast test for intersection, and, when f and g do */
+/* intersect, we can call cmu_bdd_satisfy or cmu_bdd_satisfy_support on the */
+/* result to get a valuation in the intersection. */
+
+bdd
+cmu_bdd_intersects(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(cmu_bdd_intersects_step(bddm, f, g));
+    }
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_implies(bddm, f, g) is analogous to cmu_bdd_intersects, but it */
+/* looks for things in "f and not g". */
+
+bdd
+cmu_bdd_implies(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(cmu_bdd_intersects_step(bddm, f, BDD_NOT(g)));
+    }
+  return ((bdd)0);
+}
+
+
+int
+cmu_bdd_type_aux(cmu_bdd_manager bddm, bdd f)
+{
+  BDD_SETUP(f);
+  if (BDD_IS_CONST(f))
+    {
+      if (f == BDD_ZERO(bddm))
+	return (BDD_TYPE_ZERO);
+      if (f == BDD_ONE(bddm))
+	return (BDD_TYPE_ONE);
+      return (BDD_TYPE_CONSTANT);
+    }
+  if (BDD_THEN(f) == BDD_ONE(bddm) && BDD_ELSE(f) == BDD_ZERO(bddm))
+    return (BDD_TYPE_POSVAR);
+  if (BDD_THEN(f) == BDD_ZERO(bddm) && BDD_ELSE(f) == BDD_ONE(bddm))
+    return (BDD_TYPE_NEGVAR);
+  return (BDD_TYPE_NONTERMINAL);
+}
+
+
+/* cmu_bdd_type(bddm, f) returns BDD_TYPE_ZERO if f is false, BDD_TYPE_ONE */
+/* if f is true, BDD_TYPE_CONSTANT if f is an MTBDD constant, */
+/* BDD_TYPE_POSVAR is f is an unnegated variable, BDD_TYPE_NEGVAR if */
+/* f is a negated variable, BDD_TYPE_OVERFLOW if f is null, and */
+/* BDD_TYPE_NONTERMINAL otherwise. */
+
+int
+cmu_bdd_type(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    return (cmu_bdd_type_aux(bddm, f));
+  return (BDD_TYPE_OVERFLOW);
+}
+
+
+/* cmu_bdd_unfree(bddm, f) increments the reference count for f. */
+
+void
+cmu_bdd_unfree(cmu_bdd_manager bddm, bdd f)
+{
+  if (f)
+    {
+      BDD_SETUP(f);
+      BDD_INCREFS(f);
+    }
+}
+
+
+/* cmu_bdd_free(bddm, f) decrements the reference count for f. */
+
+void
+cmu_bdd_free(cmu_bdd_manager bddm, bdd f)
+{
+  if (f)
+    {
+      BDD_SETUP(f);
+      if (BDD_REFS(f) == 0)
+	cmu_bdd_fatal("cmu_bdd_free: attempt to free node with zero references");
+      else
+	BDD_DECREFS(f);
+    }
+}
+
+
+/* cmu_bdd_vars(bddm) returns the number of variables in existence. */
+
+long
+cmu_bdd_vars(cmu_bdd_manager bddm)
+{
+  return (bddm->vars);
+}
+
+
+/* cmu_bdd_total_size(bddm) returns the number of BDD nodes in existence. */
+
+long
+cmu_bdd_total_size(cmu_bdd_manager bddm)
+{
+  return (bddm->unique_table.entries);
+}
+
+
+/* cmu_bdd_cache_ratio(bddm, new_ratio) sets the cache size ratio to */
+/* new_ratio and returns the old ratio. */
+
+int
+cmu_bdd_cache_ratio(cmu_bdd_manager bddm, int new_ratio)
+{
+  int old_ratio;
+
+  old_ratio=bddm->op_cache.cache_ratio;
+  if (new_ratio < 1)
+    new_ratio=1;
+  else if (new_ratio > 32)
+    new_ratio=32;
+  bddm->op_cache.cache_ratio=new_ratio;
+  return (old_ratio);
+}
+
+
+/* cmu_bdd_node_limit(bddm, new_limit) sets the node limit to */
+/* new_limit and returns the old limit. */
+
+long
+cmu_bdd_node_limit(cmu_bdd_manager bddm, long new_limit)
+{
+  long old_limit;
+
+  old_limit=bddm->unique_table.node_limit;
+  if (new_limit < 0)
+    new_limit=0;
+  bddm->unique_table.node_limit=new_limit;
+  if (new_limit && bddm->unique_table.gc_limit > new_limit)
+    bddm->unique_table.gc_limit=new_limit;
+  return (old_limit);
+}
+
+
+/* cmu_bdd_overflow(bddm) returns 1 if the node limit has been exceeded */
+/* and 0 otherwise.  The overflow flag is cleared. */
+
+int
+cmu_bdd_overflow(cmu_bdd_manager bddm)
+{
+  int result;
+
+  result=bddm->overflow;
+  bddm->overflow=0;
+  return (result);
+}
+
+
+/* cmu_bdd_overflow_closure(bddm, overflow_fn, overflow_env) sets the */
+/* closure to be invoked on overflow.  If overflow_fn is null, it */
+/* indicates that no function should be called. */
+
+void
+cmu_bdd_overflow_closure(cmu_bdd_manager bddm, void (*overflow_fn)(cmu_bdd_manager, pointer), pointer overflow_env)
+{
+  bddm->overflow_fn=overflow_fn;
+  bddm->overflow_env=overflow_env;
+}
+
+
+/* cmu_bdd_abort_closure(bddm, abort_fn, abort_env) sets a closure to be */
+/* invoked when the next find operation is attempted.  This is */
+/* intended for aborting BDD operations from signal handlers.  The */
+/* handler should set this closure so that invoking it will cause */
+/* a longjmp to a recovery routine. */
+
+void
+cmu_bdd_abort_closure(cmu_bdd_manager bddm, void (*abort_fn)(cmu_bdd_manager, pointer), pointer abort_env)
+{
+  bddm->bag_it_fn=abort_fn;
+  bddm->bag_it_env=abort_env;
+}
+
+
+/* cmu_bdd_stats(bddm, fp) prints random statistics to the file indicated */
+/* by fp. */
+
+void
+cmu_bdd_stats(cmu_bdd_manager bddm, FILE *fp)
+{
+  long i;
+  long ue, ce, cs, mem;
+  SIZE_T alloc;
+  assoc_list q;
+
+  ue=bddm->unique_table.entries;
+  ce=bddm->op_cache.entries;
+  cs=bddm->op_cache.size;
+  mem=0;
+  for (i=0; i < bddm->vars; ++i)
+    {
+      mem+=sizeof(struct var_table_);
+      mem+=bddm->unique_table.tables[i]->size*sizeof(bdd);
+    }
+  mem=ue*sizeof(struct bdd_);
+  mem+=cs*sizeof(struct cache_bin_)+ce*sizeof(struct cache_entry_);
+  mem+=bddm->maxvars*(sizeof(bdd_index_type)+sizeof(bdd_indexindex_type)+sizeof(bdd)+sizeof(var_table));
+  for (q=bddm->assocs, i=1; q; q=q->next, ++i);
+  mem+=i*bddm->maxvars*sizeof(bdd);
+  if ((alloc=mem_allocation()))
+    /* mem_allocation may be meaningless depending on mem library. */
+    fprintf(fp, "Memory manager bytes allocated: %ld\n", (long)alloc);
+  fprintf(fp, "Approximate bytes used: %ld\n", mem);
+  fprintf(fp, "Number of nodes: %ld\n", ue);
+  if (bddm->unique_table.node_limit)
+    fprintf(fp, "Node limit: %ld\n", bddm->unique_table.node_limit);
+  else
+    fprintf(fp, "Node limit: ---\n");
+  fprintf(fp, "Overflow: %s\n", bddm->overflow ? "yes" : "no");
+  fprintf(fp, "Approximate bytes per node: %-.2f\n", ((double)mem)/ue);
+  fprintf(fp, "Cache entries: %ld\n", ce);
+  fprintf(fp, "Cache size: %ld\n", 2*cs);
+  fprintf(fp, "Cache load factor: %-.2f\n", ((double)ce)/(2*cs));
+  fprintf(fp, "Cache look ups: %ld\n", bddm->op_cache.lookups);
+  fprintf(fp, "Cache hits: %ld\n", bddm->op_cache.hits);
+  if (bddm->op_cache.lookups)
+    fprintf(fp, "Cache hit rate: %-.2f\n", ((double)(bddm->op_cache.hits))/bddm->op_cache.lookups);
+  else
+    fprintf(fp, "Cache hit rate: ---\n");
+  fprintf(fp, "Cache insertions: %ld\n", bddm->op_cache.inserts);
+  fprintf(fp, "Cache collisions: %ld\n", bddm->op_cache.collisions);
+  fprintf(fp, "Number of variables: %ld\n", bddm->vars);
+  fprintf(fp, "Number of variable associations: %ld\n", i);
+  fprintf(fp, "Number of garbage collections: %ld\n", bddm->unique_table.gcs);
+  fprintf(fp, "Number of nodes garbage collected: %ld\n", bddm->unique_table.freed);
+  fprintf(fp, "Number of find operations: %ld\n", bddm->unique_table.finds);
+}
+
+
+static
+int
+bdd_default_canonical_fn(cmu_bdd_manager bddm, INT_PTR value1, INT_PTR value2, pointer junk)
+{
+  /* Default transformation is treat the value as a 64-bit integer and to */
+  /* negate it if it is positive. */
+  return ((long)value1 > 0 || (!value1 && (long)value2 > 0));
+}
+
+
+static
+void
+bdd_default_transform_fn(cmu_bdd_manager bddm, INT_PTR value1, INT_PTR value2, INT_PTR *result1, INT_PTR *result2, pointer junk)
+{
+  if (!value2)
+    /* Will be a carry when taking 2's complement of value2.  Thus, */
+    /* take 2's complement of high part. */
+    value1= -(long)value1;
+  else
+    {
+      value2= -(long)value2;
+      value1= ~value1;
+    }
+  *result1=value1;
+  *result2=value2;
+}
+
+
+/* cmu_bdd_init() creates and returns a new BDD manager. */
+
+cmu_bdd_manager
+cmu_bdd_init(void)
+{
+  cmu_bdd_manager bddm;
+  long i;
+
+  bddm=(cmu_bdd_manager)mem_get_block((SIZE_T)sizeof(struct bdd_manager_));
+  bddm->overflow=0;
+  bddm->overflow_fn=0;
+  bddm->overflow_env=0;
+  bddm->bag_it_fn=0;
+  bddm->bag_it_env=0;
+  bddm->canonical_fn=bdd_default_canonical_fn;
+  bddm->transform_fn=bdd_default_transform_fn;
+  bddm->transform_env=0;
+  bddm->reorder_fn=0;
+  bddm->reorder_data=0;
+  bddm->vars=0;
+  bddm->maxvars=30; 
+  bddm->check=1;
+  bddm->variables=(bdd *)mem_get_block((SIZE_T)((bddm->maxvars+1)*sizeof(bdd)));
+  bddm->indexes=(bdd_index_type *)mem_get_block((SIZE_T)((bddm->maxvars+1)*sizeof(bdd_index_type)));
+  bddm->indexindexes=(bdd_indexindex_type *)mem_get_block((SIZE_T)(bddm->maxvars*sizeof(bdd_indexindex_type)));
+  bddm->indexes[BDD_CONST_INDEXINDEX]=BDD_MAX_INDEX;
+  for (i=0; i < REC_MGRS; ++i)
+    bddm->rms[i]=mem_new_rec_mgr(MIN_REC_SIZE+ALLOC_ALIGNMENT*i);
+  bddm->temp_assoc.assoc=(bdd *)mem_get_block((SIZE_T)((bddm->maxvars+1)*sizeof(bdd)));
+  bddm->temp_assoc.last= -1;
+  for (i=0; i < bddm->maxvars; ++i)
+    bddm->temp_assoc.assoc[i+1]=0;
+  bddm->curr_assoc_id= -1;
+  bddm->curr_assoc= &bddm->temp_assoc;
+  bddm->assocs=0;
+  bddm->temp_op= -1;
+  bddm->super_block=(block)BDD_NEW_REC(bddm, sizeof(struct block_));
+  bddm->super_block->num_children=0;
+  bddm->super_block->children=0;
+  bddm->super_block->reorderable=1;
+  bddm->super_block->first_index= -1;
+  bddm->super_block->last_index=0;
+  cmu_bdd_init_unique(bddm);
+  cmu_bdd_init_cache(bddm);
+  bddm->one=bdd_find_terminal(bddm, ~(INT_PTR)0, ~(INT_PTR)0);
+  bddm->one->refs=BDD_MAX_REFS;
+  bddm->one->mark=0;
+  bddm->zero=BDD_NOT(bddm->one);
+  if (sizeof(double) > 2*sizeof(long))
+    cmu_bdd_warning("cmu_bdd_init: portability problem for cmu_bdd_satisfying_fraction");
+  return (bddm);
+}
+
+
+/* cmu_bdd_quit(bddm) frees all storage associated with the BDD manager */
+/* bddm. */
+
+void
+cmu_bdd_quit(cmu_bdd_manager bddm)
+{
+  int i;
+  assoc_list p, q;
+
+  cmu_bdd_free_unique(bddm);
+  cmu_bdd_free_cache(bddm);
+  mem_free_block((pointer)bddm->variables);
+  mem_free_block((pointer)bddm->indexes);
+  mem_free_block((pointer)bddm->indexindexes);
+  mem_free_block((pointer)bddm->temp_assoc.assoc);
+  for (p=bddm->assocs; p; p=q)
+    {
+      q=p->next;
+      mem_free_block((pointer)p->va.assoc);
+      BDD_FREE_REC(bddm, (pointer)p, sizeof(struct assoc_list_));
+    }
+  BDD_FREE_REC(bddm, (pointer)bddm->super_block, sizeof(struct block_));
+  for (i=0; i < REC_MGRS; ++i)
+    mem_free_rec_mgr(bddm->rms[i]);
+  mem_free_block((pointer)bddm);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bdd_is_cube.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bdd_is_cube.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bdd_is_cube.c	(revision 8)
@@ -0,0 +1,31 @@
+#include "bddint.h"
+/*
+ * Recursively determine if f is a cube. f is a cube if there is a single
+ * path to the constant one.
+ */
+int
+cmu_bdd_is_cube(struct bdd_manager_ *manager, struct bdd_ *f)
+{
+  struct bdd_ *f0, *f1;
+
+  BDD_SETUP(f);
+  if (BDD_IS_CONST(f)){
+    if (f == BDD_ZERO(manager)){
+      cmu_bdd_fatal("cmu_bdd_is_cube called with 0");
+    }
+    else return 1;
+  }
+  BDD_COFACTOR(BDD_INDEXINDEX(f), f, f1, f0);
+  
+  /*
+   * Exactly one branch of f must point to ZERO to be a cube.
+   */
+  if (f1 == BDD_ZERO(manager)) {
+	return (cmu_bdd_is_cube(manager, f0));
+  } else if (f0 == BDD_ZERO(manager)) {
+	return (cmu_bdd_is_cube(manager, f1));
+  } else { /* not a cube, because neither branch is zero */
+	return 0;
+  }
+}
+
Index: /vis_dev/glu-2.1/src/cmuBdd/bddapply.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddapply.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddapply.c	(revision 8)
@@ -0,0 +1,98 @@
+/* BDD generic apply routines */
+
+
+#include "bddint.h"
+
+
+static
+bdd
+bdd_apply2_step(cmu_bdd_manager bddm,
+		bdd (*terminal_fn)(cmu_bdd_manager, bdd *, bdd *, pointer),
+		long op,
+		bdd f,
+		bdd g,
+		pointer env)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+
+  if ((result=(*terminal_fn)(bddm, &f, &g, env)))
+    {
+      BDD_SETUP(result);
+      BDD_TEMP_INCREFS(result);
+      return (result);
+    }
+  if (bdd_lookup_in_cache2(bddm, op, f, g, &result))
+    return (result);
+  {
+    BDD_SETUP(f);
+    BDD_SETUP(g);
+    BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+    BDD_COFACTOR(top_indexindex, f, f1, f2);
+    BDD_COFACTOR(top_indexindex, g, g1, g2);
+    temp1=bdd_apply2_step(bddm, terminal_fn, op, f1, g1, env);
+    temp2=bdd_apply2_step(bddm, terminal_fn, op, f2, g2, env);
+    result=bdd_find(bddm, top_indexindex, temp1, temp2);
+    bdd_insert_in_cache2(bddm, op, f, g, result);
+    return (result);
+  }
+}
+
+
+bdd
+bdd_apply2(cmu_bdd_manager bddm, bdd (*terminal_fn)(cmu_bdd_manager, bdd *, bdd *, pointer), bdd f, bdd g, pointer env)
+{
+  long op;
+
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      op=bddm->temp_op--;
+      RETURN_BDD(bdd_apply2_step(bddm, terminal_fn, op, f, g, env));
+    }
+  return ((bdd)0);
+}
+
+
+static
+bdd
+bdd_apply1_step(cmu_bdd_manager bddm, bdd (*terminal_fn)(cmu_bdd_manager, bdd *, pointer), long op, bdd f, pointer env)
+{
+  bdd temp1, temp2;
+  bdd result;
+
+  if ((result=(*terminal_fn)(bddm, &f, env)))
+    {
+      BDD_SETUP(result);
+      BDD_TEMP_INCREFS(result);
+      return (result);
+    }
+  if (bdd_lookup_in_cache1(bddm, op, f, &result))
+    return (result);
+  {
+    BDD_SETUP(f);
+    temp1=bdd_apply1_step(bddm, terminal_fn, op, BDD_THEN(f), env);
+    temp2=bdd_apply1_step(bddm, terminal_fn, op, BDD_ELSE(f), env);
+    result=bdd_find(bddm, BDD_INDEXINDEX(f), temp1, temp2);
+    bdd_insert_in_cache1(bddm, op, f, result);
+    return (result);
+  }
+}
+
+
+bdd
+bdd_apply1(cmu_bdd_manager bddm, bdd (*terminal_fn)(cmu_bdd_manager, bdd *, pointer), bdd f, pointer env)
+{
+  long op;
+
+  if (bdd_check_arguments(1, f))
+    {
+      FIREWALL(bddm);
+      op=bddm->temp_op--;
+      RETURN_BDD(bdd_apply1_step(bddm, terminal_fn, op, f, env));
+    }
+  return ((bdd)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddassoc.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddassoc.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddassoc.c	(revision 8)
@@ -0,0 +1,273 @@
+/* BDD variable association routines */
+
+
+#include "bddint.h"
+
+
+static
+int
+cmu_bdd_assoc_eq(cmu_bdd_manager bddm, bdd *p, bdd *q)
+{
+  bdd_indexindex_type i;
+
+  for (i=0; i < bddm->maxvars; ++i)
+    if (p[i+1] != q[i+1])
+      return (0);
+  return (1);
+}
+
+
+static
+int
+check_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs)
+{
+  bdd_check_array(assoc_info);
+  if (pairs)
+    while (assoc_info[0] && assoc_info[1])
+      {
+	if (cmu_bdd_type_aux(bddm, assoc_info[0]) != BDD_TYPE_POSVAR)
+	  {
+	    cmu_bdd_warning("check_assoc: first element in pair is not a positive variable");
+	    return (0);
+	  }
+	assoc_info+=2;
+      }
+  return (1);
+}
+
+  
+/* cmu_bdd_new_assoc(bddm, assoc_info, pairs) creates or finds a variable */
+/* association given by assoc_info.  pairs is 0 if the information */
+/* represents only a list of variables rather than a full association. */
+
+int
+cmu_bdd_new_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs)
+{
+  long i;
+  assoc_list p, *q;
+  bdd f;
+  bdd *assoc;
+  bdd_indexindex_type j;
+  long last;
+
+  if (!check_assoc(bddm, assoc_info, pairs))
+    return (-1);
+  assoc=(bdd *)mem_get_block((SIZE_T)((bddm->maxvars+1)*sizeof(bdd)));
+  /* Unpack the association. */
+  for (i=0; i < bddm->maxvars; ++i)
+    assoc[i+1]=0;
+  if (pairs)
+    for (i=0; (f=assoc_info[i]) && assoc_info[i+1]; i+=2)
+      {
+	BDD_SETUP(f);
+	assoc[BDD_INDEXINDEX(f)]=assoc_info[i+1];
+      }
+  else
+    for (i=0; (f=assoc_info[i]); ++i)
+      {
+	BDD_SETUP(f);
+	assoc[BDD_INDEXINDEX(f)]=BDD_ONE(bddm);
+      }
+  /* Check for existence. */
+  for (p=bddm->assocs; p; p=p->next)
+    if (cmu_bdd_assoc_eq(bddm, p->va.assoc, assoc))
+      {
+	mem_free_block((pointer)assoc);
+	p->refs++;
+	return (p->id);
+      }
+  /* Find the first unused id. */
+  for (q= &bddm->assocs, p= *q, i=0; p && p->id == i; q= &p->next, p= *q, ++i);
+  p=(assoc_list)BDD_NEW_REC(bddm, sizeof(struct assoc_list_));
+  p->id=i;
+  p->next= *q;
+  *q=p;
+  p->va.assoc=assoc;
+  last= -1;
+  if (pairs)
+    for (i=0; (f=assoc_info[i]) && assoc_info[i+1]; i+=2)
+      {
+	BDD_SETUP(f);
+	j=BDD_INDEXINDEX(f);
+	if ((long)bddm->indexes[j] > last)
+	  last=bddm->indexes[j];
+      }
+  else
+    for (i=0; (f=assoc_info[i]); ++i)
+      {
+	BDD_SETUP(f);
+	j=BDD_INDEXINDEX(f);
+	if ((long)bddm->indexes[j] > last)
+	  last=bddm->indexes[j];
+      }
+  p->va.last=last;
+  p->refs=1;
+  /* Protect BDDs in the association. */
+  if (pairs)
+    for (i=0; assoc_info[i] && (f=assoc_info[i+1]); i+=2)
+      {
+	BDD_SETUP(f);
+	BDD_INCREFS(f);
+      }
+  return (p->id);
+}
+
+
+static
+int
+bdd_flush_id_entries(cmu_bdd_manager bddm, cache_entry p, pointer closure)
+{
+  int (*flush_fn)(cmu_bdd_manager, cache_entry, pointer);
+
+  flush_fn=bddm->op_cache.flush_fn[TAG(p)];
+  if (flush_fn)
+    return ((*flush_fn)(bddm, CACHE_POINTER(p), closure));
+  return (0);
+}
+
+
+/* cmu_bdd_free_assoc(bddm, id) deletes the variable association given by */
+/* id. */
+
+void
+cmu_bdd_free_assoc(cmu_bdd_manager bddm, int assoc_id)
+{
+  bdd_indexindex_type i;
+  bdd f;
+  assoc_list p, *q;
+
+  if (bddm->curr_assoc_id == assoc_id)
+    {
+      bddm->curr_assoc_id= -1;
+      bddm->curr_assoc= &bddm->temp_assoc;
+    }
+  for (q= &bddm->assocs, p= *q; p; q= &p->next, p= *q)
+    if (p->id == assoc_id)
+      {
+	p->refs--;
+	if (!p->refs)
+	  {
+	    /* Unprotect the BDDs in the association. */
+	    for (i=0; i < bddm->vars; ++i)
+	      if ((f=p->va.assoc[i+1]))
+		{
+		  BDD_SETUP(f);
+		  BDD_DECREFS(f);
+		}
+	    /* Flush old cache entries. */
+	    bdd_flush_cache(bddm, bdd_flush_id_entries, (pointer)((long)assoc_id));
+	    *q=p->next;
+	    mem_free_block((pointer)(p->va.assoc));
+	    BDD_FREE_REC(bddm, (pointer)p, sizeof(struct assoc_list_));
+	  }
+	return;
+      }
+  cmu_bdd_warning("cmu_bdd_free_assoc: no variable association with specified ID");
+}
+
+
+/* cmu_bdd_augment_temp_assoc(bddm, assoc_info, pairs) adds to the temporary */
+/* variable association as specified by assoc_info.  pairs is 0 if the */
+/* information represents only a list of variables rather than a full */
+/* association. */
+
+void
+cmu_bdd_augment_temp_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs)
+{
+  long i;
+  bdd_indexindex_type j;
+  bdd f;
+  long last;
+
+  if (check_assoc(bddm, assoc_info, pairs))
+    {
+      last=bddm->temp_assoc.last;
+      if (pairs)
+	for (i=0; (f=assoc_info[i]) && assoc_info[i+1]; i+=2)
+	  {
+	    BDD_SETUP(f);
+	    j=BDD_INDEXINDEX(f);
+	    if ((long)bddm->indexes[j] > last)
+	      last=bddm->indexes[j];
+	    if ((f=bddm->temp_assoc.assoc[j]))
+	      {
+		BDD_SETUP(f);
+		BDD_DECREFS(f);
+	      }
+	    f=assoc_info[i+1];
+	    BDD_RESET(f);
+	    bddm->temp_assoc.assoc[j]=f;
+	    /* Protect BDDs in the association. */
+	    BDD_INCREFS(f);
+	  }
+      else
+	for (i=0; (f=assoc_info[i]); ++i)
+	  {
+	    BDD_SETUP(f);
+	    j=BDD_INDEXINDEX(f);
+	    if ((long)bddm->indexes[j] > last)
+	      last=bddm->indexes[j];
+	    if ((f=bddm->temp_assoc.assoc[j]))
+	      {
+		BDD_SETUP(f);
+		BDD_DECREFS(f);
+	      }
+	    bddm->temp_assoc.assoc[j]=BDD_ONE(bddm);
+	  }
+      bddm->temp_assoc.last=last;
+    }
+}
+
+
+/* cmu_bdd_temp_assoc(bddm, assoc_info, pairs) sets the temporary variable */
+/* association as specified by assoc_info.  pairs is 0 if the */
+/* information represents only a list of variables rather than a full */
+/* association. */
+
+void
+cmu_bdd_temp_assoc(cmu_bdd_manager bddm, bdd *assoc_info, int pairs)
+{
+  long i;
+  bdd f;
+
+  /* Clean up old temporary association. */
+  for (i=0; i < bddm->vars; ++i)
+    {
+      if ((f=bddm->temp_assoc.assoc[i+1]))
+	{
+	  BDD_SETUP(f);
+	  BDD_DECREFS(f);
+	}
+      bddm->temp_assoc.assoc[i+1]=0;
+    }
+  bddm->temp_assoc.last= -1;
+  cmu_bdd_augment_temp_assoc(bddm, assoc_info, pairs);
+}
+
+
+/* cmu_bdd_assoc(bddm, id) sets the current variable association to the */
+/* one given by id and returns the ID of the old association.  An */
+/* id of -1 indicates the temporary association. */
+
+int
+cmu_bdd_assoc(cmu_bdd_manager bddm, int assoc_id)
+{
+  int old_assoc;
+  assoc_list p;
+
+  old_assoc=bddm->curr_assoc_id;
+  if (assoc_id != -1)
+    {
+      for (p=bddm->assocs; p; p=p->next)
+	if (p->id == assoc_id)
+	  {
+	    bddm->curr_assoc_id=p->id;
+	    bddm->curr_assoc= &p->va;
+	    return (old_assoc);
+	  }
+      cmu_bdd_warning("cmu_bdd_assoc: no variable association with specified ID");
+    }
+  bddm->curr_assoc_id= -1;
+  bddm->curr_assoc= &bddm->temp_assoc;
+  return (old_assoc);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddblk.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddblk.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddblk.c	(revision 8)
@@ -0,0 +1,82 @@
+/* BDD variable block routines */
+
+
+#include "bddint.h"
+
+
+static
+void
+add_block(block b1, block b2)
+{
+  long i, j, k;
+  block start, end;
+
+  if (b1->num_children)
+    {
+      i=bdd_find_block(b1, b2->first_index);
+      start=b1->children[i];
+      j=bdd_find_block(b1, b2->last_index);
+      end=b1->children[j];
+      if (i == j)
+	add_block(start, b2);
+      else
+	{
+	  if (start->first_index != b2->first_index || end->last_index != b2->last_index)
+	    cmu_bdd_fatal("add_block: illegal block overlap");
+	  b2->num_children=j-i+1;
+	  b2->children=(block *)mem_get_block((SIZE_T)(sizeof(block)*b2->num_children));
+	  for (k=0; k < b2->num_children; ++k)
+	    b2->children[k]=b1->children[i+k];
+	  b1->children[i]=b2;
+	  ++i;
+	  for (k=j+1; k < b1->num_children; ++k, ++i)
+	    b1->children[i]=b1->children[k];
+	  b1->num_children-=(b2->num_children-1);
+	  b1->children=(block *)mem_resize_block((pointer)b1->children, (SIZE_T)(sizeof(block)*b1->num_children));
+	}
+    }
+  else
+    {
+      /* b1 and b2 are blocks representing just single variables. */
+      b1->num_children=1;
+      b1->children=(block *)mem_get_block((SIZE_T)(sizeof(block)*b1->num_children));
+      b1->children[0]=b2;
+      b2->num_children=0;
+      b2->children=0;
+    }
+}
+
+
+block
+cmu_bdd_new_var_block(cmu_bdd_manager bddm, bdd v, long n)
+{
+  block b;
+
+  if (bdd_check_arguments(1, v))
+    {
+      BDD_SETUP(v);
+      if (cmu_bdd_type_aux(bddm, v) != BDD_TYPE_POSVAR)
+	{
+	  cmu_bdd_warning("cmu_bdd_new_var_block: second argument is not a positive variable");
+	  if (BDD_IS_CONST(v))
+	    return ((block)0);
+	}
+      b=(block)BDD_NEW_REC(bddm, sizeof(struct block_));
+      b->reorderable=0;
+      b->first_index=BDD_INDEX(bddm, v);
+      if (n <= 0)
+	{
+	  cmu_bdd_warning("cmu_bdd_new_var_block: invalid final argument");
+	  n=1;
+	}
+      b->last_index=b->first_index+n-1;
+      if (b->last_index >= bddm->vars)
+	{
+	  cmu_bdd_warning("cmu_bdd_new_var_block: range covers non-existent variables");
+	  b->last_index=bddm->vars-1;
+	}
+      add_block(bddm->super_block, b);
+      return (b);
+    }
+  return ((block)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddcache.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddcache.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddcache.c	(revision 8)
@@ -0,0 +1,637 @@
+/* BDD system cache routines */
+
+
+#include "bddint.h"
+
+
+#define HASH1(d1) ((INT_PTR)d1)
+#define HASH2(d1, d2) ((INT_PTR)(d1)+(((INT_PTR)(d2)) << 1))
+#define HASH3(d1, d2, d3) ((INT_PTR)(d1)+(((INT_PTR)(d2)) << 1)+(((INT_PTR)(d3)) << 2))
+
+
+static
+void
+bdd_purge_entry(cmu_bdd_manager bddm, cache_entry *bin)
+{
+  void (*purge_fn)(cmu_bdd_manager, cache_entry);
+  cache_entry p;
+
+  p= *bin;
+  purge_fn=bddm->op_cache.purge_fn[TAG(p)];
+  p=CACHE_POINTER(p);
+  if (purge_fn)
+    (*purge_fn)(bddm, p);
+  bddm->op_cache.entries--;
+  BDD_FREE_REC(bddm, (pointer)p, sizeof(struct cache_entry_));
+  *bin=0;
+}
+
+
+static
+void
+bdd_purge_lru(cmu_bdd_manager bddm, cache_entry *bin)
+{
+  if (bin[1])
+    bdd_purge_entry(bddm, bin+1);
+  bin[1]=bin[0];
+}
+
+
+static
+cache_entry
+bdd_get_entry(cmu_bdd_manager bddm, int tag, cache_entry *bin)
+{
+  void (*purge_fn)(cmu_bdd_manager, cache_entry);
+  cache_entry p;
+
+  if (bin[0] && bin[1])
+    {
+      p=bin[1];
+      purge_fn=bddm->op_cache.purge_fn[TAG(p)];
+      p=CACHE_POINTER(p);
+      if (purge_fn)
+	(*purge_fn)(bddm, p);
+      bddm->op_cache.collisions++;
+      if (bddm->op_cache.cache_level == 0)
+	bin[1]=bin[0];
+      else
+	++bin;
+    }
+  else
+    {
+      p=(cache_entry)BDD_NEW_REC(bddm, sizeof(struct cache_entry_));
+      bddm->op_cache.entries++;
+      if (bin[0])
+	++bin;
+    }
+  *bin=(cache_entry)SET_TAG(p, tag);
+  return (p);
+}
+
+
+static
+long
+bdd_rehash1(cmu_bdd_manager bddm, cache_entry p)
+{
+  return (HASH1(p->slot[0]));
+}
+
+
+static
+long
+bdd_rehash2(cmu_bdd_manager bddm, cache_entry p)
+{
+  return (HASH2(p->slot[0], p->slot[1]));
+}
+
+
+static
+long
+bdd_rehash3(cmu_bdd_manager bddm, cache_entry p)
+{
+  return (HASH3(p->slot[0], p->slot[1], p->slot[2]));
+}
+
+
+void
+bdd_rehash_cache(cmu_bdd_manager bddm, int grow)
+{
+  long i;
+  long hash;
+  int j;
+  long oldsize;
+  cache_bin *newtable;
+  cache_entry *bin;
+  cache_entry *newbin;
+  cache_entry p;
+  cache_entry q;
+
+  oldsize=bddm->op_cache.size;
+  if (grow)
+    bddm->op_cache.size_index++;
+  else
+    bddm->op_cache.size_index--;
+  bddm->op_cache.size=TABLE_SIZE(bddm->op_cache.size_index);
+  newtable=(cache_bin *)mem_get_block((SIZE_T)(bddm->op_cache.size*sizeof(struct cache_bin_)));
+  for (i=0; i < bddm->op_cache.size; ++i)
+    for (j=0; j < 2; ++j)
+      newtable[i].entry[j]=0;
+  /* Rehash LRU first. */
+  for (j=1; j >= 0; --j)
+    for (i=0; i < oldsize; ++i)
+      {
+	bin=bddm->op_cache.table[i].entry;
+	if ((p=bin[j]))
+	  {
+	    q=CACHE_POINTER(p);
+	    hash=(*bddm->op_cache.rehash_fn[TAG(p)])(bddm, q);
+	    BDD_REDUCE(hash, bddm->op_cache.size);
+	    newbin=newtable[hash].entry;
+	    bdd_purge_lru(bddm, newbin);
+	    newbin[0]=p;
+	  }
+    }
+  mem_free_block((pointer)(bddm->op_cache.table));
+  bddm->op_cache.table=newtable;
+}
+
+
+/* The routines bdd_insert_in_cachex insert things in the cache. */
+/* The routines bdd_lookup_in_cachex look up things in the cache. */
+
+void
+bdd_insert_in_cache31(cmu_bdd_manager bddm, int tag, INT_PTR d1, INT_PTR d2, INT_PTR d3, INT_PTR result)
+{
+  long hash;
+  cache_entry p;
+
+  hash=HASH3(d1, d2, d3);
+  BDD_REDUCE(hash, bddm->op_cache.size);
+  if (hash < 0)
+    hash= -hash;
+  p=bdd_get_entry(bddm, tag, bddm->op_cache.table[hash].entry);
+  p->slot[0]=d1;
+  p->slot[1]=d2;
+  p->slot[2]=d3;
+  p->slot[3]=result;
+  bddm->op_cache.inserts++;
+}
+
+
+#define RETURN_BDD_FN ((void (*)(cmu_bdd_manager, cache_entry))-1)
+
+
+int
+bdd_lookup_in_cache31(cmu_bdd_manager bddm, int tag, INT_PTR d1, INT_PTR d2, INT_PTR d3, INT_PTR *result)
+{
+  long hash;
+  cache_entry *bin;
+  cache_entry p;
+  cache_entry q;
+  bdd f;
+  void (*return_fn)(cmu_bdd_manager, cache_entry);
+
+  bddm->op_cache.lookups++;
+  hash=HASH3(d1, d2, d3);
+  BDD_REDUCE(hash, bddm->op_cache.size);
+  bin=bddm->op_cache.table[hash].entry;
+  if ((p=bin[0]))
+    {
+      q=CACHE_POINTER(p);
+      if (q->slot[0] != d1 || q->slot[1] != d2 || q->slot[2] != d3 || TAG(p) != tag)
+	{
+	if ((p=bin[1]))
+	  {
+	    q=CACHE_POINTER(p);
+	    if (q->slot[0] != d1 || q->slot[1] != d2 || q->slot[2] != d3 || TAG(p) != tag)
+	      return (0);
+	    bin[1]=bin[0];
+	    bin[0]=p;
+	  }
+	else
+	  return (0);
+	}
+    }
+  else
+    return (0);
+  bddm->op_cache.hits++;
+  if ((return_fn=bddm->op_cache.return_fn[TAG(p)]))
+    {
+    if (return_fn == RETURN_BDD_FN)
+      {
+	f=(bdd)q->slot[3];
+	{
+	  BDD_SETUP(f);
+	  BDD_TEMP_INCREFS(f);
+	}
+      }
+    else
+      (*return_fn)(bddm, q);
+    }
+  *result=q->slot[3];
+  return (1);
+}
+
+
+void
+bdd_insert_in_cache22(cmu_bdd_manager bddm, int tag, INT_PTR d1, INT_PTR d2, INT_PTR result1, INT_PTR result2)
+{
+  long hash;
+  cache_entry p;
+
+  hash=HASH2(d1, d2);
+  BDD_REDUCE(hash, bddm->op_cache.size);
+  p=bdd_get_entry(bddm, tag, bddm->op_cache.table[hash].entry);
+  p->slot[0]=d1;
+  p->slot[1]=d2;
+  p->slot[2]=result1;
+  p->slot[3]=result2;
+  bddm->op_cache.inserts++;
+}
+
+
+int
+bdd_lookup_in_cache22(cmu_bdd_manager bddm, int tag, INT_PTR d1, INT_PTR d2, INT_PTR *result1, INT_PTR *result2)
+{
+  long hash;
+  cache_entry *bin;
+  cache_entry p;
+  cache_entry q;
+  void (*return_fn)(cmu_bdd_manager, cache_entry);
+
+  bddm->op_cache.lookups++;
+  hash=HASH2(d1, d2);
+  BDD_REDUCE(hash, bddm->op_cache.size);
+  bin=bddm->op_cache.table[hash].entry;
+  if ((p=bin[0]))
+    {
+      q=CACHE_POINTER(p);
+      if (q->slot[0] != d1 || q->slot[1] != d2 || TAG(p) != tag)
+	{
+	if ((p=bin[1]))
+	  {
+	    q=CACHE_POINTER(p);
+	    if (q->slot[0] != d1 || q->slot[1] != d2 || TAG(p) != tag)
+	      return (0);
+	    bin[1]=bin[0];
+	    bin[0]=p;
+	  }
+	else
+	  return (0);
+	}
+    }
+  else
+    return (0);
+  bddm->op_cache.hits++;
+  if ((return_fn=bddm->op_cache.return_fn[TAG(p)]))
+    (*return_fn)(bddm, q);
+  *result1=q->slot[2];
+  *result2=q->slot[3];
+  return (1);
+}
+
+
+void
+bdd_insert_in_cache13(cmu_bdd_manager bddm, int tag, INT_PTR d1, INT_PTR result1, INT_PTR result2, INT_PTR result3)
+{
+  long hash;
+  cache_entry p;
+
+  hash=HASH1(d1);
+  BDD_REDUCE(hash, bddm->op_cache.size);
+  p=bdd_get_entry(bddm, tag, bddm->op_cache.table[hash].entry);
+  p->slot[0]=d1;
+  p->slot[1]=result1;
+  p->slot[2]=result2;
+  p->slot[3]=result3;
+  bddm->op_cache.inserts++;
+}
+
+
+int
+bdd_lookup_in_cache13(cmu_bdd_manager bddm, int tag, INT_PTR d1, INT_PTR *result1, INT_PTR *result2, INT_PTR *result3)
+{
+  long hash;
+  cache_entry *bin;
+  cache_entry p;
+  cache_entry q;
+  void (*return_fn)(cmu_bdd_manager, cache_entry);
+
+  bddm->op_cache.lookups++;
+  hash=HASH1(d1);
+  BDD_REDUCE(hash, bddm->op_cache.size);
+  bin=bddm->op_cache.table[hash].entry;
+  if ((p=bin[0]))
+    {
+      q=CACHE_POINTER(p);
+      if (q->slot[0] != d1 || TAG(p) != tag)
+	{
+	if ((p=bin[1]))
+	  {
+	    q=CACHE_POINTER(p);
+	    if (q->slot[0] != d1 || TAG(p) != tag)
+	      return (0);
+	    bin[1]=bin[0];
+	    bin[0]=p;
+	  }
+	else
+	  return (0);
+	}
+    }
+  else
+    return (0);
+  bddm->op_cache.hits++;
+  if ((return_fn=bddm->op_cache.return_fn[TAG(p)]))
+    (*return_fn)(bddm, q);
+  *result1=q->slot[1];
+  *result2=q->slot[2];
+  *result3=q->slot[3];
+  return (1);
+}
+
+
+static
+int
+cmu_bdd_ite_gc_fn(cmu_bdd_manager bddm, cache_entry p)
+{
+  int i;
+  bdd f;
+
+  for (i=0; i < 4; ++i)
+    {
+      f=(bdd)p->slot[i];
+      {
+	BDD_SETUP(f);
+	if (!BDD_IS_USED(f))
+	  return (1);
+      }
+    }
+  return (0);
+}
+
+
+static
+int
+bdd_two_gc_fn(cmu_bdd_manager bddm, cache_entry p)
+{
+  int i;
+  bdd f;
+
+  for (i=1; i < 4; ++i)
+    {
+      f=(bdd)p->slot[i];
+      {
+	BDD_SETUP(f);
+	if (!BDD_IS_USED(f))
+	  return (1);
+      }
+    }
+  return (0);
+}
+
+
+static
+int
+bdd_two_data_gc_fn(cmu_bdd_manager bddm, cache_entry p)
+{
+  int i;
+  bdd f;
+
+  for (i=1; i < 3; ++i)
+    {
+      f=(bdd)p->slot[i];
+      {
+	BDD_SETUP(f);
+	if (!BDD_IS_USED(f))
+	  return (1);
+      }
+    }
+  return (0);
+}
+
+
+static
+int
+cmu_bdd_one_data_gc_fn(cmu_bdd_manager bddm, cache_entry p)
+{
+  bdd f;
+
+  f=(bdd)p->slot[1];
+  {
+    BDD_SETUP(f);
+    return (!BDD_IS_USED(f));
+  }
+}
+
+
+/* bdd_purge_cache(bddm) purges the cache of any entries which mention */
+/* a BDD node that is about to be garbage collected. */
+
+void
+bdd_purge_cache(cmu_bdd_manager bddm)
+{
+  long i;
+  int j;
+  cache_entry *bin;
+  cache_entry p;
+  cache_entry q;
+
+  for (i=0; i < bddm->op_cache.size; ++i)
+    {
+      bin= &bddm->op_cache.table[i].entry[0];
+      for (j=0; j < 2; ++j)
+	if ((p=bin[j]))
+	  {
+	    q=CACHE_POINTER(p);
+	    if ((*bddm->op_cache.gc_fn[TAG(p)])(bddm, q))
+	      bdd_purge_entry(bddm, bin+j);
+	    else if (j == 1 && !bin[0])
+	      {
+		bin[0]=bin[1];	/* LRU is only one left */
+		bin[1]=0;
+	      }
+	  }
+	else
+	  break;
+    }
+}
+
+
+/* bdd_flush_cache(bddm, flush_fn, closure) purges all entries for which */
+/* the given function returns true. */
+
+void
+bdd_flush_cache(cmu_bdd_manager bddm, int (*flush_fn)(cmu_bdd_manager, cache_entry, pointer), pointer closure)
+{
+  long i;
+  int j;
+  cache_entry *bin;
+
+  for (i=0; i < bddm->op_cache.size; ++i)
+    {
+      bin=bddm->op_cache.table[i].entry;
+      for (j=0; j < 2; ++j)
+	if (bin[j])
+	  {
+	    if ((*flush_fn)(bddm, bin[j], closure))
+	      bdd_purge_entry(bddm, bin+j);
+	    else if (j == 1 && !bin[0])
+	      {
+		bin[0]=bin[1];	/* LRU is only one left */
+		bin[1]=0;
+	      }
+	  }
+	else
+	  break;
+    }
+}
+
+
+/* bdd_flush_all(bddm) flushes the entire cache. */
+
+void
+bdd_flush_all(cmu_bdd_manager bddm)
+{
+  long i;
+  int j;
+  cache_entry *bin;
+
+  for (i=0; i < bddm->op_cache.size; ++i)
+    {
+      bin=bddm->op_cache.table[i].entry;
+      for (j=0; j < 2; ++j)
+	if (bin[j])
+	  bdd_purge_entry(bddm, bin+j);
+	else
+	  break;
+    }
+}
+
+
+/* bdd_cache_functions(bddm, args, gc_fn, purge_fn, return_fn, flush_fn) */
+/* controls the user cache types.  Allocates an unused cache entry type */
+/* tag and returns the tag, or -1 if no more tags are available. */
+
+int
+bdd_cache_functions(cmu_bdd_manager bddm,
+		    int args,
+		    int (*gc_fn)(cmu_bdd_manager, cache_entry),
+		    void (*purge_fn)(cmu_bdd_manager, cache_entry),
+		    void (*return_fn)(cmu_bdd_manager, cache_entry),
+		    int (*flush_fn)(cmu_bdd_manager, cache_entry, pointer))
+{
+  long (*rehash_fn)(cmu_bdd_manager, cache_entry);
+  int i;
+
+  if (args == 1)
+    rehash_fn=bdd_rehash1;
+  else if (args == 2)
+    rehash_fn=bdd_rehash2;
+  else if (args == 3)
+    rehash_fn=bdd_rehash3;
+  else
+    {
+      rehash_fn=0;
+      cmu_bdd_fatal("bdd_cache_functions: illegal number of cache arguments");
+    }
+  for (i=CACHE_TYPE_USER1; i < CACHE_TYPE_USER1+USER_ENTRY_TYPES; ++i)
+    if (!bddm->op_cache.rehash_fn[i])
+      break;
+  if (i == CACHE_TYPE_USER1+USER_ENTRY_TYPES)
+    return (-1);
+  bddm->op_cache.rehash_fn[i]=rehash_fn;
+  bddm->op_cache.gc_fn[i]=gc_fn;
+  bddm->op_cache.purge_fn[i]=purge_fn;
+  bddm->op_cache.return_fn[i]=return_fn;
+  bddm->op_cache.flush_fn[i]=flush_fn;
+  return (i);
+}
+
+
+static
+int
+bdd_flush_tag(cmu_bdd_manager bddm, cache_entry p, pointer tag)
+{
+  /*return (TAG(p) == (int)tag);*/
+  return (TAG(p) == (long)tag);
+}
+
+
+/* cmu_bdd_free_cache_tag(bddm, tag) frees a previously allocated user */
+/* cache tag. */
+
+void
+cmu_bdd_free_cache_tag(cmu_bdd_manager bddm, long tag)
+{
+  if (tag < CACHE_TYPE_USER1 ||
+      tag >= CACHE_TYPE_USER1+USER_ENTRY_TYPES ||
+      !bddm->op_cache.rehash_fn[(long)tag])
+    cmu_bdd_fatal("cmu_bdd_free_cache_tag: attempt to free unallocated tag");
+  bdd_flush_cache(bddm, bdd_flush_tag, (pointer)tag);
+  bddm->op_cache.rehash_fn[tag]=0;
+  bddm->op_cache.gc_fn[tag]=0;
+  bddm->op_cache.purge_fn[tag]=0;
+  bddm->op_cache.return_fn[tag]=0;
+  bddm->op_cache.flush_fn[tag]=0;
+}
+
+
+static
+int
+bdd_two_flush_fn(cmu_bdd_manager bddm, cache_entry p, pointer closure)
+{
+  int id_to_nuke;
+
+  id_to_nuke=(long)closure;
+  return (p->slot[0] == OP_RELPROD+id_to_nuke ||
+	  p->slot[0] == OP_QNT+id_to_nuke ||
+	  p->slot[0] == OP_SUBST+id_to_nuke);
+}
+
+
+/* cmu_bdd_init_cache(bddm) initializes the cache for a BDD manager. */
+
+void
+cmu_bdd_init_cache(cmu_bdd_manager bddm)
+{
+  long i;
+  int j;
+
+  bddm->op_cache.size_index=13;
+  bddm->op_cache.size=TABLE_SIZE(bddm->op_cache.size_index);
+  bddm->op_cache.table=(cache_bin *)mem_get_block((SIZE_T)(bddm->op_cache.size*sizeof(cache_bin)));
+  for (i=0; i < bddm->op_cache.size; ++i)
+    for (j=0; j < 2; ++j)
+      bddm->op_cache.table[i].entry[j]=0;
+  /* ITE cache control functions. */
+  bddm->op_cache.rehash_fn[CACHE_TYPE_ITE]=bdd_rehash3;
+  bddm->op_cache.gc_fn[CACHE_TYPE_ITE]=cmu_bdd_ite_gc_fn;
+  bddm->op_cache.purge_fn[CACHE_TYPE_ITE]=0;
+  bddm->op_cache.return_fn[CACHE_TYPE_ITE]=RETURN_BDD_FN;
+  bddm->op_cache.flush_fn[CACHE_TYPE_ITE]=0;
+  /* Two argument op cache control functions. */
+  bddm->op_cache.rehash_fn[CACHE_TYPE_TWO]=bdd_rehash3;
+  bddm->op_cache.gc_fn[CACHE_TYPE_TWO]=bdd_two_gc_fn;
+  bddm->op_cache.purge_fn[CACHE_TYPE_TWO]=0;
+  bddm->op_cache.return_fn[CACHE_TYPE_TWO]=RETURN_BDD_FN;
+  bddm->op_cache.flush_fn[CACHE_TYPE_TWO]=bdd_two_flush_fn;
+  /* One argument op w/ data result cache control functions. */
+  bddm->op_cache.rehash_fn[CACHE_TYPE_ONEDATA]=bdd_rehash2;
+  bddm->op_cache.gc_fn[CACHE_TYPE_ONEDATA]=cmu_bdd_one_data_gc_fn;
+  bddm->op_cache.purge_fn[CACHE_TYPE_ONEDATA]=0;
+  bddm->op_cache.return_fn[CACHE_TYPE_ONEDATA]=0;
+  bddm->op_cache.flush_fn[CACHE_TYPE_ONEDATA]=0;
+  /* Two argument op w/ data result cache control functions. */
+  bddm->op_cache.rehash_fn[CACHE_TYPE_TWODATA]=bdd_rehash3;
+  bddm->op_cache.gc_fn[CACHE_TYPE_TWODATA]=bdd_two_data_gc_fn;
+  bddm->op_cache.purge_fn[CACHE_TYPE_TWODATA]=0;
+  bddm->op_cache.return_fn[CACHE_TYPE_TWODATA]=0;
+  bddm->op_cache.flush_fn[CACHE_TYPE_TWODATA]=0;
+  /* User-defined cache control functions. */
+  for (j=CACHE_TYPE_USER1; j < CACHE_TYPE_USER1+USER_ENTRY_TYPES; ++j)
+    {
+      bddm->op_cache.rehash_fn[j]=0;
+      bddm->op_cache.gc_fn[j]=0;
+      bddm->op_cache.purge_fn[j]=0;
+      bddm->op_cache.return_fn[j]=0;
+      bddm->op_cache.flush_fn[j]=0;
+    }
+  bddm->op_cache.cache_ratio=4;
+  bddm->op_cache.cache_level=0;
+  bddm->op_cache.entries=0;
+  bddm->op_cache.lookups=0;
+  bddm->op_cache.hits=0;
+  bddm->op_cache.inserts=0;
+  bddm->op_cache.collisions=0;
+}
+
+
+/* cmu_bdd_free_cache(bddm) frees the storage associated with the cache of */
+/* the indicated BDD manager. */
+
+void
+cmu_bdd_free_cache(cmu_bdd_manager bddm)
+{
+  bdd_flush_all(bddm);
+  mem_free_block((pointer)bddm->op_cache.table);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddcmp.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddcmp.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddcmp.c	(revision 8)
@@ -0,0 +1,83 @@
+/* BDD comparison routine */
+
+
+#include "bddint.h"
+
+
+static
+int
+bdd_fraction_compare(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  double f_frac, g_frac;
+
+  bddm->op_cache.cache_level++;
+  f_frac=cmu_bdd_satisfying_fraction_step(bddm, f);
+  g_frac=cmu_bdd_satisfying_fraction_step(bddm, g);
+  bddm->op_cache.cache_level--;
+  if (f_frac < g_frac)
+    return (-1);
+  if (f_frac > g_frac)
+    return (1);
+  return (0);
+}
+
+
+static
+int
+cmu_bdd_compare_step(cmu_bdd_manager bddm, bdd f, bdd g, bdd_indexindex_type v_indexindex, long op)
+{
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd_indexindex_type top_indexindex;
+  INT_PTR result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (f == g)
+    return (0);
+  if (BDD_IS_CONST(f) || BDD_IS_CONST(g))
+    {
+      if (f == BDD_ZERO(bddm) || g == BDD_ONE(bddm))
+	return (-1);
+      return (1);
+    }
+  if (bdd_lookup_in_cache2d(bddm, op, f, g, &result))
+    return ((int)result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  if (bddm->indexes[top_indexindex] > bddm->indexes[v_indexindex])
+    result=bdd_fraction_compare(bddm, f, g);
+  else
+    {
+      BDD_COFACTOR(top_indexindex, f, f1, f2);
+      BDD_COFACTOR(top_indexindex, g, g1, g2);
+      if (!(result=cmu_bdd_compare_step(bddm, f2, g2, v_indexindex, op)))
+	result=cmu_bdd_compare_step(bddm, f1, g1, v_indexindex, op);
+    }
+  bdd_insert_in_cache2d(bddm, op, f, g, result);
+  return ((int)result);
+}
+
+
+int
+cmu_bdd_compare_temp(cmu_bdd_manager bddm, bdd f, bdd g, bdd v)
+{
+  BDD_SETUP(v);
+  return (cmu_bdd_compare_step(bddm, f, g, BDD_INDEXINDEX(v), OP_CMPTO+BDD_INDEXINDEX(v)));
+}
+
+
+int
+cmu_bdd_compare(cmu_bdd_manager bddm, bdd f, bdd g, bdd v)
+{
+  if (bdd_check_arguments(3, f, g, v))
+    {
+      BDD_SETUP(v);
+      if (cmu_bdd_type_aux(bddm, v) != BDD_TYPE_POSVAR)
+	{
+	  cmu_bdd_warning("cmu_bdd_compare: third argument is not a positive variable");
+	  return (0);
+	}
+      return (cmu_bdd_compare_step(bddm, f, g, BDD_INDEXINDEX(v), OP_CMPTO+BDD_INDEXINDEX(v)));
+    }
+  return (0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddcomp.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddcomp.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddcomp.c	(revision 8)
@@ -0,0 +1,195 @@
+/* BDD composition routines */
+
+
+#include "bddint.h"
+
+
+static
+bdd
+bdd_restrict_step(cmu_bdd_manager bddm, bdd f, bdd_indexindex_type g_indexindex, bdd h, long op)
+{
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  if (BDD_INDEX(bddm, f) > bddm->indexes[g_indexindex])
+    {
+      /* f doesn't depend on the variable g. */
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (BDD_INDEXINDEX(f) == g_indexindex)
+    {
+      /* Do the restriction. */
+      result=(h == BDD_ONE(bddm) ? BDD_THEN(f) : BDD_ELSE(f));
+      {
+	BDD_SETUP(result);
+	BDD_TEMP_INCREFS(result);
+	return (result);
+      }
+    }
+  if (bdd_lookup_in_cache2(bddm, op, BDD_OUTPOS(f), h, &result))
+    return (BDD_IS_OUTPOS(f) ? result : BDD_NOT(result));
+  temp1=bdd_restrict_step(bddm, BDD_THEN(f), g_indexindex, h, op);
+  temp2=bdd_restrict_step(bddm, BDD_ELSE(f), g_indexindex, h, op);
+  result=bdd_find(bddm, BDD_INDEXINDEX(f), temp1, temp2);
+  if (BDD_IS_OUTPOS(f))
+    bdd_insert_in_cache2(bddm, op, f, h, result);
+  else
+    bdd_insert_in_cache2(bddm, op, BDD_NOT(f), h, BDD_NOT(result));
+  return (result);
+}
+
+
+static
+bdd
+cmu_bdd_compose_step(cmu_bdd_manager bddm, bdd f, bdd_indexindex_type g_indexindex, bdd h, long op)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd h1, h2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(h);
+  /* Use restriction if possible. */
+  if (BDD_IS_CONST(h))
+    return (bdd_restrict_step(bddm, f, g_indexindex, h, op));
+  if (BDD_INDEX(bddm, f) > bddm->indexes[g_indexindex])
+    {
+      /* f doesn't depend on the variable g. */
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (bdd_lookup_in_cache2(bddm, op, BDD_OUTPOS(f), h, &result))
+    return (BDD_IS_OUTPOS(f) ? result : BDD_NOT(result));
+  if (BDD_INDEXINDEX(f) == g_indexindex)
+    {
+      /* Do the replacement. */
+      bddm->op_cache.cache_level++;
+      result=cmu_bdd_ite_step(bddm, h, BDD_THEN(f), BDD_ELSE(f));
+      bddm->op_cache.cache_level--;
+    }
+  else
+    {
+      BDD_TOP_VAR2(top_indexindex, bddm, f, h);
+      BDD_COFACTOR(top_indexindex, f, f1, f2);
+      BDD_COFACTOR(top_indexindex, h, h1, h2);
+      temp1=cmu_bdd_compose_step(bddm, f1, g_indexindex, h1, op);
+      temp2=cmu_bdd_compose_step(bddm, f2, g_indexindex, h2, op);
+      result=bdd_find(bddm, top_indexindex, temp1, temp2);
+    }
+  if (BDD_IS_OUTPOS(f))
+    bdd_insert_in_cache2(bddm, op, f, h, result);
+  else
+    bdd_insert_in_cache2(bddm, op, BDD_NOT(f), h, BDD_NOT(result));
+  return (result);
+}
+
+
+/* cmu_bdd_compose_temp is used internally by cmu_bdd_swap_vars. */
+
+bdd
+cmu_bdd_compose_temp(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  BDD_SETUP(g);
+  return (cmu_bdd_compose_step(bddm, f, BDD_INDEXINDEX(g), h, OP_COMP+BDD_INDEXINDEX(g)));
+}
+
+
+/* cmu_bdd_compose(bddm, f, g, h) returns the BDD for substituting h for */
+/* the variable g in f.  h may depend on g. */
+
+bdd
+cmu_bdd_compose(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  if (bdd_check_arguments(3, f, g, h))
+    {
+      BDD_SETUP(f);
+      BDD_SETUP(g);
+      if (cmu_bdd_type_aux(bddm, g) != BDD_TYPE_POSVAR)
+	{
+	  cmu_bdd_warning("cmu_bdd_compose: second argument is not a positive variable");
+	  BDD_INCREFS(f);
+	  return (f);
+	}
+      FIREWALL(bddm);
+      RETURN_BDD(cmu_bdd_compose_step(bddm, f, BDD_INDEXINDEX(g), h, OP_COMP+BDD_INDEXINDEX(g)));
+    }
+  return ((bdd)0);
+}
+
+
+bdd
+cmu_bdd_substitute_step(cmu_bdd_manager bddm, bdd f, long op, bdd (*ite_fn)(cmu_bdd_manager, bdd, bdd, bdd), var_assoc subst)
+{
+  bdd g;
+  bdd temp1, temp2;
+  bdd result;
+  bdd_index_type g_index;
+
+  BDD_SETUP(f);
+  if ((long)BDD_INDEX(bddm, f) > subst->last)
+    {
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (bdd_lookup_in_cache1(bddm, op, BDD_OUTPOS(f), &result))
+    return (BDD_IS_OUTPOS(f) ? result : BDD_NOT(result));
+  g=subst->assoc[BDD_INDEXINDEX(f)];
+  /* See if we are substituting a constant at this level. */
+  if (g == BDD_ONE(bddm))
+    return (cmu_bdd_substitute_step(bddm, BDD_THEN(f), op, ite_fn, subst));
+  if (g == BDD_ZERO(bddm))
+    return (cmu_bdd_substitute_step(bddm, BDD_ELSE(f), op, ite_fn, subst));
+  temp1=cmu_bdd_substitute_step(bddm, BDD_THEN(f), op, ite_fn, subst);
+  temp2=cmu_bdd_substitute_step(bddm, BDD_ELSE(f), op, ite_fn, subst);
+  if (!g)
+    g=BDD_IF(bddm, f);
+  {
+    BDD_SETUP(g);
+    BDD_SETUP(temp1);
+    BDD_SETUP(temp2);
+    if (g == BDD_IF(bddm, g) &&
+	(g_index=BDD_INDEX(bddm, g)) < BDD_INDEX(bddm, temp1) &&
+	g_index < BDD_INDEX(bddm, temp2))
+      /* Substituting with variable above the tops of the subresults. */
+      result=bdd_find(bddm, BDD_INDEXINDEX(g), temp1, temp2);
+    else
+      {
+	/* Do an ITE. */
+	bddm->op_cache.cache_level++;
+	result=(*ite_fn)(bddm, g, temp1, temp2);
+	BDD_TEMP_DECREFS(temp1);
+	BDD_TEMP_DECREFS(temp2);
+	bddm->op_cache.cache_level--;
+      }
+  }
+  if (BDD_IS_OUTPOS(f))
+    bdd_insert_in_cache1(bddm, op, f, result);
+  else
+    bdd_insert_in_cache1(bddm, op, BDD_NOT(f), BDD_NOT(result));
+  return (result);
+}
+
+
+/* cmu_bdd_substitute(bddm, f) returns the BDD for substituting in f */
+/* according to the current variable association. */
+
+bdd
+cmu_bdd_substitute(cmu_bdd_manager bddm, bdd f)
+{
+  long op;
+
+  if (bdd_check_arguments(1, f))
+    {
+      FIREWALL(bddm);
+      if (bddm->curr_assoc_id == -1)
+	op=bddm->temp_op--;
+      else
+	op=OP_SUBST+bddm->curr_assoc_id;
+      RETURN_BDD(cmu_bdd_substitute_step(bddm, f, op, cmu_bdd_ite_step, bddm->curr_assoc));
+    }
+  return ((bdd)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddcproject.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddcproject.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddcproject.c	(revision 8)
@@ -0,0 +1,200 @@
+/* Written by Gitanjali M. Swamy */
+/* 	bddcproject.c,v 1.2 1994/06/02 02:36:30 shiple Exp	 */
+/*      bddcproject.c,v
+ * Revision 1.2  1994/06/02  02:36:30  shiple
+ * Fixed bug in RETURN_BDD use.
+ *
+ * Revision 1.1  1994/06/02  00:48:50  shiple
+ * Initial revision
+ *
+ * Revision 1.5  1994/05/31  15:19:32  gms
+ * May31 Tues
+ *                                                            */
+
+#ifndef lint
+static char vcid[] = "bddcproject.c,v 1.2 1994/06/02 02:36:30 shiple Exp";
+#endif /* lint */
+
+#include "bddint.h"   /* CMU internal routines; for use in bdd_get_node() */
+
+#define OP_CPROJ 5000001
+
+extern bdd cmu_bdd_project(cmu_bdd_manager, bdd);
+
+/* INTERNAL ONLY */
+
+/*
+ *    smooth - recursively perform the smoothing
+ *
+ *    return the result of the reorganization
+ */
+
+static
+bdd
+cmu_bdd_smooth_g_step(cmu_bdd_manager bddm, bdd f, long op, var_assoc vars ,long id)
+{
+    bdd temp1, temp2;
+    bdd result;
+    int quantifying;
+
+    BDD_SETUP(f);
+    if ((long)BDD_INDEX(bddm, f) > vars->last)
+        {
+            BDD_TEMP_INCREFS(f);
+            return (f);
+        }
+    if (bdd_lookup_in_cache1(bddm, op, f, &result))
+        return (result);
+    quantifying=(vars->assoc[BDD_INDEXINDEX(f)] != 0);
+
+    temp1=cmu_bdd_smooth_g_step(bddm, BDD_THEN(f), op, vars,id);
+
+    if ((quantifying && temp1 == BDD_ONE(bddm))&&((long)BDD_INDEX(bddm, f) > id ))
+
+        result=temp1;
+    else
+        {
+            temp2=cmu_bdd_smooth_g_step(bddm, BDD_ELSE(f), op, vars,id);
+            if (quantifying)
+                {
+                    BDD_SETUP(temp1);
+                    BDD_SETUP(temp2);
+                    bddm->op_cache.cache_level++;
+                    result=cmu_bdd_ite_step(bddm, temp1, BDD_ONE(bddm), temp2);
+                    BDD_TEMP_DECREFS(temp1);
+                    BDD_TEMP_DECREFS(temp2);
+                    bddm->op_cache.cache_level--;
+                }
+            else
+                result=bdd_find(bddm, BDD_INDEXINDEX(f), temp1, temp2);
+        }
+    bdd_insert_in_cache1(bddm, op, f, result);
+
+   
+    return (result);
+}
+
+
+static
+bdd
+cmu_bdd_smooth_g(cmu_bdd_manager bddm, bdd f, long id)
+{
+    long op;
+    
+            if (bddm->curr_assoc_id == -1)
+                op=bddm->temp_op--;
+            else
+                op=OP_QNT+bddm->curr_assoc_id;
+            RETURN_BDD(cmu_bdd_smooth_g_step(bddm, f, op, bddm->curr_assoc,id));
+  }
+
+
+/*
+ *    project - recursively perform compatible projection
+ *
+ *    return the result of the reorganization
+ */
+
+
+
+static
+bdd
+cmu_bdd_project_step(cmu_bdd_manager bddm, bdd f, long op, var_assoc vars)
+
+{
+    bdd temp1, temp2;
+    bdd sm, pr;
+    bdd result;
+    int quantifying;
+
+    BDD_SETUP(f);
+    if ((long)BDD_INDEX(bddm, f) > vars->last)
+        {
+            BDD_TEMP_INCREFS(f);
+            return (f);
+        }
+    if (bdd_lookup_in_cache1(bddm, op, f, &result))
+        return (result);
+    quantifying=(vars->assoc[BDD_INDEXINDEX(f)] != 0);
+
+    if (quantifying)
+        {
+
+            sm  = cmu_bdd_smooth_g(bddm,BDD_THEN(f),(long)BDD_INDEXINDEX(f)); 
+            if (sm == BDD_ONE(bddm))
+                {
+                    pr  = cmu_bdd_project_step(bddm, BDD_THEN(f), op, vars);
+                    {
+                    BDD_SETUP(pr);
+                    result = bdd_find(bddm, BDD_INDEXINDEX(f), pr,BDD_ZERO(bddm));
+                   BDD_TEMP_DECREFS(pr);
+                    }
+                    
+                }
+      else if (sm == BDD_ZERO(bddm))
+                {
+                    pr = cmu_bdd_project_step(bddm, BDD_ELSE(f), op, vars);
+                    {
+                    BDD_SETUP(pr);
+                    result = bdd_find(bddm, BDD_INDEXINDEX(f), BDD_ZERO(bddm), pr);
+                   BDD_TEMP_DECREFS(pr);
+                    }
+                    
+                }
+            else 
+                {
+                    temp1 = cmu_bdd_project_step(bddm, BDD_THEN(f), op, vars);
+                    temp2 = cmu_bdd_project_step(bddm, BDD_ELSE(f),op, vars);
+                    {
+                    BDD_SETUP(temp1);
+                    BDD_SETUP(temp2);
+                    pr = cmu_bdd_ite_step(bddm, sm, BDD_ZERO(bddm), temp2);
+                    bddm->op_cache.cache_level++;
+                    result = bdd_find(bddm, BDD_INDEXINDEX(f), temp1, pr);
+                    BDD_TEMP_DECREFS(temp1);
+                    BDD_TEMP_DECREFS(temp2);
+                    bddm->op_cache.cache_level--;
+                    }
+            
+                }
+        }
+  
+    else
+        {
+            temp1=cmu_bdd_project_step(bddm, BDD_THEN(f), op, vars);
+            temp2=cmu_bdd_project_step(bddm, BDD_ELSE(f), op, vars);
+            result=bdd_find(bddm, BDD_INDEXINDEX(f), temp1, temp2);
+
+        }
+  
+    bdd_insert_in_cache1(bddm, op, f, result);
+    return (result);
+}
+
+bdd
+cmu_bdd_project(cmu_bdd_manager bddm, bdd f)
+{
+    long op;
+
+    if (bdd_check_arguments(1, f))
+        {
+            FIREWALL(bddm);
+            if (bddm->curr_assoc_id == -1)
+                op=bddm->temp_op--;
+            else
+                op=OP_CPROJ+bddm->curr_assoc_id;
+            RETURN_BDD(cmu_bdd_project_step(bddm, f, op, bddm->curr_assoc));
+        }
+    return ((bdd)0);
+}
+
+
+
+
+
+
+
+
+
+
+
Index: /vis_dev/glu-2.1/src/cmuBdd/bdddump.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bdddump.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bdddump.c	(revision 8)
@@ -0,0 +1,405 @@
+/* BDD library dump/undump routines */
+
+
+#include "bddint.h"
+
+
+#define MAGIC_COOKIE 0x5e02f795l
+#define BDD_IOERROR 100
+
+
+#define TRUE_ENCODING 0xffffff00l
+#define FALSE_ENCODING 0xffffff01l
+#define POSVAR_ENCODING 0xffffff02l
+#define NEGVAR_ENCODING 0xffffff03l
+#define POSNODE_ENCODING 0xffffff04l
+#define NEGNODE_ENCODING 0xffffff05l
+#define NODELABEL_ENCODING 0xffffff06l
+#define CONSTANT_ENCODING 0xffffff07l
+
+
+static
+int
+bytes_needed(long n)
+{
+  if (n <= 0x100l)
+    return (1);
+  if (n <= 0x10000l)
+    return (2);
+  if (n <= 0x1000000l)
+    return (3);
+  return (4);
+}
+
+
+static
+void
+write(cmu_bdd_manager bddm, unsigned long n, int bytes, FILE *fp)
+{
+  while (bytes)
+    {
+      if (fputc((char)(n >> (8*(bytes-1)) & 0xff), fp) == EOF)
+	longjmp(bddm->abort.context, BDD_IOERROR);
+      --bytes;
+    }
+}
+
+
+static
+void
+cmu_bdd_dump_bdd_step(cmu_bdd_manager bddm,
+		  bdd f,
+		  FILE *fp,
+		  hash_table h,
+		  bdd_index_type *normalized_indexes,
+		  int index_size,
+		  int node_number_size)
+{
+  int negated;
+  long *number;
+
+  BDD_SETUP(f);
+  switch (cmu_bdd_type_aux(bddm, f))
+    {
+    case BDD_TYPE_ZERO:
+      write(bddm, FALSE_ENCODING, index_size+1, fp);
+      break;
+    case BDD_TYPE_ONE:
+      write(bddm, TRUE_ENCODING, index_size+1, fp);
+      break;
+    case BDD_TYPE_CONSTANT:
+      write(bddm, CONSTANT_ENCODING, index_size+1, fp);
+      write(bddm, (unsigned long)BDD_DATA(f)[0], sizeof(long), fp);
+      write(bddm, (unsigned long)BDD_DATA(f)[1], sizeof(long), fp);
+      break;
+    case BDD_TYPE_POSVAR:
+      write(bddm, POSVAR_ENCODING, index_size+1, fp);
+      write(bddm, (unsigned long)normalized_indexes[BDD_INDEX(bddm, f)], index_size, fp);
+      break;
+    case BDD_TYPE_NEGVAR:
+      write(bddm, NEGVAR_ENCODING, index_size+1, fp);
+      write(bddm, (unsigned long)normalized_indexes[BDD_INDEX(bddm, f)], index_size, fp);
+      break;
+    case BDD_TYPE_NONTERMINAL:
+      if (bdd_lookup_in_hash_table(h, BDD_NOT(f)))
+	{
+	  f=BDD_NOT(f);
+	  negated=1;
+	}
+      else
+	negated=0;
+      number=(long *)bdd_lookup_in_hash_table(h, f);
+      if (number && *number < 0)
+	{
+	  if (negated)
+	    write(bddm, NEGNODE_ENCODING, index_size+1, fp);
+	  else
+	    write(bddm, POSNODE_ENCODING, index_size+1, fp);
+	  write(bddm, (unsigned long)(-*number-1), node_number_size, fp);
+	}
+      else
+	{
+	  if (number)
+	    {
+	      write(bddm, NODELABEL_ENCODING, index_size+1, fp);
+	      *number= -*number-1;
+	    }
+	  write(bddm, (unsigned long)normalized_indexes[BDD_INDEX(bddm, f)], index_size, fp);
+	  cmu_bdd_dump_bdd_step(bddm, BDD_THEN(f), fp, h, normalized_indexes, index_size, node_number_size);
+	  cmu_bdd_dump_bdd_step(bddm, BDD_ELSE(f), fp, h, normalized_indexes, index_size, node_number_size);
+	}
+      break;
+    default:
+      cmu_bdd_fatal("cmu_bdd_dump_bdd_step: unknown type returned by cmu_bdd_type");
+    }
+}
+
+
+int
+cmu_bdd_dump_bdd(cmu_bdd_manager bddm, bdd f, bdd *vars, FILE *fp)
+{
+  long i;
+  bdd_index_type *normalized_indexes;
+  bdd_index_type v_index;
+  bdd var;
+  bdd_index_type number_vars;
+  bdd *support;
+  int ok;
+  hash_table h;
+  int index_size;
+  long next;
+  int node_number_size;
+
+  if (bdd_check_arguments(1, f))
+    {
+      for (i=0; vars[i]; ++i)
+	if (cmu_bdd_type(bddm, vars[i]) != BDD_TYPE_POSVAR)
+	  {
+	    cmu_bdd_warning("cmu_bdd_dump_bdd: support is not all positive variables");
+	    return (0);
+	  }
+      normalized_indexes=(bdd_index_type *)mem_get_block((SIZE_T)(bddm->vars*sizeof(bdd_index_type)));
+      for (i=0; i < bddm->vars; ++i)
+	normalized_indexes[i]=BDD_MAX_INDEX;
+      for (i=0; (var=vars[i]); ++i)
+	{
+	  BDD_SETUP(var);
+	  v_index=BDD_INDEX(bddm, var);
+	  if (normalized_indexes[v_index] != BDD_MAX_INDEX)
+	    {
+	      cmu_bdd_warning("cmu_bdd_dump_bdd: variables duplicated in support");
+	      mem_free_block((pointer)normalized_indexes);
+	      return (0);
+	    }
+	  normalized_indexes[v_index]=i;
+	}
+      number_vars=i;
+      support=(bdd *)mem_get_block((SIZE_T)((bddm->vars+1)*sizeof(bdd)));
+      cmu_bdd_support(bddm, f, support);
+      ok=1;
+      for (i=0; ok && (var=support[i]); ++i)
+	{
+	  BDD_SETUP(var);
+	  if (normalized_indexes[BDD_INDEX(bddm, var)] == BDD_MAX_INDEX)
+	    {
+	      cmu_bdd_warning("cmu_bdd_dump_bdd: incomplete support specified");
+	      ok=0;
+	    }
+	}
+      if (!ok)
+	{
+	  mem_free_block((pointer)normalized_indexes);
+	  mem_free_block((pointer)support);
+	  return (0);
+	}
+      mem_free_block((pointer)support);
+      /* Everything checked now; barring I/O errors, we should be able to */
+      /* write a valid output file. */
+      h=bdd_new_hash_table(bddm, sizeof(long));
+      FIREWALL1(bddm,
+		if (retcode == BDD_IOERROR)
+		  {
+		    cmu_bdd_free_hash_table(h);
+		    mem_free_block((pointer)normalized_indexes);
+		    return (0);
+		  }
+		else
+		  cmu_bdd_fatal("cmu_bdd_dump_bdd: got unexpected retcode");
+		);
+      index_size=bytes_needed(number_vars+1);
+      bdd_mark_shared_nodes(bddm, f);
+      next=0;
+      bdd_number_shared_nodes(bddm, f, h, &next);
+      node_number_size=bytes_needed(next);
+      write(bddm, MAGIC_COOKIE, sizeof(long), fp);
+      write(bddm, (unsigned long)number_vars, sizeof(bdd_index_type), fp);
+      write(bddm, (unsigned long)next, sizeof(long), fp);
+      cmu_bdd_dump_bdd_step(bddm, f, fp, h, normalized_indexes, index_size, node_number_size);
+      cmu_bdd_free_hash_table(h);
+      mem_free_block((pointer)normalized_indexes);
+      return (1);
+    }
+  return (0);
+}
+
+
+static
+unsigned long
+read(int *error, int bytes, FILE *fp)
+{
+  int c;
+  long result;
+
+  result=0;
+  if (*error)
+    return (result);
+  while (bytes)
+    {
+      c=fgetc(fp);
+      if (c == EOF)
+	{
+	  if (ferror(fp))
+	    *error=BDD_UNDUMP_IOERROR;
+	  else
+	    *error=BDD_UNDUMP_EOF;
+	  return (0l);
+	}
+      result=(result << 8)+c;
+      --bytes;
+    }
+  return (result);
+}
+
+
+static long index_mask[]={0xffl, 0xffffl, 0xffffffl};
+
+
+static
+bdd
+cmu_bdd_undump_bdd_step(cmu_bdd_manager bddm,
+		    bdd *vars,
+		    FILE *fp,
+		    bdd_index_type number_vars,
+		    bdd *shared,
+		    long number_shared,
+		    long *shared_so_far,
+		    int index_size,
+		    int node_number_size,
+		    int *error)
+{
+  long node_number;
+  long encoding;
+  bdd_index_type i;
+  INT_PTR value1, value2;
+  bdd v;
+  bdd temp1, temp2;
+  bdd result;
+
+  i=read(error, index_size, fp);
+  if (*error)
+    return ((bdd)0);
+  if (i == index_mask[index_size-1])
+    {
+      encoding=0xffffff00l+read(error, 1, fp);
+      if (*error)
+	return ((bdd)0);
+      switch (encoding)
+	{
+	case TRUE_ENCODING:
+	  return (BDD_ONE(bddm));
+	case FALSE_ENCODING:
+	  return (BDD_ZERO(bddm));
+	case CONSTANT_ENCODING:
+	  value1=read(error, sizeof(long), fp);
+	  value2=read(error, sizeof(long), fp);
+	  if (*error)
+	    return ((bdd)0);
+	  if ((result=cmu_mtbdd_get_terminal(bddm, value1, value2)))
+	    return (result);
+	  *error=BDD_UNDUMP_OVERFLOW;
+	  return ((bdd)0);
+	case POSVAR_ENCODING:
+	case NEGVAR_ENCODING:
+	  i=read(error, index_size, fp);
+	  if (!*error && i >= number_vars)
+	    *error=BDD_UNDUMP_FORMAT;
+	  if (*error)
+	    return ((bdd)0);
+	  v=vars[i];
+	  if (encoding == POSVAR_ENCODING)
+	    return (v);
+	  else
+	    return (BDD_NOT(v));
+	case POSNODE_ENCODING:
+	case NEGNODE_ENCODING:
+	  node_number=read(error, node_number_size, fp);
+	  if (!*error && (node_number >= number_shared || !shared[node_number]))
+	    *error=BDD_UNDUMP_FORMAT;
+	  if (*error)
+	    return ((bdd)0);
+	  v=shared[node_number];
+	  v=cmu_bdd_identity(bddm, v);
+	  if (encoding == POSNODE_ENCODING)
+	    return (v);
+	  else
+	    return (BDD_NOT(v));
+	case NODELABEL_ENCODING:
+	  node_number= *shared_so_far;
+	  ++*shared_so_far;
+	  v=cmu_bdd_undump_bdd_step(bddm, vars, fp, number_vars, shared, number_shared,
+				shared_so_far, index_size, node_number_size, error);
+	  shared[node_number]=v;
+	  v=cmu_bdd_identity(bddm, v);
+	  return (v);
+	default:
+	  *error=BDD_UNDUMP_FORMAT;
+	  return ((bdd)0);
+	}
+    }
+  if (i >= number_vars)
+    {
+      *error=BDD_UNDUMP_FORMAT;
+      return ((bdd)0);
+    }
+  temp1=cmu_bdd_undump_bdd_step(bddm, vars, fp, number_vars, shared, number_shared,
+			    shared_so_far, index_size, node_number_size, error);
+  temp2=cmu_bdd_undump_bdd_step(bddm, vars, fp, number_vars, shared, number_shared,
+			    shared_so_far, index_size, node_number_size, error);
+  if (*error)
+    {
+      cmu_bdd_free(bddm, temp1);
+      return ((bdd)0);
+    }
+  result=cmu_bdd_ite(bddm, vars[i], temp1, temp2);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  if (!result)
+    *error=BDD_UNDUMP_OVERFLOW;
+  return (result);
+}
+
+
+bdd
+cmu_bdd_undump_bdd(cmu_bdd_manager bddm, bdd *vars, FILE *fp, int *error)
+{
+  long i;
+  bdd_index_type number_vars;
+  long number_shared;
+  int index_size;
+  int node_number_size;
+  bdd *shared;
+  long shared_so_far;
+  bdd v;
+  bdd result;
+
+  *error=0;
+  for (i=0; vars[i]; ++i)
+    if (cmu_bdd_type(bddm, vars[i]) != BDD_TYPE_POSVAR)
+      {
+	cmu_bdd_warning("cmu_bdd_undump_bdd: support is not all positive variables");
+	return ((bdd)0);
+      }
+  if (read(error, sizeof(long), fp) != MAGIC_COOKIE)
+    {
+      if (!*error)
+	*error=BDD_UNDUMP_FORMAT;
+      return ((bdd)0);
+    }
+  number_vars=read(error, sizeof(bdd_index_type), fp);
+  if (*error)
+    return ((bdd)0);
+  if (number_vars != i)
+    {
+      *error=BDD_UNDUMP_FORMAT;
+      return ((bdd)0);
+    }
+  number_shared=read(error, sizeof(long), fp);
+  if (*error)
+    return ((bdd)0);
+  index_size=bytes_needed(number_vars+1);
+  node_number_size=bytes_needed(number_shared);
+  if (number_shared < 0)
+    {
+      *error=BDD_UNDUMP_FORMAT;
+      return ((bdd)0);
+    }
+  shared=(bdd *)mem_get_block((SIZE_T)(number_shared*sizeof(bdd)));
+  for (i=0; i < number_shared; ++i)
+    shared[i]=0;
+  shared_so_far=0;
+  result=cmu_bdd_undump_bdd_step(bddm, vars, fp, number_vars, shared, number_shared,
+			     &shared_so_far, index_size, node_number_size, error);
+  for (i=0; i < number_shared; ++i)
+    if ((v=shared[i]))
+      cmu_bdd_free(bddm, v);
+  if (!*error && shared_so_far != number_shared)
+    *error=BDD_UNDUMP_FORMAT;
+  mem_free_block((pointer)shared);
+  if (*error)
+    {
+      if (result)
+	cmu_bdd_free(bddm, result);
+      return ((bdd)0);
+    }
+  return (result);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddhash.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddhash.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddhash.c	(revision 8)
@@ -0,0 +1,121 @@
+/* BDD hash table routines */
+
+
+#include "bddint.h"
+
+
+#define HASH(d) ((INT_PTR)(d))
+
+
+/* bdd_rehash_hash_table(h) increases the size of h by roughly a */
+/* factor of 2 and rehashes all of its entries. */
+
+static
+void
+bdd_rehash_hash_table(hash_table h)
+{
+  long i;
+  long hash;
+  long oldsize;
+  hash_rec *newtable;
+  hash_rec p, q;
+
+  oldsize=h->size;
+  h->size_index++;
+  h->size=TABLE_SIZE(h->size_index);
+  newtable=(hash_rec *)mem_get_block((SIZE_T)(h->size*sizeof(hash_rec)));
+  for (i=0; i < h->size; ++i)
+    newtable[i]=0;
+  for (i=0; i < oldsize; ++i)
+    for (p=h->table[i]; p; p=q)
+      {
+	q=p->next;
+	hash=HASH(p->key);
+	BDD_REDUCE(hash, h->size);
+	p->next=newtable[hash];
+	newtable[hash]=p;
+      }
+  mem_free_block((pointer)h->table);
+  h->table=newtable;
+}
+
+
+/* bdd_insert_in_hash_table(h, f, data) associates the specified data */
+/* with f in h. */
+
+void
+bdd_insert_in_hash_table(hash_table h, bdd f, pointer data)
+{
+  long hash;
+  hash_rec p;
+
+  p=(hash_rec)BDD_NEW_REC(h->bddm, ALIGN(sizeof(struct hash_rec_))+h->item_size);
+  p->key=f;
+  mem_copy((pointer)(ALIGN(sizeof(struct hash_rec_))+(INT_PTR)p), data, (SIZE_T)h->item_size);
+  hash=HASH(f);
+  BDD_REDUCE(hash, h->size);
+  p->next=h->table[hash];
+  h->table[hash]=p;
+  h->entries++;
+  if ((h->size << 2) < h->entries)
+    bdd_rehash_hash_table(h);
+}
+
+
+/* bdd_lookup_in_hash_table(h, f) looks up f in h and returns either a */
+/* pointer to the associated data or null. */
+
+pointer
+bdd_lookup_in_hash_table(hash_table h, bdd f)
+{
+  long hash;
+  hash_rec p;
+
+  hash=HASH(f);
+  BDD_REDUCE(hash, h->size);
+  for (p=h->table[hash]; p; p=p->next)
+    if (p->key == f)
+      return ((pointer)(ALIGN(sizeof(struct hash_rec_))+(char *)p));
+  return ((pointer)0);
+}
+
+
+/* bdd_new_hash_table(bddm, item_size) creates a new hash table with */
+/* the specified data item size. */
+
+hash_table
+bdd_new_hash_table(cmu_bdd_manager bddm, int item_size)
+{
+  long i;
+  hash_table h;
+
+  h=(hash_table)BDD_NEW_REC(bddm, sizeof(struct hash_table_));
+  h->size_index=10;
+  h->size=TABLE_SIZE(h->size_index);
+  h->table=(hash_rec *)mem_get_block((SIZE_T)(h->size*sizeof(hash_rec)));
+  for (i=0; i < h->size; ++i)
+    h->table[i]=0;
+  h->entries=0;
+  h->item_size=item_size;
+  h->bddm=bddm;
+  return (h);
+}
+
+
+/* cmu_bdd_free_hash_table(h) frees up the storage associated with h. */
+
+void
+cmu_bdd_free_hash_table(hash_table h)
+{
+  long i;
+  hash_rec p, q;
+
+  for (i=0; i < h->size; ++i)
+    for (p=h->table[i]; p; p=q)
+      {
+	q=p->next;
+	BDD_FREE_REC(h->bddm, (pointer)p, ALIGN(sizeof(struct hash_rec_))+h->item_size);
+      }
+  mem_free_block((pointer)h->table);
+  BDD_FREE_REC(h->bddm, (pointer)h, sizeof(struct hash_table_));
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddint.h
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddint.h	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddint.h	(revision 8)
@@ -0,0 +1,720 @@
+/* BDD package internal definitions */
+
+
+#if !defined(_BDDINTH)
+#define _BDDINTH
+
+
+#include <setjmp.h>
+
+
+/* >>> Configuration things */
+
+/* Define this for cache and unique sizes to be a power of 2. */
+/* Probably not a good idea given the current simplistic hash function. */
+
+/* #define POWER_OF_2_SIZES */
+
+/* Define this if your C preprocessor is broken in such a way that */
+/* token concatenation can be done with something like: */
+/* #define CONCAT(f, g) f/''/g */
+/* where /''/ above would be an empty comment (' => *) if this */
+/* wasn't itself a comment.  Most of the (non-ANSI) UNIX C preprocessors */
+/* do seem to be broken, which is why this is defined.  If your C */
+/* preprocessor is ANSI, this shouldn't have any effect. */
+
+#define BROKEN_CPP
+
+
+
+/* >>> All user-visible stuff */
+
+#include "bdduser.h"
+
+
+#define ARGS(args) args
+
+
+/* Miscellaneous type definitions */
+
+typedef struct hash_table_ *hash_table;
+
+
+/* >>> BDD data structures */
+
+#if !defined(POWER_OF_2_SIZES)
+extern long bdd_primes[];
+#endif
+
+
+/* Pointer tagging stuff */
+
+#define POINTER(p) ((pointer)(((INT_PTR)(p)) & ~(INT_PTR)0x7))
+#define BDD_POINTER(p) ((bdd)POINTER(p))
+#define CACHE_POINTER(p) ((cache_entry)POINTER(p))
+
+#define TAG(p) ((int)(((INT_PTR)(p)) & 0x7))
+#define SET_TAG(p, t) ((pointer)((INT_PTR)POINTER(p) | (t)))
+
+#define TAG0(p) ((int)((INT_PTR)(p) & 0x1))
+#define FLIP_TAG0(p) ((pointer)((INT_PTR)(p) ^ 0x1))
+#define TAG0_HI(p) ((pointer)((INT_PTR)(p) | 0x1))
+#define TAG0_LO(p) ((pointer)((INT_PTR)(p) & ~(INT_PTR)0x1))
+
+#define TAG1(p) ((int)((INT_PTR)(p) & 0x2))
+#define FLIP_TAG1(p) ((pointer)((INT_PTR)(p) ^ 0x2))
+#define TAG1_HI(p) ((pointer)((INT_PTR)(p) | 0x2))
+#define TAG1_LO(p) ((pointer)((INT_PTR)(p) & ~(INT_PTR)0x2))
+
+#define TAG2(p) ((int)((INT_PTR)(p) & 0x4))
+#define FLIP_TAG2(p) ((pointer)((INT_PTR)(p) ^ 0x4))
+#define TAG2_HI(p) ((pointer)((INT_PTR)(p) | 0x4))
+#define TAG2_LO(p) ((pointer)((INT_PTR)(p) & ~(INT_PTR)0x4))
+
+
+/* Indexes */
+
+typedef unsigned short bdd_index_type;
+
+
+/* Types of various BDD node fields */
+
+typedef unsigned short bdd_indexindex_type;
+typedef unsigned char bdd_refcount_type;
+typedef unsigned char bdd_mark_type;
+
+
+/* A BDD node */
+
+struct bdd_
+{
+  bdd_indexindex_type indexindex;
+				/* Index into indexes table */
+  bdd_refcount_type refs;	/* External reference count */
+  bdd_mark_type mark;		/* Mark and temporary ref count */
+  INT_PTR data[2];		/* Then and else pointers, or data */
+				/* values for terminals */
+  struct bdd_ *next;
+};
+
+
+/* Maximum reference counts */
+
+#define BDD_MAX_REFS ((bdd_refcount_type)((1l << (8*sizeof(bdd_refcount_type))) - 1))
+#define BDD_MAX_TEMP_REFS ((bdd_mark_type)((1l << (8*sizeof(bdd_mark_type)-1)) - 1))
+
+#define BDD_GC_MARK ((bdd_mark_type)(1l << (8*sizeof(bdd_mark_type)-1)))
+
+
+/* Special indexindexes and indexes */
+
+#define BDD_CONST_INDEXINDEX 0
+#define BDD_MAX_INDEXINDEX ((bdd_indexindex_type)((1l << (8*sizeof(bdd_indexindex_type))) - 1))
+#define BDD_MAX_INDEX ((bdd_index_type)((1l << (8*sizeof(bdd_index_type))) - 1))
+
+
+/* Can this be done legally with a non-ANSI cpp? */
+
+#define CONCAT_PTR(f) f##_ptr
+
+#if defined(CONCAT_PTR)
+/* Field accessing stuff */
+
+#define BDD_SETUP(f) bdd CONCAT_PTR(f)=BDD_POINTER(f)
+#define BDD_RESET(f) CONCAT_PTR(f)=BDD_POINTER(f)
+#define BDD_INDEXINDEX(f) (CONCAT_PTR(f)->indexindex)
+#define BDD_DATA(f) (CONCAT_PTR(f)->data)
+#define BDD_DATA0(f) (CONCAT_PTR(f)->data[0])
+#define BDD_DATA1(f) (CONCAT_PTR(f)->data[1])
+#define BDD_REFS(f) (CONCAT_PTR(f)->refs)
+#define BDD_MARK(f) (CONCAT_PTR(f)->mark)
+#define BDD_TEMP_REFS(f) (CONCAT_PTR(f)->mark)
+
+
+/* Basic stuff stuff for indexes, testing, etc. */
+
+#define BDD_INDEX(bddm, f) ((bddm)->indexes[BDD_INDEXINDEX(f)])
+#define BDD_THEN(f) ((bdd)(BDD_DATA0(f) ^ TAG0(f)))
+#define BDD_ELSE(f) ((bdd)(BDD_DATA1(f) ^ TAG0(f)))
+#define BDD_SAME_OR_NEGATIONS(f, g) (CONCAT_PTR(f) == CONCAT_PTR(g))
+#define BDD_IS_CONST(f) (BDD_INDEXINDEX(f) == BDD_CONST_INDEXINDEX)
+#else
+/* Field accessing stuff */
+
+#define BDD_SETUP(f)
+#define BDD_RESET(f)
+#define BDD_INDEXINDEX(f) (BDD_POINTER(f)->indexindex)
+#define BDD_DATA(f) (BDD_POINTER(f)->data)
+#define BDD_DATA0(f) (BDD_POINTER(f)->data[0])
+#define BDD_DATA1(f) (BDD_POINTER(f)->data[1])
+#define BDD_REFS(f) (BDD_POINTER(f)->refs)
+#define BDD_MARK(f) (BDD_POINTER(f)->mark)
+#define BDD_TEMP_REFS(f) (BDD_POINTER(f)->mark)
+
+
+/* Basic stuff stuff for indexes, testing, etc. */
+
+#define BDD_INDEX(bddm, f) ((bddm)->indexes[BDD_INDEXINDEX(f)])
+#define BDD_THEN(f) ((bdd)(BDD_DATA0(f) ^ TAG0(f)))
+#define BDD_ELSE(f) ((bdd)(BDD_DATA1(f) ^ TAG0(f)))
+#define BDD_SAME_OR_NEGATIONS(f, g) (BDD_POINTER(f) == BDD_POINTER(g))
+#define BDD_IS_CONST(f) (BDD_INDEXINDEX(f) == BDD_CONST_INDEXINDEX)
+#endif
+
+
+/* BDD complement flag stuff */
+
+#define BDD_IS_OUTPOS(f) (!TAG0(f))
+#define BDD_OUTPOS(f) ((bdd)TAG0_LO(f))
+#define BDD_NOT(f) ((bdd)FLIP_TAG0(f))
+
+
+/* Cofactoring stuff */
+
+#define BDD_TOP_VAR2(top_indexindex, bddm, f, g)\
+do\
+  if (BDD_INDEX(bddm, f) < BDD_INDEX(bddm, g))\
+    top_indexindex=BDD_INDEXINDEX(f);\
+  else\
+    top_indexindex=BDD_INDEXINDEX(g);\
+while (0)
+
+#define BDD_TOP_VAR3(top_indexindex, bddm, f, g, h)\
+do\
+  if (BDD_INDEX(bddm, f) < BDD_INDEX(bddm, g))\
+    {\
+      top_indexindex=BDD_INDEXINDEX(f);\
+      if ((bddm)->indexes[top_indexindex] > BDD_INDEX(bddm, h))\
+	top_indexindex=BDD_INDEXINDEX(h);\
+    }\
+  else\
+    {\
+      top_indexindex=BDD_INDEXINDEX(g);\
+      if ((bddm)->indexes[top_indexindex] > BDD_INDEX(bddm, h))\
+	top_indexindex=BDD_INDEXINDEX(h);\
+    }\
+while (0)
+
+#define BDD_COFACTOR(top_indexindex, f, f_then, f_else)\
+do\
+  if (BDD_INDEXINDEX(f) == top_indexindex)\
+    {\
+      f_then=BDD_THEN(f);\
+      f_else=BDD_ELSE(f);\
+    }\
+  else\
+    {\
+      f_then=f;\
+      f_else=f;\
+    }\
+while (0)
+
+
+/* Ordering stuff */
+
+#define BDD_OUT_OF_ORDER(f, g) ((INT_PTR)f > (INT_PTR)g)
+
+#if defined(CONCAT_PTR)
+#define BDD_SWAP(f, g)\
+do\
+  {\
+    bdd _temp;\
+    _temp=f;\
+    f=g;\
+    g=_temp;\
+    _temp=CONCAT_PTR(f);\
+    CONCAT_PTR(f)=CONCAT_PTR(g);\
+    CONCAT_PTR(g)=_temp;\
+  }\
+while (0)
+#else
+#define BDD_SWAP(f, g)\
+do\
+  {\
+    bdd _temp;\
+    _temp=f;\
+    f=g;\
+    g=_temp;\
+  }\
+while (0)
+#endif
+
+
+/* This gets the variable at the top of a node. */
+
+#define BDD_IF(bddm, f) ((bddm)->variables[BDD_INDEXINDEX(f)])
+
+
+/* Reference count stuff */
+
+#define BDD_INCREFS(f)\
+do\
+  {\
+    if (BDD_REFS(f) >= BDD_MAX_REFS-1)\
+      {\
+	BDD_REFS(f)=BDD_MAX_REFS;\
+	BDD_TEMP_REFS(f)=0;\
+      }\
+   else\
+     BDD_REFS(f)++;\
+  }\
+while (0)
+
+#define BDD_DECREFS(f)\
+do\
+  {\
+    if (BDD_REFS(f) < BDD_MAX_REFS)\
+      BDD_REFS(f)--;\
+  }\
+while (0)
+
+#define BDD_TEMP_INCREFS(f)\
+do\
+  {\
+    if (BDD_REFS(f) < BDD_MAX_REFS)\
+      {\
+	BDD_TEMP_REFS(f)++;\
+	if (BDD_TEMP_REFS(f) == BDD_MAX_TEMP_REFS)\
+	  {\
+	    BDD_REFS(f)=BDD_MAX_REFS;\
+	    BDD_TEMP_REFS(f)=0;\
+	  }\
+      }\
+  }\
+while (0)
+
+#define BDD_TEMP_DECREFS(f)\
+do\
+  {\
+    if (BDD_REFS(f) < BDD_MAX_REFS)\
+      BDD_TEMP_REFS(f)--;\
+  }\
+while (0)
+
+#define BDD_IS_USED(f) ((BDD_MARK(f) & BDD_GC_MARK) != 0)
+
+
+/* Convert an internal reference to an external one and return. */
+
+#define RETURN_BDD(thing)\
+return (bdd_make_external(thing))
+
+
+/* These return the constants. */
+
+#define BDD_ONE(bddm) ((bddm)->one)
+#define BDD_ZERO(bddm) ((bddm)->zero)
+
+
+/* Cache entries */
+
+struct cache_entry_
+{
+  INT_PTR slot[4];
+};
+
+typedef struct cache_entry_ *cache_entry;
+
+
+/* Cache entry tags; ITE is for IF-THEN-ELSE operations.  TWO is for */
+/* the two argument operations that return a BDD result.  ONEDATA */
+/* and TWODATA are for one and two argument operations that return */
+/* double and single word data results.  Everything else is under */
+/* user control. */
+
+#define CACHE_TYPE_ITE 0x0
+#define CACHE_TYPE_TWO 0x1
+#define CACHE_TYPE_ONEDATA 0x2
+#define CACHE_TYPE_TWODATA 0x3
+#define CACHE_TYPE_USER1 0x4
+
+#define USER_ENTRY_TYPES 4
+
+
+/* Operation numbers (for CACHE_TYPE_TWO) */
+/* OP_RELPROD, OP_QNT and OP_SUBST need a reasonable number of holes */
+/* after them since the variable association number is added to them */
+/* to get the actual op.  OP_COMP, OP_SWAP and OP_CMPTO need */
+/* BDD_MAX_INDEX.  OP_SWAPAUX needs 2*BDD_MAX_INDEX.  Negative */
+/* operation numbers denote temporaries and are generated as needed. */
+
+#define OP_COFACTOR 100l
+#define OP_SATFRAC 200l
+#define OP_FWD 300l
+#define OP_REV 400l
+#define OP_RED 500l
+#define OP_EQUAL 600l
+#define OP_QNT 10000l
+#define OP_RELPROD 20000l
+#define OP_SUBST 30000l
+#define OP_COMP 100000l
+#define OP_CMPTO 200000l
+#define OP_SWAP 300000l
+#define OP_SWAPAUX 400000l
+
+
+/* Variable associations */
+
+struct var_assoc_
+{
+  bdd *assoc;			/* Array with associated BDDs */
+  long last;			/* Indexindex for lowest variable */
+};
+
+typedef struct var_assoc_ *var_assoc;
+
+
+struct assoc_list_
+{
+  struct var_assoc_ va;		/* The association */
+  int id;			/* Identifier for this association */
+  int refs;			/* Number of outstanding references */
+  struct assoc_list_ *next;	/* The next association */
+};
+
+typedef struct assoc_list_ *assoc_list;
+
+
+/* Variable blocks */
+
+struct block_
+{
+  long num_children;
+  struct block_ **children;
+  int reorderable;
+  long first_index;
+  long last_index;
+};
+
+
+/* A cache bin; the cache is two-way associative. */
+
+struct cache_bin_
+{
+  cache_entry entry[2];		/* LRU has index 1 */
+};
+
+typedef struct cache_bin_ cache_bin;
+
+
+/* The cache */
+
+struct cache_
+{
+  cache_bin *table;		/* The cache itself */
+  int size_index;		/* Index giving number of cache lines */
+  long size;			/* Number of cache lines */
+  int cache_level;		/* Bin to start search in cache */
+				/* Cache control functions: */
+  long (*rehash_fn[8]) ARGS((cmu_bdd_manager, cache_entry));
+				/* Rehashes a cache entry */
+  int (*gc_fn[8]) ARGS((cmu_bdd_manager, cache_entry));
+				/* Checks to see if an entry needs flushing */
+  void (*purge_fn[8]) ARGS((cmu_bdd_manager, cache_entry));
+				/* Called when purging an entry */
+  void (*return_fn[8]) ARGS((cmu_bdd_manager, cache_entry));
+				/* Called before returning from cache hit */
+  int (*flush_fn[8]) ARGS((cmu_bdd_manager, cache_entry, pointer));
+				/* Called when freeing variable association */
+  int cache_ratio;		/* Cache to unique table size ratio */
+  long entries;			/* Number of cache entries */
+  long lookups;			/* Number of cache lookups */
+  long hits;			/* Number of cache hits */
+  long inserts;			/* Number of cache inserts */
+  long collisions;		/* Number of cache collisions */
+};
+
+typedef struct cache_ cache;
+
+
+/* One part of the node table */
+
+struct var_table_
+{
+  bdd *table;			/* Pointers to the start of each bucket */
+  int size_index;		/* Index giving number of buckets */
+  long size;			/* Number of buckets */
+  long entries;			/* Number of BDD nodes in table */
+};
+
+typedef struct var_table_ *var_table;
+
+
+/* The BDD node table */
+
+struct unique_
+{
+  var_table *tables;		/* Individual variable tables */
+  void (*free_terminal_fn) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer));
+				/* Called when freeing MTBDD terminals */
+  pointer free_terminal_env;	/* Environment for free terminal function */
+  long entries;			/* Total number of BDD nodes */
+  long gc_limit;		/* Try garbage collection at this point */
+  long node_limit;		/* Maximum number of BDD nodes allowed */
+  long gcs;			/* Number of garbage collections */
+  long freed;			/* Number of nodes freed */
+  long finds;			/* Number of find operations */
+};
+
+typedef struct unique_ unique;
+
+
+/* Record manager size range stuff */
+
+#define MIN_REC_SIZE ALLOC_ALIGNMENT
+#define MAX_REC_SIZE 64
+
+#define REC_MGRS (((MAX_REC_SIZE-MIN_REC_SIZE)/ALLOC_ALIGNMENT)+1)
+
+
+/* Wrapper for jmp_buf since we may need to copy it sometimes and */
+/* we can't easily do it if it happens to be an array. */
+
+struct jump_buf_
+{
+  jmp_buf context;
+};
+
+typedef struct jump_buf_ jump_buf;
+
+
+/* A BDD manager */
+
+struct bdd_manager_
+{
+  unique unique_table;		/* BDD node table */
+  cache op_cache;		/* System result cache */
+  int check;			/* Number of find calls 'til size checks */
+  bdd one;			/* BDD for one */
+  bdd zero;			/* BDD for zero */
+  int overflow;			/* Nonzero if node limit exceeded */
+  void (*overflow_fn) ARGS((cmu_bdd_manager, pointer));
+				/* Function to call on overflow */
+  pointer overflow_env;		/* Environment for overflow function */
+  void (*transform_fn) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, INT_PTR *, INT_PTR *, pointer));
+				/* Function to transform terminal values */
+  pointer transform_env;	/* Environment for transform_fn */
+  int (*canonical_fn) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer));
+				/* Function to check if a terminal value is */
+				/* canonical */
+  block super_block;		/* Top-level variable block */
+  void (*reorder_fn) ARGS((cmu_bdd_manager));
+				/* Function to call to reorder variables */
+  pointer reorder_data;		/* For saving information btwn reorderings */
+  int allow_reordering;		/* Nonzero if reordering allowed */
+  long nodes_at_start;		/* Nodes at start of operation */
+  long vars;			/* Number of variables */
+  long maxvars;			/* Maximum number of variables w/o resize */
+  bdd *variables;		/* Array of variables, by indexindex */
+  bdd_index_type *indexes;	/* indexindex -> index table */
+  bdd_indexindex_type *indexindexes;
+				/* index -> indexindex table */
+  int curr_assoc_id;		/* Current variable association number */
+  var_assoc curr_assoc;		/* Current variable association */
+  assoc_list assocs;		/* Variable associations */
+  struct var_assoc_ temp_assoc;	/* Temporary variable association */
+  rec_mgr rms[REC_MGRS];	/* Record managers */
+  long temp_op;			/* Current temporary operation number */
+  jump_buf abort;		/* Jump for out-of-memory cleanup */
+  void (*bag_it_fn) ARGS((cmu_bdd_manager, pointer));
+				/* Non-null if going to abort at next find */
+  pointer bag_it_env; char *hooks;		/* Environment for bag it function */
+};
+
+
+/* Abort stuff */
+
+#define BDD_ABORTED 1
+#define BDD_OVERFLOWED 2
+#define BDD_REORDERED 3
+
+
+#define FIREWALL(bddm)\
+do\
+  {\
+    int retcode;\
+    (bddm)->allow_reordering=1;\
+    (bddm)->nodes_at_start=(bddm)->unique_table.entries;\
+    while ((retcode=(setjmp((bddm)->abort.context))))\
+      {\
+	bdd_cleanup(bddm, retcode);\
+	if (retcode == BDD_ABORTED || retcode == BDD_OVERFLOWED)\
+	  return ((bdd)0);\
+	(bddm)->nodes_at_start=(bddm)->unique_table.entries;\
+      }\
+  }\
+while (0)
+
+
+#define FIREWALL1(bddm, cleanupcode)\
+do\
+  {\
+    int retcode;\
+    (bddm)->allow_reordering=1;\
+    (bddm)->nodes_at_start=(bddm)->unique_table.entries;\
+    while ((retcode=(setjmp((bddm)->abort.context))))\
+      {\
+	bdd_cleanup(bddm, retcode);\
+	cleanupcode\
+	(bddm)->nodes_at_start=(bddm)->unique_table.entries;\
+      }\
+  }\
+while (0)
+
+
+/* Node hash function */
+
+#define HASH_NODE(f, g) (((f) << 1)+(g))
+
+
+/* Table size stuff */
+
+#if defined(POWER_OF_2_SIZES)
+#define TABLE_SIZE(size_index) (1l << (size_index))
+#define BDD_REDUCE(i, size) (i)&=(size)-1
+#else
+#define TABLE_SIZE(size_index) (bdd_primes[size_index])
+#define BDD_REDUCE(i, size)\
+do\
+  {\
+    (i)%=(size);\
+    if ((i) < 0)\
+      (i)= -(i);\
+  }\
+while (0)
+#endif
+
+
+/* Record management */
+
+#define BDD_NEW_REC(bddm, size) mem_new_rec((bddm)->rms[(ROUNDUP(size)-MIN_REC_SIZE)/ALLOC_ALIGNMENT])
+#define BDD_FREE_REC(bddm, rec, size) mem_free_rec((bddm)->rms[(ROUNDUP(size)-MIN_REC_SIZE)/ALLOC_ALIGNMENT], (rec))
+
+
+/* >>> Declarations for random routines */
+
+/* Internal BDD routines */
+
+extern int bdd_check_arguments ARGS((int, ...));
+extern void bdd_check_array ARGS((bdd *));
+extern bdd bdd_make_external ARGS((bdd));
+extern int cmu_bdd_type_aux ARGS((cmu_bdd_manager, bdd));
+extern int cmu_bdd_is_cube ARGS((cmu_bdd_manager, bdd));
+extern void bdd_rehash_var_table ARGS((var_table, int));
+extern bdd bdd_find_aux ARGS((cmu_bdd_manager, bdd_indexindex_type, INT_PTR, INT_PTR));
+extern bdd cmu_bdd_ite_step ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+extern bdd cmu_bdd_exists_temp ARGS((cmu_bdd_manager, bdd, long));
+extern bdd cmu_bdd_compose_temp ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+extern bdd cmu_bdd_substitute_step ARGS((cmu_bdd_manager, bdd, long, bdd (*) ARGS((cmu_bdd_manager, bdd, bdd, bdd)), var_assoc));
+extern bdd cmu_bdd_swap_vars_temp ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+extern int cmu_bdd_compare_temp ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+extern double cmu_bdd_satisfying_fraction_step ARGS((cmu_bdd_manager, bdd));
+extern void bdd_mark_shared_nodes ARGS((cmu_bdd_manager, bdd));
+extern void bdd_number_shared_nodes ARGS((cmu_bdd_manager, bdd, hash_table, long *));
+extern char *bdd_terminal_id ARGS((cmu_bdd_manager, bdd, char *(*) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer)), pointer));
+extern char *bdd_var_name ARGS((cmu_bdd_manager, bdd, char *(*) ARGS((cmu_bdd_manager, bdd, pointer)), pointer));
+extern long bdd_find_block ARGS((block, long));
+extern void bdd_block_delta ARGS((block, long));
+extern void cmu_bdd_reorder_aux ARGS((cmu_bdd_manager));
+extern void cmu_mtbdd_terminal_value_aux ARGS((cmu_bdd_manager, bdd, INT_PTR *, INT_PTR *));
+
+
+/* System cache routines */
+
+extern void bdd_insert_in_cache31 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR));
+extern int bdd_lookup_in_cache31 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR *));
+extern void bdd_insert_in_cache22 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR));
+extern int bdd_lookup_in_cache22 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR *, INT_PTR *));
+extern void bdd_insert_in_cache13 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR, INT_PTR, INT_PTR));
+extern int bdd_lookup_in_cache13 ARGS((cmu_bdd_manager, int, INT_PTR, INT_PTR *, INT_PTR *, INT_PTR *));
+extern void bdd_flush_cache ARGS((cmu_bdd_manager, int (*) ARGS((cmu_bdd_manager, cache_entry, pointer)), pointer));
+extern void bdd_purge_cache ARGS((cmu_bdd_manager));
+extern void bdd_flush_all ARGS((cmu_bdd_manager));
+extern int bdd_cache_functions ARGS((cmu_bdd_manager,
+				     int,
+				     int (*) ARGS((cmu_bdd_manager, cache_entry)),
+				     void (*) ARGS((cmu_bdd_manager, cache_entry)),
+				     void (*) ARGS((cmu_bdd_manager,cache_entry)),
+				     int (*) ARGS((cmu_bdd_manager, cache_entry, pointer))));
+extern void cmu_bdd_free_cache_tag ARGS((cmu_bdd_manager, long));
+extern void bdd_rehash_cache ARGS((cmu_bdd_manager, int));
+extern void cmu_bdd_init_cache ARGS((cmu_bdd_manager));
+extern void cmu_bdd_free_cache ARGS((cmu_bdd_manager));
+
+#define bdd_insert_in_cache2(bddm, op, f, g, result)\
+bdd_insert_in_cache31((bddm), CACHE_TYPE_TWO, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR)(result))
+#define bdd_lookup_in_cache2(bddm, op, f, g, result)\
+bdd_lookup_in_cache31((bddm), CACHE_TYPE_TWO, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR *)(result))
+
+#define bdd_insert_in_cache1(bddm, op, f, result)\
+bdd_insert_in_cache2((bddm), (op), (f), BDD_ONE(bddm), (result))
+#define bdd_lookup_in_cache1(bddm, op, f, result)\
+bdd_lookup_in_cache2((bddm), (op), (f), BDD_ONE(bddm), (result))
+
+#define bdd_insert_in_cache2d(bddm, op, f, g, result)\
+bdd_insert_in_cache31((bddm), CACHE_TYPE_TWODATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR)(result))
+#define bdd_lookup_in_cache2d(bddm, op, f, g, result)\
+bdd_lookup_in_cache31((bddm), CACHE_TYPE_TWODATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(g), (INT_PTR *)(result))
+
+#define bdd_insert_in_cache1d(bddm, op, f, result1, result2)\
+bdd_insert_in_cache22((bddm), CACHE_TYPE_ONEDATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR)(result1), (INT_PTR)(result2))
+#define bdd_lookup_in_cache1d(bddm, op, f, result1, result2)\
+bdd_lookup_in_cache22((bddm), CACHE_TYPE_ONEDATA, (INT_PTR)(op), (INT_PTR)(f), (INT_PTR *)(result1), (INT_PTR *)(result2))
+
+#define cache_return_fn_none ((void (*)(cmu_bdd_manager, cache_entry))0)
+#define cache_purge_fn_none ((void (*)(cmu_bdd_manager, cache_entry))0)
+#define cache_reclaim_fn_none ((int (*)(cmu_bdd_manager, cache_entry, pointer))0)
+
+
+/* Unique table routines */
+
+extern void bdd_clear_temps ARGS((cmu_bdd_manager));
+extern void bdd_sweep_var_table ARGS((cmu_bdd_manager, long, int));
+extern void bdd_sweep ARGS((cmu_bdd_manager));
+extern void bdd_cleanup ARGS((cmu_bdd_manager, int));
+extern bdd bdd_find ARGS((cmu_bdd_manager, bdd_indexindex_type, bdd, bdd));
+extern bdd bdd_find_terminal ARGS((cmu_bdd_manager, INT_PTR, INT_PTR));
+extern var_table bdd_new_var_table ARGS((cmu_bdd_manager));
+extern void cmu_bdd_init_unique ARGS((cmu_bdd_manager));
+extern void cmu_bdd_free_unique ARGS((cmu_bdd_manager));
+
+
+/* Error routines */
+
+extern void cmu_bdd_fatal ARGS((char *));
+extern void cmu_bdd_warning ARGS((char *));
+
+
+/* >>> Hash table declarations */
+
+struct hash_rec_
+{
+  bdd key;
+  struct hash_rec_ *next;
+};
+
+typedef struct hash_rec_ *hash_rec;
+
+
+struct hash_table_
+{
+  hash_rec *table;
+  int size_index;
+  long size;
+  long entries;
+  int item_size;
+  cmu_bdd_manager bddm;
+};
+
+
+/* Hash table routines */
+
+extern void bdd_insert_in_hash_table ARGS((hash_table, bdd, pointer));
+extern pointer bdd_lookup_in_hash_table ARGS((hash_table, bdd));
+extern hash_table bdd_new_hash_table ARGS((cmu_bdd_manager, int));
+extern void cmu_bdd_free_hash_table ARGS((hash_table));
+
+
+#undef ARGS
+
+#endif
Index: /vis_dev/glu-2.1/src/cmuBdd/bddmisc.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddmisc.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddmisc.c	(revision 8)
@@ -0,0 +1,103 @@
+/* Support functions need by miscellaneous BDD routines */
+
+
+#include "bddint.h"
+
+
+void
+bdd_mark_shared_nodes(cmu_bdd_manager bddm, bdd f)
+{
+  BDD_SETUP(f);
+  f=BDD_OUTPOS(f);
+  if (BDD_IS_CONST(f) || cmu_bdd_type_aux(bddm, f) == BDD_TYPE_POSVAR)
+    return;
+  if (BDD_MARK(f))
+    {
+      if (BDD_MARK(f) == 1)
+	BDD_MARK(f)=2;
+      return;
+    }
+  BDD_MARK(f)=1;
+  bdd_mark_shared_nodes(bddm, BDD_THEN(f));
+  bdd_mark_shared_nodes(bddm, BDD_ELSE(f));
+}
+
+
+void
+bdd_number_shared_nodes(cmu_bdd_manager bddm, bdd f, hash_table h, long *next)
+{
+  BDD_SETUP(f);
+  if (BDD_IS_CONST(f) || ((1 << cmu_bdd_type_aux(bddm, f)) & ((1 << BDD_TYPE_POSVAR) | (1 << BDD_TYPE_NEGVAR))))
+    return;
+  if (BDD_MARK(f) == 0)
+    return;
+  if (BDD_MARK(f) == 2)
+    {
+      bdd_insert_in_hash_table(h, f, (pointer)next);
+      ++*next;
+    }
+  BDD_MARK(f)=0;
+  bdd_number_shared_nodes(bddm, BDD_THEN(f), h, next);
+  bdd_number_shared_nodes(bddm, BDD_ELSE(f), h, next);
+}
+
+
+static char default_terminal_id[]="terminal XXXXXXXXXX XXXXXXXXXX";
+static char default_var_name[]="var.XXXXXXXXXX";
+
+
+char *
+bdd_terminal_id(cmu_bdd_manager bddm, bdd f, char *(*terminal_id_fn)(cmu_bdd_manager, INT_PTR, INT_PTR, pointer), pointer env)
+{
+  char *id;
+  INT_PTR v1, v2;
+
+  cmu_mtbdd_terminal_value_aux(bddm, f, &v1, &v2);
+  if (terminal_id_fn)
+    id=(*terminal_id_fn)(bddm, v1, v2, env);
+  else
+    id=0;
+  if (!id)
+    {
+      if (f == BDD_ONE(bddm))
+	return ("1");
+      if (f == BDD_ZERO(bddm))
+	return ("0");
+      sprintf(default_terminal_id, "terminal %ld %ld", (long)v1, (long)v2);
+      id=default_terminal_id;
+    }
+  return (id);
+}
+
+
+char *
+bdd_var_name(cmu_bdd_manager bddm, bdd v, char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer), pointer env)
+{
+  char *name;
+
+  if (var_naming_fn)
+    name=(*var_naming_fn)(bddm, v, env);
+  else
+    name=0;
+  if (!name)
+    {
+      BDD_SETUP(v);
+      sprintf(default_var_name, "var.%d", BDD_INDEX(bddm, v));
+      name=default_var_name;
+    }
+  return (name);
+}
+
+
+void
+cmu_mtbdd_terminal_value_aux(cmu_bdd_manager bddm, bdd f, INT_PTR *value1, INT_PTR *value2)
+{
+  BDD_SETUP(f);
+  if (BDD_IS_OUTPOS(f))
+    {
+      *value1=BDD_DATA0(f);
+      *value2=BDD_DATA1(f);
+    }
+  else
+    (*bddm->transform_fn)(bddm, BDD_DATA0(f), BDD_DATA1(f), value1, value2, bddm->transform_env);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddprimes.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddprimes.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddprimes.c	(revision 8)
@@ -0,0 +1,55 @@
+/* BDD routine prime numbers for table sizes */
+
+
+long bdd_primes[]=
+{
+  1,
+  2,
+  3,
+  7,
+  13,
+  23,
+  59,
+  113,
+  241,
+  503,
+  1019,
+  2039,
+  4091,
+  8179,
+  11587,
+  16369,
+  23143,
+  32749,
+  46349,
+  65521,
+  92683,
+  131063,
+  185363,
+  262139,
+  330287,
+  416147,
+  524269,
+  660557,
+  832253,
+  1048571,
+  1321109,
+  1664501,
+  2097143,
+  2642201,
+  3328979,
+  4194287,
+  5284393,
+  6657919,
+  8388593,
+  10568797,
+  13315831,
+  16777199,
+  33554393,
+  67108859,
+  134217689,
+  268435399,
+  536870879,
+  1073741789,
+  2147483629
+};
Index: /vis_dev/glu-2.1/src/cmuBdd/bddprint.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddprint.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddprint.c	(revision 8)
@@ -0,0 +1,135 @@
+/* BDD library print routines */
+
+
+#include "bddint.h"
+
+
+static
+void
+chars(char c, int n, FILE *fp)
+{
+  int i;
+
+  for (i=0; i < n; ++i)
+    fputc(c, fp);
+}
+
+
+static
+void
+bdd_print_top_var(cmu_bdd_manager bddm,
+		  bdd f,
+		  char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+		  pointer env,
+		  FILE *fp)
+{
+  BDD_SETUP(f);
+  fputs(bdd_var_name(bddm, BDD_IF(bddm, f), var_naming_fn, env), fp);
+  fputc('\n', fp);
+}
+
+
+static
+void
+cmu_bdd_print_bdd_step(cmu_bdd_manager bddm,
+		   bdd f,
+		   char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+		   char *(*terminal_id_fn)(cmu_bdd_manager, INT_PTR, INT_PTR, pointer),
+		   pointer env,
+		   FILE *fp,
+		   hash_table h,
+		   int indentation)
+{
+  int negated;
+  long *number;
+
+  BDD_SETUP(f);
+  chars(' ', indentation, fp);
+  switch (cmu_bdd_type_aux(bddm, f))
+    {
+    case BDD_TYPE_ZERO:
+    case BDD_TYPE_ONE:
+    case BDD_TYPE_CONSTANT:
+      fputs(bdd_terminal_id(bddm, f, terminal_id_fn, env), fp);
+      fputc('\n', fp);
+      break;
+    case BDD_TYPE_NEGVAR:
+      fputc('!', fp);
+      /* fall through */
+    case BDD_TYPE_POSVAR:
+      bdd_print_top_var(bddm, f, var_naming_fn, env, fp);
+      break;
+    case BDD_TYPE_NONTERMINAL:
+      if (bdd_lookup_in_hash_table(h, BDD_NOT(f)))
+	{
+	  f=BDD_NOT(f);
+	  negated=1;
+	}
+      else
+	negated=0;
+      number=(long *)bdd_lookup_in_hash_table(h, f);
+      if (number && *number < 0)
+	{
+	  if (negated)
+	    fputc('!', fp);
+	  fprintf(fp, "subformula %ld\n", -*number-1);
+	}
+      else
+	{
+	  if (number)
+	    {
+	      fprintf(fp, "%ld: ", *number);
+	      *number= -*number-1;
+	    }
+	  fputs("if ", fp);
+	  bdd_print_top_var(bddm, f, var_naming_fn, env, fp);
+	  cmu_bdd_print_bdd_step(bddm, BDD_THEN(f), var_naming_fn, terminal_id_fn, env, fp, h, indentation+2);
+	  chars(' ', indentation, fp);
+	  fputs("else if !", fp);
+	  bdd_print_top_var(bddm, f, var_naming_fn, env, fp);
+	  cmu_bdd_print_bdd_step(bddm, BDD_ELSE(f), var_naming_fn, terminal_id_fn, env, fp, h, indentation+2);
+	  chars(' ', indentation, fp);
+	  fputs("endif ", fp);
+	  bdd_print_top_var(bddm, f, var_naming_fn, env, fp);
+	}
+      break;
+    default:
+      cmu_bdd_fatal("cmu_bdd_print_bdd_step: unknown type returned by cmu_bdd_type");
+    }
+}
+
+
+/* cmu_bdd_print_bdd(bddm, f, var_naming_fn, terminal_id_fn, env, fp) prints a */
+/* human-readable representation of f to the file given by fp.  If */
+/* var_naming_fn is non-null, it should be a pointer to a function that */
+/* assigns names to BDD variables.  It is passed bddm, a BDD representing */
+/* a variable, and the pointer given by env, and should return a string */
+/* giving the name of the variable or null.  If terminal_id_fn is */
+/* non-null, it should be a pointer to a function that formats terminal */
+/* nodes.  It is passed bddm, two longs representing the data value of */
+/* the terminal node, and env.  It should return a string for the */
+/* terminal node, or null. */
+
+void
+cmu_bdd_print_bdd(cmu_bdd_manager bddm,
+	      bdd f,
+	      char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+	      char *(*terminal_id_fn)(cmu_bdd_manager, INT_PTR, INT_PTR, pointer),
+	      pointer env,
+	      FILE *fp)
+{
+  long next;
+  hash_table h;
+
+  if (!bdd_check_arguments(1, f))
+    {
+      fprintf(fp, "overflow\n");
+      return;
+    }
+  bdd_mark_shared_nodes(bddm, f);
+  h=bdd_new_hash_table(bddm, sizeof(long));
+  next=0;
+  bdd_number_shared_nodes(bddm, f, h, &next);
+  cmu_bdd_print_bdd_step(bddm, f, var_naming_fn, terminal_id_fn, env, fp, h, 0);
+  cmu_bdd_free_hash_table(h);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddprprofile.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddprprofile.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddprprofile.c	(revision 8)
@@ -0,0 +1,184 @@
+/* BDD library profile printing routines */
+
+
+#include "bddint.h"
+#if STDC_HEADERS
+#include <string.h>
+#endif
+
+static char profile_width[]="XXXXXXXXX";
+
+
+static
+void
+chars(char c, int n, FILE *fp)
+{
+  int i;
+
+  for (i=0; i < n; ++i)
+    fputc(c, fp);
+}
+
+
+/* cmu_bdd_print_profile_aux(bddm, level_counts, var_naming_fn, line_length, */
+/* env, fp) prints a profile to the file given by fp.  The var_naming_fn */
+/* is as in cmu_bdd_print_bdd.  line_length gives the line width to scale the */
+/* profile to. */
+
+void
+cmu_bdd_print_profile_aux(cmu_bdd_manager bddm,
+		      long *level_counts,
+		      char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+		      pointer env,
+		      int line_length,
+		      FILE *fp)
+{
+  long i, n;
+  int l;
+  char *name;
+  int max_prefix_len;
+  int max_profile_width;
+  int histogram_column;
+  int histogram_width;
+  int profile_scale;
+  long total;
+
+  n=bddm->vars;
+  /* max_... initialized with values for leaf nodes */
+  max_prefix_len=5;
+  max_profile_width=level_counts[n];
+  total=level_counts[n];
+  for (i=0; i < n; ++i)
+    if (level_counts[i])
+      {
+	sprintf(profile_width, "%ld", level_counts[i]);
+	l=strlen(bdd_var_name(bddm, bddm->variables[bddm->indexindexes[i]], var_naming_fn, env))+strlen(profile_width);
+	if (l > max_prefix_len)
+	  max_prefix_len=l;
+	if (level_counts[i] > max_profile_width)
+	  max_profile_width=level_counts[i];
+	total+=level_counts[i];
+      }
+  histogram_column=max_prefix_len+3;
+  histogram_width=line_length-histogram_column-1;
+  if (histogram_width < 20)
+    histogram_width=20;		/* Random minimum width */
+  if (histogram_width >= max_profile_width)
+    profile_scale=1;
+  else
+    profile_scale=(max_profile_width+histogram_width-1)/histogram_width;
+  for (i=0; i < n; ++i)
+    if (level_counts[i])
+      {
+	name=bdd_var_name(bddm, bddm->variables[bddm->indexindexes[i]], var_naming_fn, env);
+	fputs(name, fp);
+	fputc(':', fp);
+	sprintf(profile_width, "%ld", level_counts[i]);
+	chars(' ', (int)(max_prefix_len-strlen(name)-strlen(profile_width)+1), fp);
+	fputs(profile_width, fp);
+	fputc(' ', fp);
+	chars('#', level_counts[i]/profile_scale, fp);
+	fputc('\n', fp);
+      }
+  fputs("leaf:", fp);
+  sprintf(profile_width, "%ld", level_counts[n]);
+  chars(' ', (int)(max_prefix_len-4-strlen(profile_width)+1), fp);
+  fputs(profile_width, fp);
+  fputc(' ', fp);
+  chars('#', level_counts[n]/profile_scale, fp);
+  fputc('\n', fp);
+  fprintf(fp, "Total: %ld\n", total);
+}
+
+
+/* cmu_bdd_print_profile(bddm, f, var_naming_fn, env, line_length, fp) displays */
+/* the node profile for f on fp.  line_length specifies the maximum line */
+/* length.  var_naming_fn is as in cmu_bdd_print_bdd. */
+
+void
+cmu_bdd_print_profile(cmu_bdd_manager bddm,
+		  bdd f,
+		  char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+		  pointer env,
+		  int line_length,
+		  FILE *fp)
+{
+  long *level_counts;
+
+  if (bdd_check_arguments(1, f))
+    {
+      level_counts=(long *)mem_get_block((SIZE_T)((bddm->vars+1)*sizeof(long)));
+      cmu_bdd_profile(bddm, f, level_counts, 1);
+      cmu_bdd_print_profile_aux(bddm, level_counts, var_naming_fn, env, line_length, fp);
+      mem_free_block((pointer)level_counts);
+    }
+  else
+    fputs("overflow\n", fp);
+}
+
+
+/* cmu_bdd_print_profile_multiple is like cmu_bdd_print_profile except it displays */
+/* the profile for a set of BDDs. */
+
+void
+cmu_bdd_print_profile_multiple(cmu_bdd_manager bddm,
+			   bdd* fs,
+			   char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+			   pointer env,
+			   int line_length,
+			   FILE *fp)
+{
+  long *level_counts;
+
+  bdd_check_array(fs);
+  level_counts=(long *)mem_get_block((SIZE_T)((bddm->vars+1)*sizeof(long)));
+  cmu_bdd_profile_multiple(bddm, fs, level_counts, 1);
+  cmu_bdd_print_profile_aux(bddm, level_counts, var_naming_fn, env, line_length, fp);
+  mem_free_block((pointer)level_counts);
+}
+
+
+/* cmu_bdd_print_function_profile is like cmu_bdd_print_profile except it displays */
+/* a function profile for f. */
+
+void
+cmu_bdd_print_function_profile(cmu_bdd_manager bddm,
+			   bdd f,
+			   char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+			   pointer env,
+			   int line_length,
+			   FILE *fp)
+{
+  long *level_counts;
+
+  if (bdd_check_arguments(1, f))
+    {
+      level_counts=(long *)mem_get_block((SIZE_T)((bddm->vars+1)*sizeof(long)));
+      cmu_bdd_function_profile(bddm, f, level_counts);
+      cmu_bdd_print_profile_aux(bddm, level_counts, var_naming_fn, env, line_length, fp);
+      mem_free_block((pointer)level_counts);
+    }
+  else
+    fputs("overflow\n", fp);
+}
+
+
+/* cmu_bdd_print_function_profile_multiple is like cmu_bdd_print_function_profile */
+/* except for multiple BDDs. */
+
+void
+cmu_bdd_print_function_profile_multiple(cmu_bdd_manager bddm,
+				    bdd* fs,
+				    char *(*var_naming_fn)(cmu_bdd_manager, bdd, pointer),
+				    pointer env,
+				    int line_length,
+				    FILE *fp)
+{
+  long *level_counts;
+
+  bdd_check_array(fs);
+  level_counts=(long *)mem_get_block((SIZE_T)((bddm->vars+1)*sizeof(long)));
+  cmu_bdd_function_profile_multiple(bddm, fs, level_counts);
+  cmu_bdd_print_profile_aux(bddm, level_counts, var_naming_fn, env, line_length, fp);
+  mem_free_block((pointer)level_counts);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddqnt.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddqnt.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddqnt.c	(revision 8)
@@ -0,0 +1,93 @@
+/* BDD quantification routines */
+
+
+#include "bddint.h"
+
+
+static
+bdd
+cmu_bdd_exists_step(cmu_bdd_manager bddm, bdd f, long op, var_assoc vars)
+{
+  bdd temp1, temp2;
+  bdd result;
+  int quantifying;
+
+  BDD_SETUP(f);
+  if ((long)BDD_INDEX(bddm, f) > vars->last)
+    {
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (bdd_lookup_in_cache1(bddm, op, f, &result))
+    return (result);
+  quantifying=(vars->assoc[BDD_INDEXINDEX(f)] != 0);
+  temp1=cmu_bdd_exists_step(bddm, BDD_THEN(f), op, vars);
+  if (quantifying && temp1 == BDD_ONE(bddm))
+    result=temp1;
+  else
+    {
+      temp2=cmu_bdd_exists_step(bddm, BDD_ELSE(f), op, vars);
+      if (quantifying)
+	{
+	  BDD_SETUP(temp1);
+	  BDD_SETUP(temp2);
+	  bddm->op_cache.cache_level++;
+	  result=cmu_bdd_ite_step(bddm, temp1, BDD_ONE(bddm), temp2);
+	  BDD_TEMP_DECREFS(temp1);
+	  BDD_TEMP_DECREFS(temp2);
+	  bddm->op_cache.cache_level--;
+	}
+      else
+	result=bdd_find(bddm, BDD_INDEXINDEX(f), temp1, temp2);
+    }
+  bdd_insert_in_cache1(bddm, op, f, result);
+  return (result);
+}
+
+
+/* cmu_bdd_exists_temp is used internally by cmu_bdd_rel_prod. */
+
+bdd
+cmu_bdd_exists_temp(cmu_bdd_manager bddm, bdd f, long op)
+{
+  if (bddm->curr_assoc_id != -1)
+    op=OP_QNT+bddm->curr_assoc_id;
+  return (cmu_bdd_exists_step(bddm, f, op, bddm->curr_assoc));
+}
+
+
+/* cmu_bdd_exists(bddm, f) returns the BDD for existentially quantifying */
+/* out in f all variables which are associated with something in the */
+/* current variable association. */
+
+bdd
+cmu_bdd_exists(cmu_bdd_manager bddm, bdd f)
+{
+  long op;
+
+  if (bdd_check_arguments(1, f))
+    {
+      FIREWALL(bddm);
+      if (bddm->curr_assoc_id == -1)
+	op=bddm->temp_op--;
+      else
+	op=OP_QNT+bddm->curr_assoc_id;
+      RETURN_BDD(cmu_bdd_exists_step(bddm, f, op, bddm->curr_assoc));
+    }
+  return ((bdd)0);
+}
+
+
+/* cmu_bdd_forall(bddm, f) returns the BDD for universally quantifying */
+/* out in f all variables which are associated with something in the */
+/* current variable association. */
+
+bdd
+cmu_bdd_forall(cmu_bdd_manager bddm, bdd f)
+{
+  bdd temp;
+
+  if ((temp=cmu_bdd_exists(bddm, BDD_NOT(f))))
+    return (BDD_NOT(temp));
+  return ((bdd)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddreduce.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddreduce.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddreduce.c	(revision 8)
@@ -0,0 +1,141 @@
+/* BDD reduce routines */
+
+
+#include "bddint.h"
+
+
+static
+bdd
+cmu_bdd_reduce_step(cmu_bdd_manager bddm, bdd f, bdd c)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd c1, c2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(c);
+  if (BDD_IS_CONST(c))
+    {
+      if (c == BDD_ZERO(bddm))
+	return ((bdd)0);
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (BDD_IS_CONST(f))
+    return (f);
+  if (bdd_lookup_in_cache2(bddm, OP_RED, f, c, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, c);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, c, c1, c2);
+  if (f == f1)
+    {
+      bddm->op_cache.cache_level++;
+      temp1=cmu_bdd_ite_step(bddm, c1, BDD_ONE(bddm), c2);
+      bddm->op_cache.cache_level--;
+      result=cmu_bdd_reduce_step(bddm, f, temp1);
+      {
+	BDD_SETUP(temp1);
+	BDD_TEMP_DECREFS(temp1);
+      }
+    }
+  else
+    {
+      temp1=cmu_bdd_reduce_step(bddm, f1, c1);
+      temp2=cmu_bdd_reduce_step(bddm, f2, c2);
+      if (!temp1)
+	result=temp2;
+      else if (!temp2)
+	result=temp1;
+      else
+	result=bdd_find(bddm, top_indexindex, temp1, temp2);
+    }
+  bdd_insert_in_cache2(bddm, OP_RED, f, c, result);
+  return (result);
+}
+
+
+/* cmu_bdd_reduce(bddm, f, c) returns a BDD which agrees with f for all */
+/* valuations for which c is true, and which is hopefully smaller than */
+/* f. */
+
+bdd
+cmu_bdd_reduce(cmu_bdd_manager bddm, bdd f, bdd c)
+{
+  bdd result;
+
+  if (bdd_check_arguments(2, f, c))
+    {
+      FIREWALL(bddm);
+      result=cmu_bdd_reduce_step(bddm, f, c);
+      if (!result)
+	return (BDD_ZERO(bddm));
+      RETURN_BDD(result);
+    }
+  return ((bdd)0);
+}
+
+
+static
+bdd
+cmu_bdd_cofactor_step(cmu_bdd_manager bddm, bdd f, bdd c)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd c1, c2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(c);
+  if (BDD_IS_CONST(c))
+    {
+      if (c == BDD_ZERO(bddm))
+	return ((bdd)0);
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (BDD_IS_CONST(f))
+    return (f);
+  if (bdd_lookup_in_cache2(bddm, OP_COFACTOR, f, c, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, c);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, c, c1, c2);
+  temp1=cmu_bdd_cofactor_step(bddm, f1, c1);
+  temp2=cmu_bdd_cofactor_step(bddm, f2, c2);
+  if (!temp1)
+    result=temp2;
+  else if (!temp2)
+    result=temp1;
+  else
+    result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache2(bddm, OP_COFACTOR, f, c, result);
+  return (result);
+}
+
+
+/* cmu_bdd_cofactor(bddm, f, c) returns a BDD for the generalized cofactor */
+/* of f by c.  This operation has the useful property that if */
+/* [f1, ..., fn] is a function vector and fi|c denotes the g.c. of fi */
+/* by c, then the image of [f1|c, ..., fn|c] over all valuations is */
+/* the same as the image of [f1, ..., fn] over the valuations for */
+/* which c is true. */
+
+bdd
+cmu_bdd_cofactor(cmu_bdd_manager bddm, bdd f, bdd c)
+{
+  if (bdd_check_arguments(2, f, c))
+    {
+      if (c == BDD_ZERO(bddm))
+	{
+	  cmu_bdd_warning("cmu_bdd_cofactor: second argument is false");
+	  return (BDD_ONE(bddm));
+	}
+      FIREWALL(bddm);
+      RETURN_BDD(cmu_bdd_cofactor_step(bddm, f, c));
+    }
+  return ((bdd)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddrelprod.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddrelprod.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddrelprod.c	(revision 8)
@@ -0,0 +1,90 @@
+/* BDD relational product routine */
+
+
+#include "bddint.h"
+
+
+static
+bdd
+cmu_bdd_rel_prod_step(cmu_bdd_manager bddm, bdd f, bdd g, long op, var_assoc vars)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+  int quantifying;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (BDD_IS_CONST(f) || BDD_IS_CONST(g))
+    {
+      if (f == BDD_ZERO(bddm) || g == BDD_ZERO(bddm))
+	return (BDD_ZERO(bddm));
+      if (f == BDD_ONE(bddm))
+	return (cmu_bdd_exists_temp(bddm, g, op-1));
+      return (cmu_bdd_exists_temp(bddm, f, op-1));
+    }
+  if ((long)BDD_INDEX(bddm, f) > vars->last && (long)BDD_INDEX(bddm, g) > vars->last)
+    return (cmu_bdd_ite_step(bddm, f, g, BDD_ZERO(bddm)));
+  /* Put in canonical order. */
+  if (BDD_OUT_OF_ORDER(f, g))
+    BDD_SWAP(f, g);
+  if (bdd_lookup_in_cache2(bddm, op, f, g, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  quantifying=(vars->assoc[top_indexindex] != 0);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=cmu_bdd_rel_prod_step(bddm, f1, g1, op, vars);
+  if (quantifying && temp1 == BDD_ONE(bddm))
+    result=temp1;
+  else
+    {
+      temp2=cmu_bdd_rel_prod_step(bddm, f2, g2, op, vars);
+      if (quantifying)
+	{
+	  BDD_SETUP(temp1);
+	  BDD_SETUP(temp2);
+	  bddm->op_cache.cache_level++;
+	  result=cmu_bdd_ite_step(bddm, temp1, BDD_ONE(bddm), temp2);
+	  BDD_TEMP_DECREFS(temp1);
+	  BDD_TEMP_DECREFS(temp2);
+	  bddm->op_cache.cache_level--;
+	}
+      else
+	result=bdd_find(bddm, top_indexindex, temp1, temp2);
+    }
+  bdd_insert_in_cache2(bddm, op, f, g, result);
+  return (result);
+}
+
+
+/* cmu_bdd_rel_prod(bddm, f, g) returns the BDD for "f and g" with those */
+/* variables which are associated with something in the current */
+/* variable association quantified out. */
+
+bdd
+cmu_bdd_rel_prod(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  long op;
+
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      if (bddm->curr_assoc_id == -1)
+	{
+	  op=bddm->temp_op--;
+	  /* We decrement the temporary opcode once more because */
+	  /* cmu_bdd_rel_prod may call cmu_bdd_exists_temp, and we don't */
+	  /* want to generate new temporary opcodes for each such */
+	  /* call.  Instead, we pass op-1 to cmu_bdd_exists_temp, and */
+	  /* have it use this opcode for caching. */
+	  bddm->temp_op--;
+	}
+      else
+	op=OP_RELPROD+bddm->curr_assoc_id;
+      RETURN_BDD(cmu_bdd_rel_prod_step(bddm, f, g, op, bddm->curr_assoc));
+    }
+  return ((bdd)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddreorder.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddreorder.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddreorder.c	(revision 8)
@@ -0,0 +1,700 @@
+/* BDD dynamic reordering stuff */
+
+
+#include "bddint.h"
+
+
+static
+void
+increfs(bdd f)
+{
+  bdd g;
+
+  BDD_SETUP(f);
+  BDD_INCREFS(f);
+  if (BDD_REFS(f) == 1 && !BDD_TEMP_REFS(f))
+    {
+      g=(bdd)BDD_DATA0(f);
+      {
+	BDD_SETUP(g);
+	BDD_INCREFS(g);
+      }
+      g=(bdd)BDD_DATA1(f);
+      {
+	BDD_SETUP(g);
+	BDD_INCREFS(g);
+      }
+    }
+}
+
+
+static
+void
+decrefs(bdd f)
+{
+  bdd g;
+
+  BDD_SETUP(f);
+  BDD_DECREFS(f);
+  if (!BDD_REFS(f) && !BDD_TEMP_REFS(f))
+    {
+      g=(bdd)BDD_DATA0(f);
+      {
+	BDD_SETUP(g);
+	BDD_DECREFS(g);
+      }
+      g=(bdd)BDD_DATA1(f);
+      {
+	BDD_SETUP(g);
+	BDD_DECREFS(g);
+      }
+    }
+}
+
+
+static
+void
+bdd_exchange_aux(cmu_bdd_manager bddm, bdd f, bdd_indexindex_type next_indexindex)
+{
+  bdd f1, f2;
+  bdd f11, f12, f21, f22;
+  bdd temp1, temp2;
+
+  BDD_SETUP(f);
+  f1=BDD_THEN(f);
+  f2=BDD_ELSE(f);
+  {
+    BDD_SETUP(f1);
+    BDD_SETUP(f2);
+    if (BDD_INDEXINDEX(f1) == next_indexindex)
+      {
+	f11=BDD_THEN(f1);
+	f12=BDD_ELSE(f1);
+      }
+    else
+      {
+	f11=f1;
+	f12=f1;
+      }
+    if (BDD_INDEXINDEX(f2) == next_indexindex)
+      {
+	f21=BDD_THEN(f2);
+	f22=BDD_ELSE(f2);
+      }
+    else
+      {
+	f21=f2;
+	f22=f2;
+      }
+    if (f11 == f21)
+      temp1=f11;
+    else
+      temp1=bdd_find_aux(bddm, BDD_INDEXINDEX(f), (INT_PTR)f11, (INT_PTR)f21);
+    if (f12 == f22)
+      temp2=f12;
+    else if (BDD_IS_OUTPOS(f12))
+      temp2=bdd_find_aux(bddm, BDD_INDEXINDEX(f), (INT_PTR)f12, (INT_PTR)f22);
+    else
+      temp2=BDD_NOT(bdd_find_aux(bddm, BDD_INDEXINDEX(f), (INT_PTR)BDD_NOT(f12), (INT_PTR)BDD_NOT(f22)));
+    BDD_INDEXINDEX(f)=next_indexindex;
+    BDD_DATA0(f)=(INT_PTR)temp1;
+    BDD_DATA1(f)=(INT_PTR)temp2;
+    if (BDD_REFS(f) || BDD_TEMP_REFS(f))
+      {
+	increfs(temp1);
+	increfs(temp2);
+	decrefs(f1);
+	decrefs(f2);
+      }
+    else
+      cmu_bdd_fatal("bdd_exchange_aux: how did this happen?");
+  }
+}
+
+
+static
+void
+fixup_assoc(cmu_bdd_manager bddm, long indexindex1, long indexindex2, var_assoc va)
+{
+  /* Variable with indexindex1 is moving down a spot. */
+  if (va->assoc[indexindex1] && va->last == bddm->indexes[indexindex1])
+    va->last++;
+  else if (!va->assoc[indexindex1] && va->assoc[indexindex2] && va->last == bddm->indexes[indexindex2])
+    va->last--;
+}
+
+
+static
+void
+sweep_var_table(cmu_bdd_manager bddm, long i)
+{
+  long j;
+  var_table table;
+  bdd f, *p;
+
+  table=bddm->unique_table.tables[i];
+  for (j=0; j < table->size; ++j)
+    for (p= &table->table[j], f= *p; f; f= *p)
+      {
+	BDD_SETUP(f);
+	if (BDD_REFS(f) || BDD_TEMP_REFS(f))
+	  p= &f->next;
+	else
+	  {
+	    *p=f->next;
+	    BDD_FREE_REC(bddm, (pointer)f, sizeof(struct bdd_));
+	    table->entries--;
+	    bddm->unique_table.entries--;
+	    bddm->unique_table.freed++;
+	  }
+      }
+}
+
+
+static
+void
+bdd_exchange(cmu_bdd_manager bddm, long i)
+{
+  bdd_indexindex_type next_indexindex;
+  var_table table, next_table;
+  long j;
+  bdd f, *p;
+  bdd f1, f2;
+  bdd g;
+  long hash;
+  bdd_index_type temp;
+  assoc_list q;
+
+  next_indexindex=bddm->indexindexes[bddm->indexes[i]+1];
+  table=bddm->unique_table.tables[i];
+  next_table=bddm->unique_table.tables[next_indexindex];
+  g=0;
+  for (j=0; j < table->size; ++j)
+    for (p= &table->table[j], f= *p; f; f= *p)
+      {
+	BDD_SETUP(f);
+	if (BDD_REFS(f) || BDD_TEMP_REFS(f))
+	  {
+	    f1=(bdd)BDD_DATA0(f);
+	    f2=(bdd)BDD_DATA1(f);
+	    {
+	      BDD_SETUP(f1);
+	      BDD_SETUP(f2);
+	      if (BDD_INDEXINDEX(f1) != next_indexindex && BDD_INDEXINDEX(f2) != next_indexindex)
+		p= &f->next;
+	      else
+		{
+		  *p=f->next;
+		  f->next=g;
+		  g=f;
+		}
+	    }
+	  }
+	else
+	  {
+	    *p=f->next;
+	    BDD_FREE_REC(bddm, (pointer)f, sizeof(struct bdd_));
+	    table->entries--;
+	    bddm->unique_table.entries--;
+	    bddm->unique_table.freed++;
+	  }
+      }
+  for (f=g; f; f=g)
+    {
+      bdd_exchange_aux(bddm, f, next_indexindex);
+      g=f->next;
+      hash=HASH_NODE(f->data[0], f->data[1]);
+      BDD_REDUCE(hash, next_table->size);
+      f->next=next_table->table[hash];
+      next_table->table[hash]=f;
+      table->entries--;
+      next_table->entries++;
+      if (4*next_table->size < next_table->entries)
+	bdd_rehash_var_table(next_table, 1);
+    }
+  fixup_assoc(bddm, i, next_indexindex, &bddm->temp_assoc);
+  for (q=bddm->assocs; q; q=q->next)
+    fixup_assoc(bddm, i, next_indexindex, &q->va);
+  sweep_var_table(bddm, next_indexindex);
+  temp=bddm->indexes[i];
+  bddm->indexes[i]=bddm->indexes[next_indexindex];
+  bddm->indexes[next_indexindex]=temp;
+  bddm->indexindexes[temp]=next_indexindex;
+  bddm->indexindexes[bddm->indexes[i]]=i;
+}
+
+
+void
+cmu_bdd_var_block_reorderable(cmu_bdd_manager bddm, block b, int reorderable)
+{
+  b->reorderable=reorderable;
+}
+
+
+static
+void
+bdd_exchange_var_blocks(cmu_bdd_manager bddm, block parent, long bi)
+{
+  block b1, b2;
+  long i, j, k, l;
+  long delta;
+  block temp;
+
+  b1=parent->children[bi];
+  b2=parent->children[bi+1];
+  /* This slides the blocks past each other in a kind of interleaving */
+  /* fashion. */
+  for (i=0; i <= b1->last_index-b1->first_index+b2->last_index-b2->first_index; ++i)
+    {
+      j=i-b1->last_index+b1->first_index;
+      if (j < 0)
+	j=0;
+      k=i;
+      if (k > b2->last_index-b2->first_index)
+	k=b2->last_index-b2->first_index;
+      while (j <= k)
+	{
+	  l=b2->first_index+j-i+j;
+	  bdd_exchange(bddm, bddm->indexindexes[l-1]);
+	  ++j;
+	}
+    }
+  delta=b2->last_index-b2->first_index+1;
+  bdd_block_delta(b1, delta);
+  delta=b1->last_index-b1->first_index+1;
+  bdd_block_delta(b2, -delta);
+  temp=parent->children[bi];
+  parent->children[bi]=parent->children[bi+1];
+  parent->children[bi+1]=temp;
+}
+
+
+static
+int
+cmu_bdd_reorder_window2(cmu_bdd_manager bddm, block b, long i)
+{
+  long size, best_size;
+
+  /* 1 2 */
+  best_size=bddm->unique_table.entries;
+  bdd_exchange_var_blocks(bddm, b, i);
+  /* 2 1 */
+  size=bddm->unique_table.entries;
+  if (size < best_size)
+    return (1);
+  bdd_exchange_var_blocks(bddm, b, i);
+  return (0);
+}
+
+
+static
+int
+cmu_bdd_reorder_window3(cmu_bdd_manager bddm, block b, long i)
+{
+  int best;
+  long size, best_size;
+
+  best=0;
+  /* 1 2 3 */
+  best_size=bddm->unique_table.entries;
+  bdd_exchange_var_blocks(bddm, b, i);
+  /* 2 1 3 */
+  size=bddm->unique_table.entries;
+  if (size < best_size)
+    {
+      best=1;
+      best_size=size;
+    }
+  bdd_exchange_var_blocks(bddm, b, i+1);
+  /* 2 3 1 */
+  size=bddm->unique_table.entries;
+  if (size < best_size)
+    {
+      best=2;
+      best_size=size;
+    }
+  bdd_exchange_var_blocks(bddm, b, i);
+  /* 3 2 1 */
+  size=bddm->unique_table.entries;
+  if (size < best_size)
+    {
+      best=3;
+      best_size=size;
+    }
+  bdd_exchange_var_blocks(bddm, b, i+1);
+  /* 3 1 2 */
+  size=bddm->unique_table.entries;
+  if (size < best_size)
+    {
+      best=4;
+      best_size=size;
+    }
+  bdd_exchange_var_blocks(bddm, b, i);
+  /* 1 3 2 */
+  size=bddm->unique_table.entries;
+  if (size < best_size)
+    {
+      best=5;
+      best_size=size;
+    }
+  switch (best)
+    {
+    case 0:
+      bdd_exchange_var_blocks(bddm, b, i+1);
+      break;
+    case 1:
+      bdd_exchange_var_blocks(bddm, b, i+1);
+      bdd_exchange_var_blocks(bddm, b, i);
+      break;
+    case 2:
+      bdd_exchange_var_blocks(bddm, b, i+1);
+      bdd_exchange_var_blocks(bddm, b, i);
+      bdd_exchange_var_blocks(bddm, b, i+1);
+      break;
+    case 3:
+      bdd_exchange_var_blocks(bddm, b, i);
+      bdd_exchange_var_blocks(bddm, b, i+1);
+      break;
+    case 4:
+      bdd_exchange_var_blocks(bddm, b, i);
+      break;
+    case 5:
+      break;
+    }
+  return (best > 0);
+}
+
+
+static
+void
+cmu_bdd_reorder_stable_window3_aux(cmu_bdd_manager bddm, block b, char *levels)
+{
+  long i;
+  int moved;
+  int any_swapped;
+
+  if (b->reorderable)
+    {
+      for (i=0; i < b->num_children-1; ++i)
+	levels[i]=1;
+      do
+	{
+	  any_swapped=0;
+	  for (i=0; i < b->num_children-1; ++i)
+	    if (levels[i])
+	      {
+		if (i < b->num_children-2)
+		  moved=cmu_bdd_reorder_window3(bddm, b, i);
+		else
+		  moved=cmu_bdd_reorder_window2(bddm, b, i);
+		if (moved)
+		  {
+		    if (i > 0)
+		      {
+			levels[i-1]=1;
+			if (i > 1)
+			  levels[i-2]=1;
+		      }
+		    levels[i]=1;
+		    levels[i+1]=1;
+		    if (i < b->num_children-2)
+		      {
+			levels[i+2]=1;
+			if (i < b->num_children-3)
+			  {
+			    levels[i+3]=1;
+			    if (i < b->num_children-4)
+			      levels[i+4]=1;
+			  }
+		      }
+		    any_swapped=1;
+		  }
+		else
+		  levels[i]=0;
+	      }
+	}
+      while (any_swapped);
+    }
+  for (i=0; i < b->num_children; ++i)
+    cmu_bdd_reorder_stable_window3_aux(bddm, b->children[i], levels);
+}
+
+
+void
+cmu_bdd_reorder_stable_window3(cmu_bdd_manager bddm)
+{
+  char *levels;
+
+  levels=(char *)mem_get_block(bddm->vars*sizeof(char));
+  cmu_bdd_reorder_stable_window3_aux(bddm, bddm->super_block, levels);
+  mem_free_block((pointer)levels);
+}
+
+
+static
+void
+bdd_sift_block(cmu_bdd_manager bddm, block b, long start_pos, double max_size_factor)
+{
+  long start_size;
+  long best_size;
+  long best_pos;
+  long curr_size;
+  long curr_pos;
+  long max_size;
+
+  start_size=bddm->unique_table.entries;
+  best_size=start_size;
+  best_pos=start_pos;
+  curr_size=start_size;
+  curr_pos=start_pos;
+  max_size=max_size_factor*start_size;
+  if (bddm->unique_table.node_limit && max_size > bddm->unique_table.node_limit)
+    max_size=bddm->unique_table.node_limit;
+  while (curr_pos < b->num_children-1 && curr_size <= max_size)
+    {
+      bdd_exchange_var_blocks(bddm, b, curr_pos);
+      ++curr_pos;
+      curr_size=bddm->unique_table.entries;
+      if (curr_size < best_size)
+	{
+	  best_size=curr_size;
+	  best_pos=curr_pos;
+	}
+    }
+  while (curr_pos != start_pos)
+    {
+      --curr_pos;
+      bdd_exchange_var_blocks(bddm, b, curr_pos);
+    }
+  curr_size=start_size;
+  while (curr_pos && curr_size <= max_size)
+    {
+      --curr_pos;
+      bdd_exchange_var_blocks(bddm, b, curr_pos);
+      curr_size=bddm->unique_table.entries;
+      if (curr_size < best_size)
+	{
+	  best_size=curr_size;
+	  best_pos=curr_pos;
+	}
+    }
+  while (curr_pos != best_pos)
+    {
+      bdd_exchange_var_blocks(bddm, b, curr_pos);
+      ++curr_pos;
+    }
+}
+
+
+static
+void
+cmu_bdd_reorder_sift_aux(cmu_bdd_manager bddm, block b, block *to_sift, double max_size_factor)
+{
+  long i, j, k;
+  long w;
+  long max_w;
+  long widest;
+
+  if (b->reorderable)
+    {
+      for (i=0; i < b->num_children; ++i)
+	to_sift[i]=b->children[i];
+      while (i)
+	{
+	  --i;
+	  max_w=0;
+	  widest=0;
+	  for (j=0; j <= i; ++j)
+	    {
+	      for (w=0, k=to_sift[j]->first_index; k <= to_sift[j]->last_index; ++k)
+		w+=bddm->unique_table.tables[bddm->indexindexes[k]]->entries;
+	      w/=to_sift[j]->last_index-to_sift[j]->first_index+1;
+	      if (w > max_w)
+		{
+		  max_w=w;
+		  widest=j;
+		}
+	    }
+	  if (max_w > 1)
+	    {
+	      for (j=0; b->children[j] != to_sift[widest]; ++j);
+	      bdd_sift_block(bddm, b, j, max_size_factor);
+	      to_sift[widest]=to_sift[i];
+	    }
+	  else
+	    break;
+	}
+    }
+  for (i=0; i < b->num_children; ++i)
+    cmu_bdd_reorder_sift_aux(bddm, b->children[i], to_sift, max_size_factor);
+}
+
+
+static
+void
+cmu_bdd_reorder_sift_aux1(cmu_bdd_manager bddm, double max_size_factor)
+{
+  block *to_sift;
+
+  to_sift=(block *)mem_get_block(bddm->vars*sizeof(block));
+  cmu_bdd_reorder_sift_aux(bddm, bddm->super_block, to_sift, max_size_factor);
+  mem_free_block((pointer)to_sift);
+}
+
+
+void
+cmu_bdd_reorder_sift(cmu_bdd_manager bddm)
+{
+  cmu_bdd_reorder_sift_aux1(bddm, 2.0);
+}
+
+
+void
+cmu_bdd_reorder_hybrid(cmu_bdd_manager bddm)
+{
+  long nodes;
+  double max_size_factor;
+
+  nodes=bddm->unique_table.entries;
+  max_size_factor= *(double *)bddm->reorder_data;
+  if (max_size_factor > 2.0 || nodes < 10000)
+    max_size_factor=2.0;
+  cmu_bdd_reorder_sift_aux1(bddm, max_size_factor);
+  *(double *)bddm->reorder_data=1.0+(2.0*(nodes-bddm->unique_table.entries))/nodes;
+}
+
+
+/* cmu_bdd_dynamic_reordering(bddm, reorder_fn) sets the dynamic reordering */
+/* method to that specified by reorder_fn. */
+
+void
+cmu_bdd_dynamic_reordering(cmu_bdd_manager bddm, void (*reorder_fn)(cmu_bdd_manager))
+{
+  bddm->reorder_fn=reorder_fn;
+  if (bddm->reorder_data)
+    mem_free_block(bddm->reorder_data);
+  bddm->reorder_data=0;
+  if (reorder_fn == cmu_bdd_reorder_hybrid)
+    {
+      bddm->reorder_data=mem_get_block((SIZE_T)sizeof(double));
+      *(double *)bddm->reorder_data=2.0;
+    }
+}
+
+
+static
+void
+bdd_add_internal_references(cmu_bdd_manager bddm)
+{
+  long i, j;
+  var_table table;
+  bdd *f, g, h;
+
+  for (i=0; i <= bddm->vars; ++i)
+    {
+      if (i == bddm->vars)
+	table=bddm->unique_table.tables[BDD_CONST_INDEXINDEX];
+      else
+	table=bddm->unique_table.tables[bddm->indexindexes[i]];
+      for (j=0; j < table->size; ++j)
+	{
+	  f= &table->table[j];
+	  while ((g= *f))
+	    {
+	      BDD_SETUP(g);
+	      if (BDD_REFS(g) || BDD_TEMP_REFS(g))
+		{
+		  if (!BDD_IS_CONST(g))
+		    {
+		      h=(bdd)BDD_DATA0(g);
+		      {
+			BDD_SETUP(h);
+			BDD_INCREFS(h);
+		      }
+		      h=(bdd)BDD_DATA1(g);
+		      {
+			BDD_SETUP(h);
+			BDD_INCREFS(h);
+		      }
+		    }
+		  f= &g->next;
+		}
+	      else
+		{
+		  *f=g->next;
+		  if (i == bddm->vars && bddm->unique_table.free_terminal_fn)
+		    (*bddm->unique_table.free_terminal_fn)(bddm,
+							   BDD_DATA0(g),
+							   BDD_DATA1(g),
+							   bddm->unique_table.free_terminal_env);
+		  BDD_FREE_REC(bddm, (pointer)g, sizeof(struct bdd_));
+		  table->entries--;
+		  bddm->unique_table.entries--;
+		  bddm->unique_table.freed++;
+		}
+	    }
+	}
+    }
+}
+
+
+static
+void
+bdd_nuke_internal_references(cmu_bdd_manager bddm)
+{
+  long i, j;
+  var_table table;
+  bdd *f, g, h;
+
+  for (i=bddm->vars-1; i >= 0; --i)
+    {
+      table=bddm->unique_table.tables[bddm->indexindexes[i]];
+      for (j=0; j < table->size; ++j)
+	{
+	  f= &table->table[j];
+	  while ((g= *f))
+	    {
+	      BDD_SETUP(g);
+	      if (BDD_REFS(g) || BDD_TEMP_REFS(g))
+		{
+		  h=(bdd)BDD_DATA0(g);
+		  {
+		    BDD_SETUP(h);
+		    BDD_DECREFS(h);
+		  }
+		  h=(bdd)BDD_DATA1(g);
+		  {
+		    BDD_SETUP(h);
+		    BDD_DECREFS(h);
+		  }
+		  f= &g->next;
+		}
+	      else
+		cmu_bdd_fatal("bdd_nuke_internal_references: what happened?");
+	    }
+	}
+    }
+}
+
+
+void
+cmu_bdd_reorder_aux(cmu_bdd_manager bddm)
+{
+  if (bddm->reorder_fn)
+    {
+      bdd_flush_all(bddm);
+      bdd_add_internal_references(bddm);
+      (*bddm->reorder_fn)(bddm);
+      bdd_nuke_internal_references(bddm);
+    }
+}
+
+
+/* cmu_bdd_reorder(bddm) invokes the current dynamic reordering method. */
+
+void
+cmu_bdd_reorder(cmu_bdd_manager bddm)
+{
+  cmu_bdd_gc(bddm);
+  cmu_bdd_reorder_aux(bddm);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddsat.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddsat.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddsat.c	(revision 8)
@@ -0,0 +1,196 @@
+/* BDD satisfying valuation routines */
+
+
+#include "bddint.h"
+
+#ifdef STDC_HEADERS
+#  include <stdlib.h>
+#else
+extern void qsort(pointer, unsigned long, unsigned long, int (*)(const void *, const void *));
+#endif
+
+static
+bdd
+cmu_bdd_satisfy_step(cmu_bdd_manager bddm, bdd f)
+{
+  bdd temp;
+  bdd result;
+
+  BDD_SETUP(f);
+  if (BDD_IS_CONST(f))
+    return (f);
+  if (BDD_THEN(f) == BDD_ZERO(bddm))
+    {
+      temp=cmu_bdd_satisfy_step(bddm, BDD_ELSE(f));
+      result=bdd_find(bddm, BDD_INDEXINDEX(f), BDD_ZERO(bddm), temp);
+    }
+  else
+    {
+      temp=cmu_bdd_satisfy_step(bddm, BDD_THEN(f));
+      result=bdd_find(bddm, BDD_INDEXINDEX(f), temp, BDD_ZERO(bddm));
+    }
+  return (result);
+}
+
+
+/* cmu_bdd_satisfy(bddm, f) returns a BDD which implies f, is true for */
+/* some valuation on which f is true, and which has at most one node */
+/* at each level. */
+
+bdd
+cmu_bdd_satisfy(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      if (f == BDD_ZERO(bddm))
+	{
+	  cmu_bdd_warning("cmu_bdd_satisfy: argument is false");
+	  return (f);
+	}
+      FIREWALL(bddm);
+      RETURN_BDD(cmu_bdd_satisfy_step(bddm, f));
+    }
+  return ((bdd)0);
+}
+
+
+static
+bdd
+cmu_bdd_satisfy_support_step(cmu_bdd_manager bddm, bdd f, bdd_indexindex_type *support)
+{
+  bdd temp;
+  bdd result;
+
+  BDD_SETUP(f);
+  if (!*support)
+    return (cmu_bdd_satisfy_step(bddm, f));
+  if (BDD_INDEX(bddm, f) <= bddm->indexes[*support])
+    {
+      if (BDD_INDEXINDEX(f) == *support)
+	++support;
+      if (BDD_THEN(f) == BDD_ZERO(bddm))
+	{
+	  temp=cmu_bdd_satisfy_support_step(bddm, BDD_ELSE(f), support);
+	  result=bdd_find(bddm, BDD_INDEXINDEX(f), BDD_ZERO(bddm), temp);
+	}
+      else
+	{
+	  temp=cmu_bdd_satisfy_support_step(bddm, BDD_THEN(f), support);
+	  result=bdd_find(bddm, BDD_INDEXINDEX(f), temp, BDD_ZERO(bddm));
+	}
+    }
+  else
+    {
+      temp=cmu_bdd_satisfy_support_step(bddm, f, support+1);
+      result=bdd_find(bddm, *support, BDD_ZERO(bddm), temp);
+    }
+  return (result);
+}
+
+
+static
+int
+index_cmp(pointer p1, pointer p2)
+{
+  bdd_index_type i1, i2;
+
+  i1= *(bdd_indexindex_type *)p1;
+  i2= *(bdd_indexindex_type *)p2;
+  if (i1 < i2)
+    return (-1);
+  if (i1 > i2)
+    return (1);
+  return (0);
+}
+
+
+/* cmu_bdd_satisfy_support(bddm, f) returns a BDD which implies f, is true */
+/* for some valuation on which f is true, which has at most one node */
+/* at each level, and which has exactly one node corresponding to each */
+/* variable which is associated with something in the current variable */
+/* association. */
+
+bdd
+cmu_bdd_satisfy_support(cmu_bdd_manager bddm, bdd f)
+{
+  bdd_indexindex_type *support, *p;
+  long i;
+  bdd result;
+
+  if (bdd_check_arguments(1, f))
+    {
+      if (f == BDD_ZERO(bddm))
+	{
+	  cmu_bdd_warning("cmu_bdd_satisfy_support: argument is false");
+	  return (f);
+	}
+      support=(bdd_indexindex_type *)mem_get_block((bddm->vars+1)*sizeof(bdd));
+      FIREWALL1(bddm,
+		if (retcode == BDD_ABORTED || retcode == BDD_OVERFLOWED)
+		  {
+		    mem_free_block((pointer)support);
+		    return ((bdd)0);
+		  }
+		);
+      for (i=0, p=support; i < bddm->vars; ++i)
+	if (bddm->curr_assoc->assoc[i+1])
+	  {
+	    *p=bddm->indexes[i+1];
+	    ++p;
+	  }
+      *p=0;
+      qsort((pointer)support, (unsigned)(p-support),
+	    sizeof(bdd_indexindex_type),
+	    (int (*)(const void *, const void *))index_cmp);
+      while (p != support)
+	{
+	  --p;
+	  *p=bddm->indexindexes[*p];
+	}
+      result=cmu_bdd_satisfy_support_step(bddm, f, support);
+      mem_free_block((pointer)support);
+      RETURN_BDD(result);
+    }
+  return ((bdd)0);
+}
+
+
+double
+cmu_bdd_satisfying_fraction_step(cmu_bdd_manager bddm, bdd f)
+{
+  union {
+    long cache_result[2];
+    double result;
+  } u;
+
+  BDD_SETUP(f);
+  if (BDD_IS_CONST(f))
+    {
+      if (f == BDD_ZERO(bddm))
+	return (0.0);
+      return (1.0);
+    }
+  if (bdd_lookup_in_cache1d(bddm, OP_SATFRAC, f,
+			    &(u.cache_result[0]), &(u.cache_result[1])))
+    {
+      return (u.result);
+    }
+  u.result=0.5*cmu_bdd_satisfying_fraction_step(bddm, BDD_THEN(f))+
+    0.5*cmu_bdd_satisfying_fraction_step(bddm, BDD_ELSE(f));
+  bdd_insert_in_cache1d(bddm, OP_SATFRAC, f, u.cache_result[0],
+			u.cache_result[1]);
+  return (u.result);
+}
+
+
+/* cmu_bdd_satisfying_fraction(bddm, f) returns the fraction of valuations */
+/* which make f true.  (Note that this fraction is independent of */
+/* whatever set of variables f is supposed to be a function of.) */
+
+double
+cmu_bdd_satisfying_fraction(cmu_bdd_manager bddm, bdd f)
+{
+  if (bdd_check_arguments(1, f))
+    return (cmu_bdd_satisfying_fraction_step(bddm, f));
+  return (0.0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddsize.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddsize.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddsize.c	(revision 8)
@@ -0,0 +1,345 @@
+/* BDD size and profile routines */
+
+
+#include "bddint.h"
+
+
+static
+void
+bdd_mark_bdd(bdd f)
+{
+  int curr_marking, this_marking;
+
+  BDD_SETUP(f);
+  curr_marking=BDD_MARK(f);
+  this_marking=(1 << TAG(f));
+  if (curr_marking & this_marking)
+    return;
+  BDD_MARK(f)=curr_marking | this_marking;
+  if (BDD_IS_CONST(f))
+    return;
+  bdd_mark_bdd(BDD_THEN(f));
+  bdd_mark_bdd(BDD_ELSE(f));
+}
+
+
+static
+int
+bdd_count_no_nodes(bdd f)
+{
+  BDD_SETUP(f);
+  return (BDD_MARK(f) > 0);
+}
+
+
+static
+int
+bdd_count_nodes(bdd f)
+{
+  int mark;
+
+  BDD_SETUP(f);
+  mark=BDD_MARK(f);
+  return (((mark & 0x1) != 0)+((mark & 0x2) != 0));
+}
+
+
+static
+int (*(counting_fns[]))(bdd)=
+{
+  bdd_count_no_nodes,
+  bdd_count_nodes,
+};
+
+
+static
+long
+cmu_bdd_size_step(bdd f, int (*count_fn)(bdd))
+{
+  long result;
+
+  BDD_SETUP(f);
+  if (!BDD_MARK(f))
+    return (0l);
+  result=(*count_fn)(f);
+  if (!BDD_IS_CONST(f))
+    result+=cmu_bdd_size_step(BDD_THEN(f), count_fn)+cmu_bdd_size_step(BDD_ELSE(f), count_fn);
+  BDD_MARK(f)=0;
+  return (result);
+}
+
+
+/* cmu_bdd_size(bddm, f, negout) returns the number of nodes in f when */
+/* negout is nonzero.  If negout is zero, we pretend that the BDDs */
+/* don't have negative-output pointers. */
+
+long
+cmu_bdd_size(cmu_bdd_manager bddm, bdd f, int negout)
+{
+  bdd g;
+
+  if (bdd_check_arguments(1, f))
+    {
+      g=BDD_ONE(bddm);
+      {
+	BDD_SETUP(g);
+	BDD_MARK(g)=0;
+      }
+      bdd_mark_bdd(f);
+      return (cmu_bdd_size_step(f, counting_fns[!negout]));
+    }
+  return (0l);
+}
+
+
+/* cmu_bdd_size_multiple is like cmu_bdd_size, but takes a null-terminated */
+/* array of BDDs and accounts for sharing of nodes. */
+
+long
+cmu_bdd_size_multiple(cmu_bdd_manager bddm, bdd* fs, int negout)
+{
+  long size;
+  bdd *f;
+  bdd g;
+
+  bdd_check_array(fs);
+  g=BDD_ONE(bddm);
+  {
+    BDD_SETUP(g);
+    BDD_MARK(g)=0;
+  }
+  for (f=fs; *f; ++f)
+    bdd_mark_bdd(*f);
+  size=0l;
+  for (f=fs; *f; ++f)
+    size+=cmu_bdd_size_step(*f, counting_fns[!negout]);
+  return (size);
+}
+
+
+static
+void
+cmu_bdd_profile_step(cmu_bdd_manager bddm, bdd f, long *level_counts, int (*count_fn)(bdd))
+{
+  BDD_SETUP(f);
+  if (!BDD_MARK(f))
+    return;
+  if (BDD_IS_CONST(f))
+    level_counts[bddm->vars]+=(*count_fn)(f);
+  else
+    {
+      level_counts[BDD_INDEX(bddm, f)]+=(*count_fn)(f);
+      cmu_bdd_profile_step(bddm, BDD_THEN(f), level_counts, count_fn);
+      cmu_bdd_profile_step(bddm, BDD_ELSE(f), level_counts, count_fn);
+    }
+  BDD_MARK(f)=0;
+}
+
+
+/* cmu_bdd_profile(bddm, f, level_counts, negout) returns a "node profile" */
+/* of f, i.e., the number of nodes at each level in f.  negout is as in */
+/* cmu_bdd_size.  level_counts should be an array of size cmu_bdd_vars(bddm)+1 */
+/* to hold the profile. */
+
+void
+cmu_bdd_profile(cmu_bdd_manager bddm, bdd f, long *level_counts, int negout)
+{
+  bdd_index_type i;
+  bdd g;
+
+  for (i=0; i <= bddm->vars; ++i)
+    level_counts[i]=0l;
+  if (bdd_check_arguments(1, f))
+    {
+      g=BDD_ONE(bddm);
+      {
+	BDD_SETUP(g);
+	BDD_MARK(g)=0;
+      }
+      bdd_mark_bdd(f);
+      cmu_bdd_profile_step(bddm, f, level_counts, counting_fns[!negout]);
+    }
+}
+
+
+/* cmu_bdd_profile_multiple is to cmu_bdd_profile as cmu_bdd_size_multiple is to */
+/* cmu_bdd_size. */
+
+void
+cmu_bdd_profile_multiple(cmu_bdd_manager bddm, bdd *fs, long *level_counts, int negout)
+{
+  bdd_index_type i;
+  bdd *f;
+  bdd g;
+
+  bdd_check_array(fs);
+  for (i=0; i <= bddm->vars; ++i)
+    level_counts[i]=0l;
+  g=BDD_ONE(bddm);
+  {
+    BDD_SETUP(g);
+    BDD_MARK(g)=0;
+  }
+  for (f=fs; *f; ++f)
+    bdd_mark_bdd(*f);
+  for (f=fs; *f; ++f)
+    cmu_bdd_profile_step(bddm, *f, level_counts, counting_fns[!negout]);
+}
+
+
+static
+void
+bdd_highest_ref_step(cmu_bdd_manager bddm, bdd f, hash_table h)
+{
+  long *hash_result;
+  long f_index;
+
+  BDD_SETUP(f);
+  if (BDD_IS_CONST(f))
+    return;
+  f_index=BDD_INDEX(bddm, f);
+  if ((hash_result=(long *)bdd_lookup_in_hash_table(h, BDD_THEN(f))))
+    {
+      if (*hash_result > f_index)
+	*hash_result=f_index;
+    }
+  else
+    {
+      bdd_insert_in_hash_table(h, BDD_THEN(f), (pointer)&f_index);
+      bdd_highest_ref_step(bddm, BDD_THEN(f), h);
+    }
+  if ((hash_result=(long *)bdd_lookup_in_hash_table(h, BDD_ELSE(f))))
+    {
+      if (*hash_result > f_index)
+	*hash_result=f_index;
+    }
+  else
+    {
+      bdd_insert_in_hash_table(h, BDD_ELSE(f), (pointer)&f_index);
+      bdd_highest_ref_step(bddm, BDD_ELSE(f), h);
+    }
+}
+
+
+static
+void
+bdd_dominated_step(cmu_bdd_manager bddm, bdd f, long *func_counts, hash_table h)
+{
+  long *hash_result;
+
+  hash_result=(long *)bdd_lookup_in_hash_table(h, f);
+  if (*hash_result >= 0)
+    func_counts[*hash_result]-=2;
+  if (*hash_result > -2)
+    {
+      BDD_SETUP(f);
+      *hash_result= -2;
+      if (!BDD_IS_CONST(f))
+	{
+	  bdd_dominated_step(bddm, BDD_THEN(f), func_counts, h);
+	  bdd_dominated_step(bddm, BDD_ELSE(f), func_counts, h);
+	}
+    }
+}
+
+
+/* cmu_bdd_function_profile(bddm, f, func_counts) returns a "function */
+/* profile" for f.  The nth entry of the function profile array is the */
+/* number of subfunctions of f which may be obtained by restricting */
+/* the variables whose index is less than n.  An entry of zero */
+/* indicates that f is independent of the variable with the */
+/* corresponding index. */
+
+void
+cmu_bdd_function_profile(cmu_bdd_manager bddm, bdd f, long *func_counts)
+{
+  long i;
+  bdd_index_type j;
+  hash_table h;
+
+  /* The number of subfunctions obtainable by restricting the */
+  /* variables of index < n is the number of subfunctions whose top */
+  /* variable has index n plus the number of subfunctions obtainable */
+  /* by restricting the variables of index < n+1 minus the number of */
+  /* these latter subfunctions whose highest reference is by a node at */
+  /* level n. */
+  /* The strategy will be to start with the number of subfunctions */
+  /* whose top variable has index n.  We compute the highest level at */
+  /* which each subfunction is referenced.  Then we work bottom up; at */
+  /* level n we add in the result from level n+1 and subtract the */
+  /* number of subfunctions whose highest reference is at level n. */
+  cmu_bdd_profile(bddm, f, func_counts, 0);
+  if (bdd_check_arguments(1, f))
+    {
+      /* Encode the profile.  The low bit of a count will be zero for */
+      /* those levels where f actually has a node. */
+      for (j=0; j < bddm->vars; ++j)
+	if (!func_counts[j])
+	  func_counts[j]=1;
+	else
+	  func_counts[j]<<=1;
+      h=bdd_new_hash_table(bddm, sizeof(long));
+      /* For each subfunction in f, compute the highest level where it is */
+      /* referenced.  f itself is conceptually referenced at the highest */
+      /* possible level, which we represent by -1. */
+      i= -1;
+      bdd_insert_in_hash_table(h, f, (pointer)&i);
+      bdd_highest_ref_step(bddm, f, h);
+      /* Walk through these results.  For each subfunction, decrement the */
+      /* count at the highest level where it is referenced. */
+      bdd_dominated_step(bddm, f, func_counts, h);
+      cmu_bdd_free_hash_table(h);
+      /* Now add each level n+1 result to that of level n. */
+      for (i=bddm->vars-1, j=i+1; i>= 0; --i)
+	if (func_counts[i] != 1)
+	  {
+	    func_counts[i]=(func_counts[i] >> 1)+func_counts[j];
+	    j=i;
+	  }
+	else
+	  func_counts[i]=0;
+    }
+}
+
+
+/* cmu_bdd_function_profile_multiple is to cmu_bdd_function_profile as */
+/* cmu_bdd_size_multiple is to cmu_bdd_size. */
+
+void
+cmu_bdd_function_profile_multiple(cmu_bdd_manager bddm, bdd *fs, long *func_counts)
+{
+  long i;
+  bdd_index_type j;
+  bdd *f;
+  long *hash_result;
+  hash_table h;
+
+  bdd_check_array(fs);
+  /* See cmu_bdd_function_profile for the strategy involved here. */
+  cmu_bdd_profile_multiple(bddm, fs, func_counts, 0);
+  for (j=0; j < bddm->vars; ++j)
+    if (!func_counts[j])
+      func_counts[j]=1;
+    else
+      func_counts[j]<<=1;
+  h=bdd_new_hash_table(bddm, sizeof(long));
+  for (f=fs; *f; ++f)
+    bdd_highest_ref_step(bddm, *f, h);
+  i= -1;
+  for (f=fs; *f; ++f)
+    if ((hash_result=(long *)bdd_lookup_in_hash_table(h, *f)))
+      *hash_result= -1;
+    else
+      bdd_insert_in_hash_table(h, *f, (pointer)&i);
+  for (f=fs; *f; ++f)
+    bdd_dominated_step(bddm, *f, func_counts, h);
+  cmu_bdd_free_hash_table(h);
+  for (i=bddm->vars-1, j=i+1; i>= 0; --i)
+    if (func_counts[i] != 1)
+      {
+	func_counts[i]=(func_counts[i] >> 1)+func_counts[j];
+	j=i;
+      }
+    else
+      func_counts[i]=0;
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddsupport.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddsupport.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddsupport.c	(revision 8)
@@ -0,0 +1,111 @@
+/* BDD support routines */
+
+
+#include "bddint.h"
+
+
+static
+int
+cmu_bdd_depends_on_step(cmu_bdd_manager bddm, bdd f, bdd_index_type var_index, int mark)
+{
+  bdd_index_type f_index;
+
+  BDD_SETUP(f);
+  f_index=BDD_INDEX(bddm, f);
+  if (f_index > var_index)
+    return (0);
+  if (f_index == var_index)
+    return (1);
+  if (BDD_MARK(f) == mark)
+    return (0);
+  BDD_MARK(f)=mark;
+  if (cmu_bdd_depends_on_step(bddm, BDD_THEN(f), var_index, mark))
+    return (1);
+  return (cmu_bdd_depends_on_step(bddm, BDD_ELSE(f), var_index, mark));
+}
+
+
+/* cmu_bdd_depends_on(bddm, f, var) returns 1 if f depends on var and */
+/* returns 0 otherwise. */
+
+int
+cmu_bdd_depends_on(cmu_bdd_manager bddm, bdd f, bdd var)
+{
+  if (bdd_check_arguments(2, f, var))
+    {
+      BDD_SETUP(var);
+      if (cmu_bdd_type_aux(bddm, var) != BDD_TYPE_POSVAR)
+	{
+	  cmu_bdd_warning("cmu_bdd_depends_on: second argument is not a positive variable");
+	  if (BDD_IS_CONST(var))
+	    return (1);
+	}
+      (void)cmu_bdd_depends_on_step(bddm, f, BDD_INDEX(bddm, var), 1);
+      return (cmu_bdd_depends_on_step(bddm, f, BDD_INDEX(bddm, var), 0));
+    }
+  return (0);
+}
+
+
+static
+void
+bdd_unmark_nodes(cmu_bdd_manager bddm, bdd f)
+{
+  bdd temp;
+
+  BDD_SETUP(f);
+  if (!BDD_MARK(f) || BDD_IS_CONST(f))
+    return;
+  BDD_MARK(f)=0;
+  temp=BDD_IF(bddm, f);
+  {
+    BDD_SETUP(temp);
+    BDD_MARK(temp)=0;
+  }
+  bdd_unmark_nodes(bddm, BDD_THEN(f));
+  bdd_unmark_nodes(bddm, BDD_ELSE(f));
+}
+
+
+static
+bdd *
+cmu_bdd_support_step(cmu_bdd_manager bddm, bdd f, bdd *support)
+{
+  bdd temp;
+
+  BDD_SETUP(f);
+  if (BDD_MARK(f) || BDD_IS_CONST(f))
+    return (support);
+  temp=BDD_IF(bddm, f);
+  {
+    BDD_SETUP(temp);
+    if (!BDD_MARK(temp))
+      {
+	BDD_MARK(temp)=1;
+	*support=temp;
+	++support;
+      }
+  }
+  BDD_MARK(f)=1;
+  support=cmu_bdd_support_step(bddm, BDD_THEN(f), support);
+  return (cmu_bdd_support_step(bddm, BDD_ELSE(f), support));
+}
+
+
+/* cmu_bdd_support(bddm, f, support) returns the support of f as a */
+/* null-terminated array of variables. */
+
+void
+cmu_bdd_support(cmu_bdd_manager bddm, bdd f, bdd *support)
+{
+  bdd *end;
+
+  if (bdd_check_arguments(1, f))
+    {
+      end=cmu_bdd_support_step(bddm, f, support);
+      *end=0;
+      bdd_unmark_nodes(bddm, f);
+    }
+  else
+    *support=0;
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddswap.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddswap.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddswap.c	(revision 8)
@@ -0,0 +1,156 @@
+/* BDD variable exchange routine */
+
+
+#include "bddint.h"
+
+
+static
+bdd
+cmu_bdd_swap_vars_aux_step(cmu_bdd_manager bddm, bdd f, bdd g, bdd h, bdd_indexindex_type h_indexindex, long op)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd_index_type f_index, g_index;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  f_index=BDD_INDEX(bddm, f);
+  g_index=BDD_INDEX(bddm, g);
+  if (f_index == bddm->indexes[h_indexindex])
+    {
+      if (op & 1)
+	f=BDD_THEN(f);
+      else
+	f=BDD_ELSE(f);
+      BDD_RESET(f);
+    }
+  if (g_index == bddm->indexes[h_indexindex])
+    {
+      if (op & 1)
+	g=BDD_THEN(g);
+      else
+	g=BDD_ELSE(g);
+      BDD_RESET(g);
+    }
+  if (f == g)
+    {
+    if (op & 1)
+      return (cmu_bdd_compose_temp(bddm, f, h, BDD_ONE(bddm)));
+    else
+      return (cmu_bdd_compose_temp(bddm, f, h, BDD_ZERO(bddm)));
+    }
+  if (f_index >= bddm->indexes[h_indexindex] && g_index >= bddm->indexes[h_indexindex])
+    {
+      BDD_TEMP_INCREFS(f);
+      BDD_TEMP_INCREFS(g);
+      return (bdd_find(bddm, h_indexindex, f, g));
+    }
+  if (bdd_lookup_in_cache2(bddm, op, f, g, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=cmu_bdd_swap_vars_aux_step(bddm, f1, g1, h, h_indexindex, op);
+  temp2=cmu_bdd_swap_vars_aux_step(bddm, f2, g2, h, h_indexindex, op);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache2(bddm, op, f, g, result);
+  return (result);
+}
+
+
+static
+bdd
+cmu_bdd_swap_vars_step(cmu_bdd_manager bddm, bdd f, bdd_indexindex_type g_indexindex, bdd h, long op)
+{
+  bdd_index_type f_index;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  if (BDD_IS_CONST(f))
+    return (f);
+  if (bdd_lookup_in_cache2(bddm, op, f, h, &result))
+    return (result);
+  f_index=BDD_INDEX(bddm, f);
+  if (f_index > bddm->indexes[g_indexindex])
+    {
+      temp1=cmu_bdd_compose_temp(bddm, f, h, BDD_ONE(bddm));
+      temp2=cmu_bdd_compose_temp(bddm, f, h, BDD_ZERO(bddm));
+      result=bdd_find(bddm, g_indexindex, temp1, temp2);
+    }
+  else if (f_index < bddm->indexes[g_indexindex])
+    {
+      temp1=cmu_bdd_swap_vars_step(bddm, BDD_THEN(f), g_indexindex, h, op);
+      temp2=cmu_bdd_swap_vars_step(bddm, BDD_ELSE(f), g_indexindex, h, op);
+      result=bdd_find(bddm, BDD_INDEXINDEX(f), temp1, temp2);
+    }
+  else
+    {
+      BDD_SETUP(h);
+      temp1=cmu_bdd_swap_vars_aux_step(bddm, BDD_THEN(f), BDD_ELSE(f), h, BDD_INDEXINDEX(h), OP_SWAPAUX+2*BDD_INDEXINDEX(h)+1);
+      temp2=cmu_bdd_swap_vars_aux_step(bddm, BDD_THEN(f), BDD_ELSE(f), h, BDD_INDEXINDEX(h), OP_SWAPAUX+2*BDD_INDEXINDEX(h));
+      result=bdd_find(bddm, g_indexindex, temp1, temp2);
+    }
+  bdd_insert_in_cache2(bddm, op, f, h, result);
+  return (result);
+}
+
+
+bdd
+cmu_bdd_swap_vars_temp(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  bdd_index_type g_index, h_index;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  BDD_SETUP(h);
+  g_index=BDD_INDEX(bddm, g);
+  h_index=BDD_INDEX(bddm, h);
+  if (g_index == h_index)
+    {
+      BDD_TEMP_INCREFS(f);
+      return (f);
+    }
+  if (g_index > h_index)
+    return (cmu_bdd_swap_vars_step(bddm, f, BDD_INDEXINDEX(h), g, OP_SWAP+BDD_INDEXINDEX(h)));
+  else
+    return (cmu_bdd_swap_vars_step(bddm, f, BDD_INDEXINDEX(g), h, OP_SWAP+BDD_INDEXINDEX(g)));
+}
+
+
+/* cmu_bdd_swap_vars(bddm, f, g, h) substitutes g for h and h for g in f. */
+
+bdd
+cmu_bdd_swap_vars(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  bdd_index_type g_index, h_index;
+
+  if (bdd_check_arguments(3, f, g, h))
+    {
+      BDD_SETUP(f);
+      BDD_SETUP(g);
+      BDD_SETUP(h);
+      if (cmu_bdd_type_aux(bddm, g) != BDD_TYPE_POSVAR || cmu_bdd_type_aux(bddm, h) != BDD_TYPE_POSVAR)
+	{
+	  cmu_bdd_warning("cmu_bdd_swap_vars: second and third arguments are not both positive variables");
+	  BDD_INCREFS(f);
+	  return (f);
+	}
+      FIREWALL(bddm);
+      g_index=BDD_INDEX(bddm, g);
+      h_index=BDD_INDEX(bddm, h);
+      if (g_index == h_index)
+	{
+	  BDD_INCREFS(f);
+	  return (f);
+	}
+      if (g_index > h_index)
+	RETURN_BDD(cmu_bdd_swap_vars_step(bddm, f, BDD_INDEXINDEX(h), g, OP_SWAP+BDD_INDEXINDEX(h)));
+      else
+	RETURN_BDD(cmu_bdd_swap_vars_step(bddm, f, BDD_INDEXINDEX(g), h, OP_SWAP+BDD_INDEXINDEX(g)));
+    }
+  return ((bdd)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bddunique.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddunique.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddunique.c	(revision 8)
@@ -0,0 +1,414 @@
+/* BDD unique table routines */
+
+
+#include "bddint.h"
+
+
+#define MIN_GC_LIMIT 10000
+
+
+void
+bdd_rehash_var_table(var_table table, int grow)
+{
+  long i;
+  long hash;
+  long oldsize;
+  bdd *newtable;
+  bdd p, q;
+
+  oldsize=table->size;
+  if (grow)
+    table->size_index++;
+  else
+    table->size_index--;
+  table->size=TABLE_SIZE(table->size_index);
+  newtable=(bdd *)mem_get_block((SIZE_T)(table->size*sizeof(bdd)));
+  for (i=0; i < table->size; ++i)
+    newtable[i]=0;
+  for (i=0; i < oldsize; ++i)
+    for (p=table->table[i]; p; p=q)
+      {
+	q=p->next;
+	hash=HASH_NODE(p->data[0], p->data[1]);
+	BDD_REDUCE(hash, table->size);
+	p->next=newtable[hash];
+	newtable[hash]=p;
+      }
+  mem_free_block((pointer)table->table);
+  table->table=newtable;
+}
+
+
+static
+void
+bdd_mark(cmu_bdd_manager bddm)
+{
+  long i, j;
+  var_table table;
+  bdd f, g;
+
+  for (i=0; i <= bddm->vars; ++i)
+    {
+      if (i == bddm->vars)
+	table=bddm->unique_table.tables[BDD_CONST_INDEXINDEX];
+      else
+	table=bddm->unique_table.tables[bddm->indexindexes[i]];
+      for (j=0; j < table->size; ++j)
+	for (f=table->table[j]; f; f=f->next)
+	  {
+	    BDD_SETUP(f);
+	    if (BDD_REFS(f) || BDD_TEMP_REFS(f))
+	      BDD_MARK(f)|=BDD_GC_MARK;
+	    if (BDD_IS_USED(f) && !BDD_IS_CONST(f))
+	      {
+		g=(bdd)BDD_DATA0(f);
+		{
+		  BDD_SETUP(g);
+		  BDD_MARK(g)|=BDD_GC_MARK;
+		}
+		g=(bdd)BDD_DATA1(f);
+		{
+		  BDD_SETUP(g);
+		  BDD_MARK(g)|=BDD_GC_MARK;
+		}
+	      }
+	  }
+    }
+}
+
+
+void
+bdd_sweep_var_table(cmu_bdd_manager bddm, long i, int maybe_rehash)
+{
+  long j;
+  var_table table;
+  bdd f, *p;
+
+  table=bddm->unique_table.tables[i];
+  for (j=0; j < table->size; ++j)
+    for (p= &table->table[j], f= *p; f; f= *p)
+      {
+	BDD_SETUP(f);
+	if (BDD_IS_USED(f))
+	  {
+	    BDD_SETUP(f);
+	    BDD_MARK(f)&=~BDD_GC_MARK;
+	    p= &f->next;
+	  }
+	else
+	  {
+	    *p=f->next;
+	    if (i == BDD_CONST_INDEXINDEX && bddm->unique_table.free_terminal_fn)
+	      (*bddm->unique_table.free_terminal_fn)(bddm,
+						     BDD_DATA0(f),
+						     BDD_DATA1(f),
+						     bddm->unique_table.free_terminal_env);
+	    BDD_FREE_REC(bddm, (pointer)f, sizeof(struct bdd_));
+	    table->entries--;
+	    bddm->unique_table.entries--;
+	    bddm->unique_table.freed++;
+	  }
+      }
+  if (maybe_rehash && table->size > table->entries && table->size_index > 3)
+    bdd_rehash_var_table(table, 0);
+}
+
+
+void
+bdd_sweep(cmu_bdd_manager bddm)
+{
+  long i;
+
+  for (i=0; i <= bddm->vars; ++i)
+    bdd_sweep_var_table(bddm, i, 1);
+}
+
+
+/* cmu_bdd_gc(bddm) performs a garbage collection. */
+
+void
+cmu_bdd_gc(cmu_bdd_manager bddm)
+{
+  bdd_mark(bddm);
+  bdd_purge_cache(bddm);
+  bdd_sweep(bddm);
+  bddm->unique_table.gcs++;
+}
+
+
+static
+void
+bdd_set_gc_limit(cmu_bdd_manager bddm)
+{
+  bddm->unique_table.gc_limit=2*bddm->unique_table.entries;
+  if (bddm->unique_table.gc_limit < MIN_GC_LIMIT)
+    bddm->unique_table.gc_limit=MIN_GC_LIMIT;
+  if (bddm->unique_table.node_limit &&
+      bddm->unique_table.gc_limit > bddm->unique_table.node_limit)
+    bddm->unique_table.gc_limit=bddm->unique_table.node_limit;
+}
+
+
+void
+bdd_clear_temps(cmu_bdd_manager bddm)
+{
+  long i, j;
+  var_table table;
+  bdd f;
+
+  for (i=0; i <= bddm->vars; ++i)
+    {
+      table=bddm->unique_table.tables[i];
+      for (j=0; j < table->size; ++j)
+	for (f=table->table[j]; f; f=f->next)
+	  {
+	    BDD_SETUP(f);
+	    BDD_TEMP_REFS(f)=0;
+	  }
+    }
+  cmu_bdd_gc(bddm);
+  bdd_set_gc_limit(bddm);
+}  
+
+
+void
+bdd_cleanup(cmu_bdd_manager bddm, int code)
+{
+  bdd_clear_temps(bddm);
+  switch (code)
+    {
+    case BDD_ABORTED:
+      (*bddm->bag_it_fn)(bddm, bddm->bag_it_env);
+      break;
+    case BDD_OVERFLOWED:
+      if (bddm->overflow_fn)
+	(*bddm->overflow_fn)(bddm, bddm->overflow_env);
+      break;
+    }
+}
+
+
+bdd
+bdd_find_aux(cmu_bdd_manager bddm, bdd_indexindex_type indexindex, INT_PTR d1, INT_PTR d2)
+{
+  var_table table;
+  long hash;
+  bdd temp;
+
+  table=bddm->unique_table.tables[indexindex];
+  hash=HASH_NODE(d1, d2);
+  BDD_REDUCE(hash, table->size);
+  for (temp=table->table[hash]; temp; temp=temp->next)
+    if (temp->data[0] == d1 && temp->data[1] == d2)
+      break;
+  if (!temp)
+    {
+      /* Not found; make a new node. */
+      temp=(bdd)BDD_NEW_REC(bddm, sizeof(struct bdd_));
+      temp->indexindex=indexindex;
+      temp->refs=0;
+      temp->mark=0;
+      temp->data[0]=d1;
+      temp->data[1]=d2;
+      temp->next=table->table[hash];
+      table->table[hash]=temp;
+      table->entries++;
+      bddm->unique_table.entries++;
+      if (4*table->size < table->entries)
+	bdd_rehash_var_table(table, 1);
+    }
+  bddm->unique_table.finds++;
+  return (temp);
+}
+
+
+static
+void
+bdd_check(cmu_bdd_manager bddm)
+{
+  long nodes;
+
+  bddm->check=100;
+  /* When bag_it_fn set, clean up and abort immediately. */
+  if (bddm->bag_it_fn)
+    longjmp(bddm->abort.context, BDD_ABORTED);
+  if (bddm->unique_table.entries > bddm->unique_table.gc_limit)
+    {
+      cmu_bdd_gc(bddm);
+      /* Table full. */
+      nodes=bddm->unique_table.entries;
+      if (3*nodes > 2*bddm->unique_table.gc_limit && bddm->allow_reordering && bddm->reorder_fn)
+	{
+	  cmu_bdd_reorder_aux(bddm);
+	  if (4*bddm->unique_table.entries > 3*nodes && 3*nodes > 4*bddm->nodes_at_start)
+	    /* If we didn't save much, but we have created a reasonable number */
+	    /* of nodes, then don't bother reordering next time. */
+	    bddm->allow_reordering=0;
+	  /* Go try again. */
+	  bdd_set_gc_limit(bddm);
+	  longjmp(bddm->abort.context, BDD_REORDERED);
+	}
+      bdd_set_gc_limit(bddm);
+      if (bddm->unique_table.node_limit &&
+	  bddm->unique_table.entries >= bddm->unique_table.node_limit-1000)
+	{
+	  /* Out of memory; go clean up. */
+	  bddm->overflow=1;
+	  longjmp(bddm->abort.context, BDD_OVERFLOWED);
+	}
+    }
+  /* Maybe increase cache size if it's getting full. */
+  if (3*bddm->op_cache.size < 2*bddm->op_cache.entries &&
+      32*bddm->op_cache.size < bddm->op_cache.cache_ratio*bddm->unique_table.entries)
+    bdd_rehash_cache(bddm, 1);
+}
+
+
+/* bdd_find(bddm, indexindex, f, g) creates or finds a node with the */
+/* given indexindex, "then" pointer, and "else" pointer. */
+
+bdd
+bdd_find(cmu_bdd_manager bddm, bdd_indexindex_type indexindex, bdd f, bdd g)
+{
+  bdd temp;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (f == g)
+    {
+      BDD_TEMP_DECREFS(f);
+      temp=f;
+    }
+  else
+    {
+      if (BDD_IS_OUTPOS(f))
+	temp=bdd_find_aux(bddm, indexindex, (INT_PTR)f, (INT_PTR)g);
+      else
+	temp=BDD_NOT(bdd_find_aux(bddm, indexindex, (INT_PTR)BDD_NOT(f), (INT_PTR)BDD_NOT(g)));
+      {
+	BDD_SETUP(temp);
+	BDD_TEMP_INCREFS(temp);
+      }
+      BDD_TEMP_DECREFS(f);
+      BDD_TEMP_DECREFS(g);
+    }
+  bddm->check--;
+  if (!bddm->check)
+    bdd_check(bddm);
+  return (temp);
+}
+
+
+/* bdd_find_terminal(bddm, value1, value2) creates or finds a terminal */
+/* node with the given data value. */
+
+bdd
+bdd_find_terminal(cmu_bdd_manager bddm, INT_PTR value1, INT_PTR value2)
+{
+  bdd temp;
+
+  if ((*bddm->canonical_fn)(bddm, value1, value2, bddm->transform_env))
+    {
+      (*bddm->transform_fn)(bddm, value1, value2, &value1, &value2, bddm->transform_env);
+      temp=BDD_NOT(bdd_find_aux(bddm, BDD_CONST_INDEXINDEX, value1, value2));
+    }
+  else
+    temp=bdd_find_aux(bddm, BDD_CONST_INDEXINDEX, value1, value2);
+  {
+    BDD_SETUP(temp);
+    BDD_TEMP_INCREFS(temp);
+  }
+  bddm->check--;
+  if (!bddm->check)
+    bdd_check(bddm);
+  return (temp);
+}
+
+
+/* cmu_bdd_clear_refs(bddm) sets the reference count of all nodes to 0. */
+
+void
+cmu_bdd_clear_refs(cmu_bdd_manager bddm)
+{
+  long i, j;
+  var_table table;
+  bdd f;
+  assoc_list q;
+
+  for (i=0; i <= bddm->vars; ++i)
+    {
+      table=bddm->unique_table.tables[i];
+      for (j=0; j < table->size; ++j)
+	for (f=table->table[j]; f; f=f->next)
+	  {
+	    BDD_SETUP(f);
+	    BDD_REFS(f)=0;
+	  }
+    }
+  for (i=0; i < bddm->vars; ++i)
+    bddm->variables[i+1]->refs=BDD_MAX_REFS;
+  bddm->one->refs=BDD_MAX_REFS;
+  for (q=bddm->assocs; q; q=q->next)
+    for (i=0; i < bddm->vars; ++i)
+      if ((f=q->va.assoc[i+1]))
+	{
+	  BDD_SETUP(f);
+	  BDD_INCREFS(f);
+	}
+}
+
+
+var_table
+bdd_new_var_table(cmu_bdd_manager bddm)
+{
+  long i;
+  var_table table;
+
+  table=(var_table)BDD_NEW_REC(bddm, sizeof(struct var_table_));
+  table->size_index=3;
+  table->size=TABLE_SIZE(table->size_index);
+  table->entries=0;
+  table->table=(bdd *)mem_get_block((SIZE_T)(table->size*sizeof(bdd)));
+  for (i=0; i < table->size; ++i)
+    table->table[i]=0;
+  return (table);
+}
+
+
+void
+cmu_bdd_init_unique(cmu_bdd_manager bddm)
+{
+  bddm->unique_table.tables=(var_table *)mem_get_block((SIZE_T)((bddm->maxvars+1)*sizeof(var_table)));
+  bddm->unique_table.tables[BDD_CONST_INDEXINDEX]=bdd_new_var_table(bddm);
+  bddm->unique_table.gc_limit=MIN_GC_LIMIT;
+  bddm->unique_table.node_limit=0;
+  bddm->unique_table.entries=0;
+  bddm->unique_table.freed=0;
+  bddm->unique_table.gcs=0;
+  bddm->unique_table.finds=0;
+  bddm->unique_table.free_terminal_fn=0;
+  bddm->unique_table.free_terminal_env=0;
+}
+
+
+void
+cmu_bdd_free_unique(cmu_bdd_manager bddm)
+{
+  long i, j;
+  var_table table;
+  bdd p, q;
+
+  for (i=0; i <= bddm->vars; ++i)
+    {
+      table=bddm->unique_table.tables[i];
+      for (j=0; j < table->size; ++j)
+	for (p=table->table[j]; p; p=q)
+	  {
+	    q=p->next;
+	    BDD_FREE_REC(bddm, (pointer)p, sizeof(struct bdd_));
+	  }
+      mem_free_block((pointer)table->table);
+      BDD_FREE_REC(bddm, (pointer)table, sizeof(struct var_table_));
+    }
+  mem_free_block((pointer)bddm->unique_table.tables);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/bdduser.h
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bdduser.h	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bdduser.h	(revision 8)
@@ -0,0 +1,246 @@
+/* BDD user-visible definitions */
+
+
+#if !defined(_BDDUSERH)
+#define _BDDUSERH
+
+
+#include <stdio.h>
+#include <memuser.h>
+
+
+#define ARGS(args) args
+
+
+/* Types */
+
+typedef struct bdd_ *bdd;
+typedef struct bdd_manager_ *cmu_bdd_manager;
+typedef struct block_ *block;
+
+
+/* Return values for cmu_bdd_type */
+
+#define BDD_TYPE_NONTERMINAL 0
+#define BDD_TYPE_ZERO 1
+#define BDD_TYPE_ONE 2
+#define BDD_TYPE_POSVAR 3
+#define BDD_TYPE_NEGVAR 4
+#define BDD_TYPE_OVERFLOW 5
+#define BDD_TYPE_CONSTANT 6
+
+
+/* Error codes for cmu_bdd_undump_bdd */
+
+#define BDD_UNDUMP_FORMAT 1
+#define BDD_UNDUMP_OVERFLOW 2
+#define BDD_UNDUMP_IOERROR 3
+#define BDD_UNDUMP_EOF 4
+
+
+/* Basic BDD routine declarations */
+
+extern bdd cmu_bdd_one ARGS((cmu_bdd_manager));
+extern bdd cmu_bdd_zero ARGS((cmu_bdd_manager));
+extern bdd cmu_bdd_new_var_first ARGS((cmu_bdd_manager));
+extern bdd cmu_bdd_new_var_last ARGS((cmu_bdd_manager));
+extern bdd cmu_bdd_new_var_before ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_new_var_after ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_var_with_index ARGS((cmu_bdd_manager, long));
+extern bdd cmu_bdd_var_with_id ARGS((cmu_bdd_manager, long));
+extern bdd cmu_bdd_ite ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+extern bdd cmu_bdd_and ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_nand ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_or ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_nor ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_xor ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_xnor ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_identity ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_not ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_if ARGS((cmu_bdd_manager, bdd));
+extern long cmu_bdd_if_index ARGS((cmu_bdd_manager, bdd));
+extern long cmu_bdd_if_id ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_then ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_else ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_intersects ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_implies ARGS((cmu_bdd_manager, bdd, bdd));
+extern int cmu_bdd_type ARGS((cmu_bdd_manager, bdd));
+extern void cmu_bdd_unfree ARGS((cmu_bdd_manager, bdd));
+extern void cmu_bdd_free ARGS((cmu_bdd_manager, bdd));
+extern long cmu_bdd_vars ARGS((cmu_bdd_manager));
+extern long cmu_bdd_total_size ARGS((cmu_bdd_manager));
+extern int cmu_bdd_cache_ratio ARGS((cmu_bdd_manager, int));
+extern long cmu_bdd_node_limit ARGS((cmu_bdd_manager, long));
+extern int cmu_bdd_overflow ARGS((cmu_bdd_manager));
+extern void cmu_bdd_overflow_closure ARGS((cmu_bdd_manager, void (*) ARGS((cmu_bdd_manager, pointer)), pointer));
+extern void cmu_bdd_abort_closure ARGS((cmu_bdd_manager, void (*) ARGS((cmu_bdd_manager, pointer)), pointer));
+extern void cmu_bdd_stats ARGS((cmu_bdd_manager, FILE *));
+extern cmu_bdd_manager cmu_bdd_init ARGS((void));
+extern void cmu_bdd_quit ARGS((cmu_bdd_manager));
+
+
+/* Variable association routine declarations */
+
+extern int cmu_bdd_new_assoc ARGS((cmu_bdd_manager, bdd *, int));
+extern void cmu_bdd_free_assoc ARGS((cmu_bdd_manager, int));
+extern void cmu_bdd_temp_assoc ARGS((cmu_bdd_manager, bdd *, int));
+extern void cmu_bdd_augment_temp_assoc ARGS((cmu_bdd_manager, bdd *, int));
+extern int cmu_bdd_assoc ARGS((cmu_bdd_manager, int));
+
+
+/* Comparison routine declarations */
+
+extern int cmu_bdd_compare ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+
+
+/* Composition routine declarations */
+
+extern bdd cmu_bdd_compose ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+extern bdd cmu_bdd_substitute ARGS((cmu_bdd_manager, bdd));
+
+
+/* Variable exchange routine declarations */
+
+extern bdd cmu_bdd_swap_vars ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+
+
+/* Quantification routine declarations */
+
+extern bdd cmu_bdd_exists ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_forall ARGS((cmu_bdd_manager, bdd));
+
+
+/* Reduce routine declarations */
+
+extern bdd cmu_bdd_reduce ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd cmu_bdd_cofactor ARGS((cmu_bdd_manager, bdd, bdd));
+
+
+/* Relational product routine declarations */
+
+extern bdd cmu_bdd_rel_prod ARGS((cmu_bdd_manager, bdd, bdd));
+
+
+/* Satisfying valuation routine declarations */
+
+extern bdd cmu_bdd_satisfy ARGS((cmu_bdd_manager, bdd));
+extern bdd cmu_bdd_satisfy_support ARGS((cmu_bdd_manager, bdd));
+extern double cmu_bdd_satisfying_fraction ARGS((cmu_bdd_manager, bdd));
+
+
+/* Generic apply routine declarations */
+
+extern bdd bdd_apply2 ARGS((cmu_bdd_manager, bdd (*) ARGS((cmu_bdd_manager, bdd *, bdd *, pointer)), bdd, bdd, pointer));
+extern bdd bdd_apply1 ARGS((cmu_bdd_manager, bdd (*) ARGS((cmu_bdd_manager, bdd *, pointer)), bdd, pointer));
+
+
+/* Size and profile routine declarations */
+
+extern long cmu_bdd_size ARGS((cmu_bdd_manager, bdd, int));
+extern long cmu_bdd_size_multiple ARGS((cmu_bdd_manager, bdd *, int));
+extern void cmu_bdd_profile ARGS((cmu_bdd_manager, bdd, long *, int));
+extern void cmu_bdd_profile_multiple ARGS((cmu_bdd_manager, bdd *, long *, int));
+extern void cmu_bdd_function_profile ARGS((cmu_bdd_manager, bdd, long *));
+extern void cmu_bdd_function_profile_multiple ARGS((cmu_bdd_manager, bdd *, long *));
+
+
+/* Print routine declarations */
+
+#define bdd_naming_fn_none ((char *(*)(cmu_bdd_manager, bdd, pointer))0)
+#define bdd_terminal_id_fn_none ((char *(*)(cmu_bdd_manager, INT_PTR, INT_PTR, pointer))0)
+
+extern void cmu_bdd_print_bdd ARGS((cmu_bdd_manager,
+				bdd,
+				char *(*) ARGS((cmu_bdd_manager, bdd, pointer)),
+				char *(*) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer)),
+				pointer,
+				FILE *));
+extern void cmu_bdd_print_profile_aux ARGS((cmu_bdd_manager,
+					long *,
+					char *(*) ARGS((cmu_bdd_manager, bdd, pointer)),
+					pointer,
+					int,
+					FILE *));
+extern void cmu_bdd_print_profile ARGS((cmu_bdd_manager,
+				    bdd,
+				    char *(*) ARGS((cmu_bdd_manager, bdd, pointer)),
+				    pointer,
+				    int,
+				    FILE *));
+extern void cmu_bdd_print_profile_multiple ARGS((cmu_bdd_manager,
+					     bdd *,
+					     char *(*) ARGS((cmu_bdd_manager, bdd, pointer)),
+					     pointer,
+					     int,
+					     FILE *));
+extern void cmu_bdd_print_function_profile ARGS((cmu_bdd_manager,
+					     bdd,
+					     char *(*) ARGS((cmu_bdd_manager, bdd, pointer)),
+					     pointer,
+					     int,
+					     FILE *));
+extern void cmu_bdd_print_function_profile_multiple ARGS((cmu_bdd_manager,
+						      bdd *,
+						      char *(*) ARGS((cmu_bdd_manager, bdd, pointer)),
+						      pointer,
+						      int,
+						      FILE *));
+
+
+/* Dump/undump routine declarations */
+
+extern int cmu_bdd_dump_bdd ARGS((cmu_bdd_manager, bdd, bdd *, FILE *));
+extern bdd cmu_bdd_undump_bdd ARGS((cmu_bdd_manager, bdd *, FILE *, int *));
+
+
+/* Support routine declarations */
+
+extern int cmu_bdd_depends_on ARGS((cmu_bdd_manager, bdd, bdd));
+extern void cmu_bdd_support ARGS((cmu_bdd_manager, bdd, bdd *));
+
+
+/* Unique table routine declarations */
+
+extern void cmu_bdd_gc ARGS((cmu_bdd_manager));
+extern void cmu_bdd_clear_refs ARGS((cmu_bdd_manager));
+
+
+/* Dynamic reordering routines */
+
+#define cmu_bdd_reorder_none ((void (*)(cmu_bdd_manager))0)
+
+extern void cmu_bdd_reorder_stable_window3 ARGS((cmu_bdd_manager));
+extern void cmu_bdd_reorder_sift ARGS((cmu_bdd_manager));
+extern void cmu_bdd_reorder_hybrid ARGS((cmu_bdd_manager));
+extern void cmu_bdd_var_block_reorderable ARGS((cmu_bdd_manager, block, int));
+extern void cmu_bdd_dynamic_reordering ARGS((cmu_bdd_manager, void (*) ARGS((cmu_bdd_manager))));
+extern void cmu_bdd_reorder ARGS((cmu_bdd_manager));
+
+extern bdd cmu_bdd_project ARGS((cmu_bdd_manager, bdd));
+
+/* Variable block routines */
+
+extern block cmu_bdd_new_var_block ARGS((cmu_bdd_manager, bdd, long));
+
+
+/* Multi-terminal BDD routine declarations */
+
+extern void mtbdd_transform_closure ARGS((cmu_bdd_manager,
+					  int (*) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer)),
+					  void (*) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, INT_PTR *, INT_PTR *, pointer)),
+					  pointer));
+extern void mtcmu_bdd_one_data ARGS((cmu_bdd_manager, INT_PTR, INT_PTR));
+extern void cmu_mtbdd_free_terminal_closure ARGS((cmu_bdd_manager,
+					      void (*) ARGS((cmu_bdd_manager, INT_PTR, INT_PTR, pointer)),
+					      pointer));
+extern bdd cmu_mtbdd_get_terminal ARGS((cmu_bdd_manager, INT_PTR, INT_PTR));
+extern void cmu_mtbdd_terminal_value ARGS((cmu_bdd_manager, bdd, INT_PTR *, INT_PTR *));
+extern bdd mtcmu_bdd_ite ARGS((cmu_bdd_manager, bdd, bdd, bdd));
+extern bdd cmu_mtbdd_equal ARGS((cmu_bdd_manager, bdd, bdd));
+extern bdd mtcmu_bdd_substitute ARGS((cmu_bdd_manager, bdd));
+#define mtbdd_transform(bddm, f) (cmu_bdd_not(bddm, f))
+
+
+#undef ARGS
+
+#endif
Index: /vis_dev/glu-2.1/src/cmuBdd/bddwarn.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/bddwarn.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/bddwarn.c	(revision 8)
@@ -0,0 +1,72 @@
+/* BDD error and argument checking routines */
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "bddint.h"
+
+#if STDC_HEADERS
+#  include <stdlib.h>
+#else
+#  if defined(__STDC__)
+extern void exit(int);
+#  else
+extern void exit();
+#  endif
+#endif
+
+
+/* cmu_bdd_warning(message) prints a warning and returns. */
+
+void
+cmu_bdd_warning(char *message)
+{
+  fprintf(stderr, "BDD library: warning: %s\n", message);
+}
+
+
+/* cmu_bdd_fatal(message) prints an error message and exits. */
+
+void
+cmu_bdd_fatal(char *message)
+{
+  fprintf(stderr, "BDD library: error: %s\n", message);
+  exit(1);
+  /* NOTREACHED */
+}
+
+
+int
+bdd_check_arguments(int count, ...)
+{
+  int all_valid;
+  va_list ap;
+  bdd f;
+
+  va_start(ap, count);
+  all_valid=1;
+  while (count)
+    {
+      f=va_arg(ap, bdd);
+      {
+	BDD_SETUP(f);
+	if (!f)
+	  all_valid=0;
+	else if (BDD_REFS(f) == 0)
+	  cmu_bdd_fatal("bdd_check_arguments: argument has zero references");
+      }
+      --count;
+    }
+  return (all_valid);
+}
+
+
+void
+bdd_check_array(bdd *fs)
+{
+  while (*fs)
+    {
+      bdd_check_arguments(1, *fs);
+      ++fs;
+    }
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/cmuBdd.make
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/cmuBdd.make	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/cmuBdd.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC_cmu += bdd.c bdd_is_cube.c bddapply.c bddassoc.c bddblk.c bddcache.c bddcmp.c bddcomp.c bddcproject.c bdddump.c bddhash.c bddmisc.c bddprimes.c bddprint.c bddprprofile.c bddqnt.c bddreduce.c bddrelprod.c bddreorder.c bddsat.c bddsize.c bddsupport.c bddswap.c bddunique.c bddwarn.c mtbdd.c 
+HEADERS_cmu += bddint.h bdduser.h 
+MISC += testbdd.c bdd.3 
+
+DEPENDENCYFILES = $(CSRC_cmu)
Index: /vis_dev/glu-2.1/src/cmuBdd/mtbdd.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/mtbdd.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/mtbdd.c	(revision 8)
@@ -0,0 +1,228 @@
+/* Basic multi-terminal BDD routines */
+
+
+#include "bddint.h"
+
+
+/* mtbdd_transform_closure(bddm, canonical_fn, transform_fn, env) sets */
+/* the transformation for MTBDD terminal values for the "negative-output" */
+/* pointer flag.  The canonical_fn receives the BDD manager, two longs */
+/* representing the input value, and the value of env.  It should return */
+/* a non-zero value if the result needs to be transformed.  The */
+/* transform_fn receives the BDD manager, two longs (the input value), */
+/* pointers to two longs (for the output) and the value of env.  This */
+/* should not be called after any MTBDD terminals are created. */
+
+void
+mtbdd_transform_closure(cmu_bdd_manager bddm,
+			int (*canonical_fn)(cmu_bdd_manager, INT_PTR, INT_PTR, pointer),
+			void (*transform_fn)(cmu_bdd_manager, INT_PTR, INT_PTR, INT_PTR *, INT_PTR *, pointer),
+			pointer transform_env)
+{
+  bddm->transform_fn=transform_fn;
+  bddm->transform_env=transform_env;
+  bddm->canonical_fn=canonical_fn;
+}
+
+
+/* mtcmu_bdd_one_data(bddm, value1, value2) sets the MTBDD value for TRUE. */
+/* This should not be called after MTBDD terminals have been created. */
+
+void
+mtcmu_bdd_one_data(cmu_bdd_manager bddm, INT_PTR value1, INT_PTR value2)
+{
+  var_table table;
+  long hash;
+
+  table=bddm->unique_table.tables[BDD_CONST_INDEXINDEX];
+  if (table->entries != 1)
+    cmu_bdd_fatal("mtcmu_bdd_one_data: other terminal nodes already exist");
+  hash=HASH_NODE(bddm->one->data[0], bddm->one->data[1]);
+  BDD_REDUCE(hash, table->size);
+  table->table[hash]=0;
+  bddm->one->data[0]=value1;
+  bddm->one->data[1]=value2;
+  hash=HASH_NODE(bddm->one->data[0], bddm->one->data[1]);
+  BDD_REDUCE(hash, table->size);
+  table->table[hash]=bddm->one;
+}
+
+
+/* cmu_mtbdd_free_terminal_closure(bddm, free_terminal_fn, free_terminal_env) */
+/* sets the closure to be invoked on when freeing MTBDD terminals.  If */
+/* free_terminal_fn is null, it indicates that no function should be */
+/* called.  The free_terminal_fn gets the BDD manager, two longs */
+/* holding the data for the terminal, and the value of free_terminal_env. */
+
+void
+cmu_mtbdd_free_terminal_closure(cmu_bdd_manager bddm,
+			    void (*free_terminal_fn)(cmu_bdd_manager, INT_PTR, INT_PTR, pointer),
+			    pointer free_terminal_env)
+{
+  bddm->unique_table.free_terminal_fn=free_terminal_fn;
+  bddm->unique_table.free_terminal_env=free_terminal_env;
+}
+
+
+/* cmu_mtbdd_get_terminal(bddm, value1, value2) returns the multi-terminal */
+/* BDD for a constant. */
+
+bdd
+cmu_mtbdd_get_terminal(cmu_bdd_manager bddm, INT_PTR value1, INT_PTR value2)
+{
+  FIREWALL(bddm);
+  RETURN_BDD(bdd_find_terminal(bddm, value1, value2));
+}
+
+
+/* cmu_mtbdd_terminal_value(bddm, f, value1, value2) returns the data value */
+/* for the terminal node f. */
+
+void
+cmu_mtbdd_terminal_value(cmu_bdd_manager bddm, bdd f, INT_PTR *value1, INT_PTR *value2)
+{
+  if (bdd_check_arguments(1, f))
+    {
+      BDD_SETUP(f);
+      if (!BDD_IS_CONST(f))
+	{
+	  cmu_bdd_warning("mtbdd_terminal_data: argument is terminal node");
+	  *value1=0;
+	  *value2=0;
+	  return;
+	}
+      cmu_mtbdd_terminal_value_aux(bddm, f, value1, value2);
+    }
+}
+
+
+static
+bdd
+mtcmu_bdd_ite_step(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd h1, h2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  BDD_SETUP(h);
+  if (BDD_IS_CONST(f))
+    {
+      if (f == BDD_ONE(bddm))
+	{
+	  BDD_TEMP_INCREFS(g);
+	  return (g);
+	}
+      BDD_TEMP_INCREFS(h);
+      return (h);
+    }
+  /* f is not constant. */
+  if (g == h)
+    {
+      BDD_TEMP_INCREFS(g);
+      return (g);
+    }
+  /* f is not constant, g and h are distinct. */
+  if (!BDD_IS_OUTPOS(f))
+    {
+      f=BDD_NOT(f);
+      BDD_SWAP(g, h);
+    }
+  /* f is now an uncomplemented output pointer. */
+  if (bdd_lookup_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)h, (INT_PTR *)&result))
+    return (result);
+  BDD_TOP_VAR3(top_indexindex, bddm, f, g, h);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  BDD_COFACTOR(top_indexindex, h, h1, h2);
+  temp1=mtcmu_bdd_ite_step(bddm, f1, g1, h1);
+  temp2=mtcmu_bdd_ite_step(bddm, f2, g2, h2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache31(bddm, CACHE_TYPE_ITE, (INT_PTR)f, (INT_PTR)g, (INT_PTR)h, (INT_PTR)result);
+  return (result);
+}
+
+
+/* mtcmu_bdd_ite(bddm, f, g, h) returns the BDD for "if f then g else h", */
+/* where g and h are multi-terminal BDDs. */
+
+bdd
+mtcmu_bdd_ite(cmu_bdd_manager bddm, bdd f, bdd g, bdd h)
+{
+  if (bdd_check_arguments(3, f, g, h))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(mtcmu_bdd_ite_step(bddm, f, g, h));
+    }
+  return ((bdd)0);
+}
+
+
+/* mtcmu_bdd_substitute(bddm, f) does the analog of cmu_bdd_substitute for MTBDDs. */
+
+bdd
+mtcmu_bdd_substitute(cmu_bdd_manager bddm, bdd f)
+{
+  long op;
+
+  if (bdd_check_arguments(1, f))
+    {
+      FIREWALL(bddm);
+      if (bddm->curr_assoc_id == -1)
+	op=bddm->temp_op--;
+      else
+	op=OP_SUBST+bddm->curr_assoc_id;
+      RETURN_BDD(cmu_bdd_substitute_step(bddm, f, op, mtcmu_bdd_ite_step, bddm->curr_assoc));
+    }
+  return ((bdd)0);
+}
+
+
+static
+bdd
+cmu_mtbdd_equal_step(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (f == g)
+    return (BDD_ONE(bddm));
+  if (BDD_IS_CONST(f) && BDD_IS_CONST(g))
+    return (BDD_ZERO(bddm));
+  if (BDD_OUT_OF_ORDER(f, g))
+    BDD_SWAP(f, g);
+  if (bdd_lookup_in_cache2(bddm, OP_EQUAL, f, g, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=cmu_mtbdd_equal_step(bddm, f1, g1);
+  temp2=cmu_mtbdd_equal_step(bddm, f2, g2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache2(bddm, OP_EQUAL, f, g, result);
+  return (result);
+}
+
+
+/* cmu_mtbdd_equal(bddm, f, g) returns a BDD indicating when the */
+/* multi-terminal BDDs f and g are equal. */
+
+bdd
+cmu_mtbdd_equal(cmu_bdd_manager bddm, bdd f, bdd g)
+{
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(cmu_mtbdd_equal_step(bddm, f, g));
+    }
+  return ((bdd)0);
+}
Index: /vis_dev/glu-2.1/src/cmuBdd/testbdd.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuBdd/testbdd.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuBdd/testbdd.c	(revision 8)
@@ -0,0 +1,1319 @@
+/* Basic operation tests */
+
+
+#include <stdio.h>
+#if HAVE_STDARG_H
+#  include <stdarg.h>
+#else
+#  if HAVE_VARARGS_H
+#    include <varargs.h>
+#  else
+#    error "Need to have HAVE_STDARG_H or HAVE_VARARGS_H defined for variable arguments"
+#  endif
+#endif
+#if STDC_HEADERS
+#  include <stdlib.h>
+#endif
+
+#include "bddint.h"
+
+
+#define VARS 500
+
+
+#define TT_BITS 32		/* Size of tt in bits */
+#define TT_VARS 5		/* log2 of BITS */
+/* Also see cofactor_masks below. */
+
+	/* Number of trials to run */
+/* #define ITERATIONS 20000 */
+#define ITERATIONS 200
+
+
+#if defined(__STDC__)
+#if STDC_HEADERS
+#include <stdlib.h>
+#else
+extern void srandom(unsigned int);
+extern long random(void);
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#else
+extern int unlink(char *);
+#endif
+#else
+extern void srandom();
+extern long random();
+extern int unlink();
+#endif
+
+
+typedef unsigned long tt;	/* "Truth table" */
+
+
+static cmu_bdd_manager bddm;
+
+
+static bdd vars[VARS];
+static bdd aux_vars[VARS];
+
+
+static tt cofactor_masks[]=
+{
+  0xffff0000,
+  0xff00ff00,
+  0xf0f0f0f0,
+  0xcccccccc,
+  0xaaaaaaaa,
+};
+
+
+static
+bdd
+#if defined(__STDC__)
+decode(int var, tt table)
+#else
+decode(var, table)
+     int var;
+     tt table;
+#endif
+{
+  bdd temp1, temp2;
+  bdd result;
+
+  if (var == TT_VARS)
+    return ((table & 1) ? cmu_bdd_one(bddm) : cmu_bdd_zero(bddm));
+  temp1=decode(var+1, table >> (1 << (TT_VARS-var-1)));
+  temp2=decode(var+1, table);
+  result=cmu_bdd_ite(bddm, vars[var], temp1, temp2);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  return (result);
+}
+
+
+#define encoding_to_bdd(table) (decode(0, (table)))
+
+
+static union hack_u {
+  INT_PTR as_double_space[2];
+  double  double_value;
+} hack;
+
+static
+double
+#if defined(__STDC__)
+as_double(INT_PTR v1, INT_PTR v2)
+#else
+as_double(v1, v2)
+     INT_PTR v1;
+     INT_PTR v2;
+#endif
+{
+  hack.as_double_space[0]=v1;
+  hack.as_double_space[1]=v2;
+  return (hack.double_value);
+}
+
+
+static
+void
+#if defined(__STDC__)
+as_INT_PTRs(double n, INT_PTR *r1, INT_PTR *r2)
+#else
+as_INT_PTRs(n, r1, r2)
+     double n;
+     INT_PTR *r1;
+     INT_PTR *r2;
+#endif
+{
+  hack.double_value=n;
+  *r1=hack.as_double_space[0];
+  *r2=hack.as_double_space[1];
+}
+
+
+static
+char *
+#if defined(__STDC__)
+terminal_id_fn(cmu_bdd_manager bddm, INT_PTR v1, INT_PTR v2, pointer junk)
+#else
+terminal_id_fn(bddm, v1, v2, junk)
+     cmu_bdd_manager bddm;
+     INT_PTR v1;
+     INT_PTR v2;
+     pointer junk;
+#endif
+{
+  static char result[100];
+
+  sprintf(result, "%g", as_double(v1, v2));
+  return (result);
+}
+
+
+static
+void
+#if defined(__STDC__)
+print_bdd(bdd f)
+#else
+print_bdd(f)
+     bdd f;
+#endif
+{
+  cmu_bdd_print_bdd(bddm, f, bdd_naming_fn_none, terminal_id_fn, (pointer)0, stderr);
+}
+
+
+#if defined(__STDC__)
+static
+void
+error(char *op, bdd result, bdd expected, ...)
+{
+  int i;
+  va_list ap;
+  bdd f;
+
+  va_start(ap, expected);
+  fprintf(stderr, "\nError: operation %s:\n", op);
+  i=0;
+  while (1)
+    {
+      f=va_arg(ap, bdd);
+      if (f)
+	{
+	  ++i;
+	  fprintf(stderr, "Argument %d:\n", i);
+	  print_bdd(f);
+	}
+      else
+	break;
+    }
+  fprintf(stderr, "Result:\n");
+  print_bdd(result);
+  fprintf(stderr, "Expected result:\n");
+  print_bdd(expected);
+  va_end(ap);
+}
+#else
+static
+void
+error(va_alist)
+     va_dcl
+{
+  int i;
+  va_list ap;
+  char *op;
+  bdd result;
+  bdd expected;
+  bdd f;
+
+  va_start(ap);
+  op=va_arg(ap, char *);
+  result=va_arg(ap, bdd);
+  expected=va_arg(ap, bdd);
+  fprintf(stderr, "\nError: operation %s:\n", op);
+  i=0;
+  while (1)
+    {
+      f=va_arg(ap, bdd);
+      if (f)
+	{
+	  ++i;
+	  fprintf(stderr, "Argument %d:\n", i);
+	  print_bdd(f);
+	}
+      else
+	break;
+    }
+  fprintf(stderr, "Result:\n");
+  print_bdd(result);
+  fprintf(stderr, "Expected result:\n");
+  print_bdd(expected);
+  va_end(ap);
+}
+#endif
+
+
+static
+tt
+#if defined(__STDC__)
+cofactor(tt table, int var, int value)
+#else
+cofactor(table, var, value)
+     tt table;
+     int var;
+     int value;
+#endif
+{
+  int shift;
+
+  shift=1 << (TT_VARS-var-1);
+  if (value)
+    {
+      table&=cofactor_masks[var];
+      table|=table >> shift;
+    }
+  else
+    {
+      table&=~cofactor_masks[var];
+      table|=table << shift;
+    }
+  return (table);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_ite(bdd f1, tt table1, bdd f2, tt table2, bdd f3, tt table3)
+#else
+test_ite(f1, table1, f2, table2, f3, table3)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+     bdd f3;
+     tt table3;
+#endif
+{
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  result=cmu_bdd_ite(bddm, f1, f2, f3);
+  resulttable=(table1 & table2) | (~table1 & table3);
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("ITE", result, expected, f1, f2, f3, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_and(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_and(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  result=cmu_bdd_and(bddm, f1, f2);
+  resulttable=table1 & table2;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("and", result, expected, f1, f2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_or(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_or(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  result=cmu_bdd_or(bddm, f1, f2);
+  resulttable=table1 | table2;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("or", result, expected, f1, f2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_xor(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_xor(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  result=cmu_bdd_xor(bddm, f1, f2);
+  resulttable=table1 ^ table2;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("xor", result, expected, f1, f2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_id_not(bdd f, tt table)
+#else
+test_id_not(f, table)
+     bdd f;
+     tt table;
+#endif
+{
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  result=cmu_bdd_not(bddm, f);
+  resulttable= ~table;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("not", result, expected, f, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+  result=cmu_bdd_identity(bddm, f);
+  resulttable=table;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("identity", result, expected, f, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_compose(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_compose(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  int var;
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  var=((unsigned long)random())%TT_VARS;
+  result=cmu_bdd_compose(bddm, f1, vars[var], cmu_bdd_one(bddm));
+  resulttable=cofactor(table1, var, 1);
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("restrict1", result, expected, f1, vars[var], (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+  result=cmu_bdd_compose(bddm, f1, vars[var], cmu_bdd_zero(bddm));
+  resulttable=cofactor(table1, var, 0);
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("restrict0", result, expected, f1, vars[var], (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+  result=cmu_bdd_compose(bddm, f1, vars[var], f2);
+  resulttable=(table2 & cofactor(table1, var, 1)) | (~table2 & cofactor(table1, var, 0));
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("compose", result, expected, f1, vars[var], f2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_qnt(bdd f, tt table)
+#else
+test_qnt(f, table)
+     bdd f;
+     tt table;
+#endif
+{
+  int var1, var2;
+  bdd assoc[3];
+  bdd temp;
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  var1=((unsigned long)random())%TT_VARS;
+  do
+    var2=((unsigned long)random())%TT_VARS;
+  while (var1 == var2);
+  assoc[0]=vars[var1];
+  assoc[1]=vars[var2];
+  assoc[2]=0;
+  cmu_bdd_temp_assoc(bddm, assoc, 0);
+  cmu_bdd_assoc(bddm, -1);
+  if (random()%2)
+    result=cmu_bdd_exists(bddm, f);
+  else
+    {
+      temp=cmu_bdd_not(bddm, f);
+      result=cmu_bdd_forall(bddm, temp);
+      cmu_bdd_free(bddm, temp);
+      temp=result;
+      result=cmu_bdd_not(bddm, temp);
+      cmu_bdd_free(bddm, temp);
+    }
+  resulttable=cofactor(table, var1, 1) | cofactor(table, var1, 0);
+  resulttable=cofactor(resulttable, var2, 1) | cofactor(resulttable, var2, 0);
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("quantification", result, expected, f, vars[var1], vars[var2], (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_rel_prod(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_rel_prod(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  int var1, var2;
+  bdd assoc[3];
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  var1=((unsigned long)random())%TT_VARS;
+  do
+    var2=((unsigned long)random())%TT_VARS;
+  while (var1 == var2);
+  assoc[0]=vars[var1];
+  assoc[1]=vars[var2];
+  assoc[2]=0;
+  cmu_bdd_temp_assoc(bddm, assoc, 0);
+  cmu_bdd_assoc(bddm, -1);
+  result=cmu_bdd_rel_prod(bddm, f1, f2);
+  table1&=table2;
+  resulttable=cofactor(table1, var1, 1) | cofactor(table1, var1, 0);
+  resulttable=cofactor(resulttable, var2, 1) | cofactor(resulttable, var2, 0);
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("relational product", result, expected, f1, f2, vars[var1], vars[var2], (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_subst(bdd f1, tt table1, bdd f2, tt table2, bdd f3, tt table3)
+#else
+test_subst(f1, table1, f2, table2, f3, table3)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+     bdd f3;
+     tt table3;
+#endif
+{
+  int var1, var2;
+  bdd assoc[6];
+  bdd result;
+  tt resulttable;
+  tt temp1, temp2, temp3, temp4;
+  bdd expected;
+
+  var1=((unsigned long)random())%TT_VARS;
+  do
+    var2=((unsigned long)random())%TT_VARS;
+  while (var1 == var2);
+  assoc[0]=vars[var1];
+  assoc[1]=f2;
+  assoc[2]=vars[var2];
+  assoc[3]=f3;
+  assoc[4]=0;
+  assoc[5]=0;
+  cmu_bdd_temp_assoc(bddm, assoc, 1);
+  cmu_bdd_assoc(bddm, -1);
+  result=cmu_bdd_substitute(bddm, f1);
+  temp1=cofactor(cofactor(table1, var1, 1), var2, 1);
+  temp2=cofactor(cofactor(table1, var1, 1), var2, 0);
+  temp3=cofactor(cofactor(table1, var1, 0), var2, 1);
+  temp4=cofactor(cofactor(table1, var1, 0), var2, 0);
+  resulttable=table2 & table3 & temp1;
+  resulttable|=table2 & ~table3 & temp2;
+  resulttable|=~table2 & table3 & temp3;
+  resulttable|=~table2 & ~table3 & temp4;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("substitute", result, expected, f1, vars[var1], f2, vars[var2], f3, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_inter_impl(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_inter_impl(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  bdd result;
+  tt resulttable;
+  bdd expected;
+  bdd implies_result;
+
+  result=cmu_bdd_intersects(bddm, f1, f2);
+  resulttable=table1 & table2;
+  expected=encoding_to_bdd(resulttable);
+  implies_result=cmu_bdd_implies(bddm, result, expected);
+  if (implies_result != cmu_bdd_zero(bddm))
+    {
+      error("intersection test", result, expected, f1, f2, (bdd)0);
+      cmu_bdd_free(bddm, implies_result);
+    }
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_sat(bdd f, tt table)
+#else
+test_sat(f, table)
+     bdd f;
+     tt table;
+#endif
+{
+  int var1, var2;
+  bdd assoc[TT_VARS+1];
+  bdd result;
+  bdd temp1, temp2, temp3;
+
+  if (f == cmu_bdd_zero(bddm))
+    return;
+  result=cmu_bdd_satisfy(bddm, f);
+  temp1=cmu_bdd_not(bddm, f);
+  temp2=cmu_bdd_intersects(bddm, temp1, result);
+  if (temp2 != cmu_bdd_zero(bddm))
+    error("intersection of satisfy result with negated argument", temp2, cmu_bdd_zero(bddm), f, (bdd)0);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  var1=((unsigned long)random())%TT_VARS;
+  do
+    var2=((unsigned long)random())%TT_VARS;
+  while (var1 == var2);
+  assoc[0]=vars[var1];
+  assoc[1]=vars[var2];
+  assoc[2]=0;
+  cmu_bdd_temp_assoc(bddm, assoc, 0);
+  cmu_bdd_assoc(bddm, -1);
+  temp1=cmu_bdd_satisfy_support(bddm, result);
+  temp2=cmu_bdd_not(bddm, result);
+  temp3=cmu_bdd_intersects(bddm, temp2, temp1);
+  if (temp3 != cmu_bdd_zero(bddm))
+    error("intersection of satisfy support result with negated argument", temp3, cmu_bdd_zero(bddm), result, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  cmu_bdd_free(bddm, temp3);
+  temp1=cmu_bdd_compose(bddm, f, vars[var1], cmu_bdd_zero(bddm));
+  temp2=cmu_bdd_compose(bddm, f, vars[var1], cmu_bdd_one(bddm));
+  if (cmu_bdd_satisfying_fraction(bddm, temp1)+cmu_bdd_satisfying_fraction(bddm, temp2) !=
+      2.0*cmu_bdd_satisfying_fraction(bddm, f))
+    {
+      fprintf(stderr, "\nError: operation satisfying fraction:\n");
+      fprintf(stderr, "Argument:\n");
+      print_bdd(f);
+      fprintf(stderr, "Cofactor on:\n");
+      print_bdd(vars[var1]);
+    }
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_gen_cof(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_gen_cof(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  int var1, var2;
+  bdd result;
+  bdd temp1, temp2, temp3;
+  tt resulttable;
+  bdd expected;
+
+  result=cmu_bdd_cofactor(bddm, f1, f2);
+  temp1=cmu_bdd_xnor(bddm, result, f1);
+  temp2=cmu_bdd_not(bddm, f2);
+  temp3=cmu_bdd_or(bddm, temp1, temp2);
+  if (temp3 != cmu_bdd_one(bddm))
+    error("d.c. comparison of generalized cofactor", temp3, cmu_bdd_one(bddm), f1, f2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  cmu_bdd_free(bddm, temp3);
+  var1=((unsigned long)random())%TT_VARS;
+  do
+    var2=((unsigned long)random())%TT_VARS;
+  while (var1 == var2);
+  temp1=cmu_bdd_not(bddm, vars[var2]);
+  temp2=cmu_bdd_and(bddm, vars[var1], temp1);
+  cmu_bdd_free(bddm, temp1);
+  result=cmu_bdd_cofactor(bddm, f1, temp2);
+  resulttable=cofactor(cofactor(table1, var1, 1), var2, 0);
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("generalized cofactor", result, expected, f1, temp2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+  cmu_bdd_free(bddm, temp2);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_reduce(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_reduce(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  bdd result;
+  bdd temp1, temp2, temp3;
+
+  result=cmu_bdd_reduce(bddm, f1, f2);
+  temp1=cmu_bdd_xnor(bddm, result, f1);
+  temp2=cmu_bdd_not(bddm, f2);
+  temp3=cmu_bdd_or(bddm, temp1, temp2);
+  if (temp3 != cmu_bdd_one(bddm))
+    error("d.c. comparison of reduce", temp3, cmu_bdd_one(bddm), f1, f2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  cmu_bdd_free(bddm, temp3);
+}
+
+
+static
+bdd
+#if defined(__STDC__)
+apply_and(cmu_bdd_manager bddm, bdd *f, bdd *g, pointer env)
+#else
+apply_and(bddm, f, g, env)
+     cmu_bdd_manager bddm;
+     bdd *f;
+     bdd *g;
+     pointer env;
+#endif
+{
+  bdd f1, g1;
+
+  f1= *f;
+  g1= *g;
+  {
+    if (f1 == BDD_ZERO(bddm))
+      return (f1);
+    if (g1 == BDD_ZERO(bddm))
+      return (g1);
+    if (f1 == BDD_ONE(bddm))
+      return (g1);
+    if (g1 == BDD_ONE(bddm))
+      return (f1);
+    if ((INT_PTR)f1 < (INT_PTR)g1)
+      {
+	*f=g1;
+	*g=f1;
+      }
+    return ((bdd)0);
+  }
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_apply(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_apply(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  bdd result;
+  tt resulttable;
+  bdd expected;
+
+  result=bdd_apply2(bddm, apply_and, f1, f2, (pointer)0);
+  resulttable=table1 & table2;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("apply2", result, expected, f1, f2, (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_size(bdd f1, tt table1, bdd f2, tt table2)
+#else
+test_size(f1, table1, f2, table2)
+     bdd f1;
+     tt table1;
+     bdd f2;
+     tt table2;
+#endif
+{
+  int i;
+  long size;
+  long profile[2*TT_VARS+1];
+  bdd fs[3];
+
+  size=cmu_bdd_size(bddm, f1, 1);
+  cmu_bdd_profile(bddm, f1, profile, 1);
+  for (i=0; i < 2*TT_VARS+1; ++i)
+    size-=profile[i];
+  if (size)
+    {
+      fprintf(stderr, "\nError: size count vs. profile sum:\n");
+      fprintf(stderr, "Argument:\n");
+      print_bdd(f1);
+    }
+  size=cmu_bdd_size(bddm, f1, 0);
+  cmu_bdd_profile(bddm, f1, profile, 0);
+  for (i=0; i < 2*TT_VARS+1; ++i)
+    size-=profile[i];
+  if (size)
+    {
+      fprintf(stderr, "\nError: no negout size count vs. profile sum:\n");
+      fprintf(stderr, "Argument:\n");
+      print_bdd(f1);
+    }
+  fs[0]=f1;
+  fs[1]=f2;
+  fs[2]=0;
+  size=cmu_bdd_size_multiple(bddm, fs, 1);
+  cmu_bdd_profile_multiple(bddm, fs, profile, 1);
+  for (i=0; i < 2*TT_VARS+1; ++i)
+    size-=profile[i];
+  if (size)
+    {
+      fprintf(stderr, "\nError: multiple size count vs. multiple profile sum:\n");
+      fprintf(stderr, "Argument 1:\n");
+      print_bdd(f1);
+      fprintf(stderr, "Argument 2:\n");
+      print_bdd(f2);
+    }
+}
+
+
+static
+int
+#if defined(__STDC__)
+canonical_fn(cmu_bdd_manager bddm, INT_PTR v1, INT_PTR v2, pointer env)
+#else
+canonical_fn(bddm, v1, v2, env)
+     cmu_bdd_manager bddm;
+     INT_PTR v1;
+     INT_PTR v2;
+     pointer env;
+#endif
+{
+  return (as_double(v1, v2) > 0);
+}
+
+
+static
+void
+#if defined(__STDC__)
+transform_fn(cmu_bdd_manager bddm, INT_PTR v1, INT_PTR v2, INT_PTR *r1, INT_PTR *r2, pointer env)
+#else
+transform_fn(bddm, v1, v2, r1, r2, env)
+     cmu_bdd_manager bddm;
+     INT_PTR v1;
+     INT_PTR v2;
+     INT_PTR *r1;
+     INT_PTR *r2;
+     pointer env;
+#endif
+{
+  as_INT_PTRs(-as_double(v1, v2), r1, r2);
+}
+
+
+static
+bdd
+#if defined(__STDC__)
+terminal(double n)
+#else
+terminal(n)
+     double n;
+#endif
+{
+  INT_PTR v1, v2;
+
+  as_INT_PTRs(n, &v1, &v2);
+  return (cmu_mtbdd_get_terminal(bddm, v1, v2));
+}
+
+
+static
+bdd
+#if defined(__STDC__)
+walsh_matrix(int n)
+#else
+walsh_matrix(n)
+     int n;
+#endif
+{
+  bdd temp1, temp2, temp3;
+  bdd result;
+
+  if (n == TT_VARS)
+    return (terminal(1.0));
+  temp1=walsh_matrix(n+1);
+  temp2=mtbdd_transform(bddm, temp1);
+  temp3=temp2;
+  temp2=mtcmu_bdd_ite(bddm, aux_vars[n], temp3, temp1);
+  cmu_bdd_free(bddm, temp3);
+  result=mtcmu_bdd_ite(bddm, vars[n], temp2, temp1);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  return (result);
+}
+
+
+#define OP_MULT 1000l
+#define OP_ADD 1100l
+
+
+static
+bdd
+#if defined(__STDC__)
+mtbdd_mult_step(cmu_bdd_manager bddm, bdd f, bdd g)
+#else
+mtbdd_mult_step(bddm, f, g)
+     cmu_bdd_manager bddm;
+     bdd f;
+     bdd g;
+#endif
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+  INT_PTR u1, u2;
+  INT_PTR v1, v2;
+  
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (BDD_IS_CONST(f) && BDD_IS_CONST(g))
+    {
+      cmu_mtbdd_terminal_value_aux(bddm, f, &u1, &u2);
+      cmu_mtbdd_terminal_value_aux(bddm, g, &v1, &v2);
+      as_INT_PTRs(as_double(u1, u2)*as_double(v1, v2), &u1, &u2);
+      return (bdd_find_terminal(bddm, u1, u2));
+    }
+  if (BDD_OUT_OF_ORDER(f, g))
+    BDD_SWAP(f, g);
+  if (bdd_lookup_in_cache2(bddm, OP_MULT, f, g, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=mtbdd_mult_step(bddm, f1, g1);
+  temp2=mtbdd_mult_step(bddm, f2, g2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache2(bddm, OP_MULT, f, g, result);
+  return (result);
+}
+
+
+static
+bdd
+#if defined(__STDC__)
+mtbdd_mult(cmu_bdd_manager bddm, bdd f, bdd g)
+#else
+mtbdd_mult(bddm, f, g)
+     cmu_bdd_manager bddm;
+     bdd f;
+     bdd g;
+#endif
+{
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(mtbdd_mult_step(bddm, f, g));
+    }
+  return ((bdd)0);
+}
+
+
+static
+bdd
+#if defined(__STDC__)
+mtbdd_add_step(cmu_bdd_manager bddm, bdd f, bdd g)
+#else
+mtbdd_add_step(bddm, f, g)
+     cmu_bdd_manager bddm;
+     bdd f;
+     bdd g;
+#endif
+{
+  bdd_indexindex_type top_indexindex;
+  bdd f1, f2;
+  bdd g1, g2;
+  bdd temp1, temp2;
+  bdd result;
+  INT_PTR u1, u2;
+  INT_PTR v1, v2;
+  
+  BDD_SETUP(f);
+  BDD_SETUP(g);
+  if (BDD_IS_CONST(f) && BDD_IS_CONST(g))
+    {
+      cmu_mtbdd_terminal_value_aux(bddm, f, &u1, &u2);
+      cmu_mtbdd_terminal_value_aux(bddm, g, &v1, &v2);
+      as_INT_PTRs(as_double(u1, u2)+as_double(v1, v2), &u1, &u2);
+      return (bdd_find_terminal(bddm, u1, u2));
+    }
+  if (BDD_OUT_OF_ORDER(f, g))
+    BDD_SWAP(f, g);
+  if (bdd_lookup_in_cache2(bddm, OP_ADD, f, g, &result))
+    return (result);
+  BDD_TOP_VAR2(top_indexindex, bddm, f, g);
+  BDD_COFACTOR(top_indexindex, f, f1, f2);
+  BDD_COFACTOR(top_indexindex, g, g1, g2);
+  temp1=mtbdd_add_step(bddm, f1, g1);
+  temp2=mtbdd_add_step(bddm, f2, g2);
+  result=bdd_find(bddm, top_indexindex, temp1, temp2);
+  bdd_insert_in_cache2(bddm, OP_ADD, f, g, result);
+  return (result);
+}
+
+
+static
+bdd
+#if defined(__STDC__)
+mtbdd_add(cmu_bdd_manager bddm, bdd f, bdd g)
+#else
+mtbdd_add(bddm, f, g)
+     cmu_bdd_manager bddm;
+     bdd f;
+     bdd g;
+#endif
+{
+  if (bdd_check_arguments(2, f, g))
+    {
+      FIREWALL(bddm);
+      RETURN_BDD(mtbdd_add_step(bddm, f, g));
+    }
+  return ((bdd)0);
+}
+
+
+static
+bdd
+#if defined(__STDC__)
+transform(bdd f, bdd g, bdd *elim_vars)
+#else
+transform(f, g, elim_vars)
+     bdd f;
+     bdd g;
+     bdd *elim_vars;
+#endif
+{
+  int i;
+  bdd temp1, temp2;
+  bdd result;
+
+  result=mtbdd_mult(bddm, f, g);
+  for (i=0; i < TT_VARS; ++i)
+    {
+      temp1=cmu_bdd_compose(bddm, result, elim_vars[i], cmu_bdd_one(bddm));
+      temp2=cmu_bdd_compose(bddm, result, elim_vars[i], cmu_bdd_zero(bddm));
+      cmu_bdd_free(bddm, result);
+      result=mtbdd_add(bddm, temp1, temp2);
+      cmu_bdd_free(bddm, temp1);
+      cmu_bdd_free(bddm, temp2);
+    }
+  return (result);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_mtbdd(bdd f1, tt table1)
+#else
+test_mtbdd(f1, table1)
+     bdd f1;
+     tt table1;
+#endif
+{
+  bdd wm;
+  bdd temp1, temp2;
+  bdd result;
+
+  wm=walsh_matrix(0);
+  temp1=transform(wm, f1, vars);
+  temp2=temp1;
+  temp1=transform(wm, temp2, aux_vars);
+  cmu_bdd_free(bddm, wm);
+  cmu_bdd_free(bddm, temp2);
+  temp2=terminal(1.0/TT_BITS);
+  result=mtbdd_mult(bddm, temp1, temp2);
+  cmu_bdd_free(bddm, temp1);
+  cmu_bdd_free(bddm, temp2);
+  if (f1 != result)
+    error("Walsh transformation and inverse", result, f1, (bdd)0);
+  cmu_bdd_free(bddm, result);
+}
+
+
+static
+void
+#if defined(__STDC__)
+test_swap(bdd f, tt table)
+#else
+test_swap(f, table)
+     bdd f;
+     tt table;
+#endif
+{
+  int var1, var2;
+  bdd result;
+  tt resulttable;
+  tt temp1, temp2, temp3, temp4;
+  bdd expected;
+
+  var1=((unsigned long)random())%TT_VARS;
+  var2=((unsigned long)random())%TT_VARS;
+  result=cmu_bdd_swap_vars(bddm, f, vars[var1], vars[var2]);
+  temp1=cofactor(cofactor(table, var1, 1), var2, 1);
+  temp2=cofactor(cofactor(table, var1, 1), var2, 0);
+  temp3=cofactor(cofactor(table, var1, 0), var2, 1);
+  temp4=cofactor(cofactor(table, var1, 0), var2, 0);
+  resulttable=cofactor_masks[var2] & cofactor_masks[var1] & temp1;
+  resulttable|=cofactor_masks[var2] & ~cofactor_masks[var1] & temp2;
+  resulttable|=~cofactor_masks[var2] & cofactor_masks[var1] & temp3;
+  resulttable|=~cofactor_masks[var2] & ~cofactor_masks[var1] & temp4;
+  expected=encoding_to_bdd(resulttable);
+  if (result != expected)
+    error("swap variables", result, expected, f, vars[var1], vars[var2], (bdd)0);
+  cmu_bdd_free(bddm, result);
+  cmu_bdd_free(bddm, expected);
+}
+
+
+static void
+#if defined(__STDC__)
+test_dump(bdd f, tt table)
+#else
+test_dump(f, table)
+     bdd f;
+     tt table;
+#endif
+{
+  FILE *fp;
+  int i, j;
+  bdd dump_vars[TT_VARS+1];
+  bdd temp;
+  bdd result;
+  int err;
+
+  if (!(fp=tmpfile()))
+    {
+      fprintf(stderr, "could not open temporary file\n");
+      exit(1);
+    }
+  for (i=0; i < TT_VARS; ++i)
+    dump_vars[i]=vars[i];
+  dump_vars[i]=0;
+  for (i=0; i < TT_VARS-1; ++i)
+    {
+      j=i+((unsigned long)random())%(TT_VARS-i);
+      temp=dump_vars[i];
+      dump_vars[i]=dump_vars[j];
+      dump_vars[j]=temp;
+    }
+  if (!cmu_bdd_dump_bdd(bddm, f, dump_vars, fp))
+    {
+      fprintf(stderr, "Error: dump failure:\n");
+      fprintf(stderr, "Argument:\n");
+      print_bdd(f);
+      fclose(fp);
+      return;
+    }
+  rewind(fp);
+  if (!(result=cmu_bdd_undump_bdd(bddm, dump_vars, fp, &err)) || err)
+    {
+      fprintf(stderr, "Error: undump failure: code %d:\n", err);
+      fprintf(stderr, "Argument:\n");
+      print_bdd(f);
+      fclose(fp);
+      return;
+    }
+  fclose(fp);
+  if (result != f)
+    error("dump/undump", result, f, f, (bdd)0);
+  cmu_bdd_free(bddm, result);
+}
+
+
+static
+void
+#if defined(__STDC__)
+check_leak(void)
+#else
+check_leak()
+#endif
+{
+  bdd assoc[1];
+
+  assoc[0]=0;
+  cmu_bdd_temp_assoc(bddm, assoc, 0);
+  cmu_bdd_gc(bddm);
+  if (cmu_bdd_total_size(bddm) != 2*TT_VARS+1l)
+    fprintf(stderr, "Memory leak somewhere...\n");
+}
+
+
+static
+void
+#if defined(__STDC__)
+random_tests(int iterations)
+#else
+random_tests(iterations)
+     int iterations;
+#endif
+{
+  int i;
+  tt table1, table2, table3;
+  bdd f1, f2, f3;
+  INT_PTR v1, v2;
+
+  printf("Random operation tests...\n");
+  bddm=cmu_bdd_init();
+  cmu_bdd_node_limit(bddm, 5000);
+  mtbdd_transform_closure(bddm, canonical_fn, transform_fn, (pointer)0);
+  as_INT_PTRs(-1.0, &v1, &v2);
+  mtcmu_bdd_one_data(bddm, v1, v2);
+  vars[1]=cmu_bdd_new_var_last(bddm);
+  vars[0]=cmu_bdd_new_var_first(bddm);
+  vars[4]=cmu_bdd_new_var_after(bddm, vars[1]);
+  vars[3]=cmu_bdd_new_var_before(bddm, vars[4]);
+  vars[2]=cmu_bdd_new_var_after(bddm, vars[1]);
+  for (i=0; i < 5; ++i)
+    aux_vars[i]=cmu_bdd_new_var_after(bddm, vars[i]);
+  for (i=0; i < iterations; ++i)
+    {
+      if ((i & 0xf) == 0)
+	{
+	  putchar('.');
+	  fflush(stdout);
+	}
+      if ((i & 0x3ff) == 0x3ff)
+	{
+	  putchar('\n');
+	  fflush(stdout);
+	  check_leak();
+	}
+      table1=random();
+      table2=random();
+      table3=random();
+      f1=encoding_to_bdd(table1);
+      f2=encoding_to_bdd(table2);
+      f3=encoding_to_bdd(table3);
+      test_ite(f1, table1, f2, table2, f3, table3);
+      test_and(f1, table1, f2, table2);
+      test_or(f1, table1, f2, table2);
+      test_xor(f1, table1, f2, table2);
+      test_id_not(f1, table1);
+      test_compose(f1, table1, f2, table2);
+      test_qnt(f1, table1);
+      test_rel_prod(f1, table1, f2, table2);
+      test_subst(f1, table1, f2, table2, f3, table3);
+      test_inter_impl(f1, table1, f2, table2);
+      test_sat(f1, table1);
+      test_gen_cof(f1, table1, f2, table2);
+      test_reduce(f1, table1, f2, table2);
+      test_apply(f1, table1, f2, table2);
+      test_size(f1, table1, f2, table2);
+      test_mtbdd(f1, table1);
+      test_swap(f1, table1);
+      if (i < 100)
+	test_dump(f1, table1);
+      cmu_bdd_free(bddm, f1);
+      cmu_bdd_free(bddm, f2);
+      cmu_bdd_free(bddm, f3);
+    }
+  putchar('\n');
+  cmu_bdd_stats(bddm, stdout);
+  cmu_bdd_quit(bddm);
+}
+
+
+int
+#if defined(__STDC__)
+main(void)
+#else
+main()
+#endif
+{
+  (void) srandom((unsigned) 1);
+  random_tests(ITERATIONS);
+  exit(0);
+}
Index: /vis_dev/glu-2.1/src/cmuPort/cmuPort.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuPort/cmuPort.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuPort/cmuPort.c	(revision 8)
@@ -0,0 +1,2936 @@
+/**CFile***********************************************************************
+
+  FileName    [cmuPort.c]
+
+  PackageName [cmu_port]
+
+  Synopsis    [Port routines for CMU package.]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Thomas R. Shiple. Some changes by Rajeev K. Ranjan.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: cmuPort.c,v 1.78 2003/08/05 20:28:24 fabio Exp $]
+
+******************************************************************************/
+
+#include "cmuPortInt.h" 
+#ifndef	EPD_MAX_BIN
+#include "epd.h" 
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the bdd_t structure.]
+
+  Description [Builds the bdd_t structure from manager and node.
+  Assumes that the reference count of the node has already been
+  increased.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_construct_bdd_t(bdd_manager *manager, bdd_node *func)
+{
+    bdd_t *result;
+    cmu_bdd_manager mgr = (cmu_bdd_manager)manager;
+    bdd fn = (bdd)func;
+
+    if (fn == (struct bdd_ *) 0) {
+	cmu_bdd_fatal("bdd_construct_bdd_t: possible memory overflow");
+    }
+
+    result = ALLOC(bdd_t, 1);
+    result->mgr = mgr;
+    result->node = fn;
+    result->free = FALSE;
+    return result;
+}
+
+/**Function********************************************************************
+  Synopsis           [required]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+******************************************************************************/
+bdd_package_type_t
+bdd_get_package_name(void)
+{
+  return CMU;
+}
+
+/*
+BDD Manager Allocation And Destruction ----------------------------------------
+*/
+void
+bdd_end(bdd_manager *manager)
+{
+    bdd_external_hooks *hooks;
+    cmu_bdd_manager mgr = (cmu_bdd_manager)manager;
+    hooks = (bdd_external_hooks *) mgr->hooks;
+    FREE(hooks); 
+    cmu_bdd_quit(mgr);
+}
+
+
+bdd_manager *
+bdd_start(int nvariables)
+{
+    struct bdd_manager_ *mgr;
+    int i;
+    bdd_external_hooks *hooks;
+   
+    mgr = cmu_bdd_init();    /*no args*/
+
+    /*
+     * Calls to UCB bdd_get_variable are translated into cmu_bdd_var_with_id calls.  However,
+     * cmu_bdd_var_with_id assumes that single variable BDDs have already been created for 
+     * all the variables that we wish to access.  Thus, following, we explicitly create n
+     * variables.  We do not care about the return value of cmu_bdd_new_var_last; in the 
+     * CMU package, the single variable BDDs are NEVER garbage collected.
+     */
+    for (i = 0; i < nvariables; i++) {
+	(void) cmu_bdd_new_var_last(mgr);
+    }
+
+    hooks = ALLOC(bdd_external_hooks, 1);
+    hooks->mdd = hooks->network = hooks->undef1 = (char *) 0;
+    mgr->hooks = (char *) hooks;  /* new field added to CMU manager */
+
+    return (bdd_manager *) mgr;
+}
+
+/*
+BDD Variable Allocation -------------------------------------------------------
+*/
+
+bdd_t *
+bdd_create_variable(bdd_manager *manager)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  return bdd_construct_bdd_t(mgr, cmu_bdd_new_var_last(mgr));
+}
+
+bdd_t *
+bdd_create_variable_after(bdd_manager *manager, bdd_variableId after_id)
+{
+  struct bdd_ *after_var;
+  bdd_t 	*result;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+
+  after_var = cmu_bdd_var_with_id(mgr, (long)after_id + 1);
+  
+  result =  bdd_construct_bdd_t(mgr, cmu_bdd_new_var_after(mgr, after_var));
+  
+  /* No need to free after_var, since single variable BDDs are never garbage collected */
+  
+  return result;
+}
+
+
+
+bdd_t *
+bdd_get_variable(bdd_manager *manager, bdd_variableId variable_ID)
+{
+  struct bdd_ *fn;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  fn = cmu_bdd_var_with_id(mgr, (long) (variable_ID + 1));
+
+  if (fn == (struct bdd_ *) 0) {
+	/* variable should always be found, since they are created at bdd_start */
+	cmu_bdd_fatal("bdd_get_variable: assumption violated");
+  }
+  
+  return bdd_construct_bdd_t(mgr, fn);
+}
+
+/*
+BDD Formula Management --------------------------------------------------------
+*/
+
+bdd_t *
+bdd_dup(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->mgr, cmu_bdd_identity(f->mgr, f->node));
+}
+
+void
+bdd_free(bdd_t *f)
+{
+  if (f == NIL(bdd_t)) {
+	fail("bdd_free: trying to free a NIL bdd_t");			
+  }
+  
+  if (f->free == TRUE) {
+	fail("bdd_free: trying to free a freed bdd_t");			
+  }	
+  
+  cmu_bdd_free(f->mgr, f->node);
+  
+  /*
+   * In case the user tries to free this bdd_t again, set the free field to TRUE, 
+     * and NIL out the other fields.  Then free the bdd_t structure itself.
+     */
+  f->free = TRUE;
+  f->node = NIL(struct bdd_);
+  f->mgr = NIL(struct bdd_manager_);
+  FREE(f);  
+}
+
+/*
+  Operations on BDD Formulas ----------------------------------------------------
+  */
+
+bdd_t *
+bdd_and(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase)
+{
+  struct bdd_ *temp1, *temp2;
+  bdd_t *result;
+  struct bdd_manager_ *mgr;
+  
+  mgr = f->mgr;
+  temp1 = ( (f_phase == TRUE) ? cmu_bdd_identity(mgr, f->node) : cmu_bdd_not(mgr, f->node));
+  temp2 = ( (g_phase == TRUE) ? cmu_bdd_identity(mgr, g->node) : cmu_bdd_not(mgr, g->node));
+  result = bdd_construct_bdd_t(mgr, cmu_bdd_and(mgr, temp1, temp2));
+  cmu_bdd_free(mgr, temp1);
+  cmu_bdd_free(mgr, temp2);
+  return result;
+}
+
+bdd_t *
+bdd_and_with_limit(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase,
+  unsigned int limit)
+{
+  /* Unsupported: fall back on standard AND. */
+  return bdd_and(f, g, f_phase, g_phase);
+}
+
+bdd_t *
+bdd_and_array(
+  bdd_t *f,
+  array_t *g_array,
+  boolean f_phase,
+  boolean g_phase)
+{
+  struct bdd_ *temp1, *temp2, *result;
+  bdd_t *g;
+  struct bdd_manager_ *mgr;
+  int i;
+
+  mgr = f->mgr;
+  result = ((f_phase == TRUE) ? cmu_bdd_identity(mgr, f->node) :
+            cmu_bdd_not(mgr, f->node)); 
+
+  for (i = 0; i < array_n(g_array); i++) {
+    g = array_fetch(bdd_t *, g_array, i);
+    temp1 = result;
+    temp2 = ((g_phase == TRUE) ? cmu_bdd_identity(mgr, g->node) :
+             cmu_bdd_not(mgr, g->node));
+    result = cmu_bdd_and(mgr, temp1, temp2);
+    cmu_bdd_free(mgr, temp1);
+    cmu_bdd_free(mgr, temp2);
+    if (result == NULL)
+      return(NULL);
+  }
+
+  return(bdd_construct_bdd_t(mgr, result));
+}
+
+bdd_t *
+bdd_multiway_and(bdd_manager *manager, array_t *bddArray)
+{
+  int i;
+  bdd temp, result;
+  bdd_t *operand;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  result = cmu_bdd_one(mgr);
+  for (i=0; i<array_n(bddArray); i++){
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = cmu_bdd_and(mgr, result, operand->node);
+    cmu_bdd_free(mgr, result);
+    result = temp;
+  }
+  return bdd_construct_bdd_t(mgr, result);
+}
+
+bdd_t *
+bdd_multiway_or(bdd_manager *manager, array_t *bddArray)
+{
+  int i;
+  bdd temp, result;
+  bdd_t *operand;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  result = cmu_bdd_zero(mgr);
+  for (i=0; i<array_n(bddArray); i++){
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = cmu_bdd_or(mgr, result, operand->node);
+    cmu_bdd_free(mgr, result);
+    result = temp;
+  }
+  return bdd_construct_bdd_t(mgr, result);
+}
+
+bdd_t *
+bdd_multiway_xor(bdd_manager *manager, array_t *bddArray)
+{
+  int i;
+  bdd temp, result;
+  bdd_t *operand;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  result = cmu_bdd_zero(mgr);
+  for (i=0; i<array_n(bddArray); i++){
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = cmu_bdd_xor(mgr, result, operand->node);
+    cmu_bdd_free(mgr, result);
+    result = temp;
+  }
+  return bdd_construct_bdd_t(mgr, result);
+}
+
+array_t *
+bdd_pairwise_or(bdd_manager *manager, array_t *bddArray1, array_t
+                *bddArray2) 
+{
+  int i;
+  bdd_t *operand1, *operand2;
+  array_t *resultArray;
+  bdd result;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  if (array_n(bddArray1) != array_n(bddArray2)){
+    fprintf(stderr, "bdd_pairwise_or: Arrays of different lengths.\n");
+    return NIL(array_t);
+  }
+  resultArray = array_alloc(bdd_t *, 0);
+  for (i=0; i<array_n(bddArray1); i++){
+    operand1 = array_fetch(bdd_t *, bddArray1, i);
+    operand2 = array_fetch(bdd_t *, bddArray2, i);
+    result = cmu_bdd_or(mgr, operand1->node, operand2->node);
+    array_insert_last(bdd_t*, resultArray,
+                      bdd_construct_bdd_t(mgr, result)); 
+  }
+  return resultArray;
+}
+
+array_t *
+bdd_pairwise_and(bdd_manager *manager, array_t *bddArray1, array_t
+                 *bddArray2) 
+{
+  int i;
+  bdd_t *operand1, *operand2;
+  array_t *resultArray;
+  bdd result;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  if (array_n(bddArray1) != array_n(bddArray2)){
+    fprintf(stderr, "bdd_pairwise_and: Arrays of different lengths.\n");
+    return NIL(array_t);
+  }
+  resultArray = array_alloc(bdd_t *, 0);
+  for (i=0; i<array_n(bddArray1); i++){
+    operand1 = array_fetch(bdd_t *, bddArray1, i);
+    operand2 = array_fetch(bdd_t *, bddArray2, i);
+    result = cmu_bdd_and(mgr, operand1->node, operand2->node);
+    array_insert_last(bdd_t*, resultArray,
+                      bdd_construct_bdd_t(mgr, result)); 
+  }
+  return resultArray;
+}
+
+array_t *
+bdd_pairwise_xor(bdd_manager *manager, array_t *bddArray1, array_t
+                 *bddArray2) 
+{
+  int i;
+  bdd_t *operand1, *operand2;
+  array_t *resultArray;
+  bdd result;
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  if (array_n(bddArray1) != array_n(bddArray2)){
+    fprintf(stderr, "bdd_pairwise_xor: Arrays of different lengths.\n");
+    return NIL(array_t);
+  }
+  resultArray = array_alloc(bdd_t *, 0);
+  for (i=0; i<array_n(bddArray1); i++){
+    operand1 = array_fetch(bdd_t *, bddArray1, i);
+    operand2 = array_fetch(bdd_t *, bddArray2, i);
+    result = cmu_bdd_xor(mgr, operand1->node, operand2->node);
+    array_insert_last(bdd_t*, resultArray,
+                      bdd_construct_bdd_t(mgr, result)); 
+  }
+  return resultArray;
+}
+
+bdd_t *
+bdd_and_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars /* of bdd_t *'s */)
+{
+  int num_vars, i;
+  bdd_t *fn, *result;
+  struct bdd_ **assoc;
+  struct bdd_manager_ *mgr;
+  
+  num_vars = array_n(smoothing_vars);
+  if (num_vars <= 0) {
+	cmu_bdd_fatal("bdd_and_smooth: no smoothing variables");
+  }
+  
+  assoc = ALLOC(struct bdd_ *, num_vars+1);
+  
+  for (i = 0; i < num_vars; i++) {
+	fn = array_fetch(bdd_t *, smoothing_vars, i);
+	assoc[i] = fn->node;
+  }
+  assoc[num_vars] = (struct bdd_ *) 0;
+  
+  mgr = f->mgr;
+  cmu_bdd_temp_assoc(mgr, assoc, 0);
+  (void) cmu_bdd_assoc(mgr, -1);  /* set the temp association as the current association */
+  
+  result = bdd_construct_bdd_t(mgr, cmu_bdd_rel_prod(mgr, f->node, g->node));
+  FREE(assoc);
+  return result;
+}
+
+bdd_t *
+bdd_and_smooth_with_limit(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars /* of bdd_t *'s */,
+  unsigned int limit)
+{
+  /* Unsupported: fall back to standard and_smooth */
+  return bdd_and_smooth(f, g, smoothing_vars);
+}
+
+bdd_t *
+bdd_between(bdd_t *f_min, bdd_t *f_max)
+{
+  bdd_t *temp, *ret;
+  long size1, size2, size3; 
+  temp = bdd_or(f_min, f_max, 1, 0);
+  ret = bdd_minimize(f_min, temp);
+  bdd_free(temp);
+  size1 = bdd_size(f_min);
+  size2 = bdd_size(f_max);
+  size3 = bdd_size(ret);
+  if (size3 < size1) {
+	if (size3 < size2){
+      return ret;
+    }
+    else {
+      bdd_free(ret);
+      return bdd_dup(f_max);
+    }
+  }
+  else {
+    bdd_free(ret);
+    if (size1 < size2){
+      return bdd_dup(f_min);
+    }
+    else {
+      return bdd_dup(f_max);
+    }
+  }
+}
+
+bdd_t *
+bdd_cofactor(bdd_t *f, bdd_t *g)
+{
+  return bdd_construct_bdd_t(f->mgr, cmu_bdd_cofactor(f->mgr, f->node, g->node));
+}
+
+bdd_t *
+bdd_cofactor_array(bdd_t *f, array_t *bddArray)
+{
+  bdd_t *operand;
+  struct bdd_ *result, *temp;
+  int i;
+
+  result = cmu_bdd_identity(f->mgr, f->node);
+
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = cmu_bdd_cofactor(f->mgr, result, operand->node);
+    if (temp == NULL) {
+      cmu_bdd_free(f->mgr, result);
+      return(NULL);
+    }
+    cmu_bdd_free(f->mgr, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(f->mgr, result));
+}
+
+bdd_t *
+bdd_compose(
+  bdd_t *f,
+  bdd_t *v,
+  bdd_t *g)
+{
+  return bdd_construct_bdd_t(f->mgr, cmu_bdd_compose(f->mgr, f->node, v->node, g->node));
+}
+
+bdd_t *
+bdd_consensus(
+  bdd_t *f,
+  array_t *quantifying_vars /* of bdd_t *'s */)
+{
+  int num_vars, i;
+  bdd_t *fn, *result;
+  struct bdd_ **assoc;
+  struct bdd_manager_ *mgr;
+  
+  num_vars = array_n(quantifying_vars);
+  if (num_vars <= 0) {
+	cmu_bdd_fatal("bdd_consensus: no quantifying variables");
+  }
+  
+  assoc = ALLOC(struct bdd_ *, num_vars+1);
+  
+  for (i = 0; i < num_vars; i++) {
+	fn = array_fetch(bdd_t *, quantifying_vars, i);
+	assoc[i] = fn->node;
+  }
+  assoc[num_vars] = (struct bdd_ *) 0;
+  
+  mgr = f->mgr;
+  cmu_bdd_temp_assoc(mgr, assoc, 0);
+  (void) cmu_bdd_assoc(mgr, -1);  /* set the temp association as the current association */
+  
+  result = bdd_construct_bdd_t(mgr, cmu_bdd_forall(mgr, f->node));
+  FREE(assoc);
+  return result;
+}
+
+
+bdd_t *
+bdd_cproject(
+  bdd_t *f,
+  array_t *quantifying_vars /* of bdd_t* */)
+{
+  int num_vars, i;
+  bdd_t *fn, *result;
+  struct bdd_ **assoc;
+  struct bdd_manager_ *mgr;
+  
+  if (f == NIL(bdd_t)) fail ("bdd_cproject: invalid BDD");
+  
+  num_vars = array_n(quantifying_vars);
+  if (num_vars <= 0) {
+    printf("Warning: bdd_cproject: no projection variables\n");
+    result = bdd_dup(f);
+  }
+  else {
+    assoc = ALLOC(struct bdd_ *, num_vars+1);
+    for (i = 0; i < num_vars; i++) {
+      fn = array_fetch(bdd_t *, quantifying_vars, i);
+      assoc[i] = fn->node;
+    }
+    assoc[num_vars] = (struct bdd_ *) 0;
+    mgr = f->mgr;
+    cmu_bdd_temp_assoc(mgr, assoc, 0);
+    (void) cmu_bdd_assoc(mgr, -1);  /* set the temp association as the current a
+                                       ssociation */
+    
+    result = bdd_construct_bdd_t(mgr, cmu_bdd_project(mgr, f->node));
+    FREE(assoc);
+  }
+  return result;
+}
+
+
+bdd_t *
+bdd_else(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->mgr, cmu_bdd_else(f->mgr, f->node));
+}
+
+
+bdd_t *
+bdd_ite(
+  bdd_t *i,
+  bdd_t *t,
+  bdd_t *e,
+  boolean i_phase,
+  boolean t_phase,
+  boolean e_phase)
+{
+  struct bdd_ *temp1, *temp2, *temp3;
+  bdd_t *result;
+  struct bdd_manager_ *mgr;
+  
+  mgr = i->mgr;
+  temp1 = ( (i_phase == TRUE) ? cmu_bdd_identity(mgr, i->node) : cmu_bdd_not(mgr, i->node));
+  temp2 = ( (t_phase == TRUE) ? cmu_bdd_identity(mgr, t->node) : cmu_bdd_not(mgr, t->node));
+  temp3 = ( (e_phase == TRUE) ? cmu_bdd_identity(mgr, e->node) : cmu_bdd_not(mgr, e->node));
+  result = bdd_construct_bdd_t(mgr, cmu_bdd_ite(mgr, temp1, temp2, temp3));
+  cmu_bdd_free(mgr, temp1);
+  cmu_bdd_free(mgr, temp2);
+  cmu_bdd_free(mgr, temp3);
+  return result;
+}
+
+bdd_t *
+bdd_minimize(bdd_t *f, bdd_t *c)
+{
+  bdd_t *result = bdd_construct_bdd_t(f->mgr, cmu_bdd_reduce(f->mgr,
+                                                             f->node,
+                                                             c->node)); 
+  if (bdd_size(result) < bdd_size(f)){
+    return result;
+  }
+  else{
+    bdd_free(result);
+    return bdd_dup(f);
+  }
+}
+
+bdd_t *
+bdd_minimize_array(bdd_t *f, array_t *bddArray)
+{
+  bdd_t *operand;
+  struct bdd_ *result, *temp;
+  bdd_t *final;
+  int i;
+
+  result = cmu_bdd_identity(f->mgr, f->node);
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = cmu_bdd_reduce(f->mgr, result, operand->node);
+    if (temp == NULL) {
+      cmu_bdd_free(f->mgr, result);
+      return(NULL);
+    }
+    cmu_bdd_free(f->mgr, result);
+    result = temp;
+  }
+
+  final = bdd_construct_bdd_t(f->mgr, result);
+
+  if (bdd_size(final) < bdd_size(f)){
+    return final;
+  }
+  else{
+    bdd_free(final);
+    return bdd_dup(f);
+  }
+}
+
+
+bdd_t *
+bdd_not(bdd_t *f)
+{
+  return bdd_construct_bdd_t(f->mgr, cmu_bdd_not(f->mgr, f->node));
+}
+
+bdd_t *
+bdd_one(bdd_manager *manager)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  return bdd_construct_bdd_t(mgr, cmu_bdd_one(mgr));
+}
+
+bdd_t *
+bdd_or(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase)
+{
+  struct bdd_ *temp1, *temp2;
+  bdd_t *result;
+  struct bdd_manager_ *mgr;
+  
+  mgr = f->mgr;
+  temp1 = ( (f_phase == TRUE) ? cmu_bdd_identity(mgr, f->node) : cmu_bdd_not(mgr, f->node));
+  temp2 = ( (g_phase == TRUE) ? cmu_bdd_identity(mgr, g->node) : cmu_bdd_not(mgr, g->node));
+  result = bdd_construct_bdd_t(mgr, cmu_bdd_or(mgr, temp1, temp2));
+  cmu_bdd_free(mgr, temp1);
+  cmu_bdd_free(mgr, temp2);
+  return result;
+}
+
+bdd_t *
+bdd_smooth(
+  bdd_t *f,
+  array_t *smoothing_vars /* of bdd_t *'s */)
+{
+  int num_vars, i;
+  bdd_t *fn, *result;
+  struct bdd_ **assoc;
+  struct bdd_manager_ *mgr;
+  
+  num_vars = array_n(smoothing_vars);
+  if (num_vars <= 0) {
+	cmu_bdd_fatal("bdd_smooth: no smoothing variables");
+  }
+  
+  assoc = ALLOC(struct bdd_ *, num_vars+1);
+  
+  for (i = 0; i < num_vars; i++) {
+	fn = array_fetch(bdd_t *, smoothing_vars, i);
+	assoc[i] = fn->node;
+  }
+  assoc[num_vars] = (struct bdd_ *) 0;
+  
+  mgr = f->mgr;
+  cmu_bdd_temp_assoc(mgr, assoc, 0);
+  (void) cmu_bdd_assoc(mgr, -1);  /* set the temp association as the current association */
+  
+  result = bdd_construct_bdd_t(mgr, cmu_bdd_exists(mgr, f->node));
+  FREE(assoc);
+  return result;
+}
+
+bdd_t *
+bdd_substitute(
+  bdd_t *f,
+  array_t *old_array /* of bdd_t *'s */,
+  array_t *new_array /* of bdd_t *'s */)
+{
+    int num_old_vars, num_new_vars, i;
+    bdd_t *fn_old, *fn_new, *result;
+    struct bdd_ **assoc;
+    struct bdd_manager_ *mgr;
+
+    num_old_vars = array_n(old_array);
+    num_new_vars = array_n(new_array);
+    if (num_old_vars != num_new_vars) {
+	cmu_bdd_fatal("bdd_substitute: mismatch of number of new and old variables");
+    }
+
+    assoc = ALLOC(struct bdd_ *, 2*(num_old_vars+1));
+
+    for (i = 0; i < num_old_vars; i++) {
+	fn_old = array_fetch(bdd_t *, old_array, i);
+	fn_new = array_fetch(bdd_t *, new_array, i);
+	assoc[2*i]   = fn_old->node;
+	assoc[2*i+1] = fn_new->node;
+    }
+    assoc[2*num_old_vars]   = (struct bdd_ *) 0;
+    assoc[2*num_old_vars+1] = (struct bdd_ *) 0;  /* not sure if we need this second 0 */
+
+    mgr = f->mgr;
+    cmu_bdd_temp_assoc(mgr, assoc, 1);
+    (void) cmu_bdd_assoc(mgr, -1);  /* set the temp association as the current association */
+
+    result = bdd_construct_bdd_t(mgr, cmu_bdd_substitute(mgr, f->node));
+    FREE(assoc);
+    return result;
+}
+
+array_t *
+bdd_substitute_array(
+  array_t *f_array,
+  array_t *old_array /* of bdd_t *'s */,
+  array_t *new_array /* of bdd_t *'s */)
+{
+  int	i;
+  bdd_t	*f, *new_;
+  array_t *substitute_array = array_alloc(bdd_t *, 0);
+
+  arrayForEachItem(bdd_t *, f_array, i, f) {
+    new_ = bdd_substitute(f, old_array, new_array);
+    array_insert_last(bdd_t *, substitute_array, new_);
+  }
+  return(substitute_array);
+}
+
+void *
+bdd_pointer(bdd_t *f)
+{
+    return((void *)f->node);
+}
+
+bdd_t *
+bdd_then(bdd_t *f)
+{
+    return bdd_construct_bdd_t(f->mgr, cmu_bdd_then(f->mgr, f->node));
+}
+
+bdd_t *
+bdd_top_var(bdd_t *f)
+{
+    return bdd_construct_bdd_t(f->mgr, cmu_bdd_if(f->mgr, f->node));
+}
+
+bdd_t *
+bdd_xnor(bdd_t *f, bdd_t *g)
+{
+    return bdd_construct_bdd_t(f->mgr, cmu_bdd_xnor(f->mgr, f->node, g->node));
+}
+
+bdd_t *
+bdd_xor(bdd_t *f, bdd_t *g)
+{
+    return bdd_construct_bdd_t(f->mgr, cmu_bdd_xor(f->mgr, f->node, g->node));
+}
+
+bdd_t *
+bdd_zero(bdd_manager *manager)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  return bdd_construct_bdd_t(mgr, cmu_bdd_zero(mgr));
+}
+
+/*
+Queries about BDD Formulas ----------------------------------------------------
+*/
+
+boolean
+bdd_equal(bdd_t *f, bdd_t *g)
+{
+    return (f->node == g->node);
+}
+
+boolean
+bdd_equal_mod_care_set(bdd_t *f, bdd_t *g, bdd_t *CareSet)
+{
+  bdd_t	*diffBdd;
+  boolean result;
+
+  if (bdd_equal(f, g))
+    return 1;
+
+  diffBdd = bdd_xor(f, g);
+
+  result = bdd_leq(diffBdd, CareSet, 1, 0);
+  bdd_free(diffBdd);
+
+  return(result);
+}
+
+bdd_t *
+bdd_intersects(bdd_t *f, bdd_t *g)
+{
+    return bdd_construct_bdd_t(f->mgr, cmu_bdd_intersects(f->mgr, f->node, g->node));
+}
+
+bdd_t *
+bdd_closest_cube(bdd_t *f, bdd_t *g, int *dist)
+{
+    return (NULL);
+}
+
+boolean
+bdd_is_tautology(bdd_t *f, boolean phase)
+{
+    return ((phase == TRUE) ? (f->node == cmu_bdd_one(f->mgr)) : (f->node == cmu_bdd_zero(f->mgr)));
+}
+
+boolean
+bdd_leq(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase)
+{
+    struct bdd_ *temp1, *temp2, *implies_fn;
+    struct bdd_manager_ *mgr;
+    boolean result_value;
+
+    mgr = f->mgr;
+    temp1 = ( (f_phase == TRUE) ? cmu_bdd_identity(mgr, f->node) : cmu_bdd_not(mgr, f->node));
+    temp2 = ( (g_phase == TRUE) ? cmu_bdd_identity(mgr, g->node) : cmu_bdd_not(mgr, g->node));
+    implies_fn = cmu_bdd_implies(mgr, temp1, temp2); /* returns a minterm of temp1*!temp2 */
+    result_value = (implies_fn == cmu_bdd_zero(mgr));
+    cmu_bdd_free(mgr, temp1);
+    cmu_bdd_free(mgr, temp2);
+    cmu_bdd_free(mgr, implies_fn);
+    return result_value;
+}
+
+boolean
+bdd_lequal_mod_care_set(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase,
+  bdd_t *careSet)
+{
+  bdd_t *temp;
+  boolean result;
+
+  if (bdd_leq(f, g, f_phase, g_phase))
+    return 1;
+
+  temp = bdd_and(f, careSet, f_phase, 1);
+
+  result = bdd_leq(temp, g, 1, g_phase);
+  bdd_free(temp);
+
+  return(result);
+}
+
+boolean
+bdd_leq_array(
+  bdd_t *f,
+  array_t *g_array,
+  boolean f_phase,
+  boolean g_phase)
+{
+  int	i;
+  bdd_t	*g;
+  boolean result;
+
+  arrayForEachItem(bdd_t *, g_array, i, g) {
+    result = bdd_leq(f, g, f_phase, g_phase);
+    if (g_phase) {
+      if (!result)
+	return(0);
+    } else {
+      if (result)
+	return(1);
+    }
+  }
+  if (g_phase)
+    return(1);
+  else
+    return(0);
+}
+
+/*
+Statistics and Other Queries --------------------------------------------------
+*/
+
+double 
+bdd_count_onset(
+  bdd_t *f,
+  array_t *var_array /* of bdd_t *'s */)
+{
+    int num_vars;
+    double fraction;
+
+    num_vars = array_n(var_array);
+    fraction = cmu_bdd_satisfying_fraction(f->mgr, f->node); /* cannot give support vars */
+    return (fraction * pow((double) 2, (double) num_vars));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms in the on set.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_epd_count_onset(
+  bdd_t *f,
+  array_t *var_array /* of bdd_t *'s */,
+  EpDouble *epd)
+{
+  double nMinterms;
+
+  nMinterms = bdd_count_onset(f, var_array);
+  EpdConvert(nMinterms, epd);
+  return 0;
+} /* end of bdd_epd_count_onset */
+
+int
+bdd_get_free(bdd_t *f)
+{
+    return (f->free);
+}
+
+bdd_manager *
+bdd_get_manager(bdd_t *f)
+{
+    return (bdd_manager *) (f->mgr);
+}
+
+bdd_node *
+bdd_get_node(
+  bdd_t *f,
+  boolean *is_complemented /* return */)
+{
+    *is_complemented = (boolean) TAG0(f->node);  /* using bddint.h */
+    return ((bdd_node *) BDD_POINTER(f->node));  /* using bddint.h */
+}
+
+var_set_t *
+bdd_get_support(bdd_t *f)
+{
+    struct bdd_ **support, *var;
+    struct bdd_manager_ *mgr;
+    long num_vars;
+    var_set_t *result;
+    int id, i;
+
+    mgr = f->mgr;
+    num_vars = cmu_bdd_vars(mgr);
+
+    result = var_set_new((int) num_vars);
+    support = (struct bdd_ **) mem_get_block((num_vars+1) * sizeof(struct bdd_ *));
+    (void) cmu_bdd_support(mgr, f->node, support);
+
+    for (i = 0; i < num_vars; ++i) {  /* can never have more than num_var non-zero entries in array */
+	var = support[i]; 
+	if (var == (struct bdd_ *) 0) {
+	    break;  /* have reach end of null-terminated array */
+	}
+	id = (int) (cmu_bdd_if_id(mgr, var) - 1);  /* a variable is never garbage collected, so no need to free */
+	var_set_set_elt(result, id);
+    }
+
+    mem_free_block((pointer)support);
+
+    return result;
+}
+
+int
+bdd_is_support_var(bdd_t *f, bdd_t *var)
+{
+    return(bdd_is_support_var_id(f, bdd_top_var_id(var)));
+}
+
+int
+bdd_is_support_var_id(bdd_t *f, int index)
+{
+    struct bdd_ **support, *var;
+    struct bdd_manager_ *mgr;
+    long num_vars;
+    int id, i;
+
+    mgr = f->mgr;
+    num_vars = cmu_bdd_vars(mgr);
+
+    support = (struct bdd_ **) mem_get_block((num_vars+1) * sizeof(struct bdd_ *));
+    (void) cmu_bdd_support(mgr, f->node, support);
+
+    for (i = 0; i < num_vars; ++i) {  /* can never have more than num_var non-zero entries in array */
+	var = support[i]; 
+	if (var == (struct bdd_ *) 0) {
+	    break;  /* have reach end of null-terminated array */
+	}
+	id = (int) (cmu_bdd_if_id(mgr, var) - 1);  /* a variable is never garbage collected, so no need to free */
+	if (id == index) {
+	    mem_free_block((pointer)support);
+	    return 1;
+	}
+    }
+
+    mem_free_block((pointer)support);
+
+    return 0;
+}
+
+array_t *
+bdd_get_varids(array_t *var_array)
+{
+  int i;
+  bdd_t *var;
+  array_t *result;
+ 
+  result = array_alloc(bdd_variableId, 0);
+  for (i = 0; i < array_n(var_array); i++) {
+    var = array_fetch(bdd_t *, var_array, i);
+    array_insert_last(bdd_variableId, result, bdd_top_var_id(var));
+  }
+  return result;
+}
+
+unsigned int 
+bdd_num_vars(bdd_manager *manager)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  return (cmu_bdd_vars(mgr));
+}
+
+void
+bdd_print(bdd_t *f)
+{
+    cmu_bdd_print_bdd(f->mgr, f->node, bdd_naming_fn_none, bdd_terminal_id_fn_none, (pointer) 0, stdout);
+}
+
+void
+bdd_print_stats(bdd_manager *manager, FILE *file)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  cmu_bdd_stats(mgr, file);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Sets the internal parameters of the package to the given values.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_set_parameters(
+  bdd_manager *mgr,
+  avl_tree *valueTable,
+  FILE *file)
+{
+  (void) fprintf(file, "Functionality not supported yet in the CMU package\n");
+  return 1;
+} /* End of bdd_set_parameters */
+
+int
+bdd_size(bdd_t *f)
+{
+    return ((int) cmu_bdd_size(f->mgr, f->node, 1));
+}
+
+int
+bdd_node_size(bdd_node *f)
+{
+  return(0);
+}
+
+long
+bdd_size_multiple(array_t *bdd_array)
+{
+    long result;
+    struct bdd_ **vector_bdd;
+    bdd_t *f;
+    int i;
+    struct bdd_manager_ *mgr;
+
+    if ((bdd_array == NIL(array_t)) || (array_n(bdd_array) == 0))
+        return 0;
+
+    f = array_fetch(bdd_t*, bdd_array, 0);
+    mgr = f->mgr;
+
+    vector_bdd = (struct bdd_ **)
+                        malloc((array_n(bdd_array)+1)*sizeof(struct bdd_ *));
+
+    for(i=0; i<array_n(bdd_array);i++){
+        f = array_fetch(bdd_t*, bdd_array, i);
+        vector_bdd[i] = f->node;
+    }
+    vector_bdd[array_n(bdd_array)] = 0;
+    result =  cmu_bdd_size_multiple(mgr, vector_bdd,1);
+    FREE(vector_bdd);
+    return result;
+}
+
+bdd_variableId
+bdd_top_var_id(bdd_t *f)
+{
+    return ((bdd_variableId) (cmu_bdd_if_id(f->mgr, f->node) - 1));
+}
+
+/*
+Miscellaneous -----------------------------------------------------------------
+*/
+
+bdd_external_hooks *
+bdd_get_external_hooks(bdd_manager *manager)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  return ((bdd_external_hooks *) mgr->hooks);
+}
+
+
+void
+bdd_set_gc_mode(bdd_manager *manager, boolean no_gc)
+{
+  cmu_bdd_warning("bdd_set_gc_mode: translated to no-op in CMU package");
+}
+
+void 
+bdd_dynamic_reordering(bdd_manager *manager, bdd_reorder_type_t
+                       algorithm_type, bdd_reorder_verbosity_t verbosity) 
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+    switch(algorithm_type) {
+    case BDD_REORDER_SIFT:
+	cmu_bdd_dynamic_reordering(mgr, cmu_bdd_reorder_sift);
+	break;
+    case BDD_REORDER_WINDOW:
+	cmu_bdd_dynamic_reordering(mgr, cmu_bdd_reorder_stable_window3);
+	break;
+    case BDD_REORDER_NONE:
+	cmu_bdd_dynamic_reordering(mgr, cmu_bdd_reorder_none);
+	break;
+    default:
+      fprintf(stderr,"CMU: bdd_dynamic_reordering: unknown algorithm type\n");
+      fprintf(stderr,"Using SIFT method instead\n");
+      cmu_bdd_dynamic_reordering(mgr, cmu_bdd_reorder_sift);
+    }
+}
+
+void 
+bdd_dynamic_reordering_zdd(bdd_manager *manager, bdd_reorder_type_t
+                       algorithm_type, bdd_reorder_verbosity_t verbosity) 
+{
+    return;
+}
+
+void 
+bdd_reorder(bdd_manager *manager)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  cmu_bdd_reorder(mgr);
+}
+
+bdd_variableId
+bdd_get_id_from_level(bdd_manager *manager, long level)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  struct bdd_ *fn;
+
+  fn = cmu_bdd_var_with_index(mgr, level);
+  
+  if (fn == (struct bdd_ *) 0) {
+    /* variable should always be found, since they are created at bdd_start */
+    cmu_bdd_fatal("bdd_get_id_from_level: assumption violated");
+  }
+  
+  return ((bdd_variableId)(cmu_bdd_if_id(mgr, fn) - 1 ));
+  
+}
+
+long
+bdd_top_var_level(bdd_manager *manager, bdd_t *fn)
+{
+  cmu_bdd_manager mgr = (cmu_bdd_manager) manager;
+  return cmu_bdd_if_index(mgr, fn->node);
+}
+
+/*
+ * Return TRUE if f is a cube, else return FALSE.
+ */
+boolean
+bdd_is_cube(bdd_t *f)
+{
+  struct bdd_manager_ *manager;
+
+  if (f == NIL(bdd_t)) {
+        fail("bdd_is_cube: invalid BDD");
+  }
+  if(  f->free ) fail ("Freed Bdd passed to bdd_is_cube");
+  manager = f->mgr;
+  return ((boolean)cmu_bdd_is_cube(manager, f->node));
+}
+
+bdd_block *
+bdd_new_var_block(bdd_t *f, long length)
+{
+  struct bdd_manager_ *manager;
+  if (f == NIL(bdd_t)) {
+        fail("bdd_new_var_block: invalid BDD");
+  }
+  manager = f->mgr;
+  return (bdd_block *)cmu_bdd_new_var_block(manager, f->node, length);
+}
+
+bdd_t *
+bdd_var_with_index(bdd_manager *manager, int index)
+{
+  return bdd_construct_bdd_t(manager, 
+		            cmu_bdd_var_with_index((cmu_bdd_manager) manager,
+                                                   index));
+}
+
+bdd_t *
+bdd_compact(bdd_t *f, bdd_t *g)
+{
+    return (NULL);
+}
+
+
+bdd_t *
+bdd_squeeze(bdd_t *f, bdd_t *g)
+{
+    return (NULL);
+}
+
+double
+bdd_correlation(bdd_t *f, bdd_t *g)
+{
+    return (0.0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Dummy functions defined in bdd.h]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_reordering_status(
+  bdd_manager *mgr,
+  bdd_reorder_type_t *method)
+{
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Dummy functions defined in bdd.h]
+
+  SideEffects []
+
+******************************************************************************/
+
+bdd_t *
+bdd_compute_cube(
+  bdd_manager *mgr,
+  array_t *vars)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_compute_cube_with_phase(
+  bdd_manager *mgr,
+  array_t *vars,
+  array_t *phase)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_clipping_and_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars /* of bdd_t *'s */,
+  int maxDepth,
+  int over)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_hb(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_sp(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  int hardlimit)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_ua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  int safe,
+  double quality)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_remap_ua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  double quality)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_biased_rua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  bdd_t *bias,
+  int numVars,
+  int threshold,
+  double quality,
+  double quality1)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_approx_compress(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold)
+{
+  return NIL(bdd_t);
+}
+
+int
+bdd_gen_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t ***conjArray)
+{
+  return 0;
+}
+
+int
+bdd_var_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t ***conjArray)
+{
+  return 0;
+}
+
+int 
+bdd_approx_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t ***conjArray)
+{
+  return 0;
+}
+
+int
+bdd_iter_decomp(
+  bdd_t *f,
+  bdd_partition_type_t partType,
+  bdd_t  ***conjArray)
+{
+  return 0;
+}
+
+int
+bdd_add_hook(
+  bdd_manager *mgr,
+  int (*procedure)(bdd_manager *, char *, void *),
+  bdd_hook_type_t whichHook)
+{
+  return 0;
+}
+
+int
+bdd_remove_hook(
+  bdd_manager *mgr,
+  int (*procedure)(bdd_manager *, char *, void *),
+  bdd_hook_type_t whichHook)
+{
+  return 0;
+}
+
+int
+bdd_enable_reordering_reporting(bdd_manager *mgr)
+{
+  return 0;
+}
+
+int
+bdd_disable_reordering_reporting(bdd_manager *mgr)
+{
+  return 0;
+}
+
+bdd_reorder_verbosity_t 
+bdd_reordering_reporting(bdd_manager *mgr)
+{
+  return BDD_REORDER_VERBOSITY_DEFAULT;
+}
+
+int 
+bdd_print_apa_minterm(
+  FILE *fp,
+  bdd_t *f,
+  int nvars,
+  int precision)
+{
+  return 0;
+}
+
+int 
+bdd_apa_compare_ratios(
+  int nvars,
+  bdd_t *f1,
+  bdd_t *f2,
+  int f1Num,
+  int f2Num)
+{
+  return 0;
+}
+
+int
+bdd_read_node_count(bdd_manager *mgr)
+{
+  return 0;
+}
+
+
+int
+bdd_reordering_zdd_status(
+  bdd_manager *mgr,
+  bdd_reorder_type_t *method)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_bdd_to_add(
+  bdd_manager *mgr,
+  bdd_node *fn)
+{
+  return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_add_permute(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  int *permut)
+{
+  return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_permute(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  int *permut)
+{
+  return NIL(bdd_node);
+}
+
+void
+bdd_ref(bdd_node *fn)
+{
+  return ;
+}
+
+
+void
+bdd_recursive_deref(bdd_manager *mgr, bdd_node *f)
+{
+  return;
+}
+
+
+bdd_node *
+bdd_add_exist_abstract(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *vars)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_apply(
+  bdd_manager *mgr,
+  bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **),
+  bdd_node *fn1,
+  bdd_node *fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_nonsim_compose(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node **vector)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_residue(
+  bdd_manager *mgr,
+  int n,
+  int m,
+  int options,
+  int top)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node **vector)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_times(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+  
+
+int
+bdd_check_zero_ref(bdd_manager *mgr)
+{
+  return 0;
+}
+
+
+void
+bdd_dynamic_reordering_disable(bdd_manager *mgr)
+{
+  return;
+}
+
+void
+bdd_dynamic_reordering_zdd_disable(bdd_manager *mgr)
+{
+  return;
+}
+
+
+bdd_node *
+bdd_add_xnor(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_shuffle_heap(
+  bdd_manager *mgr,
+  int *permut)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_add_compose(
+  bdd_manager *mgr,
+  bdd_node *fn1,
+  bdd_node *fn2,
+  int var)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_ith_var(
+  bdd_manager *mgr,
+  int i)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_get_level_from_id(
+  bdd_manager *mgr,
+  int id)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_bdd_exist_abstract(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *cube)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_equal_sup_norm(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *gn,
+  BDD_VALUE_TYPE tolerance,
+  int pr)
+{
+  return 0;
+}
+
+
+bdd_node *
+bdd_read_logic_zero(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_ith_var(bdd_manager *mgr, int i)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_divide(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_constrain(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *c)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_restrict(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *c)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_hamming(
+  bdd_manager *mgr,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  int nVars)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_ite(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *h)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_find_max(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+
+int
+bdd_bdd_pick_one_cube(
+  bdd_manager *mgr,
+  bdd_node *node,
+  char *string)
+{
+    return 0;
+}
+
+
+bdd_node *
+bdd_add_swap_variables(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  bdd_node **y,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_swap_variables(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  bdd_node **y,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_or(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_compute_cube(
+  bdd_manager *mgr,
+  bdd_node **vars,
+  int *phase,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_indices_to_cube(
+  bdd_manager *mgr,
+  int *idArray,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_and(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_matrix_multiply(
+  bdd_manager *mgr,
+  bdd_node *A,
+  bdd_node *B,
+  bdd_node **z,
+  int nz)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_compute_cube(
+  bdd_manager *mgr,
+  bdd_node **vars,
+  int *phase,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_const(
+  bdd_manager *mgr,
+  BDD_VALUE_TYPE c)
+{
+    return NIL(bdd_node);
+}
+
+
+double
+bdd_count_minterm(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int n)
+{
+    return 0;
+}
+
+
+bdd_node *
+bdd_add_bdd_threshold(
+  bdd_manager *mgr,
+  bdd_node *f,
+  BDD_VALUE_TYPE value)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_add_bdd_strict_threshold(
+  bdd_manager *mgr,
+  bdd_node *f,
+  BDD_VALUE_TYPE value)
+{
+    return NIL(bdd_node);
+}
+
+BDD_VALUE_TYPE
+bdd_read_epsilon(bdd_manager *mgr)
+{
+    return 0;
+}
+
+bdd_node *
+bdd_read_one(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_pick_one_minterm(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vars,
+  int n)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_t *
+bdd_pick_one_minterm(
+  bdd_t *f,
+  array_t *varsArray)
+{
+    return NIL(bdd_t);
+}
+
+
+array_t *
+bdd_bdd_pick_arbitrary_minterms(
+  bdd_t *f,
+  array_t *varsArray,
+  int n,
+  int k)
+{
+    return NIL(array_t);
+}
+
+bdd_node *
+bdd_read_zero(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_new_var(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_bdd_and_abstract(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *cube)
+{
+    return NIL(bdd_node);
+}
+
+void
+bdd_deref(bdd_node *f)
+{
+}
+
+bdd_node *
+bdd_add_plus(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  return NIL(bdd_node);
+}
+
+
+int
+bdd_read_reorderings(bdd_manager *mgr)
+{
+    return 0;
+}
+
+int
+bdd_read_next_reordering(bdd_manager *mgr)
+{
+    return 0;
+}
+
+void
+bdd_set_next_reordering(bdd_manager *mgr, int next)
+{
+}
+
+
+bdd_node *
+bdd_bdd_xnor(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vector)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_extract_node_as_is(bdd_t *fn)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_zdd_get_node(
+  bdd_manager *mgr,
+  int id,
+  bdd_node *g,
+  bdd_node *h)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_product(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_product_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_zdd_union(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+  return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_zdd_weak_div(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_weak_div_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_zdd_isop_recur(
+  bdd_manager *mgr,
+  bdd_node *L,
+  bdd_node *U,
+  bdd_node **zdd_I)
+{
+    return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_zdd_isop(
+  bdd_manager *mgr,
+  bdd_node *L,
+  bdd_node *U,
+  bdd_node **zdd_I)
+{
+    return NIL(bdd_node);
+}
+
+int
+bdd_zdd_get_cofactors3(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int v,
+  bdd_node **f1,
+  bdd_node **f0,
+  bdd_node **fd)
+{
+    return 0;
+}
+
+bdd_node *
+bdd_bdd_and_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+     return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_unique_inter(
+  bdd_manager *mgr,
+  int v,
+  bdd_node *f,
+  bdd_node *g)
+{
+     return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_unique_inter_ivo(
+  bdd_manager *mgr,
+  int v,
+  bdd_node *f,
+  bdd_node *g)
+{
+     return NIL(bdd_node);
+}
+
+
+bdd_node *
+bdd_zdd_diff(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+} 
+
+bdd_node *
+bdd_zdd_diff_recur(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+} 
+
+int
+bdd_num_zdd_vars(bdd_manager *mgr)
+{
+    return -1;
+}
+
+bdd_node *
+bdd_regular(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+int
+bdd_is_constant(bdd_node *f)
+{
+    return 0;
+}
+
+int
+bdd_is_complement(bdd_node *f)
+{
+    return 0;
+}
+
+bdd_node *
+bdd_bdd_T(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_bdd_E(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_not_bdd_node(bdd_node *f)
+{
+    return NIL(bdd_node);
+} 
+
+void
+bdd_recursive_deref_zdd(bdd_manager *mgr, bdd_node *f)
+{
+    return;
+} 
+
+int
+bdd_zdd_count(bdd_manager *mgr, bdd_node *f)
+{
+    return 0;
+}
+
+int
+bdd_read_zdd_level(bdd_manager *mgr, int index)
+{
+    return -1;
+} 
+
+int
+bdd_zdd_vars_from_bdd_vars(bdd_manager *mgr, int multiplicity)
+{
+   return 0;
+} 
+
+void
+bdd_zdd_realign_enable(bdd_manager *mgr)
+{
+    return;
+} 
+
+void
+bdd_zdd_realign_disable(bdd_manager *mgr)
+{
+    return;
+} 
+
+int
+bdd_zdd_realignment_enabled(bdd_manager *mgr)
+{
+    return 0;
+} 
+
+void
+bdd_realign_enable(bdd_manager *mgr)
+{
+    return;
+} 
+
+void
+bdd_realign_disable(bdd_manager *mgr)
+{
+    return;
+} 
+
+int
+bdd_realignment_enabled(bdd_manager *mgr)
+{
+    return 0;
+} 
+
+int
+bdd_node_read_index(bdd_node *f)
+{
+    return -1;
+}
+
+bdd_node *
+bdd_read_next(bdd_node *f)
+{
+    return NIL(bdd_node);
+}
+
+
+void
+bdd_set_next(bdd_node *f, bdd_node *g)
+{
+    return;
+}
+
+
+int
+bdd_read_reordered_field(bdd_manager *mgr)
+{
+    return -1;
+}
+
+void
+bdd_set_reordered_field(bdd_manager *mgr, int n)
+{
+    return;
+}
+
+bdd_node *
+bdd_add_apply_recur(
+  bdd_manager *mgr,
+  bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **),
+  bdd_node *fn1,
+  bdd_node *fn2)
+{
+    return NIL(bdd_node);
+}
+
+BDD_VALUE_TYPE
+bdd_add_value(bdd_node *f)
+{
+    return 0.0; 
+}
+
+int
+bdd_print_minterm(bdd_t *f)
+{
+  return 0;
+}
+
+bdd_t *
+bdd_xor_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars)
+{
+    return NIL(bdd_t);
+}
+
+
+bdd_node *
+bdd_read_plus_infinity(bdd_manager *mgr)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_read_plus_infinity */
+
+
+bdd_node *
+bdd_priority_select(
+  bdd_manager *mgr,
+  bdd_node *R,
+  bdd_node **x,
+  bdd_node **y,
+  bdd_node **z,
+  bdd_node *Pi,
+  int n,
+  bdd_node *(*Pifunc)(bdd_manager *, int, bdd_node **, bdd_node **, bdd_node **))
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_priority_select */
+
+
+void
+bdd_set_background(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+    return;
+ 
+} /* end of bdd_set_background */
+
+
+bdd_node *
+bdd_read_background(bdd_manager *mgr)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_read_background */
+
+
+bdd_node *
+bdd_bdd_cofactor(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_cofactor */
+
+
+bdd_node *
+bdd_bdd_ite(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *h)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_ite */
+
+
+bdd_node *
+bdd_add_minus(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_add_plus */
+
+
+bdd_node *
+bdd_dxygtdxz(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y,
+  bdd_node **z)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_dxygtdxz */
+
+
+bdd_node *
+bdd_bdd_univ_abstract(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *vars)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_univ_abstract */
+
+
+bdd_node *
+bdd_bdd_cprojection(
+  bdd_manager *mgr,
+  bdd_node *R,
+  bdd_node *Y)
+{
+    return NIL(bdd_node);
+
+} /* end of bdd_bdd_cprojection */
+
+bdd_node *
+bdd_xeqy(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_xeqy */
+
+bdd_node *
+bdd_add_roundoff(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int N)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_add_roundoff */
+
+bdd_node *
+bdd_xgty(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_xgty */
+
+bdd_node *
+bdd_add_cmpl(
+  bdd_manager *mgr,
+  bdd_node *f)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_add_cmpl */
+
+bdd_node *
+bdd_split_set(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  int n,
+  double m)
+{
+  return NIL(bdd_node);
+
+} /* end of bdd_split_set */
+
+
+int
+bdd_debug_check(bdd_manager *mgr)
+{
+    return (-1);
+
+} /* end of bdd_debug_check */
+
+bdd_node *
+bdd_bdd_xor(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+    return NIL(bdd_node);
+}
+
+void 
+bdd_dump_blif(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  char *model,
+  FILE *fp)
+{
+  return;
+}
+
+void 
+bdd_dump_blif_body(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  FILE *fp)
+{
+  return;
+}
+
+void 
+bdd_dump_dot(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  FILE *fp)
+{
+  return;
+}
+
+bdd_node *
+bdd_make_bdd_from_zdd_cover(bdd_manager *mgr, bdd_node *node)
+{
+    return(NIL(bdd_node));
+}
+
+bdd_node *
+bdd_zdd_complement(bdd_manager *mgr, bdd_node *node)
+{
+    return(NIL(bdd_node));
+}
+
+bdd_node *
+bdd_bdd_vector_support(
+  bdd_manager *mgr,
+  bdd_node **F,
+  int n)
+{
+  return NIL(bdd_node);
+}
+
+int
+bdd_bdd_vector_support_size(
+  bdd_manager *mgr,
+  bdd_node **F,
+  int n)
+{
+  return -1;
+}
+
+int
+bdd_bdd_support_size(
+  bdd_manager *mgr,
+  bdd_node *F)
+{
+  return -1;
+}
+
+bdd_node *
+bdd_bdd_support(
+  bdd_manager *mgr,
+  bdd_node *F)
+{
+  return NIL(bdd_node);
+}
+
+bdd_node *
+bdd_add_general_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vectorOn,
+  bdd_node **vectorOff)
+{
+  return NIL(bdd_node);
+}
+
+int
+bdd_bdd_leq(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g)
+{
+  return -1;
+} 
+
+bdd_node *
+bdd_bdd_boolean_diff(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int x)
+{
+  return NIL(bdd_node);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two bdds are same.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_ptrcmp(bdd_t *f, bdd_t *g)
+{
+  if (f->node == g->node)
+    return(0);
+  else
+    return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash value of a bdd.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_ptrhash(bdd_t *f, int size)
+{
+  int hash;
+
+  hash = (int)((unsigned long)f->node >> 2) % size;
+  return(hash);
+}
+
+bdd_t *
+bdd_subset_with_mask_vars(
+  bdd_t *f,
+  array_t *varsArray,
+  array_t *maskVarsArray)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_and_smooth_with_cube(
+  bdd_t *f,
+  bdd_t *g,
+  bdd_t *cube)
+{
+  return NIL(bdd_t);
+}
+
+bdd_t *
+bdd_smooth_with_cube(bdd_t *f, bdd_t *cube)
+{
+  int i;
+  bdd_t *var, *res;
+  array_t *smoothingVars;
+  var_set_t *supportVarSet;
+
+  smoothingVars = array_alloc(bdd_t *, 0);
+  supportVarSet = bdd_get_support(f);
+  for (i = 0; i < supportVarSet->n_elts; i++) {
+    if (var_set_get_elt(supportVarSet, i) == 1) {
+      var = bdd_var_with_index(f->mgr, i);
+      array_insert_last(bdd_t *, smoothingVars, var);
+    }
+  }
+  var_set_free(supportVarSet);
+
+  res = bdd_smooth(f, smoothingVars);
+
+  for (i = 0; i < array_n(smoothingVars); i++) {
+    var = array_fetch(bdd_t *, smoothingVars, i);
+    bdd_free(var);
+  }
+  array_free(smoothingVars);
+  return res;
+}
+
+bdd_t *
+bdd_substitute_with_permut(bdd_t *f, int *permut)
+{
+  return NIL(bdd_t);
+}
+
+array_t *
+bdd_substitute_array_with_permut(
+  array_t *f_array,
+  int *permut)
+{
+  return NIL(array_t);
+}
+
+bdd_t *
+bdd_vector_compose(
+  bdd_t *f,
+  array_t *varArray,
+  array_t *funcArray)
+{
+  return NIL(bdd_t);
+}
+
+double *
+bdd_cof_minterm(bdd_t *f)
+{
+  return(NIL(double));
+}
+
+int
+bdd_var_is_dependent(bdd_t *f, bdd_t *var)
+{
+  return(0);
+}
+
+array_t *
+bdd_find_essential(bdd_t *f)
+{
+  return(NIL(array_t));
+}
+
+bdd_t *
+bdd_find_essential_cube(bdd_t *f)
+{
+  return(NIL(bdd_t));
+}
+
+int
+bdd_estimate_cofactor(bdd_t *f, bdd_t *var, int phase)
+{
+  return(0);
+}
+
+long
+bdd_read_peak_memory(bdd_manager *mgr)
+{
+  return(0);
+}
+
+int
+bdd_read_peak_live_node(bdd_manager *mgr)
+{
+  return(0);
+}
+
+int
+bdd_set_pi_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_set_ps_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_set_ns_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_is_pi_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_is_ps_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_is_ns_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_set_pair_index(bdd_manager *mgr, int index, int pairIndex)
+{
+    return(0);
+}
+
+int
+bdd_read_pair_index(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_set_var_to_be_grouped(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_set_var_hard_group(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_reset_var_to_be_grouped(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_is_var_to_be_grouped(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_is_var_hard_group(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_is_var_to_be_ungrouped(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_set_var_to_be_ungrouped(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_bind_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_unbind_var(bdd_manager *mgr, int index)
+{
+    return(0);
+}
+
+int
+bdd_is_lazy_sift(bdd_manager *mgr)
+{
+    return(0);
+}
+
+void
+bdd_discard_all_var_groups(bdd_manager *mgr)
+{
+    return;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
Index: /vis_dev/glu-2.1/src/cmuPort/cmuPort.make
===================================================================
--- /vis_dev/glu-2.1/src/cmuPort/cmuPort.make	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuPort/cmuPort.make	(revision 8)
@@ -0,0 +1,4 @@
+CSRC_cmu += cmuPortIter.c cmuPort.c
+HEADERS_cmu += cmuPortInt.h
+
+DEPENDENCYFILES = $(CSRC_cmu)
Index: /vis_dev/glu-2.1/src/cmuPort/cmuPortInt.h
===================================================================
--- /vis_dev/glu-2.1/src/cmuPort/cmuPortInt.h	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuPort/cmuPortInt.h	(revision 8)
@@ -0,0 +1,93 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cmuPortInt.h]
+
+  PackageName [cmu_port]
+
+  Synopsis    [Header file used by cmu_port.]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Rajeev K. Ranjan]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: cmuPortInt.h,v 1.1.1.2 1997/02/12 21:15:26 hsv Exp $]
+
+******************************************************************************/
+
+#ifndef _CMU_PORT_INT
+#define _CMU_PORT_INT
+
+#include "util.h"     /* includes math.h */
+#include "array.h"
+#include "st.h"
+#include "bdd.h"      
+#include "bddint.h"   /* CMU internal routines; for use in bdd_get_branches() and for BDD_POINTER */
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#ifndef refany
+/* this otta be a typedef somewhere */
+#define refany char *	/* a void * or any sort of untyped pointer */
+#endif
+
+#ifndef any	/* Ansi C defines this right? */
+/* this otta be a typedef somewhere */
+#define any char	/* so that NIL(any) == refany */
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+struct bdd_t {
+  boolean free; /* TRUE if this is free, FALSE otherwise ... */
+  struct bdd_ *node; /* ptr to the top node of the function */
+  struct bdd_manager_ *mgr; /* the manager */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CMU_PORT_INT */
Index: /vis_dev/glu-2.1/src/cmuPort/cmuPortIter.c
===================================================================
--- /vis_dev/glu-2.1/src/cmuPort/cmuPortIter.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cmuPort/cmuPortIter.c	(revision 8)
@@ -0,0 +1,642 @@
+/**CFile***********************************************************************
+
+  FileName    [cmuPort.c]
+
+  PackageName [cmu_port]
+
+  Synopsis    [Port routines for CMU package.]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Thomas R. Shiple. Some changes by Rajeev K. Ranjan.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: cmuPortIter.c,v 1.4 2005/04/15 23:24:39 fabio Exp $]
+
+******************************************************************************/
+#include "cmuPortInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+/*
+ * Traversal of BDD Formulas
+ */
+
+typedef enum {
+    bdd_gen_cubes,
+    bdd_gen_nodes
+} bdd_gen_type;
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+typedef struct {
+  cmu_bdd_manager manager;
+    bdd_gen_status status;
+    bdd_gen_type type;
+    union {
+	struct {
+	    array_t *cube;	/* of bdd_literal */
+	    /* ... expansion ... */
+	} cubes;
+	struct {
+	    st_table *visited;	/* of bdd_node* */
+	    /* ... expansion ... */
+	} nodes;
+    } gen;	
+    struct {
+	int sp;
+	bdd_node **stack;
+    } stack;
+    bdd_node *node;
+} cmu_bdd_gen;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static void pop_cube_stack(cmu_bdd_gen *gen);
+static void pop_node_stack(cmu_bdd_gen *gen);
+static void push_cube_stack(bdd_node *f, cmu_bdd_gen *gen);
+static void push_node_stack(bdd_node *f, cmu_bdd_gen *gen);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+bdd_gen_status
+bdd_gen_read_status(bdd_gen *gen)
+{
+  return ((cmu_bdd_gen *)gen)->status;
+}
+
+/*
+ *    Defines an iterator on the onset of a BDD.  Two routines are
+ *    provided: bdd_first_cube, which extracts one cube from a BDD and
+ *    returns a bdd_gen structure containing the information necessary to
+ *    continue the enumeration; and bdd_next_cube, which returns 1 if another cube was
+ *    found, and 0 otherwise. A cube is represented
+ *    as an array of bdd_literal (which are integers in {0, 1, 2}), where 0 represents
+ *    negated literal, 1 for literal, and 2 for don't care.  Returns a disjoint
+ *    cover.  A third routine is there to clean up. 
+ */
+
+/*
+ *    bdd_first_cube - return the first cube of the function.
+ *    A generator is returned that will iterate over the rest.
+ *    Return the generator.
+ */
+bdd_gen *
+bdd_first_cube(bdd_t *fn, array_t **cube /* of bdd_literal */)
+{
+    struct bdd_manager_ *manager;
+    cmu_bdd_gen *gen;
+    int i;
+    long num_vars;
+    bdd_node *f;
+
+    if (fn == NIL(bdd_t)) {
+	cmu_bdd_fatal("bdd_first_cube: invalid BDD");
+    }
+
+    manager = fn->mgr;
+
+    /*
+     *    Allocate a new generator structure and fill it in; the stack and the 
+     *    cube will be used, but the visited table and the node will not be used.
+     */
+    gen = ALLOC(cmu_bdd_gen, 1);
+    if (gen == NIL(cmu_bdd_gen)) {
+	cmu_bdd_fatal("bdd_first_cube: failed on memory allocation, location 1");
+    }
+
+    /*
+     *    first - init all the members to a rational value for cube iteration
+     */
+    gen->manager = manager;
+    gen->status = bdd_EMPTY;
+    gen->type = bdd_gen_cubes;
+    gen->gen.cubes.cube = NIL(array_t);
+    gen->stack.sp = 0;
+    gen->stack.stack = NIL(bdd_node *);
+    gen->node = NIL(bdd_node);
+
+    num_vars = cmu_bdd_vars(manager);
+    gen->gen.cubes.cube = array_alloc(bdd_literal, num_vars);
+    if (gen->gen.cubes.cube == NIL(array_t)) {
+	cmu_bdd_fatal("bdd_first_cube: failed on memory allocation, location 2");
+    }
+    
+    /*
+     * Initialize each literal to 2 (don't care).
+     */
+    for (i = 0; i < num_vars; i++) {
+        array_insert(bdd_literal, gen->gen.cubes.cube, i, 2);
+    }
+
+    /*
+     * The stack size will never exceed the number of variables in the BDD, since
+     * the longest possible path from root to constant 1 is the number of variables 
+     * in the BDD.
+     */
+    gen->stack.sp = 0;
+    gen->stack.stack = ALLOC(bdd_node *, num_vars);
+    if (gen->stack.stack == NIL(bdd_node *)) {
+	cmu_bdd_fatal("bdd_first_cube: failed on memory allocation, location 3");
+    }
+    /*
+     * Clear out the stack so that in bdd_gen_free, we can decrement the ref count
+     * of those nodes still on the stack.
+     */
+    for (i = 0; i < num_vars; i++) {
+	gen->stack.stack[i] = NIL(bdd_node);
+    }
+
+    if (bdd_is_tautology(fn, 0)) {
+	/*
+	 *    All done, for this was but the zero constant ...
+	 *    We are enumerating the onset, (which is vacuous).
+         *    gen->status initialized to bdd_EMPTY above, so this
+         *    appears to be redundant.
+	 */
+	gen->status = bdd_EMPTY;
+    } else {
+	/*
+	 *    Get to work enumerating the onset.  Get the first cube.  Note that
+         *    if fn is just the constant 1, push_cube_stack will properly handle this.
+	 *    Get a new pointer to fn->node beforehand: this increments
+	 *    the reference count of fn->node; this is necessary, because when fn->node
+	 *    is popped from the stack at the very end, it's ref count is decremented.
+	 */
+	gen->status = bdd_NONEMPTY;
+	f = cmu_bdd_identity(manager, fn->node);
+	push_cube_stack(f, gen);
+    }
+
+    *cube = gen->gen.cubes.cube;
+    return (bdd_gen *)(gen);
+}
+
+/*
+ *    bdd_next_cube - get the next cube on the generator.
+ *    Returns {TRUE, FALSE} when {more, no more}.
+ */
+boolean
+bdd_next_cube(bdd_gen *gen_, array_t **cube /* of bdd_literal */)
+{
+  cmu_bdd_gen *gen = (cmu_bdd_gen *) gen_;
+  pop_cube_stack(gen);
+  if (gen->status == bdd_EMPTY) {
+    return (FALSE);
+  }
+  *cube = gen->gen.cubes.cube;
+  return (TRUE);
+}
+
+bdd_gen *
+bdd_first_disjoint_cube(bdd_t *fn,array_t **cube)
+{
+  return(bdd_first_cube(fn,cube));
+}
+
+boolean
+bdd_next_disjoint_cube(bdd_gen *gen_, array_t **cube)
+{
+  return(bdd_next_cube(gen_,cube));
+}
+
+/*
+ *    bdd_first_node - enumerates all bdd_node * in fn.
+ *    Return the generator.
+ */
+bdd_gen *
+bdd_first_node(bdd_t *fn, bdd_node **node /* return */)
+{
+    struct bdd_manager_ *manager;
+    cmu_bdd_gen *gen;
+    long num_vars;
+    bdd_node *f;
+    int i;
+
+    if (fn == NIL(bdd_t)) {
+	cmu_bdd_fatal("bdd_first_node: invalid BDD");
+    }
+
+    manager = fn->mgr;
+
+    /*
+     *    Allocate a new generator structure and fill it in; the
+     *    visited table will be used, as will the stack, but the
+     *    cube array will not be used.
+     */
+    gen = ALLOC(cmu_bdd_gen, 1);
+    if (gen == NIL(bdd_gen)) {
+	cmu_bdd_fatal("bdd_first_node: failed on memory allocation, location 1");
+    }
+
+    /*
+     *    first - init all the members to a rational value for node iteration.
+     */
+    gen->manager = manager;
+    gen->status = bdd_NONEMPTY;
+    gen->type = bdd_gen_nodes;
+    gen->gen.nodes.visited = NIL(st_table);
+    gen->stack.sp = 0;
+    gen->stack.stack = NIL(bdd_node *);
+    gen->node = NIL(bdd_node);
+  
+    /* 
+     * Set up the hash table for visited nodes.  Every time we visit a node,
+     * we insert it into the table.
+     */
+    gen->gen.nodes.visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (gen->gen.nodes.visited == NIL(st_table)) {
+	cmu_bdd_fatal("bdd_first_node: failed on memory allocation, location 2");
+    }
+
+    /*
+     * The stack size will never exceed the number of variables in the BDD, since
+     * the longest possible path from root to constant 1 is the number of variables 
+     * in the BDD.
+     */
+    gen->stack.sp = 0;
+    num_vars = cmu_bdd_vars(manager);
+    gen->stack.stack = ALLOC(bdd_node *, num_vars);
+    if (gen->stack.stack == NIL(bdd_node *)) {
+	cmu_bdd_fatal("bdd_first_node: failed on memory allocation, location 3");
+    }
+    /*
+     * Clear out the stack so that in bdd_gen_free, we can decrement the ref count
+     * of those nodes still on the stack.
+     */
+    for (i = 0; i < num_vars; i++) {
+	gen->stack.stack[i] = NIL(bdd_node);
+    }
+
+    /*
+     * Get the first node.  Get a new pointer to fn->node beforehand: this increments
+     * the reference count of fn->node; this is necessary, because when fn->node
+     * is popped from the stack at the very end, it's ref count is decremented.
+     */
+    f = cmu_bdd_identity(manager, fn->node);
+    push_node_stack(f, gen);
+    gen->status = bdd_NONEMPTY;
+
+    *node = gen->node;	/* return the node */
+    return (bdd_gen *) (gen);	/* and the new generator */
+}
+
+/*
+ *    bdd_next_node - get the next node in the BDD.
+ *    Return {TRUE, FALSE} when {more, no more}.
+ */
+boolean
+bdd_next_node(bdd_gen *gen_, bdd_node **node /* return */)
+{
+  cmu_bdd_gen *gen = (cmu_bdd_gen *) gen_;
+  
+    pop_node_stack(gen);
+    if (gen->status == bdd_EMPTY) {
+	return (FALSE);
+    }
+    *node = gen->node;
+    return (TRUE);
+}
+
+/*
+ *    bdd_gen_free - frees up the space used by the generator.
+ *    Return an int so that it is easier to fit in a foreach macro.
+ *    Return 0 (to make it easy to put in expressions).
+ */
+int
+bdd_gen_free(bdd_gen *gen_)
+{
+    long num_vars;
+    int i;
+    struct bdd_manager_ *mgr;
+    bdd_node *f;
+    st_table *visited_table;
+    st_generator *visited_gen;
+    cmu_bdd_gen *gen = (cmu_bdd_gen *) gen_;
+
+    mgr = gen->manager;
+
+    switch (gen->type) {
+    case bdd_gen_cubes:
+	array_free(gen->gen.cubes.cube);
+	gen->gen.cubes.cube = NIL(array_t);
+	break;
+    case bdd_gen_nodes:
+        visited_table = gen->gen.nodes.visited;
+	st_foreach_item(visited_table, visited_gen, &f, NIL(refany)) {
+	    cmu_bdd_free(mgr, (bdd) f);
+	}
+	st_free_table(visited_table);
+	visited_table = NIL(st_table);
+	break;
+    }
+
+    /*
+     * Free the data associated with this generator.  If there are any nodes remaining
+     * on the stack, we must free them, to get their ref counts back to what they were before.
+     */
+    num_vars = cmu_bdd_vars(mgr);
+    for (i = 0; i < num_vars; i++) {
+	f = gen->stack.stack[i];
+	if (f != NIL(bdd_node)) {
+	    cmu_bdd_free(mgr, (bdd) f);
+	}
+    }
+    FREE(gen->stack.stack);
+
+    FREE(gen);
+
+    return (0);	/* make it return some sort of an int */
+}
+
+/*
+ *    INTERNAL INTERFACE
+ *
+ *    Invariants:
+ *
+ *    gen->stack.stack contains nodes that remain to be explored.
+ *
+ *    For a cube generator,
+ *        gen->gen.cubes.cube reflects the choices made to reach node at top of the stack.
+ *    For a node generator,
+ *        gen->gen.nodes.visited reflects the nodes already visited in the BDD dag.
+ */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/*
+ *    push_cube_stack - push a cube onto the stack to visit.
+ *    Return nothing, just do it.
+ *
+ *    The BDD is traversed using depth-first search, with the ELSE branch 
+ *    searched before the THEN branch.
+ *
+ *    Caution: If you are creating new BDD's while iterating through the
+ *    cubes, and a garbage collection happens to be performed during this
+ *    process, then the BDD generator will get lost and an error will result.
+ *
+ */
+static void
+push_cube_stack(bdd_node *f, cmu_bdd_gen *gen)
+{
+    bdd_variableId topf_id;
+    bdd_node *f0, *f1;
+    struct bdd_manager_ *mgr;
+
+    mgr = gen->manager;
+
+    if (f == cmu_bdd_one(mgr)) {
+	return;
+    }
+
+    topf_id = (bdd_variableId) (cmu_bdd_if_id(mgr, (bdd) f) - 1);
+
+    /* 
+     * Get the then and else branches of f. Note that cmu_bdd_then and cmu_bdd_else 
+     * automatically take care of inverted pointers.  
+     */
+    f0 = cmu_bdd_else(mgr, (bdd) f);
+    f1 = cmu_bdd_then(mgr, (bdd) f);
+
+    if (f1 == cmu_bdd_zero(mgr)) {
+	/*
+	 *    No choice: take the 0 branch.  Since there is only one branch to 
+         *    explore from f, there is no need to push f onto the stack, because
+         *    after exploring this branch we are done with f.  A consequence of 
+         *    this is that there will be no f to pop either.  Same goes for the
+         *    next case.  Decrement the ref count of f and of the branch leading
+         *    to zero, since we will no longer need to access these nodes.
+	 */
+	array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 0);
+	push_cube_stack(f0, gen);
+        cmu_bdd_free(mgr, (bdd) f1);
+        cmu_bdd_free(mgr, (bdd) f);
+    } else if (f0 == cmu_bdd_zero(mgr)) {
+	/*
+	 *    No choice: take the 1 branch
+	 */
+	array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 1);
+	push_cube_stack(f1, gen);
+        cmu_bdd_free(mgr, (bdd) f0);
+        cmu_bdd_free(mgr, (bdd) f);
+    } else {
+        /*
+         * In this case, we must explore both branches of f.  We always choose
+         * to explore the 0 branch first.  We must push f on the stack, so that
+         * we can later pop it and explore its 1 branch. Decrement the ref count 
+	 * of f1 since we will no longer need to access this node.  Note that 
+         * the parent of f1 was bdd_freed above or in pop_cube_stack.
+         */
+	gen->stack.stack[gen->stack.sp++] = f;
+	array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 0);
+	push_cube_stack(f0, gen);
+        cmu_bdd_free(mgr, (bdd) f1);
+    }
+}
+
+static void
+pop_cube_stack(cmu_bdd_gen *gen)
+{
+    bdd_variableId topf_id, level_i_id;
+    bdd_node *branch_f;
+    bdd_node *f1;
+    int i;
+    long topf_level;
+    struct bdd_manager_ *mgr;
+    struct bdd_ *var_bdd;
+
+    mgr = gen->manager;
+
+    if (gen->stack.sp == 0) {
+        /*
+         * Stack is empty.  Have already explored both the 0 and 1 branches of 
+         * the root of the BDD.
+         */
+	gen->status = bdd_EMPTY;
+    } else {
+        /*
+         * Explore the 1 branch of the node at the top of the stack (since it is
+         * on the stack, this means we have already explored the 0 branch).  We 
+         * permanently pop the top node, and bdd_free it, since there are no more edges left to 
+         * explore. 
+         */
+	branch_f = gen->stack.stack[--gen->stack.sp];
+	gen->stack.stack[gen->stack.sp] = NIL(bdd_node); /* overwrite with NIL */
+        topf_id = (bdd_variableId) (cmu_bdd_if_id(mgr, (bdd) branch_f) - 1);
+	array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 1);
+
+        /* 
+         * We must set the variables with levels greater than the level of branch_f,
+         * back to 2 (don't care).  This is because these variables are not
+         * on the current path, and thus there values are don't care.
+         *
+         * Note the following correspondence:
+         *   CMU          UCB
+         *  index         level   (both start at zero)
+         *  indexindex    id      (CMU has id 0 for constant, thus really start numbering at 1;
+         *                                           UCB starts numbering at 0)
+         */
+        topf_level = cmu_bdd_if_index(mgr, (bdd) branch_f);
+	for (i = topf_level + 1; i < array_n(gen->gen.cubes.cube); i++) {
+            var_bdd = cmu_bdd_var_with_index(mgr, i);
+            level_i_id = (bdd_variableId) (cmu_bdd_if_id(mgr, var_bdd) - 1);
+	    /*
+             * No need to free var_bdd, since single variable BDDs are never garbage collected.
+             * Note that level_i_id is just (mgr->indexindexes[i] - 1); however, wanted
+             * to avoid using CMU internals.
+             */
+	    array_insert(bdd_literal, gen->gen.cubes.cube, level_i_id, 2);
+	}
+	f1 = cmu_bdd_then(mgr, (bdd) branch_f);
+	push_cube_stack(f1, gen);
+	cmu_bdd_free(mgr, (bdd) branch_f);
+    }
+}
+
+/*
+ *    push_node_stack - push a node onto the stack.
+ *
+ *    The same as push_cube_stack but for enumerating nodes instead of cubes.
+ *    The BDD is traversed using depth-first search, with the ELSE branch searched 
+ *    before the THEN branch, and a node returned only after its children have been
+ *    returned.  Note that the returned bdd_node pointer has the complement
+ *    bit zeroed out.
+ *
+ *    Caution: If you are creating new BDD's while iterating through the
+ *    nodes, and a garbage collection happens to be performed during this
+ *    process, then the BDD generator will get lost and an error will result.
+ *
+ *    Return nothing, just do it.
+ */
+static void
+push_node_stack(bdd_node *f, cmu_bdd_gen *gen)
+{
+    bdd_node *f0, *f1;
+    bdd_node *reg_f, *reg_f0, *reg_f1;
+    struct bdd_manager_ *mgr;
+
+    mgr = gen->manager;
+
+    reg_f = (bdd_node *) BDD_POINTER(f);  /* use of bddint.h */
+    if (st_lookup(gen->gen.nodes.visited, (refany) reg_f, NIL(refany))) {
+        /* 
+         * Already been visited.
+         */
+	return;
+    }
+
+    if (f == cmu_bdd_one(mgr) || f == cmu_bdd_zero(mgr)) {
+        /*
+         * If f is the constant node and it has not been visited yet, then put it in the visited table
+         * and set the gen->node pointer.  There is no need to put it in the stack because
+         * the constant node does not have any branches, and there is no need to free f because 
+         * constant nodes have a saturated reference count.
+         */
+	st_insert(gen->gen.nodes.visited, (refany) reg_f, NIL(any));
+	gen->node = reg_f;
+    } else {
+        /*
+         * f has not been marked as visited.  We don't know yet if any of its branches 
+         * remain to be explored.  First get its branches.  Note that cmu_bdd_then and 
+         * cmu_bdd_else automatically take care of inverted pointers.  
+         */
+	f0 = cmu_bdd_else(mgr, (bdd) f);
+	f1 = cmu_bdd_then(mgr, (bdd) f);
+
+	reg_f0 = (bdd_node *) BDD_POINTER(f0);  /* use of bddint.h */
+	reg_f1 = (bdd_node *) BDD_POINTER(f1);
+	if (! st_lookup(gen->gen.nodes.visited, (refany) reg_f0, NIL(refany))) {
+            /* 
+             * The 0 child has not been visited, so explore the 0 branch.  First push f on 
+             * the stack.  Bdd_free f1 since we will not need to access this exact pointer
+             * any more.
+             */
+	    gen->stack.stack[gen->stack.sp++] = f;
+            push_node_stack(f0, gen);
+	    cmu_bdd_free(mgr, (bdd) f1);
+	} else if (! st_lookup(gen->gen.nodes.visited, (refany) reg_f1, NIL(refany))) {
+            /* 
+             * The 0 child has been visited, but the 1 child has not been visited, so 
+             * explore the 1 branch.  First push f on the stack. We are done with f0, 
+	     * so bdd_free it.
+             */
+	    gen->stack.stack[gen->stack.sp++] = f;
+            push_node_stack(f1, gen);
+	    cmu_bdd_free(mgr, (bdd) f0);
+	} else {
+            /*
+             * Both the 0 and 1 children have been visited. Thus we are done exploring from f.  
+             * Mark f as visited (put it in the visited table), and set the gen->node pointer.
+	     * We will no longer need to refer to f0 and f1, so bdd_free them.  f will be
+             * bdd_freed when the visited table is freed.
+             */
+            st_insert(gen->gen.nodes.visited, (refany) reg_f, NIL(any));
+	    gen->node = reg_f;
+	    cmu_bdd_free(mgr, (bdd) f0);
+	    cmu_bdd_free(mgr, (bdd) f1);
+	}
+    }
+}
+
+static void
+pop_node_stack(cmu_bdd_gen *gen)
+{
+    bdd_node *branch_f;
+
+    if (gen->stack.sp == 0) {
+	gen->status = bdd_EMPTY;
+    } else {
+	branch_f = gen->stack.stack[--gen->stack.sp];  /* overwrite with NIL */
+	gen->stack.stack[gen->stack.sp] = NIL(bdd_node);
+	push_node_stack(branch_f, gen);
+    }
+}
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuBdd.make
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuBdd.make	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuBdd.make	(revision 8)
@@ -0,0 +1,42 @@
+CSRC_cu += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \
+        cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \
+        cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \
+	cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \
+	cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \
+	cuddExport.c cuddGenCof.c cuddGenetic.c \
+        cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \
+	cuddLCache.c cuddLevelQ.c \
+        cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \
+        cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \
+        cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \
+	cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \
+	cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \
+	cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c 
+HEADERS_cu += cudd.h cuddInt.h
+MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html \
+	doc/cuddAllDet.html doc/cuddExtAbs.html doc/cuddExtDet.html \
+	doc/cuddIntro.css doc/cuddIntro.html doc/footnode.html \
+	doc/img10.png doc/img11.png doc/img12.png doc/img13.png doc/img14.png \
+	doc/img15.png doc/img16.png doc/img17.png doc/img18.png \
+	doc/img19.png doc/img1.png doc/img20.png doc/img21.png \
+	doc/img22.png doc/img2.png doc/img3.png doc/img4.png doc/img5.png \
+	doc/img6.png doc/img7.png doc/img8.png doc/img9.png doc/index.html \
+	doc/node1.html doc/node2.html doc/node3.html doc/node4.html \
+	doc/node5.html doc/node6.html doc/node7.html doc/node8.html \
+	doc/icons/blueball.png doc/icons/ch_begin.png \
+	doc/icons/ch_beg_r.png doc/icons/ch_delet.png \
+	doc/icons/ch_del_r.png doc/icons/ch_end.png \
+	doc/icons/ch_end_r.png doc/icons/contents.png \
+	doc/icons/crossref.png doc/icons/footnote.png \
+	doc/icons/greenball.png doc/icons/image.png \
+	doc/icons/index.png doc/icons/next_g.png \
+	doc/icons/next.png doc/icons/nx_grp_g.png \
+	doc/icons/nx_grp.png doc/icons/orangeball.png \
+	doc/icons/pinkball.png doc/icons/prev_g.png \
+	doc/icons/prev.png doc/icons/purpleball.png \
+	doc/icons/pv_grp_g.png doc/icons/pv_grp.png \
+	doc/icons/redball.png doc/icons/up_g.png \
+	doc/icons/up.png doc/icons/whiteball.png \
+	doc/icons/yellowball.png
+
+DEPENDENCYFILES = $(CSRC_cu)
Index: /vis_dev/glu-2.1/src/cuBdd/cudd.h
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cudd.h	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cudd.h	(revision 8)
@@ -0,0 +1,1039 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cudd.h]
+
+  PackageName [cudd]
+
+  Synopsis    [The University of Colorado decision diagram package.]
+
+  Description [External functions and data strucures of the CUDD package.
+  <ul>
+  <li> To turn on the gathering of statistics, define DD_STATS.
+  <li> To link with mis, define DD_MIS.
+  </ul>
+  Modified by Abelardo Pardo to interface it to VIS.
+  ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: cudd.h,v 1.170 2005/05/18 06:07:41 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CUDD
+#define _CUDD
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "mtr.h"
+#include "epd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CUDD_VERSION "2.4.1"
+
+#ifndef SIZEOF_VOID_P
+#define SIZEOF_VOID_P 4
+#endif
+#ifndef SIZEOF_INT
+#define SIZEOF_INT 4
+#endif
+#ifndef SIZEOF_LONG
+#define SIZEOF_LONG 4
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define CUDD_VALUE_TYPE		double
+#define CUDD_OUT_OF_MEM		-1
+/* The sizes of the subtables and the cache must be powers of two. */
+#define CUDD_UNIQUE_SLOTS	256	/* initial size of subtables */
+#define CUDD_CACHE_SLOTS	262144	/* default size of the cache */
+
+/* Constants for residue functions. */
+#define CUDD_RESIDUE_DEFAULT	0
+#define CUDD_RESIDUE_MSB	1
+#define CUDD_RESIDUE_TC		2
+
+/* CUDD_MAXINDEX is defined in such a way that on 32-bit and 64-bit
+** machines one can cast an index to (int) without generating a negative
+** number.
+*/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define CUDD_MAXINDEX		(((DdHalfWord) ~0) >> 1)
+#else
+#define CUDD_MAXINDEX		((DdHalfWord) ~0)
+#endif
+
+/* CUDD_CONST_INDEX is the index of constant nodes.  Currently this
+** is a synonim for CUDD_MAXINDEX. */
+#define CUDD_CONST_INDEX	CUDD_MAXINDEX
+
+/* These constants define the digits used in the representation of
+** arbitrary precision integers.  The two configurations tested use 8
+** and 16 bits for each digit.  The typedefs should be in agreement
+** with these definitions.
+*/
+#define DD_APA_BITS	16
+#define DD_APA_BASE	(1 << DD_APA_BITS)
+#define DD_APA_MASK	(DD_APA_BASE - 1)
+#define DD_APA_HEXPRINT	"%04x"
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of reordering algorithm.]
+
+  Description [Type of reordering algorithm.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_REORDER_SAME,
+    CUDD_REORDER_NONE,
+    CUDD_REORDER_RANDOM,
+    CUDD_REORDER_RANDOM_PIVOT,
+    CUDD_REORDER_SIFT,
+    CUDD_REORDER_SIFT_CONVERGE,
+    CUDD_REORDER_SYMM_SIFT,
+    CUDD_REORDER_SYMM_SIFT_CONV,
+    CUDD_REORDER_WINDOW2,
+    CUDD_REORDER_WINDOW3,
+    CUDD_REORDER_WINDOW4,
+    CUDD_REORDER_WINDOW2_CONV,
+    CUDD_REORDER_WINDOW3_CONV,
+    CUDD_REORDER_WINDOW4_CONV,
+    CUDD_REORDER_GROUP_SIFT,
+    CUDD_REORDER_GROUP_SIFT_CONV,
+    CUDD_REORDER_ANNEALING,
+    CUDD_REORDER_GENETIC,
+    CUDD_REORDER_LINEAR,
+    CUDD_REORDER_LINEAR_CONVERGE,
+    CUDD_REORDER_LAZY_SIFT,
+    CUDD_REORDER_EXACT
+} Cudd_ReorderingType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of aggregation methods.]
+
+  Description [Type of aggregation methods.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_NO_CHECK,
+    CUDD_GROUP_CHECK,
+    CUDD_GROUP_CHECK2,
+    CUDD_GROUP_CHECK3,
+    CUDD_GROUP_CHECK4,
+    CUDD_GROUP_CHECK5,
+    CUDD_GROUP_CHECK6,
+    CUDD_GROUP_CHECK7,
+    CUDD_GROUP_CHECK8,
+    CUDD_GROUP_CHECK9
+} Cudd_AggregationType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of hooks.]
+
+  Description [Type of hooks.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_PRE_GC_HOOK,
+    CUDD_POST_GC_HOOK,
+    CUDD_PRE_REORDERING_HOOK,
+    CUDD_POST_REORDERING_HOOK
+} Cudd_HookType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of error codes.]
+
+  Description [Type of  error codes.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_NO_ERROR,
+    CUDD_MEMORY_OUT,
+    CUDD_TOO_MANY_NODES,
+    CUDD_MAX_MEM_EXCEEDED,
+    CUDD_INVALID_ARG,
+    CUDD_INTERNAL_ERROR
+} Cudd_ErrorType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Group type for lazy sifting.]
+
+  Description [Group type for lazy sifting.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_LAZY_NONE,
+    CUDD_LAZY_SOFT_GROUP,
+    CUDD_LAZY_HARD_GROUP,
+    CUDD_LAZY_UNGROUP
+} Cudd_LazyGroupType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Variable type.]
+
+  Description [Variable type. Currently used only in lazy sifting.]
+
+******************************************************************************/
+typedef enum {
+    CUDD_VAR_PRIMARY_INPUT,
+    CUDD_VAR_PRESENT_STATE,
+    CUDD_VAR_NEXT_STATE
+} Cudd_VariableType;
+
+
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+typedef unsigned int   DdHalfWord;
+#else
+typedef unsigned short DdHalfWord;
+#endif
+
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+
+typedef struct DdNode DdNode;
+
+typedef struct DdChildren {
+    struct DdNode *T;
+    struct DdNode *E;
+} DdChildren;
+
+/* The DdNode structure is the only one exported out of the package */
+struct DdNode {
+    DdHalfWord index;
+    DdHalfWord ref;		/* reference count */
+    DdNode *next;		/* next pointer for unique table */
+    union {
+	CUDD_VALUE_TYPE value;	/* for constant nodes */
+	DdChildren kids;	/* for internal nodes */
+    } type;
+};
+
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+typedef struct DdManager DdManager;
+
+typedef struct DdGen DdGen;
+
+/* These typedefs for arbitrary precision arithmetic should agree with
+** the corresponding constant definitions above. */
+typedef unsigned short int DdApaDigit;
+typedef unsigned long int DdApaDoubleDigit;
+typedef DdApaDigit * DdApaNumber;
+
+/* Return type for function computing two-literal clauses. */
+typedef struct DdTlcInfo DdTlcInfo;
+
+/* Type of hook function. */
+typedef int (*DD_HFP)(DdManager *, const char *, void *);
+/* Type of priority function */
+typedef DdNode * (*DD_PRFP)(DdManager * , int, DdNode **, DdNode **,
+			    DdNode **);
+/* Type of apply operator. */
+typedef DdNode * (*DD_AOP)(DdManager *, DdNode **, DdNode **);
+/* Type of monadic apply operator. */
+typedef DdNode * (*DD_MAOP)(DdManager *, DdNode *);
+/* Types of cache tag functions. */
+typedef DdNode * (*DD_CTFP)(DdManager *, DdNode *, DdNode *);
+typedef DdNode * (*DD_CTFP1)(DdManager *, DdNode *);
+/* Type of memory-out function. */
+typedef void (*DD_OOMFP)(long);
+/* Type of comparison function for qsort. */
+typedef int (*DD_QSFP)(const void *, const void *);
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns 1 if the node is a constant node.]
+
+  Description  [Returns 1 if the node is a constant node (rather than an
+  internal node). All constant nodes have the same index
+  (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either
+  regular or complemented.]
+
+  SideEffects  [none]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Cudd_IsConstant(node) ((Cudd_Regular(node))->index == CUDD_CONST_INDEX)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Complements a DD.]
+
+  Description  [Complements a DD by flipping the complement attribute of
+  the pointer (the least significant bit).]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_NotCond]
+
+******************************************************************************/
+#define Cudd_Not(node) ((DdNode *)((long)(node) ^ 01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Complements a DD if a condition is true.]
+
+  Description  [Complements a DD if condition c is true; c should be
+  either 0 or 1, because it is used directly (for efficiency). If in
+  doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Not]
+
+******************************************************************************/
+#define Cudd_NotCond(node,c) ((DdNode *)((long)(node) ^ (c)))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the regular version of a pointer.]
+
+  Description  []
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Complement Cudd_IsComplement]
+
+******************************************************************************/
+#define Cudd_Regular(node) ((DdNode *)((unsigned long)(node) & ~01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the complemented version of a pointer.]
+
+  Description  []
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Regular Cudd_IsComplement]
+
+******************************************************************************/
+#define Cudd_Complement(node) ((DdNode *)((unsigned long)(node) | 01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns 1 if a pointer is complemented.]
+
+  Description  []
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Regular Cudd_Complement]
+
+******************************************************************************/
+#define Cudd_IsComplement(node)	((int) ((long) (node) & 01))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the then child of an internal node.]
+
+  Description  [Returns the then child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_E Cudd_V]
+
+******************************************************************************/
+#define Cudd_T(node) ((Cudd_Regular(node))->type.kids.T)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the else child of an internal node.]
+
+  Description  [Returns the else child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_T Cudd_V]
+
+******************************************************************************/
+#define Cudd_E(node) ((Cudd_Regular(node))->type.kids.E)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the value of a constant node.]
+
+  Description  [Returns the value of a constant node. If
+  <code>node</code> is an internal node, the result is unpredictable.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_T Cudd_E]
+
+******************************************************************************/
+#define Cudd_V(node) ((Cudd_Regular(node))->type.value)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the current position in the order of variable
+  index.]
+
+  Description [Returns the current position in the order of variable
+  index. This macro is obsolete and is kept for compatibility. New
+  applications should use Cudd_ReadPerm instead.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ReadPerm]
+
+******************************************************************************/
+#define Cudd_ReadIndex(dd,index) (Cudd_ReadPerm(dd,index))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the cubes of a decision diagram.]
+
+  Description  [Iterates over the cubes of a decision diagram f.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *f;
+  <li> DdGen *gen;
+  <li> int *cube;
+  <li> CUDD_VALUE_TYPE value;
+  </ul>
+  Cudd_ForeachCube allocates and frees the generator. Therefore the
+  application should not try to do that. Also, the cube is freed at the
+  end of Cudd_ForeachCube and hence is not available outside of the loop.<p>
+  CAUTION: It is assumed that dynamic reordering will not occur while
+  there are open generators. It is the user's responsibility to make sure
+  that dynamic reordering does not occur. As long as new nodes are not created
+  during generation, and dynamic reordering is not called explicitly,
+  dynamic reordering will not occur. Alternatively, it is sufficient to
+  disable dynamic reordering. It is a mistake to dispose of a diagram
+  on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_GenFree
+  Cudd_IsGenEmpty Cudd_AutodynDisable]
+
+******************************************************************************/
+#define Cudd_ForeachCube(manager, f, gen, cube, value)\
+    for((gen) = Cudd_FirstCube(manager, f, &cube, &value);\
+	Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+	(void) Cudd_NextCube(gen, &cube, &value))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the primes of a Boolean function.]
+
+  Description  [Iterates over the primes of a Boolean function producing
+  a prime and irredundant cover.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *l;
+  <li> DdNode *u;
+  <li> DdGen *gen;
+  <li> int *cube;
+  </ul>
+  The Boolean function is described by an upper bound and a lower bound.  If
+  the function is completely specified, the two bounds coincide.
+  Cudd_ForeachPrime allocates and frees the generator.  Therefore the
+  application should not try to do that.  Also, the cube is freed at the
+  end of Cudd_ForeachPrime and hence is not available outside of the loop.<p>
+  CAUTION: It is a mistake to change a diagram on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ForeachCube Cudd_FirstPrime Cudd_NextPrime Cudd_GenFree
+  Cudd_IsGenEmpty]
+
+******************************************************************************/
+#define Cudd_ForeachPrime(manager, l, u, gen, cube)\
+    for((gen) = Cudd_FirstPrime(manager, l, u, &cube);\
+	Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+	(void) Cudd_NextPrime(gen, &cube))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the nodes of a decision diagram.]
+
+  Description  [Iterates over the nodes of a decision diagram f.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *f;
+  <li> DdGen *gen;
+  <li> DdNode *node;
+  </ul>
+  The nodes are returned in a seemingly random order.
+  Cudd_ForeachNode allocates and frees the generator. Therefore the
+  application should not try to do that.<p>
+  CAUTION: It is assumed that dynamic reordering will not occur while
+  there are open generators. It is the user's responsibility to make sure
+  that dynamic reordering does not occur. As long as new nodes are not created
+  during generation, and dynamic reordering is not called explicitly,
+  dynamic reordering will not occur. Alternatively, it is sufficient to
+  disable dynamic reordering. It is a mistake to dispose of a diagram
+  on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_ForeachCube Cudd_FirstNode Cudd_NextNode Cudd_GenFree
+  Cudd_IsGenEmpty Cudd_AutodynDisable]
+
+******************************************************************************/
+#define Cudd_ForeachNode(manager, f, gen, node)\
+    for((gen) = Cudd_FirstNode(manager, f, &node);\
+	Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+	(void) Cudd_NextNode(gen, &node))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the paths of a ZDD.]
+
+  Description  [Iterates over the paths of a ZDD f.
+  <ul>
+  <li> DdManager *manager;
+  <li> DdNode *f;
+  <li> DdGen *gen;
+  <li> int *path;
+  </ul>
+  Cudd_zddForeachPath allocates and frees the generator. Therefore the
+  application should not try to do that. Also, the path is freed at the
+  end of Cudd_zddForeachPath and hence is not available outside of the loop.<p>
+  CAUTION: It is assumed that dynamic reordering will not occur while
+  there are open generators.  It is the user's responsibility to make sure
+  that dynamic reordering does not occur.  As long as new nodes are not created
+  during generation, and dynamic reordering is not called explicitly,
+  dynamic reordering will not occur.  Alternatively, it is sufficient to
+  disable dynamic reordering.  It is a mistake to dispose of a diagram
+  on which generation is ongoing.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_zddFirstPath Cudd_zddNextPath Cudd_GenFree
+  Cudd_IsGenEmpty Cudd_AutodynDisable]
+
+******************************************************************************/
+#define Cudd_zddForeachPath(manager, f, gen, path)\
+    for((gen) = Cudd_zddFirstPath(manager, f, &path);\
+	Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\
+	(void) Cudd_zddNextPath(gen, &path))
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern DdNode * Cudd_addNewVar (DdManager *dd);
+extern DdNode * Cudd_addNewVarAtLevel (DdManager *dd, int level);
+extern DdNode * Cudd_bddNewVar (DdManager *dd);
+extern DdNode * Cudd_bddNewVarAtLevel (DdManager *dd, int level);
+extern DdNode * Cudd_addIthVar (DdManager *dd, int i);
+extern DdNode * Cudd_bddIthVar (DdManager *dd, int i);
+extern DdNode * Cudd_zddIthVar (DdManager *dd, int i);
+extern int Cudd_zddVarsFromBddVars (DdManager *dd, int multiplicity);
+extern DdNode * Cudd_addConst (DdManager *dd, CUDD_VALUE_TYPE c);
+extern int Cudd_IsNonConstant (DdNode *f);
+extern void Cudd_AutodynEnable (DdManager *unique, Cudd_ReorderingType method);
+extern void Cudd_AutodynDisable (DdManager *unique);
+extern int Cudd_ReorderingStatus (DdManager *unique, Cudd_ReorderingType *method);
+extern void Cudd_AutodynEnableZdd (DdManager *unique, Cudd_ReorderingType method);
+extern void Cudd_AutodynDisableZdd (DdManager *unique);
+extern int Cudd_ReorderingStatusZdd (DdManager *unique, Cudd_ReorderingType *method);
+extern int Cudd_zddRealignmentEnabled (DdManager *unique);
+extern void Cudd_zddRealignEnable (DdManager *unique);
+extern void Cudd_zddRealignDisable (DdManager *unique);
+extern int Cudd_bddRealignmentEnabled (DdManager *unique);
+extern void Cudd_bddRealignEnable (DdManager *unique);
+extern void Cudd_bddRealignDisable (DdManager *unique);
+extern DdNode * Cudd_ReadOne (DdManager *dd);
+extern DdNode * Cudd_ReadZddOne (DdManager *dd, int i);
+extern DdNode * Cudd_ReadZero (DdManager *dd);
+extern DdNode * Cudd_ReadLogicZero (DdManager *dd);
+extern DdNode * Cudd_ReadPlusInfinity (DdManager *dd);
+extern DdNode * Cudd_ReadMinusInfinity (DdManager *dd);
+extern DdNode * Cudd_ReadBackground (DdManager *dd);
+extern void Cudd_SetBackground (DdManager *dd, DdNode *bck);
+extern unsigned int Cudd_ReadCacheSlots (DdManager *dd);
+extern double Cudd_ReadCacheUsedSlots (DdManager * dd);
+extern double Cudd_ReadCacheLookUps (DdManager *dd);
+extern double Cudd_ReadCacheHits (DdManager *dd);
+extern double Cudd_ReadRecursiveCalls (DdManager * dd);
+extern unsigned int Cudd_ReadMinHit (DdManager *dd);
+extern void Cudd_SetMinHit (DdManager *dd, unsigned int hr);
+extern unsigned int Cudd_ReadLooseUpTo (DdManager *dd);
+extern void Cudd_SetLooseUpTo (DdManager *dd, unsigned int lut);
+extern unsigned int Cudd_ReadMaxCache (DdManager *dd);
+extern unsigned int Cudd_ReadMaxCacheHard (DdManager *dd);
+extern void Cudd_SetMaxCacheHard (DdManager *dd, unsigned int mc);
+extern int Cudd_ReadSize (DdManager *dd);
+extern int Cudd_ReadZddSize (DdManager *dd);
+extern unsigned int Cudd_ReadSlots (DdManager *dd);
+extern double Cudd_ReadUsedSlots (DdManager * dd);
+extern double Cudd_ExpectedUsedSlots (DdManager * dd);
+extern unsigned int Cudd_ReadKeys (DdManager *dd);
+extern unsigned int Cudd_ReadDead (DdManager *dd);
+extern unsigned int Cudd_ReadMinDead (DdManager *dd);
+extern int Cudd_ReadReorderings (DdManager *dd);
+extern long Cudd_ReadReorderingTime (DdManager * dd);
+extern int Cudd_ReadGarbageCollections (DdManager * dd);
+extern long Cudd_ReadGarbageCollectionTime (DdManager * dd);
+extern double Cudd_ReadNodesFreed (DdManager * dd);
+extern double Cudd_ReadNodesDropped (DdManager * dd);
+extern double Cudd_ReadUniqueLookUps (DdManager * dd);
+extern double Cudd_ReadUniqueLinks (DdManager * dd);
+extern int Cudd_ReadSiftMaxVar (DdManager *dd);
+extern void Cudd_SetSiftMaxVar (DdManager *dd, int smv);
+extern int Cudd_ReadSiftMaxSwap (DdManager *dd);
+extern void Cudd_SetSiftMaxSwap (DdManager *dd, int sms);
+extern double Cudd_ReadMaxGrowth (DdManager *dd);
+extern void Cudd_SetMaxGrowth (DdManager *dd, double mg);
+extern double Cudd_ReadMaxGrowthAlternate (DdManager * dd);
+extern void Cudd_SetMaxGrowthAlternate (DdManager * dd, double mg);
+extern int Cudd_ReadReorderingCycle (DdManager * dd);
+extern void Cudd_SetReorderingCycle (DdManager * dd, int cycle);
+extern MtrNode * Cudd_ReadTree (DdManager *dd);
+extern void Cudd_SetTree (DdManager *dd, MtrNode *tree);
+extern void Cudd_FreeTree (DdManager *dd);
+extern MtrNode * Cudd_ReadZddTree (DdManager *dd);
+extern void Cudd_SetZddTree (DdManager *dd, MtrNode *tree);
+extern void Cudd_FreeZddTree (DdManager *dd);
+extern unsigned int Cudd_NodeReadIndex (DdNode *node);
+extern int Cudd_ReadPerm (DdManager *dd, int i);
+extern int Cudd_ReadPermZdd (DdManager *dd, int i);
+extern int Cudd_ReadInvPerm (DdManager *dd, int i);
+extern int Cudd_ReadInvPermZdd (DdManager *dd, int i);
+extern DdNode * Cudd_ReadVars (DdManager *dd, int i);
+extern CUDD_VALUE_TYPE Cudd_ReadEpsilon (DdManager *dd);
+extern void Cudd_SetEpsilon (DdManager *dd, CUDD_VALUE_TYPE ep);
+extern Cudd_AggregationType Cudd_ReadGroupcheck (DdManager *dd);
+extern void Cudd_SetGroupcheck (DdManager *dd, Cudd_AggregationType gc);
+extern int Cudd_GarbageCollectionEnabled (DdManager *dd);
+extern void Cudd_EnableGarbageCollection (DdManager *dd);
+extern void Cudd_DisableGarbageCollection (DdManager *dd);
+extern int Cudd_DeadAreCounted (DdManager *dd);
+extern void Cudd_TurnOnCountDead (DdManager *dd);
+extern void Cudd_TurnOffCountDead (DdManager *dd);
+extern int Cudd_ReadRecomb (DdManager *dd);
+extern void Cudd_SetRecomb (DdManager *dd, int recomb);
+extern int Cudd_ReadSymmviolation (DdManager *dd);
+extern void Cudd_SetSymmviolation (DdManager *dd, int symmviolation);
+extern int Cudd_ReadArcviolation (DdManager *dd);
+extern void Cudd_SetArcviolation (DdManager *dd, int arcviolation);
+extern int Cudd_ReadPopulationSize (DdManager *dd);
+extern void Cudd_SetPopulationSize (DdManager *dd, int populationSize);
+extern int Cudd_ReadNumberXovers (DdManager *dd);
+extern void Cudd_SetNumberXovers (DdManager *dd, int numberXovers);
+extern unsigned long Cudd_ReadMemoryInUse (DdManager *dd);
+extern int Cudd_PrintInfo (DdManager *dd, FILE *fp);
+extern long Cudd_ReadPeakNodeCount (DdManager *dd);
+extern int Cudd_ReadPeakLiveNodeCount (DdManager * dd);
+extern long Cudd_ReadNodeCount (DdManager *dd);
+extern long Cudd_zddReadNodeCount (DdManager *dd);
+extern int Cudd_AddHook (DdManager *dd, DD_HFP f, Cudd_HookType where);
+extern int Cudd_RemoveHook (DdManager *dd, DD_HFP f, Cudd_HookType where);
+extern int Cudd_IsInHook (DdManager * dd, DD_HFP f, Cudd_HookType where);
+extern int Cudd_StdPreReordHook (DdManager *dd, const char *str, void *data);
+extern int Cudd_StdPostReordHook (DdManager *dd, const char *str, void *data);
+extern int Cudd_EnableReorderingReporting (DdManager *dd);
+extern int Cudd_DisableReorderingReporting (DdManager *dd);
+extern int Cudd_ReorderingReporting (DdManager *dd);
+extern Cudd_ErrorType Cudd_ReadErrorCode (DdManager *dd);
+extern void Cudd_ClearErrorCode (DdManager *dd);
+extern FILE * Cudd_ReadStdout (DdManager *dd);
+extern void Cudd_SetStdout (DdManager *dd, FILE *fp);
+extern FILE * Cudd_ReadStderr (DdManager *dd);
+extern void Cudd_SetStderr (DdManager *dd, FILE *fp);
+extern unsigned int Cudd_ReadNextReordering (DdManager *dd);
+extern void Cudd_SetNextReordering (DdManager *dd, unsigned int next);
+extern double Cudd_ReadSwapSteps (DdManager *dd);
+extern unsigned int Cudd_ReadMaxLive (DdManager *dd);
+extern void Cudd_SetMaxLive (DdManager *dd, unsigned int maxLive);
+extern unsigned long Cudd_ReadMaxMemory (DdManager *dd);
+extern void Cudd_SetMaxMemory (DdManager *dd, unsigned long maxMemory);
+extern int Cudd_bddBindVar (DdManager *dd, int index);
+extern int Cudd_bddUnbindVar (DdManager *dd, int index);
+extern int Cudd_bddVarIsBound (DdManager *dd, int index);
+extern DdNode * Cudd_addExistAbstract (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * Cudd_addUnivAbstract (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * Cudd_addOrAbstract (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * Cudd_addApply (DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g);
+extern DdNode * Cudd_addPlus (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addTimes (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addThreshold (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addSetNZ (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addDivide (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addMinus (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addMinimum (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addMaximum (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addOneZeroMaximum (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addDiff (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addAgreement (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addOr (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addNand (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addNor (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addXor (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addXnor (DdManager *dd, DdNode **f, DdNode **g);
+extern DdNode * Cudd_addMonadicApply (DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f);
+extern DdNode * Cudd_addLog (DdManager * dd, DdNode * f);
+extern DdNode * Cudd_addFindMax (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_addFindMin (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_addIthBit (DdManager *dd, DdNode *f, int bit);
+extern DdNode * Cudd_addScalarInverse (DdManager *dd, DdNode *f, DdNode *epsilon);
+extern DdNode * Cudd_addIte (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * Cudd_addIteConstant (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * Cudd_addEvalConst (DdManager *dd, DdNode *f, DdNode *g);
+extern int Cudd_addLeq (DdManager * dd, DdNode * f, DdNode * g);
+extern DdNode * Cudd_addCmpl (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_addNegate (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_addRoundOff (DdManager *dd, DdNode *f, int N);
+extern DdNode * Cudd_addWalsh (DdManager *dd, DdNode **x, DdNode **y, int n);
+extern DdNode * Cudd_addResidue (DdManager *dd, int n, int m, int options, int top);
+extern DdNode * Cudd_bddAndAbstract (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube);
+extern DdNode * Cudd_bddAndAbstractLimit (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, unsigned int limit);
+extern int Cudd_ApaNumberOfDigits (int binaryDigits);
+extern DdApaNumber Cudd_NewApaNumber (int digits);
+extern void Cudd_ApaCopy (int digits, DdApaNumber source, DdApaNumber dest);
+extern DdApaDigit Cudd_ApaAdd (int digits, DdApaNumber a, DdApaNumber b, DdApaNumber sum);
+extern DdApaDigit Cudd_ApaSubtract (int digits, DdApaNumber a, DdApaNumber b, DdApaNumber diff);
+extern DdApaDigit Cudd_ApaShortDivision (int digits, DdApaNumber dividend, DdApaDigit divisor, DdApaNumber quotient);
+extern unsigned int Cudd_ApaIntDivision (int  digits, DdApaNumber dividend, unsigned int  divisor, DdApaNumber  quotient);
+extern void Cudd_ApaShiftRight (int digits, DdApaDigit in, DdApaNumber a, DdApaNumber b);
+extern void Cudd_ApaSetToLiteral (int digits, DdApaNumber number, DdApaDigit literal);
+extern void Cudd_ApaPowerOfTwo (int digits, DdApaNumber number, int power);
+extern int Cudd_ApaCompare (int digitsFirst, DdApaNumber  first, int digitsSecond, DdApaNumber  second);
+extern int Cudd_ApaCompareRatios (int digitsFirst, DdApaNumber firstNum, unsigned int firstDen, int digitsSecond, DdApaNumber secondNum, unsigned int secondDen);
+extern int Cudd_ApaPrintHex (FILE *fp, int digits, DdApaNumber number);
+extern int Cudd_ApaPrintDecimal (FILE *fp, int digits, DdApaNumber number);
+extern int Cudd_ApaPrintExponential (FILE * fp, int  digits, DdApaNumber  number, int precision);
+extern DdApaNumber Cudd_ApaCountMinterm (DdManager *manager, DdNode *node, int nvars, int *digits);
+extern int Cudd_ApaPrintMinterm (FILE *fp, DdManager *dd, DdNode *node, int nvars);
+extern int Cudd_ApaPrintMintermExp (FILE * fp, DdManager * dd, DdNode * node, int  nvars, int precision);
+extern int Cudd_ApaPrintDensity (FILE * fp, DdManager * dd, DdNode * node, int  nvars);
+extern DdNode * Cudd_UnderApprox (DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality);
+extern DdNode * Cudd_OverApprox (DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality);
+extern DdNode * Cudd_RemapUnderApprox (DdManager *dd, DdNode *f, int numVars, int threshold, double quality);
+extern DdNode * Cudd_RemapOverApprox (DdManager *dd, DdNode *f, int numVars, int threshold, double quality);
+extern DdNode * Cudd_BiasedUnderApprox (DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0);
+extern DdNode * Cudd_BiasedOverApprox (DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0);
+extern DdNode * Cudd_bddExistAbstract (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * Cudd_bddXorExistAbstract (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube);
+extern DdNode * Cudd_bddUnivAbstract (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * Cudd_bddBooleanDiff (DdManager *manager, DdNode *f, int x);
+extern int Cudd_bddVarIsDependent (DdManager *dd, DdNode *f, DdNode *var);
+extern double Cudd_bddCorrelation (DdManager *manager, DdNode *f, DdNode *g);
+extern double Cudd_bddCorrelationWeights (DdManager *manager, DdNode *f, DdNode *g, double *prob);
+extern DdNode * Cudd_bddIte (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * Cudd_bddIteConstant (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * Cudd_bddIntersect (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_bddAnd (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_bddAndLimit (DdManager *dd, DdNode *f, DdNode *g, unsigned int limit);
+extern DdNode * Cudd_bddOr (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_bddNand (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_bddNor (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_bddXor (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_bddXnor (DdManager *dd, DdNode *f, DdNode *g);
+extern int Cudd_bddLeq (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_addBddThreshold (DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value);
+extern DdNode * Cudd_addBddStrictThreshold (DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value);
+extern DdNode * Cudd_addBddInterval (DdManager *dd, DdNode *f, CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper);
+extern DdNode * Cudd_addBddIthBit (DdManager *dd, DdNode *f, int bit);
+extern DdNode * Cudd_BddToAdd (DdManager *dd, DdNode *B);
+extern DdNode * Cudd_addBddPattern (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_bddTransfer (DdManager *ddSource, DdManager *ddDestination, DdNode *f);
+extern int Cudd_DebugCheck (DdManager *table);
+extern int Cudd_CheckKeys (DdManager *table);
+extern DdNode * Cudd_bddClippingAnd (DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction);
+extern DdNode * Cudd_bddClippingAndAbstract (DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction);
+extern DdNode * Cudd_Cofactor (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_bddCompose (DdManager *dd, DdNode *f, DdNode *g, int v);
+extern DdNode * Cudd_addCompose (DdManager *dd, DdNode *f, DdNode *g, int v);
+extern DdNode * Cudd_addPermute (DdManager *manager, DdNode *node, int *permut);
+extern DdNode * Cudd_addSwapVariables (DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n);
+extern DdNode * Cudd_bddPermute (DdManager *manager, DdNode *node, int *permut);
+extern DdNode * Cudd_bddVarMap (DdManager *manager, DdNode *f);
+extern int Cudd_SetVarMap (DdManager *manager, DdNode **x, DdNode **y, int n);
+extern DdNode * Cudd_bddSwapVariables (DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n);
+extern DdNode * Cudd_bddAdjPermuteX (DdManager *dd, DdNode *B, DdNode **x, int n);
+extern DdNode * Cudd_addVectorCompose (DdManager *dd, DdNode *f, DdNode **vector);
+extern DdNode * Cudd_addGeneralVectorCompose (DdManager *dd, DdNode *f, DdNode **vectorOn, DdNode **vectorOff);
+extern DdNode * Cudd_addNonSimCompose (DdManager *dd, DdNode *f, DdNode **vector);
+extern DdNode * Cudd_bddVectorCompose (DdManager *dd, DdNode *f, DdNode **vector);
+extern int Cudd_bddApproxConjDecomp (DdManager *dd, DdNode *f, DdNode ***conjuncts);
+extern int Cudd_bddApproxDisjDecomp (DdManager *dd, DdNode *f, DdNode ***disjuncts);
+extern int Cudd_bddIterConjDecomp (DdManager *dd, DdNode *f, DdNode ***conjuncts);
+extern int Cudd_bddIterDisjDecomp (DdManager *dd, DdNode *f, DdNode ***disjuncts);
+extern int Cudd_bddGenConjDecomp (DdManager *dd, DdNode *f, DdNode ***conjuncts);
+extern int Cudd_bddGenDisjDecomp (DdManager *dd, DdNode *f, DdNode ***disjuncts);
+extern int Cudd_bddVarConjDecomp (DdManager *dd, DdNode * f, DdNode ***conjuncts);
+extern int Cudd_bddVarDisjDecomp (DdManager *dd, DdNode * f, DdNode ***disjuncts);
+extern DdNode * Cudd_FindEssential (DdManager *dd, DdNode *f);
+extern int Cudd_bddIsVarEssential (DdManager *manager, DdNode *f, int id, int phase);
+extern DdTlcInfo * Cudd_FindTwoLiteralClauses (DdManager * dd, DdNode * f);
+extern int Cudd_PrintTwoLiteralClauses (DdManager * dd, DdNode * f, char **names, FILE *fp);
+extern int Cudd_ReadIthClause (DdTlcInfo * tlc, int i, DdHalfWord *var1, DdHalfWord *var2, int *phase1, int *phase2);
+extern void Cudd_tlcInfoFree (DdTlcInfo * t);
+extern int Cudd_DumpBlif (DdManager *dd, int n, DdNode **f, char **inames, char **onames, char *mname, FILE *fp);
+extern int Cudd_DumpBlifBody (DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp);
+extern int Cudd_DumpDot (DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp);
+extern int Cudd_DumpDaVinci (DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp);
+extern int Cudd_DumpDDcal (DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp);
+extern int Cudd_DumpFactoredForm (DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp);
+extern DdNode * Cudd_bddConstrain (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * Cudd_bddRestrict (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * Cudd_bddNPAnd (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * Cudd_addConstrain (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode ** Cudd_bddConstrainDecomp (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_addRestrict (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode ** Cudd_bddCharToVect (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_bddLICompaction (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * Cudd_bddSqueeze (DdManager *dd, DdNode *l, DdNode *u);
+extern DdNode * Cudd_bddMinimize (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * Cudd_SubsetCompress (DdManager *dd, DdNode *f, int nvars, int threshold);
+extern DdNode * Cudd_SupersetCompress (DdManager *dd, DdNode *f, int nvars, int threshold);
+extern MtrNode * Cudd_MakeTreeNode (DdManager *dd, unsigned int low, unsigned int size, unsigned int type);
+extern int Cudd_addHarwell (FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy, int pr);
+extern DdManager * Cudd_Init (unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory);
+extern void Cudd_Quit (DdManager *unique);
+extern int Cudd_PrintLinear (DdManager *table);
+extern int Cudd_ReadLinear (DdManager *table, int x, int y);
+extern DdNode * Cudd_bddLiteralSetIntersection (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * Cudd_addMatrixMultiply (DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz);
+extern DdNode * Cudd_addTimesPlus (DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz);
+extern DdNode * Cudd_addTriangle (DdManager *dd, DdNode *f, DdNode *g, DdNode **z, int nz);
+extern DdNode * Cudd_addOuterSum (DdManager *dd, DdNode *M, DdNode *r, DdNode *c);
+extern DdNode * Cudd_PrioritySelect (DdManager *dd, DdNode *R, DdNode **x, DdNode **y, DdNode **z, DdNode *Pi, int n, DdNode * (*)(DdManager *, int, DdNode **, DdNode **, DdNode **));
+extern DdNode * Cudd_Xgty (DdManager *dd, int N, DdNode **z, DdNode **x, DdNode **y);
+extern DdNode * Cudd_Xeqy (DdManager *dd, int N, DdNode **x, DdNode **y);
+extern DdNode * Cudd_addXeqy (DdManager *dd, int N, DdNode **x, DdNode **y);
+extern DdNode * Cudd_Dxygtdxz (DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z);
+extern DdNode * Cudd_Dxygtdyz (DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z);
+extern DdNode * Cudd_CProjection (DdManager *dd, DdNode *R, DdNode *Y);
+extern DdNode * Cudd_addHamming (DdManager *dd, DdNode **xVars, DdNode **yVars, int nVars);
+extern int Cudd_MinHammingDist (DdManager *dd, DdNode *f, int *minterm, int upperBound);
+extern DdNode * Cudd_bddClosestCube (DdManager *dd, DdNode * f, DdNode *g, int *distance);
+extern int Cudd_addRead (FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy);
+extern int Cudd_bddRead (FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy);
+extern void Cudd_Ref (DdNode *n);
+extern void Cudd_RecursiveDeref (DdManager *table, DdNode *n);
+extern void Cudd_IterDerefBdd (DdManager *table, DdNode *n);
+extern void Cudd_DelayedDerefBdd (DdManager * table, DdNode * n);
+extern void Cudd_RecursiveDerefZdd (DdManager *table, DdNode *n);
+extern void Cudd_Deref (DdNode *node);
+extern int Cudd_CheckZeroRef (DdManager *manager);
+extern int Cudd_ReduceHeap (DdManager *table, Cudd_ReorderingType heuristic, int minsize);
+extern int Cudd_ShuffleHeap (DdManager *table, int *permutation);
+extern DdNode * Cudd_Eval (DdManager *dd, DdNode *f, int *inputs);
+extern DdNode * Cudd_ShortestPath (DdManager *manager, DdNode *f, int *weight, int *support, int *length);
+extern DdNode * Cudd_LargestCube (DdManager *manager, DdNode *f, int *length);
+extern int Cudd_ShortestLength (DdManager *manager, DdNode *f, int *weight);
+extern DdNode * Cudd_Decreasing (DdManager *dd, DdNode *f, int i);
+extern DdNode * Cudd_Increasing (DdManager *dd, DdNode *f, int i);
+extern int Cudd_EquivDC (DdManager *dd, DdNode *F, DdNode *G, DdNode *D);
+extern int Cudd_bddLeqUnless (DdManager *dd, DdNode *f, DdNode *g, DdNode *D);
+extern int Cudd_EqualSupNorm (DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE tolerance, int pr);
+extern DdNode * Cudd_bddMakePrime (DdManager *dd, DdNode *cube, DdNode *f);
+extern double * Cudd_CofMinterm (DdManager *dd, DdNode *node);
+extern DdNode * Cudd_SolveEqn (DdManager * bdd, DdNode *F, DdNode *Y, DdNode **G, int **yIndex, int n);
+extern DdNode * Cudd_VerifySol (DdManager * bdd, DdNode *F, DdNode **G, int *yIndex, int n);
+extern DdNode * Cudd_SplitSet (DdManager *manager, DdNode *S, DdNode **xVars, int n, double m);
+extern DdNode * Cudd_SubsetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold);
+extern DdNode * Cudd_SupersetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold);
+extern DdNode * Cudd_SubsetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit);
+extern DdNode * Cudd_SupersetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit);
+extern void Cudd_SymmProfile (DdManager *table, int lower, int upper);
+extern unsigned int Cudd_Prime (unsigned int p);
+extern int Cudd_PrintMinterm (DdManager *manager, DdNode *node);
+extern int Cudd_bddPrintCover (DdManager *dd, DdNode *l, DdNode *u);
+extern int Cudd_PrintDebug (DdManager *dd, DdNode *f, int n, int pr);
+extern int Cudd_DagSize (DdNode *node);
+extern int Cudd_EstimateCofactor (DdManager *dd, DdNode * node, int i, int phase);
+extern int Cudd_EstimateCofactorSimple (DdNode * node, int i);
+extern int Cudd_SharingSize (DdNode **nodeArray, int n);
+extern double Cudd_CountMinterm (DdManager *manager, DdNode *node, int nvars);
+extern int Cudd_EpdCountMinterm (DdManager *manager, DdNode *node, int nvars, EpDouble *epd);
+extern double Cudd_CountPath (DdNode *node);
+extern double Cudd_CountPathsToNonZero (DdNode *node);
+extern DdNode * Cudd_Support (DdManager *dd, DdNode *f);
+extern int * Cudd_SupportIndex (DdManager *dd, DdNode *f);
+extern int Cudd_SupportSize (DdManager *dd, DdNode *f);
+extern DdNode * Cudd_VectorSupport (DdManager *dd, DdNode **F, int n);
+extern int * Cudd_VectorSupportIndex (DdManager *dd, DdNode **F, int n);
+extern int Cudd_VectorSupportSize (DdManager *dd, DdNode **F, int n);
+extern int Cudd_ClassifySupport (DdManager *dd, DdNode *f, DdNode *g, DdNode **common, DdNode **onlyF, DdNode **onlyG);
+extern int Cudd_CountLeaves (DdNode *node);
+extern int Cudd_bddPickOneCube (DdManager *ddm, DdNode *node, char *string);
+extern DdNode * Cudd_bddPickOneMinterm (DdManager *dd, DdNode *f, DdNode **vars, int n);
+extern DdNode ** Cudd_bddPickArbitraryMinterms (DdManager *dd, DdNode *f, DdNode **vars, int n, int k);
+extern DdNode * Cudd_SubsetWithMaskVars (DdManager *dd, DdNode *f, DdNode **vars, int nvars, DdNode **maskVars, int mvars);
+extern DdGen * Cudd_FirstCube (DdManager *dd, DdNode *f, int **cube, CUDD_VALUE_TYPE *value);
+extern int Cudd_NextCube (DdGen *gen, int **cube, CUDD_VALUE_TYPE *value);
+extern DdGen * Cudd_FirstPrime(DdManager *dd, DdNode *l, DdNode *u, int **cube);
+extern int Cudd_NextPrime(DdGen *gen, int **cube);
+extern DdNode * Cudd_bddComputeCube (DdManager *dd, DdNode **vars, int *phase, int n);
+extern DdNode * Cudd_addComputeCube (DdManager *dd, DdNode **vars, int *phase, int n);
+extern DdNode * Cudd_CubeArrayToBdd (DdManager *dd, int *array);
+extern int Cudd_BddToCubeArray (DdManager *dd, DdNode *cube, int *array);
+extern DdGen * Cudd_FirstNode (DdManager *dd, DdNode *f, DdNode **node);
+extern int Cudd_NextNode (DdGen *gen, DdNode **node);
+extern int Cudd_GenFree (DdGen *gen);
+extern int Cudd_IsGenEmpty (DdGen *gen);
+extern DdNode * Cudd_IndicesToCube (DdManager *dd, int *array, int n);
+extern void Cudd_PrintVersion (FILE *fp);
+extern double Cudd_AverageDistance (DdManager *dd);
+extern long Cudd_Random (void);
+extern void Cudd_Srandom (long seed);
+extern double Cudd_Density (DdManager *dd, DdNode *f, int nvars);
+extern void Cudd_OutOfMem (long size);
+extern int Cudd_zddCount (DdManager *zdd, DdNode *P);
+extern double Cudd_zddCountDouble (DdManager *zdd, DdNode *P);
+extern DdNode	* Cudd_zddProduct (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* Cudd_zddUnateProduct (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* Cudd_zddWeakDiv (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* Cudd_zddDivide (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* Cudd_zddWeakDivF (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* Cudd_zddDivideF (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* Cudd_zddComplement (DdManager *dd, DdNode *node);
+extern MtrNode * Cudd_MakeZddTreeNode (DdManager *dd, unsigned int low, unsigned int size, unsigned int type);
+extern DdNode	* Cudd_zddIsop (DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I);
+extern DdNode	* Cudd_bddIsop (DdManager *dd, DdNode *L, DdNode *U);
+extern DdNode	* Cudd_MakeBddFromZddCover (DdManager *dd, DdNode *node);
+extern int Cudd_zddDagSize (DdNode *p_node);
+extern double Cudd_zddCountMinterm (DdManager *zdd, DdNode *node, int path);
+extern void Cudd_zddPrintSubtable (DdManager *table);
+extern DdNode * Cudd_zddPortFromBdd (DdManager *dd, DdNode *B);
+extern DdNode * Cudd_zddPortToBdd (DdManager *dd, DdNode *f);
+extern int Cudd_zddReduceHeap (DdManager *table, Cudd_ReorderingType heuristic, int minsize);
+extern int Cudd_zddShuffleHeap (DdManager *table, int *permutation);
+extern DdNode * Cudd_zddIte (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * Cudd_zddUnion (DdManager *dd, DdNode *P, DdNode *Q);
+extern DdNode * Cudd_zddIntersect (DdManager *dd, DdNode *P, DdNode *Q);
+extern DdNode * Cudd_zddDiff (DdManager *dd, DdNode *P, DdNode *Q);
+extern DdNode * Cudd_zddDiffConst (DdManager *zdd, DdNode *P, DdNode *Q);
+extern DdNode * Cudd_zddSubset1 (DdManager *dd, DdNode *P, int var);
+extern DdNode * Cudd_zddSubset0 (DdManager *dd, DdNode *P, int var);
+extern DdNode * Cudd_zddChange (DdManager *dd, DdNode *P, int var);
+extern void Cudd_zddSymmProfile (DdManager *table, int lower, int upper);
+extern int Cudd_zddPrintMinterm (DdManager *zdd, DdNode *node);
+extern int Cudd_zddPrintCover (DdManager *zdd, DdNode *node);
+extern int Cudd_zddPrintDebug (DdManager *zdd, DdNode *f, int n, int pr);
+extern DdGen * Cudd_zddFirstPath (DdManager *zdd, DdNode *f, int **path);
+extern int Cudd_zddNextPath (DdGen *gen, int **path);
+extern char * Cudd_zddCoverPathToString (DdManager *zdd, int *path, char *str);
+extern int Cudd_zddDumpDot (DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp);
+extern int Cudd_bddSetPiVar (DdManager *dd, int index);
+extern int Cudd_bddSetPsVar (DdManager *dd, int index);
+extern int Cudd_bddSetNsVar (DdManager *dd, int index);
+extern int Cudd_bddIsPiVar (DdManager *dd, int index);
+extern int Cudd_bddIsPsVar (DdManager *dd, int index);
+extern int Cudd_bddIsNsVar (DdManager *dd, int index);
+extern int Cudd_bddSetPairIndex (DdManager *dd, int index, int pairIndex);
+extern int Cudd_bddReadPairIndex (DdManager *dd, int index);
+extern int Cudd_bddSetVarToBeGrouped (DdManager *dd, int index);
+extern int Cudd_bddSetVarHardGroup (DdManager *dd, int index);
+extern int Cudd_bddResetVarToBeGrouped (DdManager *dd, int index);
+extern int Cudd_bddIsVarToBeGrouped (DdManager *dd, int index);
+extern int Cudd_bddSetVarToBeUngrouped (DdManager *dd, int index);
+extern int Cudd_bddIsVarToBeUngrouped (DdManager *dd, int index);
+extern int Cudd_bddIsVarHardGroup (DdManager *dd, int index);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _CUDD */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAPI.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAPI.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAPI.c	(revision 8)
@@ -0,0 +1,4436 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAPI.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Application interface functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addNewVar()
+		<li> Cudd_addNewVarAtLevel()
+		<li> Cudd_bddNewVar()
+		<li> Cudd_bddNewVarAtLevel()
+		<li> Cudd_addIthVar()
+		<li> Cudd_bddIthVar()
+		<li> Cudd_zddIthVar()
+		<li> Cudd_zddVarsFromBddVars()
+		<li> Cudd_addConst()
+		<li> Cudd_IsNonConstant()
+		<li> Cudd_AutodynEnable()
+		<li> Cudd_AutodynDisable()
+		<li> Cudd_ReorderingStatus()
+		<li> Cudd_AutodynEnableZdd()
+		<li> Cudd_AutodynDisableZdd()
+		<li> Cudd_ReorderingStatusZdd()
+		<li> Cudd_zddRealignmentEnabled()
+		<li> Cudd_zddRealignEnable()
+		<li> Cudd_zddRealignDisable()
+		<li> Cudd_bddRealignmentEnabled()
+		<li> Cudd_bddRealignEnable()
+		<li> Cudd_bddRealignDisable()
+		<li> Cudd_ReadOne()
+		<li> Cudd_ReadZddOne()
+		<li> Cudd_ReadZero()
+		<li> Cudd_ReadLogicZero()
+		<li> Cudd_ReadPlusInfinity()
+		<li> Cudd_ReadMinusInfinity()
+		<li> Cudd_ReadBackground()
+		<li> Cudd_SetBackground()
+		<li> Cudd_ReadCacheSlots()
+		<li> Cudd_ReadCacheUsedSlots()
+		<li> Cudd_ReadCacheLookUps()
+		<li> Cudd_ReadCacheHits()
+		<li> Cudd_ReadMinHit()
+		<li> Cudd_SetMinHit()
+		<li> Cudd_ReadLooseUpTo()
+		<li> Cudd_SetLooseUpTo()
+		<li> Cudd_ReadMaxCache()
+		<li> Cudd_ReadMaxCacheHard()
+		<li> Cudd_SetMaxCacheHard()
+		<li> Cudd_ReadSize()
+		<li> Cudd_ReadSlots()
+		<li> Cudd_ReadUsedSlots()
+		<li> Cudd_ExpectedUsedSlots()
+		<li> Cudd_ReadKeys()
+		<li> Cudd_ReadDead()
+		<li> Cudd_ReadMinDead()
+		<li> Cudd_ReadReorderings()
+		<li> Cudd_ReadReorderingTime()
+		<li> Cudd_ReadGarbageCollections()
+		<li> Cudd_ReadGarbageCollectionTime()
+		<li> Cudd_ReadNodesFreed()
+		<li> Cudd_ReadNodesDropped()
+		<li> Cudd_ReadUniqueLookUps()
+		<li> Cudd_ReadUniqueLinks()
+		<li> Cudd_ReadSiftMaxVar()
+		<li> Cudd_SetSiftMaxVar()
+		<li> Cudd_ReadMaxGrowth()
+		<li> Cudd_SetMaxGrowth()
+		<li> Cudd_ReadMaxGrowthAlternate()
+		<li> Cudd_SetMaxGrowthAlternate()
+		<li> Cudd_ReadReorderingCycle()
+		<li> Cudd_SetReorderingCycle()
+		<li> Cudd_ReadTree()
+		<li> Cudd_SetTree()
+		<li> Cudd_FreeTree()
+		<li> Cudd_ReadZddTree()
+		<li> Cudd_SetZddTree()
+		<li> Cudd_FreeZddTree()
+                <li> Cudd_NodeReadIndex()
+		<li> Cudd_ReadPerm()
+		<li> Cudd_ReadInvPerm()
+		<li> Cudd_ReadVars()
+		<li> Cudd_ReadEpsilon()
+		<li> Cudd_SetEpsilon()
+		<li> Cudd_ReadGroupCheck()
+		<li> Cudd_SetGroupcheck()
+		<li> Cudd_GarbageCollectionEnabled()
+		<li> Cudd_EnableGarbageCollection()
+		<li> Cudd_DisableGarbageCollection()
+		<li> Cudd_DeadAreCounted()
+		<li> Cudd_TurnOnCountDead()
+		<li> Cudd_TurnOffCountDead()
+		<li> Cudd_ReadRecomb()
+		<li> Cudd_SetRecomb()
+		<li> Cudd_ReadSymmviolation()
+		<li> Cudd_SetSymmviolation()
+		<li> Cudd_ReadArcviolation()
+		<li> Cudd_SetArcviolation()
+		<li> Cudd_ReadPopulationSize()
+		<li> Cudd_SetPopulationSize()
+		<li> Cudd_ReadNumberXovers()
+		<li> Cudd_SetNumberXovers()
+		<li> Cudd_ReadMemoryInUse()
+		<li> Cudd_PrintInfo()
+		<li> Cudd_ReadPeakNodeCount()
+		<li> Cudd_ReadPeakLiveNodeCount()
+		<li> Cudd_ReadNodeCount()
+		<li> Cudd_zddReadNodeCount()
+		<li> Cudd_AddHook()
+		<li> Cudd_RemoveHook()
+		<li> Cudd_IsInHook()
+		<li> Cudd_StdPreReordHook()
+		<li> Cudd_StdPostReordHook()
+		<li> Cudd_EnableReorderingReporting()
+		<li> Cudd_DisableReorderingReporting()
+		<li> Cudd_ReorderingReporting()
+		<li> Cudd_ReadErrorCode()
+		<li> Cudd_ClearErrorCode()
+		<li> Cudd_ReadStdout()
+		<li> Cudd_SetStdout()
+		<li> Cudd_ReadStderr()
+		<li> Cudd_SetStderr()
+		<li> Cudd_ReadNextReordering()
+		<li> Cudd_SetNextReordering()
+		<li> Cudd_ReadSwapSteps()
+		<li> Cudd_ReadMaxLive()
+		<li> Cudd_SetMaxLive()
+		<li> Cudd_ReadMaxMemory()
+		<li> Cudd_SetMaxMemory()
+		<li> Cudd_bddBindVar()
+		<li> Cudd_bddUnbindVar()
+		<li> Cudd_bddVarIsBound()
+		<li> Cudd_bddSetPiVar()
+		<li> Cudd_bddSetPsVar()
+		<li> Cudd_bddSetNsVar()
+		<li> Cudd_bddIsPiVar()
+		<li> Cudd_bddIsPsVar()
+		<li> Cudd_bddIsNsVar()
+		<li> Cudd_bddSetPairIndex()
+		<li> Cudd_bddReadPairIndex()
+		<li> Cudd_bddSetVarToBeGrouped()
+		<li> Cudd_bddSetVarHardGroup()
+		<li> Cudd_bddResetVarToBeGrouped()
+		<li> Cudd_bddIsVarToBeGrouped()
+		<li> Cudd_bddSetVarToBeUngrouped()
+		<li> Cudd_bddIsVarToBeUngrouped()
+		<li> Cudd_bddIsVarHardGroup()
+		</ul>
+	      Static procedures included in this module:
+		<ul>
+		<li> fixVarTree()
+		</ul>]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAPI.c,v 1.57 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void fixVarTree (MtrNode *treenode, int *perm, int size);
+static int addMultiplicityGroups (DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new ADD variable.]
+
+  Description [Creates a new ADD variable.  The new variable has an
+  index equal to the largest previous index plus 1.  Returns a
+  pointer to the new variable if successful; NULL otherwise.
+  An ADD variable differs from a BDD variable because it points to the
+  arithmetic zero, instead of having a complement pointer to 1. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_addIthVar Cudd_addConst
+  Cudd_addNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_addNewVar(
+  DdManager * dd)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    do {
+	dd->reordered = 0;
+	res = cuddUniqueInter(dd,dd->size,DD_ONE(dd),DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addNewVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new ADD variable at a specified level.]
+
+  Description [Creates a new ADD variable.  The new variable has an
+  index equal to the largest previous index plus 1 and is positioned at
+  the specified level in the order.  Returns a pointer to the new
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_addNewVarAtLevel(
+  DdManager * dd,
+  int  level)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    if (level >= dd->size) return(Cudd_addIthVar(dd,level));
+    if (!cuddInsertSubtables(dd,1,level)) return(NULL);
+    do {
+	dd->reordered = 0;
+	res = cuddUniqueInter(dd,dd->size - 1,DD_ONE(dd),DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addNewVarAtLevel */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new BDD variable.]
+
+  Description [Creates a new BDD variable.  The new variable has an
+  index equal to the largest previous index plus 1.  Returns a
+  pointer to the new variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNewVar(
+  DdManager * dd)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    res = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one));
+
+    return(res);
+
+} /* end of Cudd_bddNewVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a new BDD variable at a specified level.]
+
+  Description [Creates a new BDD variable.  The new variable has an
+  index equal to the largest previous index plus 1 and is positioned at
+  the specified level in the order.  Returns a pointer to the new
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_bddIthVar Cudd_addNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNewVarAtLevel(
+  DdManager * dd,
+  int  level)
+{
+    DdNode *res;
+
+    if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL);
+    if (level >= dd->size) return(Cudd_bddIthVar(dd,level));
+    if (!cuddInsertSubtables(dd,1,level)) return(NULL);
+    res = dd->vars[dd->size - 1];
+
+    return(res);
+
+} /* end of Cudd_bddNewVarAtLevel */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ADD variable with index i.]
+
+  Description [Retrieves the ADD variable with index i if it already
+  exists, or creates a new ADD variable.  Returns a pointer to the
+  variable if successful; NULL otherwise.  An ADD variable differs from
+  a BDD variable because it points to the arithmetic zero, instead of
+  having a complement pointer to 1. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_bddIthVar Cudd_addConst
+  Cudd_addNewVarAtLevel]
+
+******************************************************************************/
+DdNode *
+Cudd_addIthVar(
+  DdManager * dd,
+  int  i)
+{
+    DdNode *res;
+
+    if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL);
+    do {
+	dd->reordered = 0;
+	res = cuddUniqueInter(dd,i,DD_ONE(dd),DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addIthVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD variable with index i.]
+
+  Description [Retrieves the BDD variable with index i if it already
+  exists, or creates a new BDD variable.  Returns a pointer to the
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel
+  Cudd_ReadVars]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIthVar(
+  DdManager * dd,
+  int  i)
+{
+    DdNode *res;
+
+    if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL);
+    if (i < dd->size) {
+	res = dd->vars[i];
+    } else {
+	res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+    }
+
+    return(res);
+
+} /* end of Cudd_bddIthVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ZDD variable with index i.]
+
+  Description [Retrieves the ZDD variable with index i if it already
+  exists, or creates a new ZDD variable.  Returns a pointer to the
+  variable if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIthVar Cudd_addIthVar]
+
+******************************************************************************/
+DdNode *
+Cudd_zddIthVar(
+  DdManager * dd,
+  int  i)
+{
+    DdNode *res;
+    DdNode *zvar;
+    DdNode *lower;
+    int j;
+
+    if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL);
+
+    /* The i-th variable function has the following structure:
+    ** at the level corresponding to index i there is a node whose "then"
+    ** child points to the universe, and whose "else" child points to zero.
+    ** Above that level there are nodes with identical children.
+    */
+
+    /* First we build the node at the level of index i. */
+    lower = (i < dd->sizeZ - 1) ? dd->univ[dd->permZ[i]+1] : DD_ONE(dd);
+    do {
+	dd->reordered = 0;
+	zvar = cuddUniqueInterZdd(dd, i, lower, DD_ZERO(dd));
+    } while (dd->reordered == 1);
+
+    if (zvar == NULL)
+	return(NULL);
+    cuddRef(zvar);
+
+    /* Now we add the "filler" nodes above the level of index i. */
+    for (j = dd->permZ[i] - 1; j >= 0; j--) {
+	do {
+	    dd->reordered = 0;
+	    res = cuddUniqueInterZdd(dd, dd->invpermZ[j], zvar, zvar);
+	} while (dd->reordered == 1);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(dd,zvar);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDerefZdd(dd,zvar);
+	zvar = res;
+    }
+    cuddDeref(zvar);
+    return(zvar);
+
+} /* end of Cudd_zddIthVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates one or more ZDD variables for each BDD variable.]
+
+  Description [Creates one or more ZDD variables for each BDD
+  variable.  If some ZDD variables already exist, only the missing
+  variables are created.  Parameter multiplicity allows the caller to
+  control how many variables are created for each BDD variable in
+  existence. For instance, if ZDDs are used to represent covers, two
+  ZDD variables are required for each BDD variable.  The order of the
+  BDD variables is transferred to the ZDD variables. If a variable
+  group tree exists for the BDD variables, a corresponding ZDD
+  variable group tree is created by expanding the BDD variable
+  tree. In any case, the ZDD variables derived from the same BDD
+  variable are merged in a ZDD variable group. If a ZDD variable group
+  tree exists, it is freed. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel]
+
+******************************************************************************/
+int
+Cudd_zddVarsFromBddVars(
+  DdManager * dd /* DD manager */,
+  int multiplicity /* how many ZDD variables are created for each BDD variable */)
+{
+    int res;
+    int i, j;
+    int allnew;
+    int *permutation;
+
+    if (multiplicity < 1) return(0);
+    allnew = dd->sizeZ == 0;
+    if (dd->size * multiplicity > dd->sizeZ) {
+	res = cuddResizeTableZdd(dd,dd->size * multiplicity - 1);
+	if (res == 0) return(0);
+    }
+    /* Impose the order of the BDD variables to the ZDD variables. */
+    if (allnew) {
+	for (i = 0; i < dd->size; i++) {
+	    for (j = 0; j < multiplicity; j++) {
+		dd->permZ[i * multiplicity + j] =
+		    dd->perm[i] * multiplicity + j;
+		dd->invpermZ[dd->permZ[i * multiplicity + j]] =
+		    i * multiplicity + j;
+	    }
+	}
+	for (i = 0; i < dd->sizeZ; i++) {
+	    dd->univ[i]->index = dd->invpermZ[i];
+	}
+    } else {
+	permutation = ALLOC(int,dd->sizeZ);
+	if (permutation == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	for (i = 0; i < dd->size; i++) {
+	    for (j = 0; j < multiplicity; j++) {
+		permutation[i * multiplicity + j] =
+		    dd->invperm[i] * multiplicity + j;
+	    }
+	}
+	for (i = dd->size * multiplicity; i < dd->sizeZ; i++) {
+	    permutation[i] = i;
+	}
+	res = Cudd_zddShuffleHeap(dd, permutation);
+	FREE(permutation);
+	if (res == 0) return(0);
+    }
+    /* Copy and expand the variable group tree if it exists. */
+    if (dd->treeZ != NULL) {
+	Cudd_FreeZddTree(dd);
+    }
+    if (dd->tree != NULL) {
+	dd->treeZ = Mtr_CopyTree(dd->tree, multiplicity);
+	if (dd->treeZ == NULL) return(0);
+    } else if (multiplicity > 1) {
+	dd->treeZ = Mtr_InitGroupTree(0, dd->sizeZ);
+	if (dd->treeZ == NULL) return(0);
+	dd->treeZ->index = dd->invpermZ[0];
+    }
+    /* Create groups for the ZDD variables derived from the same BDD variable.
+    */
+    if (multiplicity > 1) {
+	char *vmask, *lmask;
+
+	vmask = ALLOC(char, dd->size);
+	if (vmask == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	lmask =  ALLOC(char, dd->size);
+	if (lmask == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	for (i = 0; i < dd->size; i++) {
+	    vmask[i] = lmask[i] = 0;
+	}
+	res = addMultiplicityGroups(dd,dd->treeZ,multiplicity,vmask,lmask);
+	FREE(vmask);
+	FREE(lmask);
+	if (res == 0) return(0);
+    }
+    return(1);
+
+} /* end of Cudd_zddVarsFromBddVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ADD for constant c.]
+
+  Description [Retrieves the ADD for constant c if it already
+  exists, or creates a new ADD.  Returns a pointer to the
+  ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNewVar Cudd_addIthVar]
+
+******************************************************************************/
+DdNode *
+Cudd_addConst(
+  DdManager * dd,
+  CUDD_VALUE_TYPE  c)
+{
+    return(cuddUniqueConst(dd,c));
+
+} /* end of Cudd_addConst */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a DD node is not constant.]
+
+  Description [Returns 1 if a DD node is not constant. This function is
+  useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant,
+  Cudd_addEvalConst. These results may be a special value signifying
+  non-constant. In the other cases the macro Cudd_IsConstant can be used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_IsConstant Cudd_bddIteConstant Cudd_addIteConstant
+  Cudd_addEvalConst]
+
+******************************************************************************/
+int
+Cudd_IsNonConstant(
+  DdNode *f)
+{
+    return(f == DD_NON_CONSTANT || !Cudd_IsConstant(f));
+
+} /* end of Cudd_IsNonConstant */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables automatic dynamic reordering of BDDs and ADDs.]
+
+  Description [Enables automatic dynamic reordering of BDDs and
+  ADDs. Parameter method is used to determine the method used for
+  reordering. If CUDD_REORDER_SAME is passed, the method is
+  unchanged.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynDisable Cudd_ReorderingStatus
+  Cudd_AutodynEnableZdd]
+
+******************************************************************************/
+void
+Cudd_AutodynEnable(
+  DdManager * unique,
+  Cudd_ReorderingType  method)
+{
+    unique->autoDyn = 1;
+    if (method != CUDD_REORDER_SAME) {
+	unique->autoMethod = method;
+    }
+#ifndef DD_NO_DEATH_ROW
+    /* If reordering is enabled, using the death row causes too many
+    ** invocations. Hence, we shrink the death row to just one entry.
+    */
+    cuddClearDeathRow(unique);
+    unique->deathRowDepth = 1;
+    unique->deadMask = unique->deathRowDepth - 1;
+    if ((unsigned) unique->nextDead > unique->deadMask) {
+	unique->nextDead = 0;
+    }
+    unique->deathRow = REALLOC(DdNodePtr, unique->deathRow,
+	unique->deathRowDepth);
+#endif
+    return;
+
+} /* end of Cudd_AutodynEnable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables automatic dynamic reordering.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynEnable Cudd_ReorderingStatus
+  Cudd_AutodynDisableZdd]
+
+******************************************************************************/
+void
+Cudd_AutodynDisable(
+  DdManager * unique)
+{
+    unique->autoDyn = 0;
+    return;
+
+} /* end of Cudd_AutodynDisable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the status of automatic dynamic reordering of BDDs
+  and ADDs.]
+
+  Description [Reports the status of automatic dynamic reordering of
+  BDDs and ADDs. Parameter method is set to the reordering method
+  currently selected. Returns 1 if automatic reordering is enabled; 0
+  otherwise.]
+
+  SideEffects [Parameter method is set to the reordering method currently
+  selected.]
+
+  SeeAlso     [Cudd_AutodynEnable Cudd_AutodynDisable
+  Cudd_ReorderingStatusZdd]
+
+******************************************************************************/
+int
+Cudd_ReorderingStatus(
+  DdManager * unique,
+  Cudd_ReorderingType * method)
+{
+    *method = unique->autoMethod;
+    return(unique->autoDyn);
+
+} /* end of Cudd_ReorderingStatus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables automatic dynamic reordering of ZDDs.]
+
+  Description [Enables automatic dynamic reordering of ZDDs. Parameter
+  method is used to determine the method used for reordering ZDDs. If
+  CUDD_REORDER_SAME is passed, the method is unchanged.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynDisableZdd Cudd_ReorderingStatusZdd
+  Cudd_AutodynEnable]
+
+******************************************************************************/
+void
+Cudd_AutodynEnableZdd(
+  DdManager * unique,
+  Cudd_ReorderingType method)
+{
+    unique->autoDynZ = 1;
+    if (method != CUDD_REORDER_SAME) {
+	unique->autoMethodZ = method;
+    }
+    return;
+
+} /* end of Cudd_AutodynEnableZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables automatic dynamic reordering of ZDDs.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AutodynEnableZdd Cudd_ReorderingStatusZdd
+  Cudd_AutodynDisable]
+
+******************************************************************************/
+void
+Cudd_AutodynDisableZdd(
+  DdManager * unique)
+{
+    unique->autoDynZ = 0;
+    return;
+
+} /* end of Cudd_AutodynDisableZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the status of automatic dynamic reordering of ZDDs.]
+
+  Description [Reports the status of automatic dynamic reordering of
+  ZDDs. Parameter method is set to the ZDD reordering method currently
+  selected. Returns 1 if automatic reordering is enabled; 0
+  otherwise.]
+
+  SideEffects [Parameter method is set to the ZDD reordering method currently
+  selected.]
+
+  SeeAlso     [Cudd_AutodynEnableZdd Cudd_AutodynDisableZdd
+  Cudd_ReorderingStatus]
+
+******************************************************************************/
+int
+Cudd_ReorderingStatusZdd(
+  DdManager * unique,
+  Cudd_ReorderingType * method)
+{
+    *method = unique->autoMethodZ;
+    return(unique->autoDynZ);
+
+} /* end of Cudd_ReorderingStatusZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether the realignment of ZDD order to BDD order is
+  enabled.]
+
+  Description [Returns 1 if the realignment of ZDD order to BDD order is
+  enabled; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddRealignEnable Cudd_zddRealignDisable
+  Cudd_bddRealignEnable Cudd_bddRealignDisable]
+
+******************************************************************************/
+int
+Cudd_zddRealignmentEnabled(
+  DdManager * unique)
+{
+    return(unique->realign);
+
+} /* end of Cudd_zddRealignmentEnabled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables realignment of ZDD order to BDD order.]
+
+  Description [Enables realignment of the ZDD variable order to the
+  BDD variable order after the BDDs and ADDs have been reordered.  The
+  number of ZDD variables must be a multiple of the number of BDD
+  variables for realignment to make sense. If this condition is not met,
+  Cudd_ReduceHeap will return 0. Let <code>M</code> be the
+  ratio of the two numbers. For the purpose of realignment, the ZDD
+  variables from <code>M*i</code> to <code>(M+1)*i-1</code> are
+  reagarded as corresponding to BDD variable <code>i</code>. Realignment
+  is initially disabled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReduceHeap Cudd_zddRealignDisable
+  Cudd_zddRealignmentEnabled Cudd_bddRealignDisable
+  Cudd_bddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_zddRealignEnable(
+  DdManager * unique)
+{
+    unique->realign = 1;
+    return;
+
+} /* end of Cudd_zddRealignEnable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables realignment of ZDD order to BDD order.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddRealignEnable Cudd_zddRealignmentEnabled
+  Cudd_bddRealignEnable Cudd_bddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_zddRealignDisable(
+  DdManager * unique)
+{
+    unique->realign = 0;
+    return;
+
+} /* end of Cudd_zddRealignDisable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether the realignment of BDD order to ZDD order is
+  enabled.]
+
+  Description [Returns 1 if the realignment of BDD order to ZDD order is
+  enabled; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRealignEnable Cudd_bddRealignDisable
+  Cudd_zddRealignEnable Cudd_zddRealignDisable]
+
+******************************************************************************/
+int
+Cudd_bddRealignmentEnabled(
+  DdManager * unique)
+{
+    return(unique->realignZ);
+
+} /* end of Cudd_bddRealignmentEnabled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables realignment of BDD order to ZDD order.]
+
+  Description [Enables realignment of the BDD variable order to the
+  ZDD variable order after the ZDDs have been reordered.  The
+  number of ZDD variables must be a multiple of the number of BDD
+  variables for realignment to make sense. If this condition is not met,
+  Cudd_zddReduceHeap will return 0. Let <code>M</code> be the
+  ratio of the two numbers. For the purpose of realignment, the ZDD
+  variables from <code>M*i</code> to <code>(M+1)*i-1</code> are
+  reagarded as corresponding to BDD variable <code>i</code>. Realignment
+  is initially disabled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddReduceHeap Cudd_bddRealignDisable
+  Cudd_bddRealignmentEnabled Cudd_zddRealignDisable
+  Cudd_zddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_bddRealignEnable(
+  DdManager * unique)
+{
+    unique->realignZ = 1;
+    return;
+
+} /* end of Cudd_bddRealignEnable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables realignment of ZDD order to BDD order.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRealignEnable Cudd_bddRealignmentEnabled
+  Cudd_zddRealignEnable Cudd_zddRealignmentEnabled]
+
+******************************************************************************/
+void
+Cudd_bddRealignDisable(
+  DdManager * unique)
+{
+    unique->realignZ = 0;
+    return;
+
+} /* end of Cudd_bddRealignDisable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the one constant of the manager.]
+
+  Description [Returns the one constant of the manager. The one
+  constant is common to ADDs and BDDs.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadZero Cudd_ReadLogicZero Cudd_ReadZddOne]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadOne(
+  DdManager * dd)
+{
+    return(dd->one);
+
+} /* end of Cudd_ReadOne */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the ZDD for the constant 1 function.]
+
+  Description [Returns the ZDD for the constant 1 function.
+  The representation of the constant 1 function as a ZDD depends on
+  how many variables it (nominally) depends on. The index of the
+  topmost variable in the support is given as argument <code>i</code>.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadOne]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadZddOne(
+  DdManager * dd,
+  int  i)
+{
+    if (i < 0)
+	return(NULL);
+    return(i < dd->sizeZ ? dd->univ[i] : DD_ONE(dd));
+
+} /* end of Cudd_ReadZddOne */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the zero constant of the manager.]
+
+  Description [Returns the zero constant of the manager. The zero
+  constant is the arithmetic zero, rather than the logic zero. The
+  latter is the complement of the one constant.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadOne Cudd_ReadLogicZero]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadZero(
+  DdManager * dd)
+{
+    return(DD_ZERO(dd));
+
+} /* end of Cudd_ReadZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the logic zero constant of the manager.]
+
+  Description [Returns the zero constant of the manager. The logic zero
+  constant is the complement of the one constant, and is distinct from
+  the arithmetic zero.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadOne Cudd_ReadZero]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadLogicZero(
+  DdManager * dd)
+{
+    return(Cudd_Not(DD_ONE(dd)));
+
+} /* end of Cudd_ReadLogicZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the plus-infinity constant from the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadPlusInfinity(
+  DdManager * dd)
+{
+    return(dd->plusinfinity);
+
+} /* end of Cudd_ReadPlusInfinity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the minus-infinity constant from the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadMinusInfinity(
+  DdManager * dd)
+{
+    return(dd->minusinfinity);
+
+} /* end of Cudd_ReadMinusInfinity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the background constant of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadBackground(
+  DdManager * dd)
+{
+    return(dd->background);
+
+} /* end of Cudd_ReadBackground */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the background constant of the manager.]
+
+  Description [Sets the background constant of the manager. It assumes
+  that the DdNode pointer bck is already referenced.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cudd_SetBackground(
+  DdManager * dd,
+  DdNode * bck)
+{
+    dd->background = bck;
+
+} /* end of Cudd_SetBackground */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the number of slots in the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheUsedSlots]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadCacheSlots(
+  DdManager * dd)
+{
+    return(dd->cacheSlots);
+
+} /* end of Cudd_ReadCacheSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the fraction of used slots in the cache.]
+
+  Description [Reads the fraction of used slots in the cache. The unused
+  slots are those in which no valid data is stored. Garbage collection,
+  variable reordering, and cache resizing may cause used slots to become
+  unused.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheSlots]
+
+******************************************************************************/
+double
+Cudd_ReadCacheUsedSlots(
+  DdManager * dd)
+{
+    unsigned long used = 0;
+    int slots = dd->cacheSlots;
+    DdCache *cache = dd->cache;
+    int i;
+
+    for (i = 0; i < slots; i++) {
+	used += cache[i].h != 0;
+    }
+
+    return((double)used / (double) dd->cacheSlots);
+
+} /* end of Cudd_ReadCacheUsedSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of cache look-ups.]
+
+  Description [Returns the number of cache look-ups.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheHits]
+
+******************************************************************************/
+double
+Cudd_ReadCacheLookUps(
+  DdManager * dd)
+{
+    return(dd->cacheHits + dd->cacheMisses +
+	   dd->totCachehits + dd->totCacheMisses);
+
+} /* end of Cudd_ReadCacheLookUps */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of cache hits.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadCacheLookUps]
+
+******************************************************************************/
+double
+Cudd_ReadCacheHits(
+  DdManager * dd)
+{
+    return(dd->cacheHits + dd->totCachehits);
+
+} /* end of Cudd_ReadCacheHits */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of recursive calls.]
+
+  Description [Returns the number of recursive calls if the package is
+  compiled with DD_COUNT defined.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+double
+Cudd_ReadRecursiveCalls(
+  DdManager * dd)
+{
+#ifdef DD_COUNT
+    return(dd->recursiveCalls);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadRecursiveCalls */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the hit rate that causes resizinig of the computed
+  table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetMinHit]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMinHit(
+  DdManager * dd)
+{
+    /* Internally, the package manipulates the ratio of hits to
+    ** misses instead of the ratio of hits to accesses. */
+    return((unsigned int) (0.5 + 100 * dd->minHit / (1 + dd->minHit)));
+
+} /* end of Cudd_ReadMinHit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the hit rate that causes resizinig of the computed
+  table.]
+
+  Description [Sets the minHit parameter of the manager. This
+  parameter controls the resizing of the computed table. If the hit
+  rate is larger than the specified value, and the cache is not
+  already too large, then its size is doubled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMinHit]
+
+******************************************************************************/
+void
+Cudd_SetMinHit(
+  DdManager * dd,
+  unsigned int hr)
+{
+    /* Internally, the package manipulates the ratio of hits to
+    ** misses instead of the ratio of hits to accesses. */
+    dd->minHit = (double) hr / (100.0 - (double) hr);
+
+} /* end of Cudd_SetMinHit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the looseUpTo parameter of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetLooseUpTo Cudd_ReadMinHit Cudd_ReadMinDead]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadLooseUpTo(
+  DdManager * dd)
+{
+    return(dd->looseUpTo);
+
+} /* end of Cudd_ReadLooseUpTo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the looseUpTo parameter of the manager.]
+
+  Description [Sets the looseUpTo parameter of the manager. This
+  parameter of the manager controls the threshold beyond which no fast
+  growth of the unique table is allowed. The threshold is given as a
+  number of slots. If the value passed to this function is 0, the
+  function determines a suitable value based on the available memory.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadLooseUpTo Cudd_SetMinHit]
+
+******************************************************************************/
+void
+Cudd_SetLooseUpTo(
+  DdManager * dd,
+  unsigned int lut)
+{
+    if (lut == 0) {
+	long datalimit = getSoftDataLimit();
+	lut = (unsigned int) (datalimit / (sizeof(DdNode) *
+					   DD_MAX_LOOSE_FRACTION));
+    }
+    dd->looseUpTo = lut;
+
+} /* end of Cudd_SetLooseUpTo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the soft limit for the cache size.]
+
+  Description [Returns the soft limit for the cache size. The soft limit]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxCache]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMaxCache(
+  DdManager * dd)
+{
+    return(2 * dd->cacheSlots + dd->cacheSlack);
+
+} /* end of Cudd_ReadMaxCache */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maxCacheHard parameter of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetMaxCacheHard Cudd_ReadMaxCache]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMaxCacheHard(
+  DdManager * dd)
+{
+    return(dd->maxCacheHard);
+
+} /* end of Cudd_ReadMaxCache */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maxCacheHard parameter of the manager.]
+
+  Description [Sets the maxCacheHard parameter of the manager. The
+  cache cannot grow larger than maxCacheHard entries. This parameter
+  allows an application to control the trade-off of memory versus
+  speed. If the value passed to this function is 0, the function
+  determines a suitable maximum cache size based on the available memory.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxCacheHard Cudd_SetMaxCache]
+
+******************************************************************************/
+void
+Cudd_SetMaxCacheHard(
+  DdManager * dd,
+  unsigned int mc)
+{
+    if (mc == 0) {
+	long datalimit = getSoftDataLimit();
+	mc = (unsigned int) (datalimit / (sizeof(DdCache) *
+					  DD_MAX_CACHE_FRACTION));
+    }
+    dd->maxCacheHard = mc;
+
+} /* end of Cudd_SetMaxCacheHard */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of BDD variables in existance.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadZddSize]
+
+******************************************************************************/
+int
+Cudd_ReadSize(
+  DdManager * dd)
+{
+    return(dd->size);
+
+} /* end of Cudd_ReadSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of ZDD variables in existance.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSize]
+
+******************************************************************************/
+int
+Cudd_ReadZddSize(
+  DdManager * dd)
+{
+    return(dd->sizeZ);
+
+} /* end of Cudd_ReadZddSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the total number of slots of the unique table.]
+
+  Description [Returns the total number of slots of the unique table.
+  This number ismainly for diagnostic purposes.]
+
+  SideEffects [None]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadSlots(
+  DdManager * dd)
+{
+    return(dd->slots);
+
+} /* end of Cudd_ReadSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the fraction of used slots in the unique table.]
+
+  Description [Reads the fraction of used slots in the unique
+  table. The unused slots are those in which no valid data is
+  stored. Garbage collection, variable reordering, and subtable
+  resizing may cause used slots to become unused.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSlots]
+
+******************************************************************************/
+double
+Cudd_ReadUsedSlots(
+  DdManager * dd)
+{
+    unsigned long used = 0;
+    int i, j;
+    int size = dd->size;
+    DdNodePtr *nodelist;
+    DdSubtable *subtable;
+    DdNode *node;
+    DdNode *sentinel = &(dd->sentinel);
+
+    /* Scan each BDD/ADD subtable. */
+    for (i = 0; i < size; i++) {
+	subtable = &(dd->subtables[i]);
+	nodelist = subtable->nodelist;
+	for (j = 0; (unsigned) j < subtable->slots; j++) {
+	    node = nodelist[j];
+	    if (node != sentinel) {
+		used++;
+	    }
+	}
+    }
+
+    /* Scan the ZDD subtables. */
+    size = dd->sizeZ;
+
+    for (i = 0; i < size; i++) {
+	subtable = &(dd->subtableZ[i]);
+	nodelist = subtable->nodelist;
+	for (j = 0; (unsigned) j < subtable->slots; j++) {
+	    node = nodelist[j];
+	    if (node != NULL) {
+		used++;
+	    }
+	}
+    }
+
+    /* Constant table. */
+    subtable = &(dd->constants);
+    nodelist = subtable->nodelist;
+    for (j = 0; (unsigned) j < subtable->slots; j++) {
+	node = nodelist[j];
+	if (node != NULL) {
+	    used++;
+	}
+    }
+
+    return((double)used / (double) dd->slots);
+
+} /* end of Cudd_ReadUsedSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the expected fraction of used slots in the unique
+  table.]
+
+  Description [Computes the fraction of slots in the unique table that
+  should be in use. This expected value is based on the assumption
+  that the hash function distributes the keys randomly; it can be
+  compared with the result of Cudd_ReadUsedSlots to monitor the
+  performance of the unique table hash function.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSlots Cudd_ReadUsedSlots]
+
+******************************************************************************/
+double
+Cudd_ExpectedUsedSlots(
+  DdManager * dd)
+{
+    int i;
+    int size = dd->size;
+    DdSubtable *subtable;
+    double empty = 0.0;
+
+    /* To each subtable we apply the corollary to Theorem 8.5 (occupancy
+    ** distribution) from Sedgewick and Flajolet's Analysis of Algorithms.
+    ** The corollary says that for a a table with M buckets and a load ratio
+    ** of r, the expected number of empty buckets is asymptotically given
+    ** by M * exp(-r).
+    */
+
+    /* Scan each BDD/ADD subtable. */
+    for (i = 0; i < size; i++) {
+	subtable = &(dd->subtables[i]);
+	empty += (double) subtable->slots *
+	    exp(-(double) subtable->keys / (double) subtable->slots);
+    }
+
+    /* Scan the ZDD subtables. */
+    size = dd->sizeZ;
+
+    for (i = 0; i < size; i++) {
+	subtable = &(dd->subtableZ[i]);
+	empty += (double) subtable->slots *
+	    exp(-(double) subtable->keys / (double) subtable->slots);
+    }
+
+    /* Constant table. */
+    subtable = &(dd->constants);
+    empty += (double) subtable->slots *
+	exp(-(double) subtable->keys / (double) subtable->slots);
+
+    return(1.0 - empty / (double) dd->slots);
+
+} /* end of Cudd_ExpectedUsedSlots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes in the unique table.]
+
+  Description [Returns the total number of nodes currently in the unique
+  table, including the dead nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadDead]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadKeys(
+  DdManager * dd)
+{
+    return(dd->keys);
+
+} /* end of Cudd_ReadKeys */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of dead nodes in the unique table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadKeys]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadDead(
+  DdManager * dd)
+{
+    return(dd->dead);
+
+} /* end of Cudd_ReadDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the minDead parameter of the manager.]
+
+  Description [Reads the minDead parameter of the manager. The minDead
+  parameter is used by the package to decide whether to collect garbage
+  or resize a subtable of the unique table when the subtable becomes
+  too full. The application can indirectly control the value of minDead
+  by setting the looseUpTo parameter.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadDead Cudd_ReadLooseUpTo Cudd_SetLooseUpTo]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMinDead(
+  DdManager * dd)
+{
+    return(dd->minDead);
+
+} /* end of Cudd_ReadMinDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of times reordering has occurred.]
+
+  Description [Returns the number of times reordering has occurred in the
+  manager. The number includes both the calls to Cudd_ReduceHeap from
+  the application program and those automatically performed by the
+  package. However, calls that do not even initiate reordering are not
+  counted. A call may not initiate reordering if there are fewer than
+  minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified
+  as reordering method. The calls to Cudd_ShuffleHeap are not counted.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReduceHeap Cudd_ReadReorderingTime]
+
+******************************************************************************/
+int
+Cudd_ReadReorderings(
+  DdManager * dd)
+{
+    return(dd->reorderings);
+
+} /* end of Cudd_ReadReorderings */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the time spent in reordering.]
+
+  Description [Returns the number of milliseconds spent reordering
+  variables since the manager was initialized. The time spent in collecting
+  garbage before reordering is included.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadReorderings]
+
+******************************************************************************/
+long
+Cudd_ReadReorderingTime(
+  DdManager * dd)
+{
+    return(dd->reordTime);
+
+} /* end of Cudd_ReadReorderingTime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of times garbage collection has occurred.]
+
+  Description [Returns the number of times garbage collection has
+  occurred in the manager. The number includes both the calls from
+  reordering procedures and those caused by requests to create new
+  nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadGarbageCollectionTime]
+
+******************************************************************************/
+int
+Cudd_ReadGarbageCollections(
+  DdManager * dd)
+{
+    return(dd->garbageCollections);
+
+} /* end of Cudd_ReadGarbageCollections */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the time spent in garbage collection.]
+
+  Description [Returns the number of milliseconds spent doing garbage
+  collection since the manager was initialized.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadGarbageCollections]
+
+******************************************************************************/
+long
+Cudd_ReadGarbageCollectionTime(
+  DdManager * dd)
+{
+    return(dd->GCTime);
+
+} /* end of Cudd_ReadGarbageCollectionTime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes freed.]
+
+  Description [Returns the number of nodes returned to the free list if the
+  keeping of this statistic is enabled; -1 otherwise. This statistic is
+  enabled only if the package is compiled with DD_STATS defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodesDropped]
+
+******************************************************************************/
+double
+Cudd_ReadNodesFreed(
+  DdManager * dd)
+{
+#ifdef DD_STATS
+    return(dd->nodesFreed);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadNodesFreed */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes dropped.]
+
+  Description [Returns the number of nodes killed by dereferencing if the
+  keeping of this statistic is enabled; -1 otherwise. This statistic is
+  enabled only if the package is compiled with DD_STATS defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodesFreed]
+
+******************************************************************************/
+double
+Cudd_ReadNodesDropped(
+  DdManager * dd)
+{
+#ifdef DD_STATS
+    return(dd->nodesDropped);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadNodesDropped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of look-ups in the unique table.]
+
+  Description [Returns the number of look-ups in the unique table if the
+  keeping of this statistic is enabled; -1 otherwise. This statistic is
+  enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadUniqueLinks]
+
+******************************************************************************/
+double
+Cudd_ReadUniqueLookUps(
+  DdManager * dd)
+{
+#ifdef DD_UNIQUE_PROFILE
+    return(dd->uniqueLookUps);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadUniqueLookUps */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of links followed in the unique table.]
+
+  Description [Returns the number of links followed during look-ups in the
+  unique table if the keeping of this statistic is enabled; -1 otherwise.
+  If an item is found in the first position of its collision list, the
+  number of links followed is taken to be 0. If it is in second position,
+  the number of links is 1, and so on. This statistic is enabled only if
+  the package is compiled with DD_UNIQUE_PROFILE defined.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadUniqueLookUps]
+
+******************************************************************************/
+double
+Cudd_ReadUniqueLinks(
+  DdManager * dd)
+{
+#ifdef DD_UNIQUE_PROFILE
+    return(dd->uniqueLinks);
+#else
+    return(-1.0);
+#endif
+
+} /* end of Cudd_ReadUniqueLinks */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the siftMaxVar parameter of the manager.]
+
+  Description [Reads the siftMaxVar parameter of the manager. This
+  parameter gives the maximum number of variables that will be sifted
+  for each invocation of sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSiftMaxSwap Cudd_SetSiftMaxVar]
+
+******************************************************************************/
+int
+Cudd_ReadSiftMaxVar(
+  DdManager * dd)
+{
+    return(dd->siftMaxVar);
+
+} /* end of Cudd_ReadSiftMaxVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the siftMaxVar parameter of the manager.]
+
+  Description [Sets the siftMaxVar parameter of the manager. This
+  parameter gives the maximum number of variables that will be sifted
+  for each invocation of sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetSiftMaxSwap Cudd_ReadSiftMaxVar]
+
+******************************************************************************/
+void
+Cudd_SetSiftMaxVar(
+  DdManager * dd,
+  int  smv)
+{
+    dd->siftMaxVar = smv;
+
+} /* end of Cudd_SetSiftMaxVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the siftMaxSwap parameter of the manager.]
+
+  Description [Reads the siftMaxSwap parameter of the manager. This
+  parameter gives the maximum number of swaps that will be attempted
+  for each invocation of sifting. The real number of swaps may exceed
+  the set limit because the package will always complete the sifting
+  of the variable that causes the limit to be reached.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadSiftMaxVar Cudd_SetSiftMaxSwap]
+
+******************************************************************************/
+int
+Cudd_ReadSiftMaxSwap(
+  DdManager * dd)
+{
+    return(dd->siftMaxSwap);
+
+} /* end of Cudd_ReadSiftMaxSwap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the siftMaxSwap parameter of the manager.]
+
+  Description [Sets the siftMaxSwap parameter of the manager. This
+  parameter gives the maximum number of swaps that will be attempted
+  for each invocation of sifting. The real number of swaps may exceed
+  the set limit because the package will always complete the sifting
+  of the variable that causes the limit to be reached.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetSiftMaxVar Cudd_ReadSiftMaxSwap]
+
+******************************************************************************/
+void
+Cudd_SetSiftMaxSwap(
+  DdManager * dd,
+  int  sms)
+{
+    dd->siftMaxSwap = sms;
+
+} /* end of Cudd_SetSiftMaxSwap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maxGrowth parameter of the manager.]
+
+  Description [Reads the maxGrowth parameter of the manager.  This
+  parameter determines how much the number of nodes can grow during
+  sifting of a variable.  Overall, sifting never increases the size of
+  the decision diagrams.  This parameter only refers to intermediate
+  results.  A lower value will speed up sifting, possibly at the
+  expense of quality.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetMaxGrowth Cudd_ReadMaxGrowthAlternate]
+
+******************************************************************************/
+double
+Cudd_ReadMaxGrowth(
+  DdManager * dd)
+{
+    return(dd->maxGrowth);
+
+} /* end of Cudd_ReadMaxGrowth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maxGrowth parameter of the manager.]
+
+  Description [Sets the maxGrowth parameter of the manager.  This
+  parameter determines how much the number of nodes can grow during
+  sifting of a variable.  Overall, sifting never increases the size of
+  the decision diagrams.  This parameter only refers to intermediate
+  results.  A lower value will speed up sifting, possibly at the
+  expense of quality.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate]
+
+******************************************************************************/
+void
+Cudd_SetMaxGrowth(
+  DdManager * dd,
+  double mg)
+{
+    dd->maxGrowth = mg;
+
+} /* end of Cudd_SetMaxGrowth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maxGrowthAlt parameter of the manager.]
+
+  Description [Reads the maxGrowthAlt parameter of the manager.  This
+  parameter is analogous to the maxGrowth paramter, and is used every
+  given number of reorderings instead of maxGrowth.  The number of
+  reorderings is set with Cudd_SetReorderingCycle.  If the number of
+  reorderings is 0 (default) maxGrowthAlt is never used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate
+  Cudd_SetReorderingCycle Cudd_ReadReorderingCycle]
+
+******************************************************************************/
+double
+Cudd_ReadMaxGrowthAlternate(
+  DdManager * dd)
+{
+    return(dd->maxGrowthAlt);
+
+} /* end of Cudd_ReadMaxGrowthAlternate */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maxGrowthAlt parameter of the manager.]
+
+  Description [Sets the maxGrowthAlt parameter of the manager.  This
+  parameter is analogous to the maxGrowth paramter, and is used every
+  given number of reorderings instead of maxGrowth.  The number of
+  reorderings is set with Cudd_SetReorderingCycle.  If the number of
+  reorderings is 0 (default) maxGrowthAlt is never used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowth
+  Cudd_SetReorderingCycle Cudd_ReadReorderingCycle]
+
+******************************************************************************/
+void
+Cudd_SetMaxGrowthAlternate(
+  DdManager * dd,
+  double mg)
+{
+    dd->maxGrowthAlt = mg;
+
+} /* end of Cudd_SetMaxGrowthAlternate */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the reordCycle parameter of the manager.]
+
+  Description [Reads the reordCycle parameter of the manager.  This
+  parameter determines how often the alternate threshold on maximum
+  growth is used in reordering.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate
+  Cudd_SetReorderingCycle]
+
+******************************************************************************/
+int
+Cudd_ReadReorderingCycle(
+  DdManager * dd)
+{
+    return(dd->reordCycle);
+
+} /* end of Cudd_ReadReorderingCycle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the reordCycle parameter of the manager.]
+
+  Description [Sets the reordCycle parameter of the manager.  This
+  parameter determines how often the alternate threshold on maximum
+  growth is used in reordering.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate
+  Cudd_ReadReorderingCycle]
+
+******************************************************************************/
+void
+Cudd_SetReorderingCycle(
+  DdManager * dd,
+  int cycle)
+{
+    dd->reordCycle = cycle;
+
+} /* end of Cudd_SetReorderingCycle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetTree Cudd_FreeTree Cudd_ReadZddTree]
+
+******************************************************************************/
+MtrNode *
+Cudd_ReadTree(
+  DdManager * dd)
+{
+    return(dd->tree);
+
+} /* end of Cudd_ReadTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FreeTree Cudd_ReadTree Cudd_SetZddTree]
+
+******************************************************************************/
+void
+Cudd_SetTree(
+  DdManager * dd,
+  MtrNode * tree)
+{
+    if (dd->tree != NULL) {
+	Mtr_FreeTree(dd->tree);
+    }
+    dd->tree = tree;
+    if (tree == NULL) return;
+
+    fixVarTree(tree, dd->perm, dd->size);
+    return;
+
+} /* end of Cudd_SetTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetTree Cudd_ReadTree Cudd_FreeZddTree]
+
+******************************************************************************/
+void
+Cudd_FreeTree(
+  DdManager * dd)
+{
+    if (dd->tree != NULL) {
+	Mtr_FreeTree(dd->tree);
+	dd->tree = NULL;
+    }
+    return;
+
+} /* end of Cudd_FreeTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetZddTree Cudd_FreeZddTree Cudd_ReadTree]
+
+******************************************************************************/
+MtrNode *
+Cudd_ReadZddTree(
+  DdManager * dd)
+{
+    return(dd->treeZ);
+
+} /* end of Cudd_ReadZddTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the ZDD variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FreeZddTree Cudd_ReadZddTree Cudd_SetTree]
+
+******************************************************************************/
+void
+Cudd_SetZddTree(
+  DdManager * dd,
+  MtrNode * tree)
+{
+    if (dd->treeZ != NULL) {
+	Mtr_FreeTree(dd->treeZ);
+    }
+    dd->treeZ = tree;
+    if (tree == NULL) return;
+
+    fixVarTree(tree, dd->permZ, dd->sizeZ);
+    return;
+
+} /* end of Cudd_SetZddTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the variable group tree of the manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetZddTree Cudd_ReadZddTree Cudd_FreeTree]
+
+******************************************************************************/
+void
+Cudd_FreeZddTree(
+  DdManager * dd)
+{
+    if (dd->treeZ != NULL) {
+	Mtr_FreeTree(dd->treeZ);
+	dd->treeZ = NULL;
+    }
+    return;
+
+} /* end of Cudd_FreeZddTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the node.]
+
+  Description [Returns the index of the node. The node pointer can be
+  either regular or complemented.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_ReadIndex]
+
+******************************************************************************/
+unsigned int
+Cudd_NodeReadIndex(
+  DdNode * node)
+{
+    return((unsigned int) Cudd_Regular(node)->index);
+
+} /* end of Cudd_NodeReadIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current position of the i-th variable in the
+  order.]
+
+  Description [Returns the current position of the i-th variable in
+  the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns
+  -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadInvPerm Cudd_ReadPermZdd]
+
+******************************************************************************/
+int
+Cudd_ReadPerm(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->size) return(-1);
+    return(dd->perm[i]);
+
+} /* end of Cudd_ReadPerm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current position of the i-th ZDD variable in the
+  order.]
+
+  Description [Returns the current position of the i-th ZDD variable
+  in the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns
+  -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadInvPermZdd Cudd_ReadPerm]
+
+******************************************************************************/
+int
+Cudd_ReadPermZdd(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->sizeZ) return(-1);
+    return(dd->permZ[i]);
+
+} /* end of Cudd_ReadPermZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the variable currently in the i-th
+  position of the order.]
+
+  Description [Returns the index of the variable currently in the i-th
+  position of the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPerm Cudd_ReadInvPermZdd]
+
+******************************************************************************/
+int
+Cudd_ReadInvPerm(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->size) return(-1);
+    return(dd->invperm[i]);
+
+} /* end of Cudd_ReadInvPerm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the ZDD variable currently in the i-th
+  position of the order.]
+
+  Description [Returns the index of the ZDD variable currently in the
+  i-th position of the order. If the index is CUDD_CONST_INDEX, returns
+  CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPerm Cudd_ReadInvPermZdd]
+
+******************************************************************************/
+int
+Cudd_ReadInvPermZdd(
+  DdManager * dd,
+  int  i)
+{
+    if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
+    if (i < 0 || i >= dd->sizeZ) return(-1);
+    return(dd->invpermZ[i]);
+
+} /* end of Cudd_ReadInvPermZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the i-th element of the vars array.]
+
+  Description [Returns the i-th element of the vars array if it falls
+  within the array bounds; NULL otherwise. If i is the index of an
+  existing variable, this function produces the same result as
+  Cudd_bddIthVar. However, if the i-th var does not exist yet,
+  Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIthVar]
+
+******************************************************************************/
+DdNode *
+Cudd_ReadVars(
+  DdManager * dd,
+  int  i)
+{
+    if (i < 0 || i > dd->size) return(NULL);
+    return(dd->vars[i]);
+
+} /* end of Cudd_ReadVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the epsilon parameter of the manager.]
+
+  Description [Reads the epsilon parameter of the manager. The epsilon
+  parameter control the comparison between floating point numbers.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetEpsilon]
+
+******************************************************************************/
+CUDD_VALUE_TYPE
+Cudd_ReadEpsilon(
+  DdManager * dd)
+{
+    return(dd->epsilon);
+
+} /* end of Cudd_ReadEpsilon */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the epsilon parameter of the manager to ep.]
+
+  Description [Sets the epsilon parameter of the manager to ep. The epsilon
+  parameter control the comparison between floating point numbers.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadEpsilon]
+
+******************************************************************************/
+void
+Cudd_SetEpsilon(
+  DdManager * dd,
+  CUDD_VALUE_TYPE  ep)
+{
+    dd->epsilon = ep;
+
+} /* end of Cudd_SetEpsilon */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the groupcheck parameter of the manager.]
+
+  Description [Reads the groupcheck parameter of the manager. The
+  groupcheck parameter determines the aggregation criterion in group
+  sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetGroupcheck]
+
+******************************************************************************/
+Cudd_AggregationType
+Cudd_ReadGroupcheck(
+  DdManager * dd)
+{
+    return(dd->groupcheck);
+
+} /* end of Cudd_ReadGroupCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the parameter groupcheck of the manager to gc.]
+
+  Description [Sets the parameter groupcheck of the manager to gc. The
+  groupcheck parameter determines the aggregation criterion in group
+  sifting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadGroupCheck]
+
+******************************************************************************/
+void
+Cudd_SetGroupcheck(
+  DdManager * dd,
+  Cudd_AggregationType gc)
+{
+    dd->groupcheck = gc;
+
+} /* end of Cudd_SetGroupcheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether garbage collection is enabled.]
+
+  Description [Returns 1 if garbage collection is enabled; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_EnableGarbageCollection Cudd_DisableGarbageCollection]
+
+******************************************************************************/
+int
+Cudd_GarbageCollectionEnabled(
+  DdManager * dd)
+{
+    return(dd->gcEnabled);
+
+} /* end of Cudd_GarbageCollectionEnabled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables garbage collection.]
+
+  Description [Enables garbage collection. Garbage collection is
+  initially enabled. Therefore it is necessary to call this function
+  only if garbage collection has been explicitly disabled.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DisableGarbageCollection Cudd_GarbageCollectionEnabled]
+
+******************************************************************************/
+void
+Cudd_EnableGarbageCollection(
+  DdManager * dd)
+{
+    dd->gcEnabled = 1;
+
+} /* end of Cudd_EnableGarbageCollection */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables garbage collection.]
+
+  Description [Disables garbage collection. Garbage collection is
+  initially enabled. This function may be called to disable it.
+  However, garbage collection will still occur when a new node must be
+  created and no memory is left, or when garbage collection is required
+  for correctness. (E.g., before reordering.)]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_EnableGarbageCollection Cudd_GarbageCollectionEnabled]
+
+******************************************************************************/
+void
+Cudd_DisableGarbageCollection(
+  DdManager * dd)
+{
+    dd->gcEnabled = 0;
+
+} /* end of Cudd_DisableGarbageCollection */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether dead nodes are counted towards triggering
+  reordering.]
+
+  Description [Tells whether dead nodes are counted towards triggering
+  reordering. Returns 1 if dead nodes are counted; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_TurnOnCountDead Cudd_TurnOffCountDead]
+
+******************************************************************************/
+int
+Cudd_DeadAreCounted(
+  DdManager * dd)
+{
+    return(dd->countDead == 0 ? 1 : 0);
+
+} /* end of Cudd_DeadAreCounted */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Causes the dead nodes to be counted towards triggering
+  reordering.]
+
+  Description [Causes the dead nodes to be counted towards triggering
+  reordering. This causes more frequent reorderings. By default dead
+  nodes are not counted.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_TurnOffCountDead Cudd_DeadAreCounted]
+
+******************************************************************************/
+void
+Cudd_TurnOnCountDead(
+  DdManager * dd)
+{
+    dd->countDead = 0;
+
+} /* end of Cudd_TurnOnCountDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Causes the dead nodes not to be counted towards triggering
+  reordering.]
+
+  Description [Causes the dead nodes not to be counted towards
+  triggering reordering. This causes less frequent reorderings. By
+  default dead nodes are not counted. Therefore there is no need to
+  call this function unless Cudd_TurnOnCountDead has been previously
+  called.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_TurnOnCountDead Cudd_DeadAreCounted]
+
+******************************************************************************/
+void
+Cudd_TurnOffCountDead(
+  DdManager * dd)
+{
+    dd->countDead = ~0;
+
+} /* end of Cudd_TurnOffCountDead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current value of the recombination parameter used
+  in group sifting.]
+
+  Description [Returns the current value of the recombination
+  parameter used in group sifting. A larger (positive) value makes the
+  aggregation of variables due to the second difference criterion more
+  likely. A smaller (negative) value makes aggregation less likely.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetRecomb]
+
+******************************************************************************/
+int
+Cudd_ReadRecomb(
+  DdManager * dd)
+{
+    return(dd->recomb);
+
+} /* end of Cudd_ReadRecomb */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the value of the recombination parameter used in group
+  sifting.]
+
+  Description [Sets the value of the recombination parameter used in
+  group sifting. A larger (positive) value makes the aggregation of
+  variables due to the second difference criterion more likely. A
+  smaller (negative) value makes aggregation less likely. The default
+  value is 0.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_ReadRecomb]
+
+******************************************************************************/
+void
+Cudd_SetRecomb(
+  DdManager * dd,
+  int  recomb)
+{
+    dd->recomb = recomb;
+
+} /* end of Cudd_SetRecomb */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current value of the symmviolation parameter used
+  in group sifting.]
+
+  Description [Returns the current value of the symmviolation
+  parameter. This parameter is used in group sifting to decide how
+  many violations to the symmetry conditions <code>f10 = f01</code> or
+  <code>f11 = f00</code> are tolerable when checking for aggregation
+  due to extended symmetry. The value should be between 0 and 100. A
+  small value causes fewer variables to be aggregated. The default
+  value is 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetSymmviolation]
+
+******************************************************************************/
+int
+Cudd_ReadSymmviolation(
+  DdManager * dd)
+{
+    return(dd->symmviolation);
+
+} /* end of Cudd_ReadSymmviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the value of the symmviolation parameter used
+  in group sifting.]
+
+  Description [Sets the value of the symmviolation
+  parameter. This parameter is used in group sifting to decide how
+  many violations to the symmetry conditions <code>f10 = f01</code> or
+  <code>f11 = f00</code> are tolerable when checking for aggregation
+  due to extended symmetry. The value should be between 0 and 100. A
+  small value causes fewer variables to be aggregated. The default
+  value is 0.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_ReadSymmviolation]
+
+******************************************************************************/
+void
+Cudd_SetSymmviolation(
+  DdManager * dd,
+  int  symmviolation)
+{
+    dd->symmviolation = symmviolation;
+
+} /* end of Cudd_SetSymmviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current value of the arcviolation parameter used
+  in group sifting.]
+
+  Description [Returns the current value of the arcviolation
+  parameter. This parameter is used in group sifting to decide how
+  many arcs into <code>y</code> not coming from <code>x</code> are
+  tolerable when checking for aggregation due to extended
+  symmetry. The value should be between 0 and 100. A small value
+  causes fewer variables to be aggregated. The default value is 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetArcviolation]
+
+******************************************************************************/
+int
+Cudd_ReadArcviolation(
+  DdManager * dd)
+{
+    return(dd->arcviolation);
+
+} /* end of Cudd_ReadArcviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the value of the arcviolation parameter used
+  in group sifting.]
+
+  Description [Sets the value of the arcviolation
+  parameter. This parameter is used in group sifting to decide how
+  many arcs into <code>y</code> not coming from <code>x</code> are
+  tolerable when checking for aggregation due to extended
+  symmetry. The value should be between 0 and 100. A small value
+  causes fewer variables to be aggregated. The default value is 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadArcviolation]
+
+******************************************************************************/
+void
+Cudd_SetArcviolation(
+  DdManager * dd,
+  int  arcviolation)
+{
+    dd->arcviolation = arcviolation;
+
+} /* end of Cudd_SetArcviolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the current size of the population used by the
+  genetic algorithm for reordering.]
+
+  Description [Reads the current size of the population used by the
+  genetic algorithm for variable reordering. A larger population size will
+  cause the genetic algorithm to take more time, but will generally
+  produce better results. The default value is 0, in which case the
+  package uses three times the number of variables as population size,
+  with a maximum of 120.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetPopulationSize]
+
+******************************************************************************/
+int
+Cudd_ReadPopulationSize(
+  DdManager * dd)
+{
+    return(dd->populationSize);
+
+} /* end of Cudd_ReadPopulationSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the size of the population used by the
+  genetic algorithm for reordering.]
+
+  Description [Sets the size of the population used by the
+  genetic algorithm for variable reordering. A larger population size will
+  cause the genetic algorithm to take more time, but will generally
+  produce better results. The default value is 0, in which case the
+  package uses three times the number of variables as population size,
+  with a maximum of 120.]
+
+  SideEffects [Changes the manager.]
+
+  SeeAlso     [Cudd_ReadPopulationSize]
+
+******************************************************************************/
+void
+Cudd_SetPopulationSize(
+  DdManager * dd,
+  int  populationSize)
+{
+    dd->populationSize = populationSize;
+
+} /* end of Cudd_SetPopulationSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the current number of crossovers used by the
+  genetic algorithm for reordering.]
+
+  Description [Reads the current number of crossovers used by the
+  genetic algorithm for variable reordering. A larger number of crossovers will
+  cause the genetic algorithm to take more time, but will generally
+  produce better results. The default value is 0, in which case the
+  package uses three times the number of variables as number of crossovers,
+  with a maximum of 60.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetNumberXovers]
+
+******************************************************************************/
+int
+Cudd_ReadNumberXovers(
+  DdManager * dd)
+{
+    return(dd->numberXovers);
+
+} /* end of Cudd_ReadNumberXovers */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the number of crossovers used by the
+  genetic algorithm for reordering.]
+
+  Description [Sets the number of crossovers used by the genetic
+  algorithm for variable reordering. A larger number of crossovers
+  will cause the genetic algorithm to take more time, but will
+  generally produce better results. The default value is 0, in which
+  case the package uses three times the number of variables as number
+  of crossovers, with a maximum of 60.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNumberXovers]
+
+******************************************************************************/
+void
+Cudd_SetNumberXovers(
+  DdManager * dd,
+  int  numberXovers)
+{
+    dd->numberXovers = numberXovers;
+
+} /* end of Cudd_SetNumberXovers */
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the memory in use by the manager measured in bytes.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+unsigned long
+Cudd_ReadMemoryInUse(
+  DdManager * dd)
+{
+    return(dd->memused);
+
+} /* end of Cudd_ReadMemoryInUse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out statistics and settings for a CUDD manager.]
+
+  Description [Prints out statistics and settings for a CUDD manager.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_PrintInfo(
+  DdManager * dd,
+  FILE * fp)
+{
+    int retval;
+    Cudd_ReorderingType autoMethod, autoMethodZ;
+
+    /* Modifiable parameters. */
+    retval = fprintf(fp,"**** CUDD modifiable parameters ****\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Hard limit for cache size: %u\n",
+		     Cudd_ReadMaxCacheHard(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache hit threshold for resizing: %u%%\n",
+		     Cudd_ReadMinHit(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Garbage collection enabled: %s\n",
+		     Cudd_GarbageCollectionEnabled(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Limit for fast unique table growth: %u\n",
+		     Cudd_ReadLooseUpTo(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+		     "Maximum number of variables sifted per reordering: %d\n",
+		     Cudd_ReadSiftMaxVar(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+		     "Maximum number of variable swaps per reordering: %d\n",
+		     Cudd_ReadSiftMaxSwap(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Maximum growth while sifting a variable: %g\n",
+		     Cudd_ReadMaxGrowth(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Dynamic reordering of BDDs enabled: %s\n",
+		     Cudd_ReorderingStatus(dd,&autoMethod) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Default BDD reordering method: %d\n", autoMethod);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Dynamic reordering of ZDDs enabled: %s\n",
+		     Cudd_ReorderingStatusZdd(dd,&autoMethodZ) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Default ZDD reordering method: %d\n", autoMethodZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Realignment of ZDDs to BDDs enabled: %s\n",
+		     Cudd_zddRealignmentEnabled(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Realignment of BDDs to ZDDs enabled: %s\n",
+		     Cudd_bddRealignmentEnabled(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Dead nodes counted in triggering reordering: %s\n",
+		     Cudd_DeadAreCounted(dd) ? "yes" : "no");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Group checking criterion: %d\n",
+		     Cudd_ReadGroupcheck(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Recombination threshold: %d\n", Cudd_ReadRecomb(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Symmetry violation threshold: %d\n",
+		     Cudd_ReadSymmviolation(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Arc violation threshold: %d\n",
+		     Cudd_ReadArcviolation(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"GA population size: %d\n",
+		     Cudd_ReadPopulationSize(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of crossovers for GA: %d\n",
+		     Cudd_ReadNumberXovers(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Next reordering threshold: %u\n",
+		     Cudd_ReadNextReordering(dd));
+    if (retval == EOF) return(0);
+
+    /* Non-modifiable parameters. */
+    retval = fprintf(fp,"**** CUDD non-modifiable parameters ****\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Memory in use: %lu\n", Cudd_ReadMemoryInUse(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Peak number of nodes: %ld\n",
+		     Cudd_ReadPeakNodeCount(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Peak number of live nodes: %d\n",
+		     Cudd_ReadPeakLiveNodeCount(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of BDD variables: %d\n", dd->size);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of ZDD variables: %d\n", dd->sizeZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache entries: %u\n", dd->cacheSlots);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache look-ups: %.0f\n",
+		     Cudd_ReadCacheLookUps(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache hits: %.0f\n",
+		     Cudd_ReadCacheHits(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache insertions: %.0f\n",
+		     dd->cacheinserts);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache collisions: %.0f\n",
+		     dd->cachecollisions);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of cache deletions: %.0f\n",
+		     dd->cachedeletions);
+    if (retval == EOF) return(0);
+    retval = cuddCacheProfile(dd,fp);
+    if (retval == 0) return(0);
+    retval = fprintf(fp,"Soft limit for cache size: %u\n",
+		     Cudd_ReadMaxCache(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of buckets in unique table: %u\n", dd->slots);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Used buckets in unique table: %.2f%% (expected %.2f%%)\n",
+		     100.0 * Cudd_ReadUsedSlots(dd),
+		     100.0 * Cudd_ExpectedUsedSlots(dd));
+    if (retval == EOF) return(0);
+#ifdef DD_UNIQUE_PROFILE
+    retval = fprintf(fp,"Unique lookups: %.0f\n", dd->uniqueLookUps);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Unique links: %.0f (%g per lookup)\n",
+	    dd->uniqueLinks, dd->uniqueLinks / dd->uniqueLookUps);
+    if (retval == EOF) return(0);
+#endif
+    retval = fprintf(fp,"Number of BDD and ADD nodes: %u\n", dd->keys);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of ZDD nodes: %u\n", dd->keysZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of dead BDD and ADD nodes: %u\n", dd->dead);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Number of dead ZDD nodes: %u\n", dd->deadZ);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Total number of nodes allocated: %.0f\n",
+		     dd->allocated);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Total number of nodes reclaimed: %.0f\n",
+		     dd->reclaimed);
+    if (retval == EOF) return(0);
+#if DD_STATS
+    retval = fprintf(fp,"Nodes freed: %.0f\n", dd->nodesFreed);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Nodes dropped: %.0f\n", dd->nodesDropped);
+    if (retval == EOF) return(0);
+#endif
+#if DD_COUNT
+    retval = fprintf(fp,"Number of recursive calls: %.0f\n",
+		     Cudd_ReadRecursiveCalls(dd));
+    if (retval == EOF) return(0);
+#endif
+    retval = fprintf(fp,"Garbage collections so far: %d\n",
+		     Cudd_ReadGarbageCollections(dd));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Time for garbage collection: %.2f sec\n",
+		     ((double)Cudd_ReadGarbageCollectionTime(dd)/1000.0));
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Reorderings so far: %d\n", dd->reorderings);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Time for reordering: %.2f sec\n",
+		     ((double)Cudd_ReadReorderingTime(dd)/1000.0));
+    if (retval == EOF) return(0);
+#if DD_COUNT
+    retval = fprintf(fp,"Node swaps in reordering: %.0f\n",
+	Cudd_ReadSwapSteps(dd));
+    if (retval == EOF) return(0);
+#endif
+
+    return(1);
+
+} /* end of Cudd_PrintInfo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the peak number of nodes.]
+
+  Description [Reports the peak number of nodes. This number includes
+  node on the free list. At the peak, the number of nodes on the free
+  list is guaranteed to be less than DD_MEM_CHUNK.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodeCount Cudd_PrintInfo]
+
+******************************************************************************/
+long
+Cudd_ReadPeakNodeCount(
+  DdManager * dd)
+{
+    long count = 0;
+    DdNodePtr *scan = dd->memoryList;
+
+    while (scan != NULL) {
+	count += DD_MEM_CHUNK;
+	scan = (DdNodePtr *) *scan;
+    }
+    return(count);
+
+} /* end of Cudd_ReadPeakNodeCount */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the peak number of live nodes.]
+
+  Description [Reports the peak number of live nodes. This count is kept
+  only if CUDD is compiled with DD_STATS defined. If DD_STATS is not
+  defined, this function returns -1.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNodeCount Cudd_PrintInfo Cudd_ReadPeakNodeCount]
+
+******************************************************************************/
+int
+Cudd_ReadPeakLiveNodeCount(
+  DdManager * dd)
+{
+    unsigned int live = dd->keys - dd->dead;
+
+    if (live > dd->peakLiveNodes) {
+	dd->peakLiveNodes = live;
+    }
+    return((int)dd->peakLiveNodes);
+
+} /* end of Cudd_ReadPeakLiveNodeCount */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the number of nodes in BDDs and ADDs.]
+
+  Description [Reports the number of live nodes in BDDs and ADDs. This
+  number does not include the isolated projection functions and the
+  unused constants. These nodes that are not counted are not part of
+  the DDs manipulated by the application.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPeakNodeCount Cudd_zddReadNodeCount]
+
+******************************************************************************/
+long
+Cudd_ReadNodeCount(
+  DdManager * dd)
+{
+    long count;
+    int i;
+
+#ifndef DD_NO_DEATH_ROW
+    cuddClearDeathRow(dd);
+#endif
+
+    count = (long) (dd->keys - dd->dead);
+
+    /* Count isolated projection functions. Their number is subtracted
+    ** from the node count because they are not part of the BDDs.
+    */
+    for (i=0; i < dd->size; i++) {
+	if (dd->vars[i]->ref == 1) count--;
+    }
+    /* Subtract from the count the unused constants. */
+    if (DD_ZERO(dd)->ref == 1) count--;
+    if (DD_PLUS_INFINITY(dd)->ref == 1) count--;
+    if (DD_MINUS_INFINITY(dd)->ref == 1) count--;
+
+    return(count);
+
+} /* end of Cudd_ReadNodeCount */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the number of nodes in ZDDs.]
+
+  Description [Reports the number of nodes in ZDDs. This
+  number always includes the two constants 1 and 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadPeakNodeCount Cudd_ReadNodeCount]
+
+******************************************************************************/
+long
+Cudd_zddReadNodeCount(
+  DdManager * dd)
+{
+    return((long)(dd->keysZ - dd->deadZ + 2));
+
+} /* end of Cudd_zddReadNodeCount */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a function to a hook.]
+
+  Description [Adds a function to a hook. A hook is a list of
+  application-provided functions called on certain occasions by the
+  package. Returns 1 if the function is successfully added; 2 if the
+  function was already in the list; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RemoveHook]
+
+******************************************************************************/
+int
+Cudd_AddHook(
+  DdManager * dd,
+  DD_HFP f,
+  Cudd_HookType where)
+{
+    DdHook **hook, *nextHook, *newHook;
+
+    switch (where) {
+    case CUDD_PRE_GC_HOOK:
+	hook = &(dd->preGCHook);
+	break;
+    case CUDD_POST_GC_HOOK:
+	hook = &(dd->postGCHook);
+	break;
+    case CUDD_PRE_REORDERING_HOOK:
+	hook = &(dd->preReorderingHook);
+	break;
+    case CUDD_POST_REORDERING_HOOK:
+	hook = &(dd->postReorderingHook);
+	break;
+    default:
+	return(0);
+    }
+    /* Scan the list and find whether the function is already there.
+    ** If so, just return. */
+    nextHook = *hook;
+    while (nextHook != NULL) {
+	if (nextHook->f == f) {
+	    return(2);
+	}
+	hook = &(nextHook->next);
+	nextHook = nextHook->next;
+    }
+    /* The function was not in the list. Create a new item and append it
+    ** to the end of the list. */
+    newHook = ALLOC(DdHook,1);
+    if (newHook == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    newHook->next = NULL;
+    newHook->f = f;
+    *hook = newHook;
+    return(1);
+
+} /* end of Cudd_AddHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes a function from a hook.]
+
+  Description [Removes a function from a hook. A hook is a list of
+  application-provided functions called on certain occasions by the
+  package. Returns 1 if successful; 0 the function was not in the list.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AddHook]
+
+******************************************************************************/
+int
+Cudd_RemoveHook(
+  DdManager * dd,
+  DD_HFP f,
+  Cudd_HookType where)
+{
+    DdHook **hook, *nextHook;
+
+    switch (where) {
+    case CUDD_PRE_GC_HOOK:
+	hook = &(dd->preGCHook);
+	break;
+    case CUDD_POST_GC_HOOK:
+	hook = &(dd->postGCHook);
+	break;
+    case CUDD_PRE_REORDERING_HOOK:
+	hook = &(dd->preReorderingHook);
+	break;
+    case CUDD_POST_REORDERING_HOOK:
+	hook = &(dd->postReorderingHook);
+	break;
+    default:
+	return(0);
+    }
+    nextHook = *hook;
+    while (nextHook != NULL) {
+	if (nextHook->f == f) {
+	    *hook = nextHook->next;
+	    FREE(nextHook);
+	    return(1);
+	}
+	hook = &(nextHook->next);
+	nextHook = nextHook->next;
+    }
+
+    return(0);
+
+} /* end of Cudd_RemoveHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a function is in a hook.]
+
+  Description [Checks whether a function is in a hook. A hook is a list of
+  application-provided functions called on certain occasions by the
+  package. Returns 1 if the function is found; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_AddHook Cudd_RemoveHook]
+
+******************************************************************************/
+int
+Cudd_IsInHook(
+  DdManager * dd,
+  DD_HFP f,
+  Cudd_HookType where)
+{
+    DdHook *hook;
+
+    switch (where) {
+    case CUDD_PRE_GC_HOOK:
+	hook = dd->preGCHook;
+	break;
+    case CUDD_POST_GC_HOOK:
+	hook = dd->postGCHook;
+	break;
+    case CUDD_PRE_REORDERING_HOOK:
+	hook = dd->preReorderingHook;
+	break;
+    case CUDD_POST_REORDERING_HOOK:
+	hook = dd->postReorderingHook;
+	break;
+    default:
+	return(0);
+    }
+    /* Scan the list and find whether the function is already there. */
+    while (hook != NULL) {
+	if (hook->f == f) {
+	    return(1);
+	}
+	hook = hook->next;
+    }
+    return(0);
+
+} /* end of Cudd_IsInHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sample hook function to call before reordering.]
+
+  Description [Sample hook function to call before reordering.
+  Prints on the manager's stdout reordering method and initial size.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_StdPostReordHook]
+
+******************************************************************************/
+int
+Cudd_StdPreReordHook(
+  DdManager *dd,
+  const char *str,
+  void *data)
+{
+    Cudd_ReorderingType method = (Cudd_ReorderingType) (ptruint) data;
+    int retval;
+
+    retval = fprintf(dd->out,"%s reordering with ", str);
+    if (retval == EOF) return(0);
+    switch (method) {
+    case CUDD_REORDER_SIFT_CONVERGE:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+    case CUDD_REORDER_GROUP_SIFT_CONV:
+    case CUDD_REORDER_WINDOW2_CONV:
+    case CUDD_REORDER_WINDOW3_CONV:
+    case CUDD_REORDER_WINDOW4_CONV:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+	retval = fprintf(dd->out,"converging ");
+	if (retval == EOF) return(0);
+	break;
+    default:
+	break;
+    }
+    switch (method) {
+    case CUDD_REORDER_RANDOM:
+    case CUDD_REORDER_RANDOM_PIVOT:
+	retval = fprintf(dd->out,"random");
+	break;
+    case CUDD_REORDER_SIFT:
+    case CUDD_REORDER_SIFT_CONVERGE:
+	retval = fprintf(dd->out,"sifting");
+	break;
+    case CUDD_REORDER_SYMM_SIFT:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+	retval = fprintf(dd->out,"symmetric sifting");
+	break;
+    case CUDD_REORDER_LAZY_SIFT:
+	retval = fprintf(dd->out,"lazy sifting");
+	break;
+    case CUDD_REORDER_GROUP_SIFT:
+    case CUDD_REORDER_GROUP_SIFT_CONV:
+	retval = fprintf(dd->out,"group sifting");
+	break;
+    case CUDD_REORDER_WINDOW2:
+    case CUDD_REORDER_WINDOW3:
+    case CUDD_REORDER_WINDOW4:
+    case CUDD_REORDER_WINDOW2_CONV:
+    case CUDD_REORDER_WINDOW3_CONV:
+    case CUDD_REORDER_WINDOW4_CONV:
+	retval = fprintf(dd->out,"window");
+	break;
+    case CUDD_REORDER_ANNEALING:
+	retval = fprintf(dd->out,"annealing");
+	break;
+    case CUDD_REORDER_GENETIC:
+	retval = fprintf(dd->out,"genetic");
+	break;
+    case CUDD_REORDER_LINEAR:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+	retval = fprintf(dd->out,"linear sifting");
+	break;
+    case CUDD_REORDER_EXACT:
+	retval = fprintf(dd->out,"exact");
+	break;
+    default:
+	return(0);
+    }
+    if (retval == EOF) return(0);
+
+    retval = fprintf(dd->out,": from %ld to ... ", strcmp(str, "BDD") == 0 ?
+		     Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd));
+    if (retval == EOF) return(0);
+    fflush(dd->out);
+    return(1);
+
+} /* end of Cudd_StdPreReordHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sample hook function to call after reordering.]
+
+  Description [Sample hook function to call after reordering.
+  Prints on the manager's stdout final size and reordering time.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_StdPreReordHook]
+
+******************************************************************************/
+int
+Cudd_StdPostReordHook(
+  DdManager *dd,
+  const char *str,
+  void *data)
+{
+    long initialTime = (long) data;
+    int retval;
+    long finalTime = util_cpu_time();
+    double totalTimeSec = (double)(finalTime - initialTime) / 1000.0;
+
+    retval = fprintf(dd->out,"%ld nodes in %g sec\n", strcmp(str, "BDD") == 0 ?
+		     Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd),
+		     totalTimeSec);
+    if (retval == EOF) return(0);
+    retval = fflush(dd->out);
+    if (retval == EOF) return(0);
+    return(1);
+
+} /* end of Cudd_StdPostReordHook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables reporting of reordering stats.]
+
+  Description [Enables reporting of reordering stats.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Installs functions in the pre-reordering and post-reordering
+  hooks.]
+
+  SeeAlso     [Cudd_DisableReorderingReporting Cudd_ReorderingReporting]
+
+******************************************************************************/
+int
+Cudd_EnableReorderingReporting(
+  DdManager *dd)
+{
+    if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
+	return(0);
+    }
+    if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
+	return(0);
+    }
+    return(1);
+
+} /* end of Cudd_EnableReorderingReporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables reporting of reordering stats.]
+
+  Description [Disables reporting of reordering stats.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Removes functions from the pre-reordering and post-reordering
+  hooks.]
+
+  SeeAlso     [Cudd_EnableReorderingReporting Cudd_ReorderingReporting]
+
+******************************************************************************/
+int
+Cudd_DisableReorderingReporting(
+  DdManager *dd)
+{
+    if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
+	return(0);
+    }
+    if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
+	return(0);
+    }
+    return(1);
+
+} /* end of Cudd_DisableReorderingReporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if reporting of reordering stats is enabled.]
+
+  Description [Returns 1 if reporting of reordering stats is enabled;
+  0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_EnableReorderingReporting Cudd_DisableReorderingReporting]
+
+******************************************************************************/
+int
+Cudd_ReorderingReporting(
+  DdManager *dd)
+{
+    return(Cudd_IsInHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK));
+
+} /* end of Cudd_ReorderingReporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the code of the last error.]
+
+  Description [Returns the code of the last error. The error codes are
+  defined in cudd.h.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ClearErrorCode]
+
+******************************************************************************/
+Cudd_ErrorType
+Cudd_ReadErrorCode(
+  DdManager *dd)
+{
+    return(dd->errorCode);
+
+} /* end of Cudd_ReadErrorCode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clear the error code of a manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadErrorCode]
+
+******************************************************************************/
+void
+Cudd_ClearErrorCode(
+  DdManager *dd)
+{
+    dd->errorCode = CUDD_NO_ERROR;
+
+} /* end of Cudd_ClearErrorCode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the stdout of a manager.]
+
+  Description [Reads the stdout of a manager. This is the file pointer to
+  which messages normally going to stdout are written. It is initialized
+  to stdout. Cudd_SetStdout allows the application to redirect it.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetStdout Cudd_ReadStderr]
+
+******************************************************************************/
+FILE *
+Cudd_ReadStdout(
+  DdManager *dd)
+{
+    return(dd->out);
+
+} /* end of Cudd_ReadStdout */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the stdout of a manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadStdout Cudd_SetStderr]
+
+******************************************************************************/
+void
+Cudd_SetStdout(
+  DdManager *dd,
+  FILE *fp)
+{
+    dd->out = fp;
+
+} /* end of Cudd_SetStdout */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the stderr of a manager.]
+
+  Description [Reads the stderr of a manager. This is the file pointer to
+  which messages normally going to stderr are written. It is initialized
+  to stderr. Cudd_SetStderr allows the application to redirect it.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetStderr Cudd_ReadStdout]
+
+******************************************************************************/
+FILE *
+Cudd_ReadStderr(
+  DdManager *dd)
+{
+    return(dd->err);
+
+} /* end of Cudd_ReadStderr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the stderr of a manager.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadStderr Cudd_SetStdout]
+
+******************************************************************************/
+void
+Cudd_SetStderr(
+  DdManager *dd,
+  FILE *fp)
+{
+    dd->err = fp;
+
+} /* end of Cudd_SetStderr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the threshold for the next dynamic reordering.]
+
+  Description [Returns the threshold for the next dynamic reordering.
+  The threshold is in terms of number of nodes and is in effect only
+  if reordering is enabled. The count does not include the dead nodes,
+  unless the countDead parameter of the manager has been changed from
+  its default setting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SetNextReordering]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadNextReordering(
+  DdManager *dd)
+{
+    return(dd->nextDyn);
+
+} /* end of Cudd_ReadNextReordering */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the threshold for the next dynamic reordering.]
+
+  Description [Sets the threshold for the next dynamic reordering.
+  The threshold is in terms of number of nodes and is in effect only
+  if reordering is enabled. The count does not include the dead nodes,
+  unless the countDead parameter of the manager has been changed from
+  its default setting.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ReadNextReordering]
+
+******************************************************************************/
+void
+Cudd_SetNextReordering(
+  DdManager *dd,
+  unsigned int next)
+{
+    dd->nextDyn = next;
+
+} /* end of Cudd_SetNextReordering */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the number of elementary reordering steps.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+double
+Cudd_ReadSwapSteps(
+  DdManager *dd)
+{
+#ifdef DD_COUNT
+    return(dd->swapSteps);
+#else
+    return(-1);
+#endif
+
+} /* end of Cudd_ReadSwapSteps */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maximum allowed number of live nodes.]
+
+  Description [Reads the maximum allowed number of live nodes. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_SetMaxLive]
+
+******************************************************************************/
+unsigned int
+Cudd_ReadMaxLive(
+  DdManager *dd)
+{
+    return(dd->maxLive);
+
+} /* end of Cudd_ReadMaxLive */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maximum allowed number of live nodes.]
+
+  Description [Sets the maximum allowed number of live nodes. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadMaxLive]
+
+******************************************************************************/
+void
+Cudd_SetMaxLive(
+  DdManager *dd,
+  unsigned int maxLive)
+{
+    dd->maxLive = maxLive;
+
+} /* end of Cudd_SetMaxLive */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the maximum allowed memory.]
+
+  Description [Reads the maximum allowed memory. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_SetMaxMemory]
+
+******************************************************************************/
+unsigned long
+Cudd_ReadMaxMemory(
+  DdManager *dd)
+{
+    return(dd->maxmemhard);
+
+} /* end of Cudd_ReadMaxMemory */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the maximum allowed memory.]
+
+  Description [Sets the maximum allowed memory. When this
+  number is exceeded, the package returns NULL.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadMaxMemory]
+
+******************************************************************************/
+void
+Cudd_SetMaxMemory(
+  DdManager *dd,
+  unsigned long maxMemory)
+{
+    dd->maxmemhard = maxMemory;
+
+} /* end of Cudd_SetMaxMemory */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prevents sifting of a variable.]
+
+  Description [This function sets a flag to prevent sifting of a
+  variable.  Returns 1 if successful; 0 otherwise (i.e., invalid
+  variable index).]
+
+  SideEffects [Changes the "bindVar" flag in DdSubtable.]
+
+  SeeAlso     [Cudd_bddUnbindVar]
+
+******************************************************************************/
+int
+Cudd_bddBindVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].bindVar = 1;
+    return(1);
+
+} /* end of Cudd_bddBindVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allows the sifting of a variable.]
+
+  Description [This function resets the flag that prevents the sifting
+  of a variable. In successive variable reorderings, the variable will
+  NOT be skipped, that is, sifted.  Initially all variables can be
+  sifted. It is necessary to call this function only to re-enable
+  sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0
+  otherwise (i.e., invalid variable index).]
+
+  SideEffects [Changes the "bindVar" flag in DdSubtable.]
+
+  SeeAlso     [Cudd_bddBindVar]
+
+******************************************************************************/
+int
+Cudd_bddUnbindVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].bindVar = 0;
+    return(1);
+
+} /* end of Cudd_bddUnbindVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether a variable can be sifted.]
+
+  Description [This function returns 1 if a variable is enabled for
+  sifting.  Initially all variables can be sifted. This function returns
+  0 only if there has been a previous call to Cudd_bddBindVar for that
+  variable not followed by a call to Cudd_bddUnbindVar. The function returns
+  0 also in the case in which the index of the variable is out of bounds.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddBindVar Cudd_bddUnbindVar]
+
+******************************************************************************/
+int
+Cudd_bddVarIsBound(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    return(dd->subtables[dd->perm[index]].bindVar);
+
+} /* end of Cudd_bddVarIsBound */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to primary input.]
+
+  Description [Sets a variable type to primary input.  The variable type is
+  used by lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPsVar Cudd_bddSetNsVar Cudd_bddIsPiVar]
+
+******************************************************************************/
+int
+Cudd_bddSetPiVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return (0);
+    dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRIMARY_INPUT;
+    return(1);
+
+} /* end of Cudd_bddSetPiVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to present state.]
+
+  Description [Sets a variable type to present state.  The variable type is
+  used by lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPiVar Cudd_bddSetNsVar Cudd_bddIsPsVar]
+
+******************************************************************************/
+int
+Cudd_bddSetPsVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return (0);
+    dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRESENT_STATE;
+    return(1);
+
+} /* end of Cudd_bddSetPsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to next state.]
+
+  Description [Sets a variable type to next state.  The variable type is
+  used by lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPiVar Cudd_bddSetPsVar Cudd_bddIsNsVar]
+
+******************************************************************************/
+int
+Cudd_bddSetNsVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return (0);
+    dd->subtables[dd->perm[index]].varType = CUDD_VAR_NEXT_STATE;
+    return(1);
+
+} /* end of Cudd_bddSetNsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is primary input.]
+
+  Description [Checks whether a variable is primary input.  Returns 1 if
+  the variable's type is primary input; 0 if the variable exists but is
+  not a primary input; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetPiVar Cudd_bddIsPsVar Cudd_bddIsNsVar]
+
+******************************************************************************/
+int
+Cudd_bddIsPiVar(
+  DdManager *dd /* manager */,
+  int index /* variable index */)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRIMARY_INPUT);
+
+} /* end of Cudd_bddIsPiVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is present state.]
+
+  Description [Checks whether a variable is present state.  Returns 1 if
+  the variable's type is present state; 0 if the variable exists but is
+  not a present state; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetPsVar Cudd_bddIsPiVar Cudd_bddIsNsVar]
+
+******************************************************************************/
+int
+Cudd_bddIsPsVar(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRESENT_STATE);
+
+} /* end of Cudd_bddIsPsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is next state.]
+
+  Description [Checks whether a variable is next state.  Returns 1 if
+  the variable's type is present state; 0 if the variable exists but is
+  not a present state; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetNsVar Cudd_bddIsPiVar Cudd_bddIsPsVar]
+
+******************************************************************************/
+int
+Cudd_bddIsNsVar(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_NEXT_STATE);
+
+} /* end of Cudd_bddIsNsVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a corresponding pair index for a given index.]
+
+  Description [Sets a corresponding pair index for a given index.
+  These pair indices are present and next state variable.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddReadPairIndex]
+
+******************************************************************************/
+int
+Cudd_bddSetPairIndex(
+  DdManager *dd /* manager */,
+  int index /* variable index */,
+  int pairIndex /* corresponding variable index */)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].pairIndex = pairIndex;
+    return(1);
+
+} /* end of Cudd_bddSetPairIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads a corresponding pair index for a given index.]
+
+  Description [Reads a corresponding pair index for a given index.
+  These pair indices are present and next state variable.  Returns the
+  corresponding variable index if the variable exists; -1 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetPairIndex]
+
+******************************************************************************/
+int
+Cudd_bddReadPairIndex(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return -1;
+    return dd->subtables[dd->perm[index]].pairIndex;
+
+} /* end of Cudd_bddReadPairIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be grouped.]
+
+  Description [Sets a variable to be grouped. This function is used for
+  lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetVarHardGroup Cudd_bddResetVarToBeGrouped]
+
+******************************************************************************/
+int
+Cudd_bddSetVarToBeGrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) {
+	dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_SOFT_GROUP;
+    }
+    return(1);
+
+} /* end of Cudd_bddSetVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be a hard group.]
+
+  Description [Sets a variable to be a hard group.  This function is used
+  for lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetVarToBeGrouped Cudd_bddResetVarToBeGrouped
+  Cudd_bddIsVarHardGroup]
+
+******************************************************************************/
+int
+Cudd_bddSetVarHardGroup(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_HARD_GROUP;
+    return(1);
+
+} /* end of Cudd_bddSetVarHardGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resets a variable not to be grouped.]
+
+  Description [Resets a variable not to be grouped.  This function is
+  used for lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddSetVarToBeGrouped Cudd_bddSetVarHardGroup]
+
+******************************************************************************/
+int
+Cudd_bddResetVarToBeGrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped <=
+	CUDD_LAZY_SOFT_GROUP) {
+	dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_NONE;
+    }
+    return(1);
+
+} /* end of Cudd_bddResetVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be grouped.]
+
+  Description [Checks whether a variable is set to be grouped. This
+  function is used for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_bddIsVarToBeGrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP)
+	return(0);
+    else
+	return(dd->subtables[dd->perm[index]].varToBeGrouped);
+
+} /* end of Cudd_bddIsVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be ungrouped.]
+
+  Description [Sets a variable to be ungrouped. This function is used
+  for lazy sifting.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [modifies the manager]
+
+  SeeAlso     [Cudd_bddIsVarToBeUngrouped]
+
+******************************************************************************/
+int
+Cudd_bddSetVarToBeUngrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_UNGROUP;
+    return(1);
+
+} /* end of Cudd_bddSetVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be ungrouped.]
+
+  Description [Checks whether a variable is set to be ungrouped. This
+  function is used for lazy sifting.  Returns 1 if the variable is marked
+  to be ungrouped; 0 if the variable exists, but it is not marked to be
+  ungrouped; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetVarToBeUngrouped]
+
+******************************************************************************/
+int
+Cudd_bddIsVarToBeUngrouped(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP;
+
+} /* end of Cudd_bddIsVarToBeGrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be in a hard group.]
+
+  Description [Checks whether a variable is set to be in a hard group.  This
+  function is used for lazy sifting.  Returns 1 if the variable is marked
+  to be in a hard group; 0 if the variable exists, but it is not marked to be
+  in a hard group; -1 if the variable does not exist.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddSetVarHardGroup]
+
+******************************************************************************/
+int
+Cudd_bddIsVarHardGroup(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_HARD_GROUP)
+	return(1);
+    return(0);
+
+} /* end of Cudd_bddIsVarToBeGrouped */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes a variable group tree.]
+
+  Description []
+
+  SideEffects [Changes the variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+fixVarTree(
+  MtrNode * treenode,
+  int * perm,
+  int  size)
+{
+    treenode->index = treenode->low;
+    treenode->low = ((int) treenode->index < size) ?
+	perm[treenode->index] : treenode->index;
+    if (treenode->child != NULL)
+	fixVarTree(treenode->child, perm, size);
+    if (treenode->younger != NULL)
+	fixVarTree(treenode->younger, perm, size);
+    return;
+
+} /* end of fixVarTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds multiplicity groups to a ZDD variable group tree.]
+
+  Description [Adds multiplicity groups to a ZDD variable group tree.
+  Returns 1 if successful; 0 otherwise. This function creates the groups
+  for set of ZDD variables (whose cardinality is given by parameter
+  multiplicity) that are created for each BDD variable in
+  Cudd_zddVarsFromBddVars. The crux of the matter is to determine the index
+  each new group. (The index of the first variable in the group.)
+  We first build all the groups for the children of a node, and then deal
+  with the ZDD variables that are directly attached to the node. The problem
+  for these is that the tree itself does not provide information on their
+  position inside the group. While we deal with the children of the node,
+  therefore, we keep track of all the positions they occupy. The remaining
+  positions in the tree can be freely used. Also, we keep track of all the
+  variables placed in the children. All the remaining variables are directly
+  attached to the group. We can then place any pair of variables not yet
+  grouped in any pair of available positions in the node.]
+
+  SideEffects [Changes the variable group tree.]
+
+  SeeAlso     [Cudd_zddVarsFromBddVars]
+
+******************************************************************************/
+static int
+addMultiplicityGroups(
+  DdManager *dd /* manager */,
+  MtrNode *treenode /* current tree node */,
+  int multiplicity /* how many ZDD vars per BDD var */,
+  char *vmask /* variable pairs for which a group has been already built */,
+  char *lmask /* levels for which a group has already been built*/)
+{
+    int startV, stopV, startL;
+    int i, j;
+    MtrNode *auxnode = treenode;
+
+    while (auxnode != NULL) {
+	if (auxnode->child != NULL) {
+	    addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask);
+	}
+	/* Build remaining groups. */
+	startV = dd->permZ[auxnode->index] / multiplicity;
+	startL = auxnode->low / multiplicity;
+	stopV = startV + auxnode->size / multiplicity;
+	/* Walk down vmask starting at startV and build missing groups. */
+	for (i = startV, j = startL; i < stopV; i++) {
+	    if (vmask[i] == 0) {
+		MtrNode *node;
+		while (lmask[j] == 1) j++;
+		node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity,
+				     MTR_FIXED);
+		if (node == NULL) {
+		    return(0);
+		}
+		node->index = dd->invpermZ[i * multiplicity];
+		vmask[i] = 1;
+		lmask[j] = 1;
+	    }
+	}
+	auxnode = auxnode->younger;
+    }
+    return(1);
+
+} /* end of addMultiplicityGroups */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAddAbs.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAddAbs.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAddAbs.c	(revision 8)
@@ -0,0 +1,579 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddAbs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Quantification functions for ADDs.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addExistAbstract()
+		<li> Cudd_addUnivAbstract()
+		<li> Cudd_addOrAbstract()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddAddExistAbstractRecur()
+		<li> cuddAddUnivAbstractRecur()
+		<li> cuddAddOrAbstractRecur()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> addCheckPositiveCube()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddAbs.c,v 1.15 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+static	DdNode	*two;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int addCheckPositiveCube (DdManager *manager, DdNode *cube);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Existentially Abstracts all the variables in cube from f.]
+
+  Description [Abstracts all the variables in cube from f by summing
+  over all possible values taken by the variables. Returns the
+  abstracted ADD.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addUnivAbstract Cudd_bddExistAbstract
+  Cudd_addOrAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addExistAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2);
+    if (two == NULL) return(NULL);
+    cuddRef(two);
+
+    if (addCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,"Error: Can only abstract cubes");
+        return(NULL);
+    }
+
+    do {
+	manager->reordered = 0;
+	res = cuddAddExistAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+
+    if (res == NULL) {
+	Cudd_RecursiveDeref(manager,two);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(manager,two);
+    cuddDeref(res);
+
+    return(res);
+
+} /* end of Cudd_addExistAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Universally Abstracts all the variables in cube from f.]
+
+  Description [Abstracts all the variables in cube from f by taking
+  the product over all possible values taken by the variable. Returns
+  the abstracted ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addExistAbstract Cudd_bddUnivAbstract
+  Cudd_addOrAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addUnivAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode		*res;
+
+    if (addCheckPositiveCube(manager, cube) == 0) {
+	(void) fprintf(manager->err,"Error:  Can only abstract cubes");
+	return(NULL);
+    }
+
+    do {
+	manager->reordered = 0;
+	res = cuddAddUnivAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_addUnivAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disjunctively abstracts all the variables in cube from the
+  0-1 ADD f.]
+
+  Description [Abstracts all the variables in cube from the 0-1 ADD f
+  by taking the disjunction over all possible values taken by the
+  variables.  Returns the abstracted ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addUnivAbstract Cudd_addExistAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addOrAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    if (addCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,"Error: Can only abstract cubes");
+        return(NULL);
+    }
+
+    do {
+	manager->reordered = 0;
+	res = cuddAddOrAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addOrAbstract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addExistAbstract.]
+
+  Description [Performs the recursive step of Cudd_addExistAbstract.
+  Returns the ADD obtained by abstracting the variables of cube from f,
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddExistAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode	*T, *E, *res, *res1, *res2, *zero;
+
+    statLine(manager);
+    zero = DD_ZERO(manager);
+
+    /* Cube is guaranteed to be a cube at this point. */	
+    if (f == zero || cuddIsConstant(cube)) {  
+        return(f);
+    }
+
+    /* Abstract a variable that does not appear in f => multiply by 2. */
+    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+	res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube));
+	if (res1 == NULL) return(NULL);
+	cuddRef(res1);
+	/* Use the "internal" procedure to be alerted in case of
+	** dynamic reordering. If dynamic reordering occurs, we
+	** have to abort the entire abstraction.
+	*/
+	res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDeref(manager,res1);
+	cuddDeref(res);
+        return(res);
+    }
+
+    if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) {
+	return(res);
+    }
+
+    T = cuddT(f);
+    E = cuddE(f);
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == cube->index) {
+	res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube));
+	if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+	res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube));
+	if (res2 == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    return(NULL);
+	}
+        cuddRef(res2);
+	res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    Cudd_RecursiveDeref(manager,res2);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDeref(manager,res1);
+	Cudd_RecursiveDeref(manager,res2);
+	cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
+	cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+	res1 = cuddAddExistAbstractRecur(manager, T, cube);
+	if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+	res2 = cuddAddExistAbstractRecur(manager, E, cube);
+	if (res2 == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    return(NULL);
+	}
+        cuddRef(res2);
+	res = (res1 == res2) ? res1 :
+	    cuddUniqueInter(manager, (int) f->index, res1, res2);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    Cudd_RecursiveDeref(manager,res2);
+	    return(NULL);
+	}
+	cuddDeref(res1);
+	cuddDeref(res2);
+	cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
+        return(res);
+    }	    
+
+} /* end of cuddAddExistAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addUnivAbstract.]
+
+  Description [Performs the recursive step of Cudd_addUnivAbstract.
+  Returns the ADD obtained by abstracting the variables of cube from f,
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddUnivAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode	*T, *E, *res, *res1, *res2, *one, *zero;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    /* Cube is guaranteed to be a cube at this point.
+    ** zero and one are the only constatnts c such that c*c=c.
+    */
+    if (f == zero || f == one || cube == one) {  
+	return(f);
+    }
+
+    /* Abstract a variable that does not appear in f. */
+    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+	res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube));
+	if (res1 == NULL) return(NULL);
+	cuddRef(res1);
+	/* Use the "internal" procedure to be alerted in case of
+	** dynamic reordering. If dynamic reordering occurs, we
+	** have to abort the entire abstraction.
+	*/
+	res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDeref(manager,res1);
+	cuddDeref(res);
+	return(res);
+    }
+
+    if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) {
+	return(res);
+    }
+
+    T = cuddT(f);
+    E = cuddE(f);
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == cube->index) {
+	res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube));
+	if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+	res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube));
+	if (res2 == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    return(NULL);
+	}
+        cuddRef(res2);
+	res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    Cudd_RecursiveDeref(manager,res2);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDeref(manager,res1);
+	Cudd_RecursiveDeref(manager,res2);
+	cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
+	cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+	res1 = cuddAddUnivAbstractRecur(manager, T, cube);
+	if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+	res2 = cuddAddUnivAbstractRecur(manager, E, cube);
+	if (res2 == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    return(NULL);
+	}
+        cuddRef(res2);
+	res = (res1 == res2) ? res1 :
+	    cuddUniqueInter(manager, (int) f->index, res1, res2);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    Cudd_RecursiveDeref(manager,res2);
+	    return(NULL);
+	}
+	cuddDeref(res1);
+	cuddDeref(res2);
+	cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
+        return(res);
+    }
+
+} /* end of cuddAddUnivAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addOrAbstract.]
+
+  Description [Performs the recursive step of Cudd_addOrAbstract.
+  Returns the ADD obtained by abstracting the variables of cube from f,
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddOrAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode	*T, *E, *res, *res1, *res2, *one;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+
+    /* Cube is guaranteed to be a cube at this point. */
+    if (cuddIsConstant(f) || cube == one) {  
+	return(f);
+    }
+
+    /* Abstract a variable that does not appear in f. */
+    if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
+	res = cuddAddOrAbstractRecur(manager, f, cuddT(cube));
+	return(res);
+    }
+
+    if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) {
+	return(res);
+    }
+
+    T = cuddT(f);
+    E = cuddE(f);
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == cube->index) {
+	res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube));
+	if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+	if (res1 != one) {
+	    res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube));
+	    if (res2 == NULL) {
+		Cudd_RecursiveDeref(manager,res1);
+		return(NULL);
+	    }
+	    cuddRef(res2);
+	    res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2);
+	    if (res == NULL) {
+		Cudd_RecursiveDeref(manager,res1);
+		Cudd_RecursiveDeref(manager,res2);
+		return(NULL);
+	    }
+	    cuddRef(res);
+	    Cudd_RecursiveDeref(manager,res1);
+	    Cudd_RecursiveDeref(manager,res2);
+	} else {
+	    res = res1;
+	}
+	cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
+	cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
+	res1 = cuddAddOrAbstractRecur(manager, T, cube);
+	if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+	res2 = cuddAddOrAbstractRecur(manager, E, cube);
+	if (res2 == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    return(NULL);
+	}
+        cuddRef(res2);
+	res = (res1 == res2) ? res1 :
+	    cuddUniqueInter(manager, (int) f->index, res1, res2);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(manager,res1);
+	    Cudd_RecursiveDeref(manager,res2);
+	    return(NULL);
+	}
+	cuddDeref(res1);
+	cuddDeref(res2);
+	cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
+        return(res);
+    }
+
+} /* end of cuddAddOrAbstractRecur */
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether cube is an ADD representing the product
+  of positive literals.]
+
+  Description [Checks whether cube is an ADD representing the product of
+  positive literals. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+addCheckPositiveCube(
+  DdManager * manager,
+  DdNode * cube)
+{
+    if (Cudd_IsComplement(cube)) return(0);
+    if (cube == DD_ONE(manager)) return(1);
+    if (cuddIsConstant(cube)) return(0);
+    if (cuddE(cube) == DD_ZERO(manager)) {
+        return(addCheckPositiveCube(manager, cuddT(cube)));
+    }
+    return(0);
+
+} /* end of addCheckPositiveCube */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAddApply.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAddApply.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAddApply.c	(revision 8)
@@ -0,0 +1,942 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddApply.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Apply functions for ADDs and their operators.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addApply()
+		<li> Cudd_addMonadicApply()
+		<li> Cudd_addPlus()
+		<li> Cudd_addTimes()
+		<li> Cudd_addThreshold()
+		<li> Cudd_addSetNZ()
+		<li> Cudd_addDivide()
+		<li> Cudd_addMinus()
+		<li> Cudd_addMinimum()
+		<li> Cudd_addMaximum()
+		<li> Cudd_addOneZeroMaximum()
+		<li> Cudd_addDiff()
+		<li> Cudd_addAgreement()
+		<li> Cudd_addOr()
+		<li> Cudd_addNand()
+		<li> Cudd_addNor()
+		<li> Cudd_addXor()
+		<li> Cudd_addXnor()
+		</ul>
+	    Internal procedures included in this module:
+		<ul>
+		<li> cuddAddApplyRecur()
+		<li> cuddAddMonadicApplyRecur()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.17 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Applies op to the corresponding discriminants of f and g.]
+
+  Description [Applies op to the corresponding discriminants of f and g.
+  Returns a pointer to the result if succssful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
+  Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
+  Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
+  Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_addApply(
+  DdManager * dd,
+  DD_AOP op,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddAddApplyRecur(dd,op,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addApply */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point addition.]
+
+  Description [Integer and floating point addition. Returns NULL if not
+  a terminal case; f+g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addPlus(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    if (F == DD_ZERO(dd)) return(G);
+    if (G == DD_ZERO(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	value = cuddV(F)+cuddV(G);
+	res = cuddUniqueConst(dd,value);
+	return(res);
+    }
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addPlus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point multiplication.]
+
+  Description [Integer and floating point multiplication. Returns NULL
+  if not a terminal case; f * g otherwise.  This function can be used also
+  to take the AND of two 0-1 ADDs.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addTimes(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
+    if (F == DD_ONE(dd)) return(G);
+    if (G == DD_ONE(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	value = cuddV(F)*cuddV(G);
+	res = cuddUniqueConst(dd,value);
+	return(res);
+    }
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addTimes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [f if f&gt;=g; 0 if f&lt;g.]
+
+  Description [Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g).
+  Returns NULL if not a terminal case; f op g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addThreshold(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G || F == DD_PLUS_INFINITY(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	if (cuddV(F) >= cuddV(G)) {
+	    return(F);
+	} else {
+	    return(DD_ZERO(dd));
+	}
+    }
+    return(NULL);
+
+} /* end of Cudd_addThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This operator sets f to the value of g wherever g != 0.]
+
+  Description [This operator sets f to the value of g wherever g != 0.
+  Returns NULL if not a terminal case; f op g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addSetNZ(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(F);
+    if (F == DD_ZERO(dd)) return(G);
+    if (G == DD_ZERO(dd)) return(F);
+    if (cuddIsConstant(G)) return(G);
+    return(NULL);
+
+} /* end of Cudd_addSetNZ */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point division.]
+
+  Description [Integer and floating point division. Returns NULL if not
+  a terminal case; f / g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addDivide(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    /* We would like to use F == G -> F/G == 1, but F and G may
+    ** contain zeroes. */
+    if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
+    if (G == DD_ONE(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	value = cuddV(F)/cuddV(G);
+	res = cuddUniqueConst(dd,value);
+	return(res);
+    }
+    return(NULL);
+
+} /* end of Cudd_addDivide */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point subtraction.]
+
+  Description [Integer and floating point subtraction. Returns NULL if
+  not a terminal case; f - g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addMinus(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *res;
+    DdNode *F, *G;
+    CUDD_VALUE_TYPE value;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_ZERO(dd));
+    if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G));
+    if (G == DD_ZERO(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	value = cuddV(F)-cuddV(G);
+	res = cuddUniqueConst(dd,value);
+	return(res);
+    }
+    return(NULL);
+
+} /* end of Cudd_addMinus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point min.]
+
+  Description [Integer and floating point min for Cudd_addApply.
+  Returns NULL if not a terminal case; min(f,g) otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addMinimum(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_PLUS_INFINITY(dd)) return(G);
+    if (G == DD_PLUS_INFINITY(dd)) return(F);
+    if (F == G) return(F);
+#if 0
+    /* These special cases probably do not pay off. */
+    if (F == DD_MINUS_INFINITY(dd)) return(F);
+    if (G == DD_MINUS_INFINITY(dd)) return(G);
+#endif
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	if (cuddV(F) <= cuddV(G)) {
+	    return(F);
+	} else {
+	    return(G);
+	}
+    }
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addMinimum */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Integer and floating point max.]
+
+  Description [Integer and floating point max for Cudd_addApply.
+  Returns NULL if not a terminal case; max(f,g) otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addMaximum(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(F);
+    if (F == DD_MINUS_INFINITY(dd)) return(G);
+    if (G == DD_MINUS_INFINITY(dd)) return(F);
+#if 0
+    /* These special cases probably do not pay off. */
+    if (F == DD_PLUS_INFINITY(dd)) return(F);
+    if (G == DD_PLUS_INFINITY(dd)) return(G);
+#endif
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	if (cuddV(F) >= cuddV(G)) {
+	    return(F);
+	} else {
+	    return(G);
+	}
+    }
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addMaximum */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if f &gt; g and 0 otherwise.]
+
+  Description [Returns 1 if f &gt; g and 0 otherwise. Used in
+  conjunction with Cudd_addApply. Returns NULL if not a terminal
+  case.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addOneZeroMaximum(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+
+    if (*f == *g) return(DD_ZERO(dd));
+    if (*g == DD_PLUS_INFINITY(dd))
+	return DD_ZERO(dd);
+    if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
+	if (cuddV(*f) > cuddV(*g)) {
+	    return(DD_ONE(dd));
+	} else {
+	    return(DD_ZERO(dd));
+	}
+    }
+
+    return(NULL);
+
+} /* end of Cudd_addOneZeroMaximum */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns plusinfinity if f=g; returns min(f,g) if f!=g.]
+
+  Description [Returns NULL if not a terminal case; f op g otherwise,
+  where f op g is plusinfinity if f=g; min(f,g) if f!=g.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addDiff(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_PLUS_INFINITY(dd));
+    if (F == DD_PLUS_INFINITY(dd)) return(G);
+    if (G == DD_PLUS_INFINITY(dd)) return(F);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) {
+	if (cuddV(F) != cuddV(G)) {
+            if (cuddV(F) < cuddV(G)) {
+                return(F);
+            } else {
+                return(G);
+            }
+	} else {
+	    return(DD_PLUS_INFINITY(dd));
+	}
+    }
+    return(NULL);
+
+} /* end of Cudd_addDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis    [f if f==g; background if f!=g.]
+
+  Description [Returns NULL if not a terminal case; f op g otherwise,
+  where f op g is f if f==g; background if f!=g.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addAgreement(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(F);
+    if (F == dd->background) return(F);
+    if (G == dd->background) return(G);
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background);
+    return(NULL);
+
+} /* end of Cudd_addAgreement */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disjunction of two 0-1 ADDs.]
+
+  Description [Disjunction of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f OR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addOr(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F)) return(G);
+    if (cuddIsConstant(G)) return(F);
+    if (F == G) return(F);
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addOr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [NAND of two 0-1 ADDs.]
+
+  Description [NAND of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f NAND g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addNand(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addNand */
+
+
+/**Function********************************************************************
+
+  Synopsis    [NOR of two 0-1 ADDs.]
+
+  Description [NOR of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f NOR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addNor(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addNor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [XOR of two 0-1 ADDs.]
+
+  Description [XOR of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f XOR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addXor(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_ZERO(dd));
+    if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addXor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [XNOR of two 0-1 ADDs.]
+
+  Description [XNOR of two 0-1 ADDs. Returns NULL
+  if not a terminal case; f XNOR g otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addXnor(
+  DdManager * dd,
+  DdNode ** f,
+  DdNode ** g)
+{
+    DdNode *F, *G;
+
+    F = *f; G = *g;
+    if (F == G) return(DD_ONE(dd));
+    if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
+    if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
+    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
+    if (F > G) { /* swap f and g */
+	*f = G;
+	*g = F;
+    }
+    return(NULL);
+
+} /* end of Cudd_addXnor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies op to the discriminants of f.]
+
+  Description [Applies op to the discriminants of f.
+  Returns a pointer to the result if succssful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addApply Cudd_addLog]
+
+******************************************************************************/
+DdNode *
+Cudd_addMonadicApply(
+  DdManager * dd,
+  DD_MAOP op,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddAddMonadicApplyRecur(dd,op,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addMonadicApply */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Natural logarithm of an ADD.]
+
+  Description [Natural logarithm of an ADDs. Returns NULL
+  if not a terminal case; log(f) otherwise.  The discriminants of f must
+  be positive double's.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMonadicApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addLog(
+  DdManager * dd,
+  DdNode * f)
+{
+    if (cuddIsConstant(f)) {
+	CUDD_VALUE_TYPE value = log(cuddV(f));
+	DdNode *res = cuddUniqueConst(dd,value);
+	return(res);
+    }
+    return(NULL);
+
+} /* end of Cudd_addLog */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addApply.]
+
+  Description [Performs the recursive step of Cudd_addApply. Returns a
+  pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAddMonadicApplyRecur]
+
+******************************************************************************/
+DdNode *
+cuddAddApplyRecur(
+  DdManager * dd,
+  DD_AOP op,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res,
+	   *fv, *fvn, *gv, *gvn,
+	   *T, *E;
+    unsigned int ford, gord;
+    unsigned int index;
+    DD_CTFP cacheOp;
+
+    /* Check terminal cases. Op may swap f and g to increase the
+     * cache hit rate.
+     */
+    statLine(dd);
+    res = (*op)(dd,&f,&g);
+    if (res != NULL) return(res);
+
+    /* Check cache. */
+    cacheOp = (DD_CTFP) op;
+    res = cuddCacheLookup2(dd,cacheOp,f,g);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    ford = cuddI(dd,f->index);
+    gord = cuddI(dd,g->index);
+    if (ford <= gord) {
+	index = f->index;
+	fv = cuddT(f);
+	fvn = cuddE(f);
+    } else {
+	index = g->index;
+	fv = fvn = f;
+    }
+    if (gord <= ford) {
+	gv = cuddT(g);
+	gvn = cuddE(g);
+    } else {
+	gv = gvn = g;
+    }
+
+    T = cuddAddApplyRecur(dd,op,fv,gv);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddApplyRecur(dd,op,fvn,gvn);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd,T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	Cudd_RecursiveDeref(dd, E);
+	return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,cacheOp,f,g,res);
+
+    return(res);
+
+} /* end of cuddAddApplyRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addMonadicApply.]
+
+  Description [Performs the recursive step of Cudd_addMonadicApply. Returns a
+  pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAddApplyRecur]
+
+******************************************************************************/
+DdNode *
+cuddAddMonadicApplyRecur(
+  DdManager * dd,
+  DD_MAOP op,
+  DdNode * f)
+{
+    DdNode *res, *ft, *fe, *T, *E;
+    unsigned int index;
+
+    /* Check terminal cases. */
+    statLine(dd);
+    res = (*op)(dd,f);
+    if (res != NULL) return(res);
+
+    /* Check cache. */
+    res = cuddCacheLookup1(dd,op,f);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    index = f->index;
+    ft = cuddT(f);
+    fe = cuddE(f);
+
+    T = cuddAddMonadicApplyRecur(dd,op,ft);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddMonadicApplyRecur(dd,op,fe);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd,T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	Cudd_RecursiveDeref(dd, E);
+	return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,op,f,res);
+
+    return(res);
+
+} /* end of cuddAddMonadicApplyRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAddFind.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAddFind.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAddFind.c	(revision 8)
@@ -0,0 +1,316 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddFind.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to find maximum and minimum in an ADD and to
+  extract the i-th bit.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addFindMax()
+		<li> Cudd_addFindMin()
+		<li> Cudd_addIthBit()
+		</ul>
+	       Static functions included in this module:
+		<ul>
+		<li> addDoIthBit()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddFind.c,v 1.8 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addDoIthBit (DdManager *dd, DdNode *f, DdNode *index);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the maximum discriminant of f.]
+
+  Description [Returns a pointer to a constant ADD.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addFindMax(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *t, *e, *res;
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+	return(f);
+    }
+
+    res = cuddCacheLookup1(dd,Cudd_addFindMax,f);
+    if (res != NULL) {
+	return(res);
+    }
+
+    t  = Cudd_addFindMax(dd,cuddT(f));
+    if (t == DD_PLUS_INFINITY(dd)) return(t);
+
+    e  = Cudd_addFindMax(dd,cuddE(f));
+
+    res = (cuddV(t) >= cuddV(e)) ? t : e;
+
+    cuddCacheInsert1(dd,Cudd_addFindMax,f,res);
+
+    return(res);
+
+} /* end of Cudd_addFindMax */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the minimum discriminant of f.]
+
+  Description [Returns a pointer to a constant ADD.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addFindMin(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *t, *e, *res;
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+	return(f);
+    }
+
+    res = cuddCacheLookup1(dd,Cudd_addFindMin,f);
+    if (res != NULL) {
+	return(res);
+    }
+
+    t  = Cudd_addFindMin(dd,cuddT(f));
+    if (t == DD_MINUS_INFINITY(dd)) return(t);
+
+    e  = Cudd_addFindMin(dd,cuddE(f));
+
+    res = (cuddV(t) <= cuddV(e)) ? t : e;
+
+    cuddCacheInsert1(dd,Cudd_addFindMin,f,res);
+
+    return(res);
+
+} /* end of Cudd_addFindMin */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts the i-th bit from an ADD.]
+
+  Description [Produces an ADD from another ADD by replacing all
+  discriminants whose i-th bit is equal to 1 with 1, and all other
+  discriminants with 0. The i-th bit refers to the integer
+  representation of the leaf value. If the value is has a fractional
+  part, it is ignored. Repeated calls to this procedure allow one to
+  transform an integer-valued ADD into an array of ADDs, one for each
+  bit of the leaf values. Returns a pointer to the resulting ADD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddIthBit]
+
+******************************************************************************/
+DdNode *
+Cudd_addIthBit(
+  DdManager * dd,
+  DdNode * f,
+  int  bit)
+{
+    DdNode *res;
+    DdNode *index;
+    
+    /* Use a constant node to remember the bit, so that we can use the
+    ** global cache.
+    */
+    index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit);
+    if (index == NULL) return(NULL);
+    cuddRef(index);
+
+    do {
+	dd->reordered = 0;
+	res = addDoIthBit(dd, f, index);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, index);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, index);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addIthBit */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addIthBit.]
+
+  Description [Performs the recursive step for Cudd_addIthBit.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+addDoIthBit(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * index)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int mask, value;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+	mask = 1 << ((int) cuddV(index));
+	value = (int) cuddV(f);
+	return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addDoIthBit,f,index);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addDoIthBit(dd,fv,index);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addDoIthBit(dd,fvn,index);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	Cudd_RecursiveDeref(dd, E);
+	return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addDoIthBit,f,index,res);
+
+    return(res);
+
+} /* end of addDoIthBit */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAddInv.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAddInv.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAddInv.c	(revision 8)
@@ -0,0 +1,201 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddInv.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Function to compute the scalar inverse of an ADD.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addScalarInverse()
+		</ul>
+	    Internal procedures included in this module:
+		<ul>
+		<li> cuddAddScalarInverseRecur()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddInv.c,v 1.9 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the scalar inverse of an ADD.]
+  
+  Description [Computes an n ADD where the discriminants are the
+  multiplicative inverses of the corresponding discriminants of the
+  argument ADD.  Returns a pointer to the resulting ADD in case of
+  success. Returns NULL if any discriminants smaller than epsilon is
+  encountered.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addScalarInverse(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * epsilon)
+{
+    DdNode *res;
+
+    if (!cuddIsConstant(epsilon)) {
+	(void) fprintf(dd->err,"Invalid epsilon\n");
+	return(NULL);
+    }
+    do {
+	dd->reordered = 0;
+	res  = cuddAddScalarInverseRecur(dd,f,epsilon);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addScalarInverse */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of addScalarInverse.]
+
+  Description [Returns a pointer to the resulting ADD in case of
+  success. Returns NULL if any discriminants smaller than epsilon is
+  encountered.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddAddScalarInverseRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * epsilon)
+{
+    DdNode *t, *e, *res;
+    CUDD_VALUE_TYPE value;
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+	if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL);
+	value = 1.0 / cuddV(f);
+	res = cuddUniqueConst(dd,value);
+	return(res);
+    }
+
+    res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon);
+    if (res != NULL) return(res);
+
+    t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(dd, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, t);
+	Cudd_RecursiveDeref(dd, e);
+	return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res);
+
+    return(res);
+
+} /* end of cuddAddScalarInverseRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAddIte.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAddIte.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAddIte.c	(revision 8)
@@ -0,0 +1,639 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddIte.c]
+
+  PackageName [cudd]
+
+  Synopsis    [ADD ITE function and satellites.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addIte()
+		<li> Cudd_addIteConstant()
+		<li> Cudd_addEvalConst()
+		<li> Cudd_addCmpl()
+		<li> Cudd_addLeq()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddAddIteRecur()
+		<li> cuddAddCmplRecur()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> addVarToConst()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.15 2004/08/13 18:04:45 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void addVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITE(f,g,h).]
+
+  Description [Implements ITE(f,g,h). This procedure assumes that f is
+  a 0-1 ADD.  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addIteConstant Cudd_addApply]
+
+******************************************************************************/
+DdNode *
+Cudd_addIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddAddIteRecur(dd,f,g,h);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addIte */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITEconstant for ADDs.]
+
+  Description [Implements ITEconstant for ADDs.  f must be a 0-1 ADD.
+  Returns a pointer to the resulting ADD (which may or may not be
+  constant) or DD_NON_CONSTANT. No new nodes are created. This function
+  can be used, for instance, to check that g has a constant value
+  (specified by h) whenever f is 1. If the constant value is unknown,
+  then one should use Cudd_addEvalConst.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant]
+
+******************************************************************************/
+DdNode *
+Cudd_addIteConstant(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *one,*zero;
+    DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e;
+    unsigned int topf,topg,toph,v;
+
+    statLine(dd);
+    /* Trivial cases. */
+    if (f == (one = DD_ONE(dd))) {	/* ITE(1,G,H) = G */
+        return(g);
+    }
+    if (f == (zero = DD_ZERO(dd))) {	/* ITE(0,G,H) = H */
+        return(h);
+    }
+
+    /* From now on, f is known not to be a constant. */
+    addVarToConst(f,&g,&h,one,zero);
+
+    /* Check remaining one variable cases. */
+    if (g == h) { 			/* ITE(F,G,G) = G */
+        return(g);
+    }
+    if (cuddIsConstant(g) && cuddIsConstant(h)) {
+        return(DD_NON_CONSTANT);
+    }
+
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+    toph = cuddI(dd,h->index);
+    v = ddMin(topg,toph);
+
+    /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */
+    if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) {
+	return(DD_NON_CONSTANT);
+    }
+
+    /* Check cache. */
+    r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+	v = ddMin(topf,v);	/* v = top_var(F,G,H) */
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topg == v) {
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+    if (toph == v) {
+        Hv = cuddT(h); Hnv = cuddE(h);
+    } else {
+        Hv = Hnv = h;
+    }
+    
+    /* Recursive step. */
+    t = Cudd_addIteConstant(dd,Fv,Gv,Hv);
+    if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
+	cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+	return(DD_NON_CONSTANT);
+    }
+    e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv);
+    if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
+	cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+	return(DD_NON_CONSTANT);
+    }
+    cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t);
+    return(t);
+
+} /* end of Cudd_addIteConstant */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether ADD g is constant whenever ADD f is 1.]
+
+  Description [Checks whether ADD g is constant whenever ADD f is 1.  f
+  must be a 0-1 ADD.  Returns a pointer to the resulting ADD (which may
+  or may not be constant) or DD_NON_CONSTANT. If f is identically 0,
+  the check is assumed to be successful, and the background value is
+  returned. No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIteConstant Cudd_addLeq]
+
+******************************************************************************/
+DdNode *
+Cudd_addEvalConst(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *zero;
+    DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e;
+    unsigned int topf,topg;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    statLine(dd);
+    /* Terminal cases. */
+    if (f == DD_ONE(dd) || cuddIsConstant(g)) {
+        return(g);
+    }
+    if (f == (zero = DD_ZERO(dd))) {
+        return(dd->background);
+    }
+
+#ifdef DD_DEBUG
+    assert(!cuddIsConstant(f));
+#endif
+    /* From now on, f and g are known not to be constants. */
+
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+
+    /* Check cache. */
+    r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topg <= topf) {
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+    
+    /* Recursive step. */
+    if (Fv != zero) {
+	t = Cudd_addEvalConst(dd,Fv,Gv);
+	if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
+	    cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
+	    return(DD_NON_CONSTANT);
+	}
+	if (Fnv != zero) {
+	    e = Cudd_addEvalConst(dd,Fnv,Gnv);
+	    if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
+		cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
+		return(DD_NON_CONSTANT);
+	    }
+	}
+	cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t);
+	return(t);
+    } else { /* Fnv must be != zero */
+	e = Cudd_addEvalConst(dd,Fnv,Gnv);
+	cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e);
+	return(e);
+    }
+
+} /* end of Cudd_addEvalConst */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the complement of an ADD a la C language.]
+
+  Description [Computes the complement of an ADD a la C language: The
+  complement of 0 is 1 and the complement of everything else is 0.
+  Returns a pointer to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNegate]
+
+******************************************************************************/
+DdNode *
+Cudd_addCmpl(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddAddCmplRecur(dd,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addCmpl */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether f is less than or equal to g.]
+
+  Description [Returns 1 if f is less than or equal to g; 0 otherwise.
+  No new nodes are created. This procedure works for arbitrary ADDs.
+  For 0-1 ADDs Cudd_addEvalConst is more efficient.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq]
+
+******************************************************************************/
+int
+Cudd_addLeq(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *tmp, *fv, *fvn, *gv, *gvn;
+    unsigned int topf, topg, res;
+
+    /* Terminal cases. */
+    if (f == g) return(1);
+
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+	if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g));
+	if (f == DD_MINUS_INFINITY(dd)) return(1);
+	if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */
+    }
+    if (g == DD_PLUS_INFINITY(dd)) return(1);
+    if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_addLeq,f,g);
+    if (tmp != NULL) {
+	return(tmp == DD_ONE(dd));
+    }
+
+    /* Compute cofactors. One of f and g is not constant. */
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+    if (topf <= topg) {
+	fv = cuddT(f); fvn = cuddE(f);
+    } else {
+	fv = fvn = f;
+    }
+    if (topg <= topf) {
+	gv = cuddT(g); gvn = cuddE(g);
+    } else {
+	gv = gvn = g;
+    }
+
+    res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv);
+
+    /* Store result in cache and return. */
+    cuddCacheInsert2(dd,(DD_CTFP) Cudd_addLeq,f,g,
+		     Cudd_NotCond(DD_ONE(dd),res==0));
+    return(res);
+
+} /* end of Cudd_addLeq */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addIte(f,g,h).]
+
+  Description [Implements the recursive step of Cudd_addIte(f,g,h).
+  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIte]
+
+******************************************************************************/
+DdNode *
+cuddAddIteRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *one,*zero;
+    DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e;
+    unsigned int topf,topg,toph,v;
+    int index;
+
+    statLine(dd);
+    /* Trivial cases. */
+
+    /* One variable cases. */
+    if (f == (one = DD_ONE(dd))) {	/* ITE(1,G,H) = G */
+        return(g);
+    }
+    if (f == (zero = DD_ZERO(dd))) {	/* ITE(0,G,H) = H */
+        return(h);
+    }
+
+    /* From now on, f is known to not be a constant. */
+    addVarToConst(f,&g,&h,one,zero);
+
+    /* Check remaining one variable cases. */
+    if (g == h) {			/* ITE(F,G,G) = G */
+        return(g);
+    }
+
+    if (g == one) {			/* ITE(F,1,0) = F */
+        if (h == zero) return(f);
+    }
+
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+    toph = cuddI(dd,h->index);
+    v = ddMin(topg,toph);
+
+    /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */
+    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
+	r = cuddUniqueInter(dd,(int)f->index,g,h);
+	return(r);
+    }
+    if (topf < v && cuddT(f) == zero && cuddE(f) == one) {
+	r = cuddUniqueInter(dd,(int)f->index,h,g);
+	return(r);
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h);
+    if (r != NULL) {
+        return(r);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+	v = ddMin(topf,v);	/* v = top_var(F,G,H) */
+	index = f->index;
+        Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+        Fv = Fnv = f;
+    }
+    if (topg == v) {
+	index = g->index;
+        Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+        Gv = Gnv = g;
+    }
+    if (toph == v) {
+	index = h->index;
+        Hv = cuddT(h); Hnv = cuddE(h);
+    } else {
+        Hv = Hnv = h;
+    }
+    
+    /* Recursive step. */
+    t = cuddAddIteRecur(dd,Fv,Gv,Hv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(dd,t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+    if (r == NULL) {
+	Cudd_RecursiveDeref(dd,t);
+	Cudd_RecursiveDeref(dd,e);
+	return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r);
+
+    return(r);
+
+} /* end of cuddAddIteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addCmpl.]
+
+  Description [Performs the recursive step of Cudd_addCmpl. Returns a
+  pointer to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCmpl]
+
+******************************************************************************/
+DdNode *
+cuddAddCmplRecur(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *one,*zero;
+    DdNode *r,*Fv,*Fnv,*t,*e;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd); 
+
+    if (cuddIsConstant(f)) {
+        if (f == zero) {
+	    return(one);
+	} else {
+	    return(zero);
+	}
+    }
+    r = cuddCacheLookup1(dd,Cudd_addCmpl,f);
+    if (r != NULL) {
+	return(r);
+    }
+    Fv = cuddT(f);
+    Fnv = cuddE(f);
+    t = cuddAddCmplRecur(dd,Fv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = cuddAddCmplRecur(dd,Fnv);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(dd,t);
+	return(NULL);
+    }
+    cuddRef(e);
+    r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
+    if (r == NULL) {
+	Cudd_RecursiveDeref(dd, t);
+	Cudd_RecursiveDeref(dd, e);
+	return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+    cuddCacheInsert1(dd,Cudd_addCmpl,f,r);
+    return(r);
+
+} /* end of cuddAddCmplRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Replaces variables with constants if possible (part of
+  canonical form).]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+addVarToConst(
+  DdNode * f,
+  DdNode ** gp,
+  DdNode ** hp,
+  DdNode * one,
+  DdNode * zero)
+{
+    DdNode *g = *gp;
+    DdNode *h = *hp;
+
+    if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
+	*gp = one;
+    }
+
+    if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+	*hp = zero;
+    }
+
+} /* end of addVarToConst */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAddNeg.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAddNeg.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAddNeg.c	(revision 8)
@@ -0,0 +1,289 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddNeg.c]
+
+  PackageName [cudd]
+
+  Synopsis    [function to compute the negation of an ADD.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addNegate()
+		<li> Cudd_addRoundOff()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddAddNegateRecur()
+		<li> cuddAddRoundOffRecur()
+		</ul> ]
+
+  Author      [Fabio Somenzi, Balakrishna Kumthekar]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.11 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the additive inverse of an ADD.]
+
+  Description [Computes the additive inverse of an ADD. Returns a pointer
+  to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCmpl]
+
+******************************************************************************/
+DdNode *
+Cudd_addNegate(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+	res = cuddAddNegateRecur(dd,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addNegate */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rounds off the discriminants of an ADD.]
+
+  Description [Rounds off the discriminants of an ADD. The discriminants are
+  rounded off to N digits after the decimal. Returns a pointer to the result
+  ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addRoundOff(
+  DdManager * dd,
+  DdNode * f,
+  int  N)
+{
+    DdNode *res;
+    double trunc = pow(10.0,(double)N);
+
+    do {
+	res = cuddAddRoundOffRecur(dd,f,trunc);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addRoundOff */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addNegate.]
+
+  Description [Implements the recursive step of Cudd_addNegate.
+  Returns a pointer to the result.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddAddNegateRecur(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res,
+	    *fv, *fvn,
+	    *T, *E;
+
+    statLine(dd);
+    /* Check terminal cases. */
+    if (cuddIsConstant(f)) {
+	res = cuddUniqueConst(dd,-cuddV(f));
+	return(res);
+    }
+
+    /* Check cache */
+    res = cuddCacheLookup1(dd,Cudd_addNegate,f);
+    if (res != NULL) return(res);
+
+    /* Recursive Step */
+    fv = cuddT(f);
+    fvn = cuddE(f);
+    T = cuddAddNegateRecur(dd,fv);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddNegateRecur(dd,fvn);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd,T);
+	return(NULL);
+    }
+    cuddRef(E);
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	Cudd_RecursiveDeref(dd, E);
+	return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,Cudd_addNegate,f,res);
+
+    return(res);
+
+} /* end of cuddAddNegateRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addRoundOff.]
+
+  Description [Implements the recursive step of Cudd_addRoundOff.
+  Returns a pointer to the result.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddAddRoundOffRecur(
+  DdManager * dd,
+  DdNode * f,
+  double  trunc)
+{
+
+    DdNode *res, *fv, *fvn, *T, *E;
+    double n;
+    DD_CTFP1 cacheOp;
+  
+    statLine(dd);
+    if (cuddIsConstant(f)) {
+        n = ceil(cuddV(f)*trunc)/trunc;
+	res = cuddUniqueConst(dd,n);
+	return(res);
+    }
+    cacheOp = (DD_CTFP1) Cudd_addRoundOff;
+    res = cuddCacheLookup1(dd,cacheOp,f);
+    if (res != NULL) {
+        return(res);
+    }
+    /* Recursive Step */
+    fv = cuddT(f);
+    fvn = cuddE(f);
+    T = cuddAddRoundOffRecur(dd,fv,trunc);
+    if (T == NULL) {
+       return(NULL);
+    }
+    cuddRef(T);
+    E = cuddAddRoundOffRecur(dd,fvn,trunc);
+    if (E == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+	return(NULL);
+    }
+    cuddRef(E);
+    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
+    if (res == NULL) {
+        Cudd_RecursiveDeref(dd,T);
+	Cudd_RecursiveDeref(dd,E);
+	return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,cacheOp,f,res);
+    return(res);
+  
+} /* end of cuddAddRoundOffRecur */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAddWalsh.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAddWalsh.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAddWalsh.c	(revision 8)
@@ -0,0 +1,391 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAddWalsh.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions that generate Walsh matrices and residue
+  functions in ADD form.]
+
+  Description [External procedures included in this module:
+	    <ul>
+	    <li> Cudd_addWalsh()
+	    <li> Cudd_addResidue()
+	    </ul>
+	Static procedures included in this module:
+	    <ul>
+	    <li> addWalshInt()
+	    </ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAddWalsh.c,v 1.9 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addWalshInt (DdManager *dd, DdNode **x, DdNode **y, int n);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a Walsh matrix in ADD form.]
+
+  Description [Generates a Walsh matrix in ADD form. Returns a pointer
+  to the matrixi if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_addWalsh(
+  DdManager * dd,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = addWalshInt(dd, x, y, n);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addWalsh */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an ADD for the residue modulo m of an n-bit
+  number.]
+
+  Description [Builds an ADD for the residue modulo m of an n-bit
+  number. The modulus must be at least 2, and the number of bits at
+  least 1. Parameter options specifies whether the MSB should be on top
+  or the LSB; and whther the number whose residue is computed is in
+  two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT
+  specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB
+  specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's
+  complement residue. To request MSB on top and two's complement residue
+  simultaneously, one can OR the two macros:
+  CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC.
+  Cudd_addResidue returns a pointer to the resulting ADD if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addResidue(
+  DdManager * dd /* manager */,
+  int  n /* number of bits */,
+  int  m /* modulus */,
+  int  options /* options */,
+  int  top /* index of top variable */)
+{
+    int msbLsb;	/* MSB on top (1) or LSB on top (0) */
+    int tc;	/* two's complement (1) or unsigned (0) */
+    int i, j, k, t, residue, thisOne, previous, index;
+    DdNode **array[2], *var, *tmp, *res;
+
+    /* Sanity check. */
+    if (n < 1 && m < 2) return(NULL);
+
+    msbLsb = options & CUDD_RESIDUE_MSB;
+    tc = options & CUDD_RESIDUE_TC;
+
+    /* Allocate and initialize working arrays. */
+    array[0] = ALLOC(DdNode *,m);
+    if (array[0] == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    array[1] = ALLOC(DdNode *,m);
+    if (array[1] == NULL) {
+	FREE(array[0]);
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < m; i++) {
+	array[0][i] = array[1][i] = NULL;
+    }
+
+    /* Initialize residues. */
+    for (i = 0; i < m; i++) {
+	tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i);
+	if (tmp == NULL) {
+	    for (j = 0; j < i; j++) {
+		Cudd_RecursiveDeref(dd,array[1][j]);
+	    }
+	    FREE(array[0]);
+	    FREE(array[1]);
+	    return(NULL);
+	}
+	cuddRef(tmp);
+	array[1][i] = tmp;
+    }
+
+    /* Main iteration. */
+    residue = 1;	/* residue of 2**0 */
+    for (k = 0; k < n; k++) {
+	/* Choose current and previous arrays. */
+	thisOne = k & 1;
+	previous = thisOne ^ 1;
+	/* Build an ADD projection function. */
+	if (msbLsb) {
+	    index = top+n-k-1;
+	} else {
+	    index = top+k;
+	}
+	var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd));
+	if (var == NULL) {
+	    for (j = 0; j < m; j++) {
+		Cudd_RecursiveDeref(dd,array[previous][j]);
+	    }
+	    FREE(array[0]);
+	    FREE(array[1]);
+	    return(NULL);
+	}
+	cuddRef(var);
+	for (i = 0; i < m; i ++) {
+	    t = (i + residue) % m;
+	    tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]);
+	    if (tmp == NULL) {
+		for (j = 0; j < i; j++) {
+		    Cudd_RecursiveDeref(dd,array[thisOne][j]);
+		}
+		for (j = 0; j < m; j++) {
+		    Cudd_RecursiveDeref(dd,array[previous][j]);
+		}
+		FREE(array[0]);
+		FREE(array[1]);
+		return(NULL);
+	    }
+	    cuddRef(tmp);
+	    array[thisOne][i] = tmp;
+	}
+	/* One layer completed. Free the other array for the next iteration. */
+	for (i = 0; i < m; i++) {
+	    Cudd_RecursiveDeref(dd,array[previous][i]);
+	}
+	Cudd_RecursiveDeref(dd,var);
+	/* Update residue of 2**k. */
+	residue = (2 * residue) % m;
+	/* Adjust residue for MSB, if this is a two's complement number. */
+	if (tc && (k == n - 1)) {
+	    residue = (m - residue) % m;
+	}
+    }
+
+    /* We are only interested in the 0-residue node of the top layer. */
+    for (i = 1; i < m; i++) {
+	Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]);
+    }
+    res = array[(n - 1) & 1][0];
+
+    FREE(array[0]);
+    FREE(array[1]);
+
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addResidue */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addWalsh.]
+
+  Description [Generates a Walsh matrix in ADD form. Returns a pointer
+  to the matrixi if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+addWalshInt(
+  DdManager * dd,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *one, *minusone;
+    DdNode *t, *u, *t1, *u1, *v, *w;
+    int     i;
+
+    one = DD_ONE(dd);
+    if (n == 0) return(one);
+
+    /* Build bottom part of ADD outside loop */
+    minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1);
+    if (minusone == NULL) return(NULL);
+    cuddRef(minusone);
+    v = Cudd_addIte(dd, y[n-1], minusone, one);
+    if (v == NULL) {
+	Cudd_RecursiveDeref(dd, minusone);
+	return(NULL);
+    }
+    cuddRef(v);
+    u = Cudd_addIte(dd, x[n-1], v, one);
+    if (u == NULL) {
+	Cudd_RecursiveDeref(dd, minusone);
+	Cudd_RecursiveDeref(dd, v);
+	return(NULL);
+    }
+    cuddRef(u);
+    Cudd_RecursiveDeref(dd, v);
+    if (n>1) {
+	w = Cudd_addIte(dd, y[n-1], one, minusone);
+	if (w == NULL) {
+	    Cudd_RecursiveDeref(dd, minusone);
+	    Cudd_RecursiveDeref(dd, u);
+	    return(NULL);
+	}
+	cuddRef(w);
+	t = Cudd_addIte(dd, x[n-1], w, minusone);
+	if (t == NULL) {
+	    Cudd_RecursiveDeref(dd, minusone);
+	    Cudd_RecursiveDeref(dd, u);
+	    Cudd_RecursiveDeref(dd, w);
+	    return(NULL);
+	}
+	cuddRef(t);
+	Cudd_RecursiveDeref(dd, w);
+    }
+    cuddDeref(minusone); /* minusone is in the result; it won't die */
+
+    /* Loop to build the rest of the ADD */
+    for (i=n-2; i>=0; i--) {
+	t1 = t; u1 = u;
+	v = Cudd_addIte(dd, y[i], t1, u1);
+	if (v == NULL) {
+	    Cudd_RecursiveDeref(dd, u1);
+	    Cudd_RecursiveDeref(dd, t1);
+	    return(NULL);
+	}
+	cuddRef(v);
+	u = Cudd_addIte(dd, x[i], v, u1);
+	if (u == NULL) {
+	    Cudd_RecursiveDeref(dd, u1);
+	    Cudd_RecursiveDeref(dd, t1);
+	    Cudd_RecursiveDeref(dd, v);
+	    return(NULL);
+	}
+	cuddRef(u);
+	Cudd_RecursiveDeref(dd, v);
+	if (i>0) {
+	    w = Cudd_addIte(dd, y[i], u1, t1);
+	    if (u == NULL) {
+		Cudd_RecursiveDeref(dd, u1);
+		Cudd_RecursiveDeref(dd, t1);
+		Cudd_RecursiveDeref(dd, u);
+		return(NULL);
+	    }
+	    cuddRef(w);
+	    t = Cudd_addIte(dd, x[i], w, t1);
+	    if (u == NULL) {
+		Cudd_RecursiveDeref(dd, u1);
+		Cudd_RecursiveDeref(dd, t1);
+		Cudd_RecursiveDeref(dd, u);
+		Cudd_RecursiveDeref(dd, w);
+		return(NULL);
+	    }
+	    cuddRef(t);
+	    Cudd_RecursiveDeref(dd, w);
+	}
+	Cudd_RecursiveDeref(dd, u1);
+	Cudd_RecursiveDeref(dd, t1);
+    }
+
+    cuddDeref(u);
+    return(u);
+
+} /* end of addWalshInt */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAndAbs.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAndAbs.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAndAbs.c	(revision 8)
@@ -0,0 +1,373 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAndAbs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Combined AND and existential abstraction for BDDs]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_bddAndAbstract()
+		<li> Cudd_bddAndAbstractLimit()
+		</ul>
+	    Internal procedures included in this module:
+		<ul>
+		<li> cuddBddAndAbstractRecur()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAndAbs.c,v 1.19 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.
+  Cudd_bddAndAbstract implements the semiring matrix multiplication
+  algorithm for the boolean semiring.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAndAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    do {
+	manager->reordered = 0;
+	res = cuddBddAndAbstractRecur(manager, f, g, cube);
+    } while (manager->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddAndAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.  Returns NULL if too many nodes are required.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.
+  In particular, if the number of new nodes created exceeds
+  <code>limit</code>, this function returns NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAndAbstractLimit(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube,
+  unsigned int limit)
+{
+    DdNode *res;
+    unsigned int saveLimit = manager->maxLive;
+
+    manager->maxLive = (manager->keys - manager->dead) +
+      (manager->keysZ - manager->deadZ) + limit;
+    do {
+	manager->reordered = 0;
+	res = cuddBddAndAbstractRecur(manager, f, g, cube);
+    } while (manager->reordered == 1);
+    manager->maxLive = saveLimit;
+    return(res);
+
+} /* end of Cudd_bddAndAbstractLimit */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the AND of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.
+  Returns a pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddAndAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *zero, *r, *t, *e;
+    unsigned int topf, topg, topcube, top, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == one && g == one)	return(one);
+
+    if (cube == one) {
+	return(cuddBddAndRecur(manager, f, g));
+    }
+    if (f == one || f == g) {
+	return(cuddBddExistAbstractRecur(manager, g, cube));
+    }
+    if (g == one) {
+	return(cuddBddExistAbstractRecur(manager, f, cube));
+    }
+    /* At this point f, g, and cube are not constant. */
+
+    if (f > g) { /* Try to increase cache efficiency. */
+	DdNode *tmp = f;
+	f = g;
+	g = tmp;
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+    top = ddMin(topf, topg);
+    topcube = manager->perm[cube->index];
+
+    while (topcube < top) {
+	cube = cuddT(cube);
+	if (cube == one) {
+	    return(cuddBddAndRecur(manager, f, g));
+	}
+	topcube = manager->perm[cube->index];
+    }
+    /* Now, topcube >= top. */
+
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+	r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
+	if (r != NULL) {
+	    return(r);
+	}
+    }
+
+    if (topf == top) {
+	index = F->index;
+	ft = cuddT(F);
+	fe = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    ft = Cudd_Not(ft);
+	    fe = Cudd_Not(fe);
+	}
+    } else {
+	index = G->index;
+	ft = fe = f;
+    }
+
+    if (topg == top) {
+	gt = cuddT(G);
+	ge = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gt = Cudd_Not(gt);
+	    ge = Cudd_Not(ge);
+	}
+    } else {
+	gt = ge = g;
+    }
+
+    if (topcube == top) {	/* quantify */
+	DdNode *Cube = cuddT(cube);
+	t = cuddBddAndAbstractRecur(manager, ft, gt, Cube);
+	if (t == NULL) return(NULL);
+	/* Special case: 1 OR anything = 1. Hence, no need to compute
+	** the else branch if t is 1. Likewise t + t * anything == t.
+	** Notice that t == fe implies that fe does not depend on the
+	** variables in Cube. Likewise for t == ge.
+	*/
+	if (t == one || t == fe || t == ge) {
+	    if (F->ref != 1 || G->ref != 1)
+		cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
+				f, g, cube, t);
+	    return(t);
+	}
+	cuddRef(t);
+	/* Special case: t + !t * anything == t + anything. */
+	if (t == Cudd_Not(fe)) {
+	    e = cuddBddExistAbstractRecur(manager, ge, Cube);
+	} else if (t == Cudd_Not(ge)) {
+	    e = cuddBddExistAbstractRecur(manager, fe, Cube);
+	} else {
+	    e = cuddBddAndAbstractRecur(manager, fe, ge, Cube);
+	}
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(manager, t);
+	    return(NULL);
+	}
+	if (t == e) {
+	    r = t;
+	    cuddDeref(t);
+	} else {
+	    cuddRef(e);
+	    r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	    cuddRef(r);
+	    Cudd_DelayedDerefBdd(manager, t);
+	    Cudd_DelayedDerefBdd(manager, e);
+	    cuddDeref(r);
+	}
+    } else {
+	t = cuddBddAndAbstractRecur(manager, ft, gt, cube);
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddBddAndAbstractRecur(manager, fe, ge, cube);
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(manager, t);
+	    return(NULL);
+	}
+	if (t == e) {
+	    r = t;
+	    cuddDeref(t);
+	} else {
+	    cuddRef(e);
+	    if (Cudd_IsComplement(t)) {
+		r = cuddUniqueInter(manager, (int) index,
+				    Cudd_Not(t), Cudd_Not(e));
+		if (r == NULL) {
+		    Cudd_IterDerefBdd(manager, t);
+		    Cudd_IterDerefBdd(manager, e);
+		    return(NULL);
+		}
+		r = Cudd_Not(r);
+	    } else {
+		r = cuddUniqueInter(manager,(int)index,t,e);
+		if (r == NULL) {
+		    Cudd_IterDerefBdd(manager, t);
+		    Cudd_IterDerefBdd(manager, e);
+		    return(NULL);
+		}
+	    }
+	    cuddDeref(e);
+	    cuddDeref(t);
+	}
+    }
+
+    if (F->ref != 1 || G->ref != 1)
+	cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
+    return (r);
+
+} /* end of cuddBddAndAbstractRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddAnneal.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddAnneal.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddAnneal.c	(revision 8)
@@ -0,0 +1,814 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddAnneal.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Reordering of DDs based on simulated annealing]
+
+  Description [Internal procedures included in this file:
+		<ul>
+		<li> cuddAnnealing()
+		</ul>
+	       Static procedures included in this file:
+		<ul>
+		<li> stopping_criterion()
+		<li> random_generator()
+		<li> ddExchange()
+		<li> ddJumpingAux()
+		<li> ddJumpingUp()
+		<li> ddJumpingDown()
+		<li> siftBackwardProb()
+		<li> copyOrder()
+		<li> restoreOrder()
+		</ul>
+		]
+
+  SeeAlso     []
+
+  Author      [Jae-Young Jang, Jorgen Sivesind]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Annealing parameters */
+#define BETA 0.6 
+#define ALPHA 0.90
+#define EXC_PROB 0.4 
+#define JUMP_UP_PROB 0.36
+#define MAXGEN_RATIO 15.0
+#define STOP_TEMP 1.0
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.14 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+#ifdef DD_STATS
+extern	int	ddTotalNumberSwapping;
+extern	int	ddTotalNISwaps;
+static	int	tosses;
+static	int	acceptances;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int stopping_criterion (int c1, int c2, int c3, int c4, double temp);
+static double random_generator (void);
+static int ddExchange (DdManager *table, int x, int y, double temp);
+static int ddJumpingAux (DdManager *table, int x, int x_low, int x_high, double temp);
+static Move * ddJumpingUp (DdManager *table, int x, int x_low, int initial_size);
+static Move * ddJumpingDown (DdManager *table, int x, int x_high, int initial_size);
+static int siftBackwardProb (DdManager *table, Move *moves, int size, double temp);
+static void copyOrder (DdManager *table, int *array, int lower, int upper);
+static int restoreOrder (DdManager *table, int *array, int lower, int upper);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get new variable-order by simulated annealing algorithm.]
+
+  Description [Get x, y by random selection. Choose either
+  exchange or jump randomly. In case of jump, choose between jump_up
+  and jump_down randomly. Do exchange or jump and get optimal case.
+  Loop until there is no improvement or temperature reaches
+  minimum. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddAnnealing(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int         nvars;
+    int         size;
+    int         x,y;
+    int         result;
+    int		c1, c2, c3, c4;
+    int		BestCost;
+    int		*BestOrder;
+    double	NewTemp, temp;
+    double	rand1;
+    int         innerloop, maxGen;
+    int         ecount, ucount, dcount;
+   
+    nvars = upper - lower + 1;
+
+    result = cuddSifting(table,lower,upper);
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+#endif
+    if (result == 0) return(0);
+
+    size = table->keys - table->isolated;
+
+    /* Keep track of the best order. */
+    BestCost = size;
+    BestOrder = ALLOC(int,nvars);
+    if (BestOrder == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    copyOrder(table,BestOrder,lower,upper);
+
+    temp = BETA * size;
+    maxGen = (int) (MAXGEN_RATIO * nvars);
+
+    c1 = size + 10;
+    c2 = c1 + 10;
+    c3 = size;
+    c4 = c2 + 10;
+    ecount = ucount = dcount = 0;
+ 
+    while (!stopping_criterion(c1, c2, c3, c4, temp)) {
+#ifdef DD_STATS
+	(void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t",
+		       temp,size,maxGen);
+	tosses = acceptances = 0;
+#endif
+	for (innerloop = 0; innerloop < maxGen; innerloop++) {
+	    /* Choose x, y  randomly. */
+	    x = (int) Cudd_Random() % nvars;
+	    do {
+		y = (int) Cudd_Random() % nvars;
+	    } while (x == y);
+	    x += lower;
+	    y += lower;
+	    if (x > y) {
+		int tmp = x;
+		x = y;
+		y = tmp;
+	    }
+
+	    /* Choose move with roulette wheel. */
+	    rand1 = random_generator();
+	    if (rand1 < EXC_PROB) {
+		result = ddExchange(table,x,y,temp);       /* exchange */
+		ecount++;
+#if 0
+		(void) fprintf(table->out,
+			       "Exchange of %d and %d: size = %d\n",
+			       x,y,table->keys - table->isolated);
+#endif
+	    } else if (rand1 < EXC_PROB + JUMP_UP_PROB) {
+		result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */
+		ucount++;
+#if 0
+		(void) fprintf(table->out,
+			       "Jump up of %d to %d: size = %d\n",
+			       y,x,table->keys - table->isolated);
+#endif
+	    } else {
+		result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */
+		dcount++;
+#if 0
+		(void) fprintf(table->out,
+			       "Jump down of %d to %d: size = %d\n",
+			       x,y,table->keys - table->isolated);
+#endif
+	    }
+
+	    if (!result) {
+		FREE(BestOrder);
+		return(0);
+	    }
+
+	    size = table->keys - table->isolated;	/* keep current size */
+	    if (size < BestCost) {			/* update best order */
+		BestCost = size;
+		copyOrder(table,BestOrder,lower,upper);
+	    }
+	}
+	c1 = c2;
+	c2 = c3;
+	c3 = c4;
+	c4 = size;
+	NewTemp = ALPHA * temp;
+	if (NewTemp >= 1.0) {
+	    maxGen = (int)(log(NewTemp) / log(temp) * maxGen);
+	}
+	temp = NewTemp;	                /* control variable */
+#ifdef DD_STATS
+	(void) fprintf(table->out,"uphill = %d\taccepted = %d\n",
+		       tosses,acceptances);
+	fflush(table->out);
+#endif
+    }
+
+    result = restoreOrder(table,BestOrder,lower,upper);
+    FREE(BestOrder);
+    if (!result) return(0);
+#ifdef DD_STATS
+    fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount);
+    fprintf(table->out,"#:N_JUMPUP   %8d : total jumps up\n",ucount);
+    fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount);
+#endif
+    return(1);
+
+} /* end of cuddAnnealing */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Checks termination condition.]
+
+  Description [If temperature is STOP_TEMP or there is no improvement
+  then terminates. Returns 1 if the termination criterion is met; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+stopping_criterion(
+  int  c1,
+  int  c2,
+  int  c3,
+  int  c4,
+  double  temp)
+{
+    if (STOP_TEMP < temp) {
+	return(0);
+    } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) {
+	return(1);
+    } else {
+	return(0);
+    }
+
+} /* end of stopping_criterion */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Random number generator.]
+
+  Description [Returns a double precision value between 0.0 and 1.0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double
+random_generator(void)
+{
+    return((double)(Cudd_Random() / 2147483561.0));
+
+} /* end of random_generator */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function is for exchanging two variables, x and y.]
+
+  Description [This is the same funcion as ddSwapping except for
+  comparison expression.  Use probability function, exp(-size_change/temp).]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddExchange(
+  DdManager * table,
+  int  x,
+  int  y,
+  double  temp)
+{
+    Move       *move,*moves;
+    int        tmp;
+    int        x_ref,y_ref;
+    int        x_next,y_next;
+    int        size, result;
+    int        initial_size, limit_size;
+
+    x_ref = x;
+    y_ref = y;
+
+    x_next = cuddNextHigh(table,x);
+    y_next = cuddNextLow(table,y);
+    moves = NULL;
+    initial_size = limit_size = table->keys - table->isolated;
+
+    for (;;) {
+	if (x_next == y_next) {
+	    size = cuddSwapInPlace(table,x,x_next);
+	    if (size == 0) goto ddExchangeOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddExchangeOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    size = cuddSwapInPlace(table,y_next,y);
+	    if (size == 0) goto ddExchangeOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddExchangeOutOfMem;
+	    move->x = y_next;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    size = cuddSwapInPlace(table,x,x_next);
+	    if (size == 0) goto ddExchangeOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddExchangeOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    tmp = x;
+	    x = y;
+	    y = tmp;
+	} else if (x == y_next) {
+	    size = cuddSwapInPlace(table,x,x_next);
+	    if (size == 0) goto ddExchangeOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddExchangeOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    tmp = x;
+	    x = y;
+	    y = tmp;
+	} else {
+	    size = cuddSwapInPlace(table,x,x_next);
+	    if (size == 0) goto ddExchangeOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddExchangeOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    size = cuddSwapInPlace(table,y_next,y);
+	    if (size == 0) goto ddExchangeOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddExchangeOutOfMem;
+	    move->x = y_next;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    x = x_next;
+	    y = y_next;
+	}
+
+	x_next = cuddNextHigh(table,x);
+	y_next = cuddNextLow(table,y);
+	if (x_next > y_ref) break;
+
+	if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) {
+	    break;
+	} else if (size < limit_size) {
+	    limit_size = size;
+	}
+    }
+
+    if (y_next>=x_ref) {
+        size = cuddSwapInPlace(table,y_next,y);
+        if (size == 0) goto ddExchangeOutOfMem;
+        move = (Move *)cuddDynamicAllocNode(table);
+        if (move == NULL) goto ddExchangeOutOfMem;
+        move->x = y_next;
+        move->y = y;
+        move->size = size;
+        move->next = moves;
+        moves = move;
+    }
+
+    /* move backward and stop at best position or accept uphill move */
+    result = siftBackwardProb(table,moves,initial_size,temp);
+    if (!result) goto ddExchangeOutOfMem;
+
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(1);
+
+ddExchangeOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+    return(0);
+
+} /* end of ddExchange */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a variable to a specified position.]
+
+  Description [If x==x_low, it executes jumping_down. If x==x_high, it
+  executes jumping_up. This funcion is similar to ddSiftingAux. Returns
+  1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddJumpingAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high,
+  double  temp)
+{
+    Move       *move;
+    Move       *moves;        /* list of moves */
+    int        initial_size;
+    int        result;
+
+    initial_size = table->keys - table->isolated;
+
+#ifdef DD_DEBUG
+    assert(table->subtables[x].keys > 0);
+#endif
+
+    moves = NULL;
+
+    if (cuddNextLow(table,x) < x_low) {
+	if (cuddNextHigh(table,x) > x_high) return(1);
+	moves = ddJumpingDown(table,x,x_high,initial_size);
+	/* after that point x --> x_high unless early termination */
+	if (moves == NULL) goto ddJumpingAuxOutOfMem;
+	/* move backward and stop at best position or accept uphill move */
+	result = siftBackwardProb(table,moves,initial_size,temp);
+	if (!result) goto ddJumpingAuxOutOfMem;
+    } else if (cuddNextHigh(table,x) > x_high) {
+	moves = ddJumpingUp(table,x,x_low,initial_size);
+	/* after that point x --> x_low unless early termination */
+	if (moves == NULL) goto ddJumpingAuxOutOfMem;
+	/* move backward and stop at best position or accept uphill move */
+	result = siftBackwardProb(table,moves,initial_size,temp);
+	if (!result) goto ddJumpingAuxOutOfMem;
+    } else {
+	(void) fprintf(table->err,"Unexpected condition in ddJumping\n");
+	goto ddJumpingAuxOutOfMem;
+    }
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(1);
+
+ddJumpingAuxOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(0);
+
+} /* end of ddJumpingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function is for jumping up.]
+
+  Description [This is a simplified version of ddSiftingUp. It does not
+  use lower bounding. Returns the set of moves in case of success; NULL
+  if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+ddJumpingUp(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  initial_size)
+{
+    Move       *moves;
+    Move       *move;
+    int        y;
+    int        size;
+    int        limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddNextLow(table,x);
+    while (y >= x_low) {
+	size = cuddSwapInPlace(table,y,x);
+	if (size == 0) goto ddJumpingUpOutOfMem;
+	move = (Move *)cuddDynamicAllocNode(table);
+	if (move == NULL) goto ddJumpingUpOutOfMem;
+	move->x = y;
+	move->y = x;
+	move->size = size;
+	move->next = moves;
+	moves = move;
+	if ((double) size > table->maxGrowth * (double) limit_size) {
+	    break;
+	} else if (size < limit_size) {
+	    limit_size = size;
+	}
+	x = y;
+	y = cuddNextLow(table,x);
+    }
+    return(moves);
+
+ddJumpingUpOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(NULL);
+
+} /* end of ddJumpingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function is for jumping down.]
+
+  Description [This is a simplified version of ddSiftingDown. It does not
+  use lower bounding. Returns the set of moves in case of success; NULL
+  if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+ddJumpingDown(
+  DdManager * table,
+  int  x,
+  int  x_high,
+  int  initial_size)
+{
+    Move       *moves;
+    Move       *move;
+    int        y;
+    int        size;
+    int        limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddNextHigh(table,x);
+    while (y <= x_high) {
+	size = cuddSwapInPlace(table,x,y);
+	if (size == 0) goto ddJumpingDownOutOfMem;
+	move = (Move *)cuddDynamicAllocNode(table);
+	if (move == NULL) goto ddJumpingDownOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->size = size;
+	move->next = moves;
+	moves = move;
+	if ((double) size > table->maxGrowth * (double) limit_size) {
+	    break;
+	} else if (size < limit_size) {
+	    limit_size = size;
+	}
+	x = y;
+	y = cuddNextHigh(table,x);
+    }
+    return(moves);
+
+ddJumpingDownOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(NULL);
+
+} /* end of ddJumpingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the DD to the best position encountered during
+  sifting if there was improvement.]
+
+  Description [Otherwise, "tosses a coin" to decide whether to keep
+  the current configuration or return the DD to the original
+  one. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+siftBackwardProb(
+  DdManager * table,
+  Move * moves,
+  int  size,
+  double  temp)
+{
+    Move   *move;
+    int    res;
+    int    best_size = size;
+    double coin, threshold;
+
+    /* Look for best size during the last sifting */
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size < best_size) {
+	    best_size = move->size;
+	}
+    }
+    
+    /* If best_size equals size, the last sifting did not produce any
+    ** improvement. We now toss a coin to decide whether to retain
+    ** this change or not.
+    */
+    if (best_size == size) {
+	coin = random_generator();
+#ifdef DD_STATS
+	tosses++;
+#endif
+	threshold = exp(-((double)(table->keys - table->isolated - size))/temp);
+	if (coin < threshold) {
+#ifdef DD_STATS
+	    acceptances++;
+#endif
+	    return(1);
+	}
+    }
+
+    /* Either there was improvement, or we have decided not to
+    ** accept the uphill move. Go to best position.
+    */
+    res = table->keys - table->isolated;
+    for (move = moves; move != NULL; move = move->next) {
+	if (res == best_size) return(1);
+	res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+	if (!res) return(0);
+    }
+
+    return(1);
+
+} /* end of sift_backward_prob */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copies the current variable order to array.]
+
+  Description [Copies the current variable order to array.
+  At the same time inverts the permutation.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+copyOrder(
+  DdManager * table,
+  int * array,
+  int  lower,
+  int  upper)
+{
+    int i;
+    int nvars;
+
+    nvars = upper - lower + 1;
+    for (i = 0; i < nvars; i++) {
+	array[i] = table->invperm[i+lower];
+    }
+
+} /* end of copyOrder */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Restores the variable order in array by a series of sifts up.]
+
+  Description [Restores the variable order in array by a series of sifts up.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+restoreOrder(
+  DdManager * table,
+  int * array,
+  int  lower,
+  int  upper)
+{
+    int i, x, y, size;
+    int nvars = upper - lower + 1;
+
+    for (i = 0; i < nvars; i++) {
+	x = table->perm[array[i]];
+#ifdef DD_DEBUG
+    assert(x >= lower && x <= upper);
+#endif
+	y = cuddNextLow(table,x);
+	while (y >= i + lower) {
+	    size = cuddSwapInPlace(table,y,x);
+	    if (size == 0) return(0);
+	    x = y;
+	    y = cuddNextLow(table,x);
+	}
+    }
+
+    return(1);
+
+} /* end of restoreOrder */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddApa.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddApa.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddApa.c	(revision 8)
@@ -0,0 +1,964 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddApa.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Arbitrary precision arithmetic functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> 
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> ()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddApa.c,v 1.16 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+static	DdNode	*background, *zero;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdApaNumber cuddApaCountMintermAux (DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st_table * table);
+static enum st_retval cuddApaStCountfree (char * key, char * value, char * arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the number of digits for an arbitrary precision
+  integer.]
+
+  Description [Finds the number of digits for an arbitrary precision
+  integer given the maximum number of binary digits.  The number of
+  binary digits should be positive. Returns the number of digits if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaNumberOfDigits(
+  int  binaryDigits)
+{
+    int digits;
+
+    digits = binaryDigits / DD_APA_BITS;
+    if ((digits * DD_APA_BITS) != binaryDigits)
+	digits++;
+    return(digits);
+
+} /* end of Cudd_ApaNumberOfDigits */
+	   
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates memory for an arbitrary precision integer.]
+
+  Description [Allocates memory for an arbitrary precision
+  integer. Returns a pointer to the allocated memory if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaNumber
+Cudd_NewApaNumber(
+  int  digits)
+{
+    return(ALLOC(DdApaDigit, digits));
+
+} /* end of Cudd_NewApaNumber */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a copy of an arbitrary precision integer.]
+
+  Description [Makes a copy of an arbitrary precision integer.]
+
+  SideEffects [Changes parameter <code>dest</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaCopy(
+  int  digits,
+  DdApaNumber  source,
+  DdApaNumber  dest)
+{
+    int i;
+
+    for (i = 0; i < digits; i++) {
+	dest[i] = source[i];
+    }
+
+} /* end of Cudd_ApaCopy */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision integers.]
+
+  Description [Adds two arbitrary precision integers.  Returns the
+  carry out of the most significant digit.]
+
+  SideEffects [The result of the sum is stored in parameter <code>sum</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaDigit
+Cudd_ApaAdd(
+  int  digits,
+  DdApaNumber  a,
+  DdApaNumber  b,
+  DdApaNumber  sum)
+{
+    int i;
+    DdApaDoubleDigit partial = 0;
+
+    for (i = digits - 1; i >= 0; i--) {
+	partial = a[i] + b[i] + DD_MSDIGIT(partial);
+	sum[i] = (DdApaDigit) DD_LSDIGIT(partial);
+    }
+    return((DdApaDigit) DD_MSDIGIT(partial));
+
+} /* end of Cudd_ApaAdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision integers.]
+
+  Description [Subtracts two arbitrary precision integers.  Returns the
+  borrow out of the most significant digit.]
+
+  SideEffects [The result of the subtraction is stored in parameter
+  <code>diff</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaDigit
+Cudd_ApaSubtract(
+  int  digits,
+  DdApaNumber  a,
+  DdApaNumber  b,
+  DdApaNumber  diff)
+{
+    int i;
+    DdApaDoubleDigit partial = DD_APA_BASE;
+
+    for (i = digits - 1; i >= 0; i--) {
+	partial = a[i] - b[i] + DD_MSDIGIT(partial) + DD_APA_MASK;
+	diff[i] = (DdApaDigit) DD_LSDIGIT(partial);
+    }
+    return((DdApaDigit) DD_MSDIGIT(partial) - 1);
+
+} /* end of Cudd_ApaSubtract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides an arbitrary precision integer by a digit.]
+
+  Description [Divides an arbitrary precision integer by a digit.]
+
+  SideEffects [The quotient is returned in parameter <code>quotient</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdApaDigit
+Cudd_ApaShortDivision(
+  int  digits,
+  DdApaNumber  dividend,
+  DdApaDigit  divisor,
+  DdApaNumber  quotient)
+{
+    int i;
+    DdApaDigit remainder;
+    DdApaDoubleDigit partial;
+
+    remainder = 0;
+    for (i = 0; i < digits; i++) {
+	partial = remainder * DD_APA_BASE + dividend[i];
+	quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor);
+	remainder = (DdApaDigit) (partial % divisor);
+    }
+
+    return(remainder);
+
+} /* end of Cudd_ApaShortDivision */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides an arbitrary precision integer by an integer.]
+
+  Description [Divides an arbitrary precision integer by a 32-bit
+  unsigned integer. Returns the remainder of the division. This
+  procedure relies on the assumption that the number of bits of a
+  DdApaDigit plus the number of bits of an unsigned int is less the
+  number of bits of the mantissa of a double. This guarantees that the
+  product of a DdApaDigit and an unsigned int can be represented
+  without loss of precision by a double. On machines where this
+  assumption is not satisfied, this procedure will malfunction.]
+
+  SideEffects [The quotient is returned in parameter <code>quotient</code>.]
+
+  SeeAlso     [Cudd_ApaShortDivision]
+
+******************************************************************************/
+unsigned int
+Cudd_ApaIntDivision(
+  int  digits,
+  DdApaNumber dividend,
+  unsigned int divisor,
+  DdApaNumber quotient)
+{
+    int i;
+    double partial;
+    unsigned int remainder = 0;
+    double ddiv = (double) divisor;
+
+    for (i = 0; i < digits; i++) {
+	partial = (double) remainder * DD_APA_BASE + dividend[i];
+	quotient[i] = (DdApaDigit) (partial / ddiv);
+	remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv));
+    }
+
+    return(remainder);
+
+} /* end of Cudd_ApaIntDivision */
+
+
+/**Function********************************************************************
+
+  Synopsis [Shifts right an arbitrary precision integer by one binary
+  place.]
+
+  Description [Shifts right an arbitrary precision integer by one
+  binary place. The most significant binary digit of the result is
+  taken from parameter <code>in</code>.]
+
+  SideEffects [The result is returned in parameter <code>b</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaShiftRight(
+  int  digits,
+  DdApaDigit  in,
+  DdApaNumber  a,
+  DdApaNumber  b)
+{
+    int i;
+
+    for (i = digits - 1; i > 0; i--) {
+	b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1));
+    }
+    b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1));
+
+} /* end of Cudd_ApaShiftRight */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets an arbitrary precision integer to a one-digit literal.]
+
+  Description [Sets an arbitrary precision integer to a one-digit literal.]
+
+  SideEffects [The result is returned in parameter <code>number</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaSetToLiteral(
+  int  digits,
+  DdApaNumber  number,
+  DdApaDigit  literal)
+{
+    int i;
+
+    for (i = 0; i < digits - 1; i++)
+	number[i] = 0;
+    number[digits - 1] = literal;
+
+} /* end of Cudd_ApaSetToLiteral */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets an arbitrary precision integer to a power of two.]
+
+  Description [Sets an arbitrary precision integer to a power of
+  two. If the power of two is too large to be represented, the number
+  is set to 0.]
+
+  SideEffects [The result is returned in parameter <code>number</code>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_ApaPowerOfTwo(
+  int  digits,
+  DdApaNumber  number,
+  int  power)
+{
+    int i;
+    int index;
+
+    for (i = 0; i < digits; i++)
+	number[i] = 0;
+    i = digits - 1 - power / DD_APA_BITS;
+    if (i < 0) return;
+    index = power & (DD_APA_BITS - 1);
+    number[i] = 1 << index;
+
+} /* end of Cudd_ApaPowerOfTwo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two arbitrary precision integers.]
+
+  Description [Compares two arbitrary precision integers. Returns 1 if
+  the first number is larger; 0 if they are equal; -1 if the second
+  number is larger.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaCompare(
+  int digitsFirst,
+  DdApaNumber  first,
+  int digitsSecond,
+  DdApaNumber  second)
+{
+    int i;
+    int firstNZ, secondNZ;
+
+    /* Find first non-zero in both numbers. */
+    for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++)
+	if (first[firstNZ] != 0) break;
+    for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++)
+	if (second[secondNZ] != 0) break;
+    if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1);
+    else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1);
+    for (i = 0; i < digitsFirst - firstNZ; i++) {
+	if (first[firstNZ + i] > second[secondNZ + i]) return(1);
+	else if (first[firstNZ + i] < second[secondNZ + i]) return(-1);
+    }
+    return(0);
+
+} /* end of Cudd_ApaCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares the ratios of two arbitrary precision integers to two
+  unsigned ints.]
+
+  Description [Compares the ratios of two arbitrary precision integers
+  to two unsigned ints. Returns 1 if the first number is larger; 0 if
+  they are equal; -1 if the second number is larger.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaCompareRatios(
+  int digitsFirst,
+  DdApaNumber firstNum,
+  unsigned int firstDen,
+  int digitsSecond,
+  DdApaNumber secondNum,
+  unsigned int secondDen)
+{
+    int result;
+    DdApaNumber first, second;
+    unsigned int firstRem, secondRem;
+
+    first = Cudd_NewApaNumber(digitsFirst);
+    firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first);
+    second = Cudd_NewApaNumber(digitsSecond);
+    secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second);
+    result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second);
+    if (result == 0) {
+	if ((double)firstRem/firstDen > (double)secondRem/secondDen)
+	    return(1);
+	else if ((double)firstRem/firstDen < (double)secondRem/secondDen)
+	    return(-1);
+    }
+    return(result);
+
+} /* end of Cudd_ApaCompareRatios */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints an arbitrary precision integer in hexadecimal format.]
+
+  Description [Prints an arbitrary precision integer in hexadecimal format.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential]
+
+******************************************************************************/
+int
+Cudd_ApaPrintHex(
+  FILE * fp,
+  int  digits,
+  DdApaNumber  number)
+{
+    int i, result;
+
+    for (i = 0; i < digits; i++) {
+	result = fprintf(fp,DD_APA_HEXPRINT,number[i]);
+	if (result == EOF)
+	    return(0);
+    }
+    return(1);
+
+} /* end of Cudd_ApaPrintHex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints an arbitrary precision integer in decimal format.]
+
+  Description [Prints an arbitrary precision integer in decimal format.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintHex Cudd_ApaPrintExponential]
+
+******************************************************************************/
+int
+Cudd_ApaPrintDecimal(
+  FILE * fp,
+  int  digits,
+  DdApaNumber  number)
+{
+    int i, result;
+    DdApaDigit remainder;
+    DdApaNumber work;
+    unsigned char *decimal;
+    int leadingzero;
+    int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
+    
+    work = Cudd_NewApaNumber(digits);
+    if (work == NULL)
+	return(0);
+    decimal = ALLOC(unsigned char, decimalDigits);
+    if (decimal == NULL) {
+	FREE(work);
+	return(0);
+    }
+    Cudd_ApaCopy(digits,number,work);
+    for (i = decimalDigits - 1; i >= 0; i--) {
+	remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
+	decimal[i] = remainder;
+    }
+    FREE(work);
+
+    leadingzero = 1;
+    for (i = 0; i < decimalDigits; i++) {
+	leadingzero = leadingzero && (decimal[i] == 0);
+	if ((!leadingzero) || (i == (decimalDigits - 1))) {
+	    result = fprintf(fp,"%1d",decimal[i]);
+	    if (result == EOF) {
+		FREE(decimal);
+		return(0);
+	    }
+	}
+    }
+    FREE(decimal);
+    return(1);
+
+} /* end of Cudd_ApaPrintDecimal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints an arbitrary precision integer in exponential format.]
+
+  Description [Prints an arbitrary precision integer in exponential format.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintHex Cudd_ApaPrintDecimal]
+
+******************************************************************************/
+int
+Cudd_ApaPrintExponential(
+  FILE * fp,
+  int  digits,
+  DdApaNumber  number,
+  int precision)
+{
+    int i, first, last, result;
+    DdApaDigit remainder;
+    DdApaNumber work;
+    unsigned char *decimal;
+    int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
+    
+    work = Cudd_NewApaNumber(digits);
+    if (work == NULL)
+	return(0);
+    decimal = ALLOC(unsigned char, decimalDigits);
+    if (decimal == NULL) {
+	FREE(work);
+	return(0);
+    }
+    Cudd_ApaCopy(digits,number,work);
+    first = decimalDigits - 1;
+    for (i = decimalDigits - 1; i >= 0; i--) {
+	remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
+	decimal[i] = remainder;
+	if (remainder != 0) first = i; /* keep track of MS non-zero */
+    }
+    FREE(work);
+    last = ddMin(first + precision, decimalDigits);
+
+    for (i = first; i < last; i++) {
+	result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]);
+	if (result == EOF) {
+	    FREE(decimal);
+	    return(0);
+	}
+    }
+    FREE(decimal);
+    result = fprintf(fp,"e+%d",decimalDigits - first - 1);
+    if (result == EOF) {
+	return(0);
+    }
+    return(1);
+
+} /* end of Cudd_ApaPrintExponential */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a DD.]
+
+  Description [Counts the number of minterms of a DD. The function is
+  assumed to depend on nvars variables. The minterm count is
+  represented as an arbitrary precision unsigned integer, to allow for
+  any number of variables CUDD supports.  Returns a pointer to the
+  array representing the number of minterms of the function rooted at
+  node if successful; NULL otherwise.]
+
+  SideEffects [The number of digits of the result is returned in
+  parameter <code>digits</code>.]
+
+  SeeAlso     [Cudd_CountMinterm]
+
+******************************************************************************/
+DdApaNumber
+Cudd_ApaCountMinterm(
+  DdManager * manager,
+  DdNode * node,
+  int  nvars,
+  int * digits)
+{
+    DdApaNumber	max, min;
+    st_table	*table;
+    DdApaNumber	i,count;	
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+
+    *digits = Cudd_ApaNumberOfDigits(nvars+1);
+    max = Cudd_NewApaNumber(*digits);
+    if (max == NULL) {
+	return(NULL);
+    }
+    Cudd_ApaPowerOfTwo(*digits,max,nvars);
+    min = Cudd_NewApaNumber(*digits);
+    if (min == NULL) {
+	FREE(max);
+	return(NULL);
+    }
+    Cudd_ApaSetToLiteral(*digits,min,0);
+    table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (table == NULL) {
+	FREE(max);
+	FREE(min);
+	return(NULL);
+    }
+    i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table);
+    if (i == NULL) {
+	FREE(max);
+	FREE(min);
+	st_foreach(table, cuddApaStCountfree, NULL);
+	st_free_table(table);
+	return(NULL);
+    }
+    count = Cudd_NewApaNumber(*digits);
+    if (count == NULL) {
+	FREE(max);
+	FREE(min);
+	st_foreach(table, cuddApaStCountfree, NULL);
+	st_free_table(table);
+	if (Cudd_Regular(node)->ref == 1) FREE(i);
+	return(NULL);
+    }
+    if (Cudd_IsComplement(node)) {
+	(void) Cudd_ApaSubtract(*digits,max,i,count);
+    } else {
+	Cudd_ApaCopy(*digits,i,count);
+    }
+    FREE(max);
+    FREE(min);
+    st_foreach(table, cuddApaStCountfree, NULL);
+    st_free_table(table);
+    if (Cudd_Regular(node)->ref == 1) FREE(i);
+    return(count);
+
+} /* end of Cudd_ApaCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the number of minterms of a BDD or ADD using
+  arbitrary precision arithmetic.]
+
+  Description [Prints the number of minterms of a BDD or ADD using
+  arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintMintermExp]
+
+******************************************************************************/
+int
+Cudd_ApaPrintMinterm(
+  FILE * fp,
+  DdManager * dd,
+  DdNode * node,
+  int  nvars)
+{
+    int digits;
+    int result;
+    DdApaNumber count;
+
+    count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
+    if (count == NULL)
+	return(0);
+    result = Cudd_ApaPrintDecimal(fp,digits,count);
+    FREE(count);
+    if (fprintf(fp,"\n") == EOF) {
+	return(0);
+    }
+    return(result);
+
+} /* end of Cudd_ApaPrintMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the number of minterms of a BDD or ADD in exponential
+  format using arbitrary precision arithmetic.]
+
+  Description [Prints the number of minterms of a BDD or ADD in
+  exponential format using arbitrary precision arithmetic. Parameter
+  precision controls the number of signficant digits printed. Returns
+  1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ApaPrintMinterm]
+
+******************************************************************************/
+int
+Cudd_ApaPrintMintermExp(
+  FILE * fp,
+  DdManager * dd,
+  DdNode * node,
+  int  nvars,
+  int precision)
+{
+    int digits;
+    int result;
+    DdApaNumber count;
+
+    count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
+    if (count == NULL)
+	return(0);
+    result = Cudd_ApaPrintExponential(fp,digits,count,precision);
+    FREE(count);
+    if (fprintf(fp,"\n") == EOF) {
+	return(0);
+    }
+    return(result);
+
+} /* end of Cudd_ApaPrintMintermExp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the density of a BDD or ADD using
+  arbitrary precision arithmetic.]
+
+  Description [Prints the density of a BDD or ADD using
+  arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ApaPrintDensity(
+  FILE * fp,
+  DdManager * dd,
+  DdNode * node,
+  int  nvars)
+{
+    int digits;
+    int result;
+    DdApaNumber count,density;
+    unsigned int size, remainder, fractional;
+
+    count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
+    if (count == NULL)
+	return(0);
+    size = Cudd_DagSize(node);
+    density = Cudd_NewApaNumber(digits);
+    remainder = Cudd_ApaIntDivision(digits,count,size,density);
+    result = Cudd_ApaPrintDecimal(fp,digits,density);
+    FREE(count);
+    FREE(density);
+    fractional = (unsigned int)((double)remainder / size * 1000000);
+    if (fprintf(fp,".%u\n", fractional) == EOF) {
+	return(0);
+    }
+    return(result);
+
+} /* end of Cudd_ApaPrintDensity */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_ApaCountMinterm.]
+
+  Description [Performs the recursive step of Cudd_ApaCountMinterm.
+  It is based on the following identity. Let |f| be the
+  number of minterms of f. Then:
+  <xmp>
+    |f| = (|f0|+|f1|)/2
+  </xmp>
+  where f0 and f1 are the two cofactors of f.
+  Uses the identity <code>|f'| = max - |f|</code>.
+  The procedure expects the argument "node" to be a regular pointer, and
+  guarantees this condition is met in the recursive calls.
+  For efficiency, the result of a call is cached only if the node has
+  a reference count greater than 1.
+  Returns the number of minterms of the function rooted at node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdApaNumber
+cuddApaCountMintermAux(
+  DdNode * node,
+  int  digits,
+  DdApaNumber  max,
+  DdApaNumber  min,
+  st_table * table)
+{
+    DdNode      *Nt, *Ne;
+    DdApaNumber	mint, mint1, mint2;
+    DdApaDigit	carryout;
+
+    if (cuddIsConstant(node)) {
+	if (node == background || node == zero) {
+	    return(min);
+	} else {
+	    return(max);
+	}
+    }
+    if (node->ref > 1 && st_lookup(table, node, &mint)) {
+	return(mint);
+    }
+
+    Nt = cuddT(node); Ne = cuddE(node);
+
+    mint1 = cuddApaCountMintermAux(Nt,  digits, max, min, table);
+    if (mint1 == NULL) return(NULL);
+    mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table);
+    if (mint2 == NULL) {
+	if (Nt->ref == 1) FREE(mint1);
+	return(NULL);
+    }
+    mint = Cudd_NewApaNumber(digits);
+    if (mint == NULL) {
+	if (Nt->ref == 1) FREE(mint1);
+	if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
+	return(NULL);
+    }
+    if (Cudd_IsComplement(Ne)) {
+	(void) Cudd_ApaSubtract(digits,max,mint2,mint);
+	carryout = Cudd_ApaAdd(digits,mint1,mint,mint);
+    } else {
+	carryout = Cudd_ApaAdd(digits,mint1,mint2,mint);
+    }
+    Cudd_ApaShiftRight(digits,carryout,mint,mint);
+    /* If the refernce count of a child is 1, its minterm count
+    ** hasn't been stored in table.  Therefore, it must be explicitly
+    ** freed here. */
+    if (Nt->ref == 1) FREE(mint1);
+    if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
+    
+    if (node->ref > 1) {
+	if (st_insert(table, (char *)node, (char *)mint) == ST_OUT_OF_MEM) {
+	    FREE(mint);
+	    return(NULL);
+	}
+    }
+    return(mint);
+
+} /* end of cuddApaCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory used to store the minterm counts recorded
+  in the visited table.]
+
+  Description [Frees the memory used to store the minterm counts
+  recorded in the visited table. Returns ST_CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st_retval
+cuddApaStCountfree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    DdApaNumber	d;
+
+    d = (DdApaNumber) value;
+    FREE(d);
+    return(ST_CONTINUE);
+
+} /* end of cuddApaStCountfree */
+
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddApprox.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddApprox.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddApprox.c	(revision 8)
@@ -0,0 +1,2215 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddApprox.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures to approximate a given BDD.]
+
+  Description [External procedures provided by this module:
+                <ul>
+		<li> Cudd_UnderApprox()
+		<li> Cudd_OverApprox()
+		<li> Cudd_RemapUnderApprox()
+		<li> Cudd_RemapOverApprox()
+		<li> Cudd_BiasedUnderApprox()
+		<li> Cudd_BiasedOverApprox()
+		</ul>
+	       Internal procedures included in this module:
+		<ul>
+		<li> cuddUnderApprox()
+		<li> cuddRemapUnderApprox()
+		<li> cuddBiasedUnderApprox()
+		</ul>
+	       Static procedures included in this module:
+		<ul>
+		<li> gatherInfoAux()
+		<li> gatherInfo()
+		<li> computeSavings()
+		<li> UAmarkNodes()
+		<li> UAbuildSubset()
+		<li> updateRefs()
+		<li> RAmarkNodes()
+		<li> BAmarkNodes()
+		<li> RAbuildSubset()
+		</ul>
+		]
+
+  SeeAlso     [cuddSubsetHB.c cuddSubsetSP.c cuddGenCof.c]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#ifdef __STDC__
+#include <float.h>
+#else
+#define DBL_MAX_EXP 1024
+#endif
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define NOTHING		0
+#define REPLACE_T	1
+#define REPLACE_E	2
+#define REPLACE_N	3
+#define REPLACE_TT	4
+#define REPLACE_TE	5
+
+#define DONT_CARE	0
+#define CARE		1
+#define TOTAL_CARE	2
+#define CARE_ERROR	3
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/* Data structure to store the information on each node. It keeps the
+** number of minterms of the function rooted at this node in terms of
+** the number of variables specified by the user; the number of
+** minterms of the complement; the impact of the number of minterms of
+** this function on the number of minterms of the root function; the
+** reference count of the node from within the root function; the
+** reference count of the node from an internal node; and the flag
+** that says whether the node should be replaced and how. */
+typedef struct NodeData {
+    double mintermsP;		/* minterms for the regular node */
+    double mintermsN;		/* minterms for the complemented node */
+    int functionRef;		/* references from within this function */
+    char care;			/* node intersects care set */
+    char replace;		/* replacement decision */
+    short int parity;		/* 1: even; 2: odd; 3: both */
+    DdNode *resultP;		/* result for even parity */
+    DdNode *resultN;		/* result for odd parity */
+} NodeData;
+
+typedef struct ApproxInfo {
+    DdNode *one;		/* one constant */
+    DdNode *zero;		/* BDD zero constant */
+    NodeData *page;		/* per-node information */
+    st_table *table;		/* hash table to access the per-node info */
+    int index;			/* index of the current node */
+    double max;			/* max number of minterms */
+    int size;			/* how many nodes are left */
+    double minterms;		/* how many minterms are left */
+} ApproxInfo;
+
+/* Item of the queue used in the levelized traversal of the BDD. */
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+typedef struct GlobalQueueItem {
+    struct GlobalQueueItem *next;
+    struct GlobalQueueItem *cnext;
+    DdNode *node;
+    double impactP;
+    double impactN;
+} GlobalQueueItem;
+ 
+typedef struct LocalQueueItem {
+    struct LocalQueueItem *next;
+    struct LocalQueueItem *cnext;
+    DdNode *node;
+    int localRef;
+} LocalQueueItem;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+    
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.25 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void updateParity (DdNode *node, ApproxInfo *info, int newparity);
+static NodeData * gatherInfoAux (DdNode *node, ApproxInfo *info, int parity);
+static ApproxInfo * gatherInfo (DdManager *dd, DdNode *node, int numVars, int parity);
+static int computeSavings (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue);
+static int updateRefs (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue);
+static int UAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality);
+static DdNode * UAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info);
+static int RAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality);
+static int BAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0);
+static DdNode * RAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info);
+static int BAapplyBias (DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Extracts a dense subset from a BDD with Shiple's
+  underapproximation method.]
+
+  Description [Extracts a dense subset from a BDD. This procedure uses
+  a variant of Tom Shiple's underapproximation method. The main
+  difference from the original method is that density is used as cost
+  function.  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation.  The optimal number should be as close as possible to
+  the size of the support of f.  However, it is safe to pass the value
+  returned by Cudd_ReadSize for numVars when the number of variables
+  is under 1023.  If numVars is larger than 1023, it will cause
+  overflow. If a 0 parameter is passed then the procedure will compute
+  a value which will avoid overflow but will cause underflow with 2046
+  variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_UnderApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset;
+
+    do {
+	dd->reordered = 0;
+	subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality);
+    } while (dd->reordered == 1);
+
+    return(subset);
+
+} /* end of Cudd_UnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with Shiple's
+  underapproximation method.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the underapproximation procedure except for the fact that it
+  works on the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_OverApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);    
+    do {
+	dd->reordered = 0;
+	subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality);
+    } while (dd->reordered == 1);
+    
+    return(Cudd_NotCond(subset, (subset != NULL)));
+    
+} /* end of Cudd_OverApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis [Extracts a dense subset from a BDD with the remapping
+  underapproximation method.]
+
+  Description [Extracts a dense subset from a BDD. This procedure uses
+  a remapping technique and density as the cost function.
+  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation.  The optimal number should be as close as possible to
+  the size of the support of f.  However, it is safe to pass the value
+  returned by Cudd_ReadSize for numVars when the number of variables
+  is under 1023.  If numVars is larger than 1023, it will cause
+  overflow. If a 0 parameter is passed then the procedure will compute
+  a value which will avoid overflow but will cause underflow with 2046
+  variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_RemapUnderApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset;
+
+    do {
+	dd->reordered = 0;
+	subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality);
+    } while (dd->reordered == 1);
+
+    return(subset);
+
+} /* end of Cudd_RemapUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the remapping
+  underapproximation method.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the underapproximation procedure except for the fact that it
+  works on the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_RemapOverApprox(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* when to stop approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);    
+    do {
+	dd->reordered = 0;
+	subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality);
+    } while (dd->reordered == 1);
+    
+    return(Cudd_NotCond(subset, (subset != NULL)));
+    
+} /* end of Cudd_RemapOverApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis [Extracts a dense subset from a BDD with the biased
+  underapproximation method.]
+
+  Description [Extracts a dense subset from a BDD. This procedure uses
+  a biased remapping technique and density as the cost function. The bias
+  is a function. This procedure tries to approximate where the bias is 0
+  and preserve the given function where the bias is 1.
+  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation.  The optimal number should be as close as possible to
+  the size of the support of f.  However, it is safe to pass the value
+  returned by Cudd_ReadSize for numVars when the number of variables
+  is under 1023.  If numVars is larger than 1023, it will cause
+  overflow. If a 0 parameter is passed then the procedure will compute
+  a value which will avoid overflow but will cause underflow with 2046
+  variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox
+  Cudd_RemapUnderApprox Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_BiasedUnderApprox(
+  DdManager *dd /* manager */,
+  DdNode *f /* function to be subset */,
+  DdNode *b /* bias function */,
+  int numVars /* number of variables in the support of f */,
+  int threshold /* when to stop approximation */,
+  double quality1 /* minimum improvement for accepted changes when b=1 */,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    DdNode *subset;
+
+    do {
+	dd->reordered = 0;
+	subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1,
+				       quality0);
+    } while (dd->reordered == 1);
+
+    return(subset);
+
+} /* end of Cudd_BiasedUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the biased
+  underapproximation method.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the underapproximation procedure except for the fact that it
+  works on the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths
+  Cudd_RemapOverApprox Cudd_BiasedUnderApprox Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_BiasedOverApprox(
+  DdManager *dd /* manager */,
+  DdNode *f /* function to be superset */,
+  DdNode *b /* bias function */,
+  int numVars /* number of variables in the support of f */,
+  int threshold /* when to stop approximation */,
+  double quality1 /* minimum improvement for accepted changes when b=1*/,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);    
+    do {
+	dd->reordered = 0;
+	subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1,
+				      quality0);
+    } while (dd->reordered == 1);
+    
+    return(Cudd_NotCond(subset, (subset != NULL)));
+    
+} /* end of Cudd_BiasedOverApprox */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies Tom Shiple's underappoximation algorithm.]
+
+  Description [Applies Tom Shiple's underappoximation algorithm. Proceeds
+  in three phases:
+  <ul>
+  <li> collect information on each node in the BDD; this is done via DFS.
+  <li> traverse the BDD in top-down fashion and compute for each node
+  whether its elimination increases density.
+  <li> traverse the BDD via DFS and actually perform the elimination.
+  </ul>
+  Returns the approximated BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_UnderApprox]
+
+******************************************************************************/
+DdNode *
+cuddUnderApprox(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* current DD */,
+  int  numVars /* maximum number of variables */,
+  int  threshold /* threshold under which approximation stops */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    ApproxInfo *info;
+    DdNode *subset;
+    int result;
+
+    if (f == NULL) {
+	fprintf(dd->err, "Cannot subset, nil object\n");
+	return(NULL);
+    }
+
+    if (Cudd_IsConstant(f)) {
+	return(f);
+    }
+
+    /* Create table where node data are accessible via a hash table. */
+    info = gatherInfo(dd, f, numVars, safe);
+    if (info == NULL) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    /* Mark nodes that should be replaced by zero. */
+    result = UAmarkNodes(dd, f, info, threshold, safe, quality);
+    if (result == 0) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	FREE(info->page);
+	st_free_table(info->table);
+	FREE(info);
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    /* Build the result. */
+    subset = UAbuildSubset(dd, f, info);
+#if 1
+    if (subset && info->size < Cudd_DagSize(subset))
+	(void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
+		       info->size, Cudd_DagSize(subset));
+#endif
+    FREE(info->page);
+    st_free_table(info->table);
+    FREE(info);
+
+#ifdef DD_DEBUG
+    if (subset != NULL) {
+	cuddRef(subset);
+#if 0
+	(void) Cudd_DebugCheck(dd);
+	(void) Cudd_CheckKeys(dd);
+#endif
+	if (!Cudd_bddLeq(dd, subset, f)) {
+	    (void) fprintf(dd->err, "Wrong subset\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	}
+	cuddDeref(subset);
+    }
+#endif
+    return(subset);
+
+} /* end of cuddUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies the remapping underappoximation algorithm.]
+
+  Description [Applies the remapping underappoximation algorithm.
+  Proceeds in three phases:
+  <ul>
+  <li> collect information on each node in the BDD; this is done via DFS.
+  <li> traverse the BDD in top-down fashion and compute for each node
+  whether remapping increases density.
+  <li> traverse the BDD via DFS and actually perform the elimination.
+  </ul>
+  Returns the approximated BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RemapUnderApprox]
+
+******************************************************************************/
+DdNode *
+cuddRemapUnderApprox(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* current DD */,
+  int  numVars /* maximum number of variables */,
+  int  threshold /* threshold under which approximation stops */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    ApproxInfo *info;
+    DdNode *subset;
+    int result;
+
+    if (f == NULL) {
+	fprintf(dd->err, "Cannot subset, nil object\n");
+	dd->errorCode = CUDD_INVALID_ARG;
+	return(NULL);
+    }
+
+    if (Cudd_IsConstant(f)) {
+	return(f);
+    }
+
+    /* Create table where node data are accessible via a hash table. */
+    info = gatherInfo(dd, f, numVars, TRUE);
+    if (info == NULL) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    /* Mark nodes that should be replaced by zero. */
+    result = RAmarkNodes(dd, f, info, threshold, quality);
+    if (result == 0) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	FREE(info->page);
+	st_free_table(info->table);
+	FREE(info);
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    /* Build the result. */
+    subset = RAbuildSubset(dd, f, info);
+#if 1
+    if (subset && info->size < Cudd_DagSize(subset))
+	(void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
+		       info->size, Cudd_DagSize(subset));
+#endif
+    FREE(info->page);
+    st_free_table(info->table);
+    FREE(info);
+
+#ifdef DD_DEBUG
+    if (subset != NULL) {
+	cuddRef(subset);
+#if 0
+	(void) Cudd_DebugCheck(dd);
+	(void) Cudd_CheckKeys(dd);
+#endif
+	if (!Cudd_bddLeq(dd, subset, f)) {
+	    (void) fprintf(dd->err, "Wrong subset\n");
+	}
+	cuddDeref(subset);
+	dd->errorCode = CUDD_INTERNAL_ERROR;
+    }
+#endif
+    return(subset);
+
+} /* end of cuddRemapUnderApprox */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies the biased remapping underappoximation algorithm.]
+
+  Description [Applies the biased remapping underappoximation algorithm.
+  Proceeds in three phases:
+  <ul>
+  <li> collect information on each node in the BDD; this is done via DFS.
+  <li> traverse the BDD in top-down fashion and compute for each node
+  whether remapping increases density.
+  <li> traverse the BDD via DFS and actually perform the elimination.
+  </ul>
+  Returns the approximated BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_BiasedUnderApprox]
+
+******************************************************************************/
+DdNode *
+cuddBiasedUnderApprox(
+  DdManager *dd /* DD manager */,
+  DdNode *f /* current DD */,
+  DdNode *b /* bias function */,
+  int numVars /* maximum number of variables */,
+  int threshold /* threshold under which approximation stops */,
+  double quality1 /* minimum improvement for accepted changes when b=1 */,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    ApproxInfo *info;
+    DdNode *subset;
+    int result;
+    DdHashTable	*cache;
+
+    if (f == NULL) {
+	fprintf(dd->err, "Cannot subset, nil object\n");
+	dd->errorCode = CUDD_INVALID_ARG;
+	return(NULL);
+    }
+
+    if (Cudd_IsConstant(f)) {
+	return(f);
+    }
+
+    /* Create table where node data are accessible via a hash table. */
+    info = gatherInfo(dd, f, numVars, TRUE);
+    if (info == NULL) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    cache = cuddHashTableInit(dd,2,2);
+    result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache);
+    if (result == CARE_ERROR) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	cuddHashTableQuit(cache);
+	FREE(info->page);
+	st_free_table(info->table);
+	FREE(info);
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    cuddHashTableQuit(cache);
+
+    /* Mark nodes that should be replaced by zero. */
+    result = BAmarkNodes(dd, f, info, threshold, quality1, quality0);
+    if (result == 0) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	FREE(info->page);
+	st_free_table(info->table);
+	FREE(info);
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    /* Build the result. */
+    subset = RAbuildSubset(dd, f, info);
+#if 1
+    if (subset && info->size < Cudd_DagSize(subset))
+	(void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
+		       info->size, Cudd_DagSize(subset));
+#endif
+    FREE(info->page);
+    st_free_table(info->table);
+    FREE(info);
+
+#ifdef DD_DEBUG
+    if (subset != NULL) {
+	cuddRef(subset);
+#if 0
+	(void) Cudd_DebugCheck(dd);
+	(void) Cudd_CheckKeys(dd);
+#endif
+	if (!Cudd_bddLeq(dd, subset, f)) {
+	    (void) fprintf(dd->err, "Wrong subset\n");
+	}
+	cuddDeref(subset);
+	dd->errorCode = CUDD_INTERNAL_ERROR;
+    }
+#endif
+    return(subset);
+
+} /* end of cuddBiasedUnderApprox */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively update the parity of the paths reaching a node.]
+
+  Description [Recursively update the parity of the paths reaching a node.
+  Assumes that node is regular and propagates the invariant.]
+
+  SideEffects [None]
+
+  SeeAlso     [gatherInfoAux]
+
+******************************************************************************/
+static void
+updateParity(
+  DdNode * node /* function to analyze */,
+  ApproxInfo * info /* info on BDD */,
+  int  newparity /* new parity for node */)
+{
+    NodeData *infoN;
+    DdNode *E;
+
+    if (!st_lookup(info->table, node, &infoN)) return;
+    if ((infoN->parity & newparity) != 0) return;
+    infoN->parity |= newparity;
+    if (Cudd_IsConstant(node)) return;
+    updateParity(cuddT(node),info,newparity);
+    E = cuddE(node);
+    if (Cudd_IsComplement(E)) {
+	updateParity(Cudd_Not(E),info,3-newparity);
+    } else {
+	updateParity(E,info,newparity);
+    }
+    return;
+
+} /* end of updateParity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively counts minterms and computes reference counts
+  of each node in the BDD.]
+
+  Description [Recursively counts minterms and computes reference
+  counts of each node in the BDD.  Similar to the cuddCountMintermAux
+  which recursively counts the number of minterms for the dag rooted
+  at each node in terms of the total number of variables (max). It assumes
+  that the node pointer passed to it is regular and it maintains the
+  invariant.]
+
+  SideEffects [None]
+
+  SeeAlso     [gatherInfo]
+
+******************************************************************************/
+static NodeData *
+gatherInfoAux(
+  DdNode * node /* function to analyze */,
+  ApproxInfo * info /* info on BDD */,
+  int  parity /* gather parity information */)
+{
+    DdNode	*N, *Nt, *Ne;
+    NodeData	*infoN, *infoT, *infoE;
+
+    N = Cudd_Regular(node);
+
+    /* Check whether entry for this node exists. */
+    if (st_lookup(info->table, N, &infoN)) {
+	if (parity) {
+	    /* Update parity and propagate. */
+	    updateParity(N, info, 1 +  (int) Cudd_IsComplement(node));
+	}
+	return(infoN);
+    }
+
+    /* Compute the cofactors. */
+    Nt = Cudd_NotCond(cuddT(N), N != node);
+    Ne = Cudd_NotCond(cuddE(N), N != node);
+
+    infoT = gatherInfoAux(Nt, info, parity);
+    if (infoT == NULL) return(NULL);
+    infoE = gatherInfoAux(Ne, info, parity);
+    if (infoE == NULL) return(NULL);
+
+    infoT->functionRef++;
+    infoE->functionRef++;
+
+    /* Point to the correct location in the page. */
+    infoN = &(info->page[info->index++]);
+    infoN->parity |= 1 + (short) Cudd_IsComplement(node);
+
+    infoN->mintermsP = infoT->mintermsP/2;
+    infoN->mintermsN = infoT->mintermsN/2;
+    if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) {
+	infoN->mintermsP += infoE->mintermsN/2;
+	infoN->mintermsN += infoE->mintermsP/2;
+    } else {
+	infoN->mintermsP += infoE->mintermsP/2;
+	infoN->mintermsN += infoE->mintermsN/2;
+    }
+
+    /* Insert entry for the node in the table. */
+    if (st_insert(info->table,(char *)N, (char *)infoN) == ST_OUT_OF_MEM) {
+	return(NULL);
+    }
+    return(infoN);
+
+} /* end of gatherInfoAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gathers information about each node.]
+
+  Description [Counts minterms and computes reference counts of each
+  node in the BDD . The minterm count is separately computed for the
+  node and its complement. This is to avoid cancellation
+  errors. Returns a pointer to the data structure holding the
+  information gathered if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox gatherInfoAux]
+
+******************************************************************************/
+static ApproxInfo *
+gatherInfo(
+  DdManager * dd /* manager */,
+  DdNode * node /* function to be analyzed */,
+  int  numVars /* number of variables node depends on */,
+  int  parity /* gather parity information */)
+{
+    ApproxInfo	*info;
+    NodeData *infoTop;
+
+    /* If user did not give numVars value, set it to the maximum
+    ** exponent that the pow function can take. The -1 is due to the
+    ** discrepancy in the value that pow takes and the value that
+    ** log gives.
+    */
+    if (numVars == 0) {
+	numVars = DBL_MAX_EXP - 1;
+    }
+
+    info = ALLOC(ApproxInfo,1);
+    if (info == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    info->max = pow(2.0,(double) numVars);
+    info->one = DD_ONE(dd);
+    info->zero = Cudd_Not(info->one);
+    info->size = Cudd_DagSize(node);
+    /* All the information gathered will be stored in a contiguous
+    ** piece of memory, which is allocated here. This can be done
+    ** efficiently because we have counted the number of nodes of the
+    ** BDD. info->index points to the next available entry in the array
+    ** that stores the per-node information. */
+    info->page = ALLOC(NodeData,info->size);
+    if (info->page == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(info);
+	return(NULL);
+    }
+    memset(info->page, 0, info->size * sizeof(NodeData)); /* clear all page */
+    info->table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (info->table == NULL) {
+	FREE(info->page);
+	FREE(info);
+	return(NULL);
+    }
+    /* We visit the DAG in post-order DFS. Hence, the constant node is
+    ** in first position, and the root of the DAG is in last position. */
+
+    /* Info for the constant node: Initialize only fields different from 0. */
+    if (st_insert(info->table, (char *)info->one, (char *)info->page) == ST_OUT_OF_MEM) {
+	FREE(info->page);
+	FREE(info);
+	st_free_table(info->table);
+	return(NULL);
+    }
+    info->page[0].mintermsP = info->max;
+    info->index = 1;
+
+    infoTop = gatherInfoAux(node,info,parity);
+    if (infoTop == NULL) {
+	FREE(info->page);
+	st_free_table(info->table);
+	FREE(info);
+	return(NULL);
+    }
+    if (Cudd_IsComplement(node)) {
+	info->minterms = infoTop->mintermsN;
+    } else {
+	info->minterms = infoTop->mintermsP;
+    }
+
+    infoTop->functionRef = 1;
+    return(info);
+
+} /* end of gatherInfo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the nodes that would be eliminated if a given node
+  were replaced by zero.]
+
+  Description [Counts the nodes that would be eliminated if a given
+  node were replaced by zero. This procedure uses a queue passed by
+  the caller for efficiency: since the queue is left empty at the
+  endof the search, it can be reused as is by the next search. Returns
+  the count (always striclty positive) if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox]
+
+******************************************************************************/
+static int
+computeSavings(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * skip,
+  ApproxInfo * info,
+  DdLevelQueue * queue)
+{
+    NodeData *infoN;
+    LocalQueueItem *item;
+    DdNode *node;
+    int savings = 0;
+
+    node = Cudd_Regular(f);
+    skip = Cudd_Regular(skip);
+    /* Insert the given node in the level queue. Its local reference
+    ** count is set equal to the function reference count so that the
+    ** search will continue from it when it is retrieved. */
+    item = (LocalQueueItem *)
+	cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL)
+	return(0);
+    (void) st_lookup(info->table, node, &infoN);
+    item->localRef = infoN->functionRef;
+
+    /* Process the queue. */
+    while (queue->first != NULL) {
+	item = (LocalQueueItem *) queue->first;
+	node = item->node;
+	cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+	if (node == skip) continue;
+	(void) st_lookup(info->table, node, &infoN);
+	if (item->localRef != infoN->functionRef) {
+	    /* This node is shared. */
+	    continue;
+	}
+	savings++;
+	if (!cuddIsConstant(cuddT(node))) {
+	    item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+					 cuddI(dd,cuddT(node)->index));
+	    if (item == NULL) return(0);
+	    item->localRef++;
+	}
+	if (!Cudd_IsConstant(cuddE(node))) {
+	    item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+					 cuddI(dd,Cudd_Regular(cuddE(node))->index));
+	    if (item == NULL) return(0);
+	    item->localRef++;
+	}
+    }
+
+#ifdef DD_DEBUG
+    /* At the end of a local search the queue should be empty. */
+    assert(queue->size == 0);
+#endif
+    return(savings);
+
+} /* end of computeSavings */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Update function reference counts.]
+
+  Description [Update function reference counts to account for replacement.
+  Returns the number of nodes saved if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [UAmarkNodes RAmarkNodes]
+
+******************************************************************************/
+static int
+updateRefs(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * skip,
+  ApproxInfo * info,
+  DdLevelQueue * queue)
+{
+    NodeData *infoN;
+    LocalQueueItem *item;
+    DdNode *node;
+    int savings = 0;
+
+    node = Cudd_Regular(f);
+    /* Insert the given node in the level queue. Its function reference
+    ** count is set equal to 0 so that the search will continue from it
+    ** when it is retrieved. */
+    item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL)
+	return(0);
+    (void) st_lookup(info->table, node, &infoN);
+    infoN->functionRef = 0;
+
+    if (skip != NULL) {
+	/* Increase the function reference count of the node to be skipped
+	** by 1 to account for the node pointing to it that will be created. */
+	skip = Cudd_Regular(skip);
+	(void) st_lookup(info->table, skip, &infoN);
+	infoN->functionRef++;
+    }
+
+    /* Process the queue. */
+    while (queue->first != NULL) {
+	item = (LocalQueueItem *) queue->first;
+	node = item->node;
+	cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+	(void) st_lookup(info->table, node, &infoN);
+	if (infoN->functionRef != 0) {
+	    /* This node is shared or must be skipped. */
+	    continue;
+	}
+	savings++;
+	if (!cuddIsConstant(cuddT(node))) {
+	    item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+					 cuddI(dd,cuddT(node)->index));
+	    if (item == NULL) return(0);
+	    (void) st_lookup(info->table, cuddT(node), &infoN);
+	    infoN->functionRef--;
+	}
+	if (!Cudd_IsConstant(cuddE(node))) {
+	    item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+					 cuddI(dd,Cudd_Regular(cuddE(node))->index));
+	    if (item == NULL) return(0);
+	    (void) st_lookup(info->table, Cudd_Regular(cuddE(node)), &infoN);
+	    infoN->functionRef--;
+	}
+    }
+
+#ifdef DD_DEBUG
+    /* At the end of a local search the queue should be empty. */
+    assert(queue->size == 0);
+#endif
+    return(savings);
+
+} /* end of updateRefs */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Marks nodes for replacement by zero.]
+
+  Description [Marks nodes for replacement by zero. Returns 1 if successful;
+  0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox]
+
+******************************************************************************/
+static int
+UAmarkNodes(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be analyzed */,
+  ApproxInfo * info /* info on BDD */,
+  int  threshold /* when to stop approximating */,
+  int  safe /* enforce safe approximation */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdLevelQueue *queue;
+    DdLevelQueue *localQueue;
+    NodeData *infoN;
+    GlobalQueueItem *item;
+    DdNode *node;
+    double numOnset;
+    double impactP, impactN;
+    int savings;
+
+#if 0
+    (void) printf("initial size = %d initial minterms = %g\n",
+		  info->size, info->minterms);
+#endif
+    queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
+    if (queue == NULL) {
+	return(0);
+    }
+    localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
+				    dd->initSlots);
+    if (localQueue == NULL) {
+	cuddLevelQueueQuit(queue);
+	return(0);
+    }
+    node = Cudd_Regular(f);
+    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL) {
+	cuddLevelQueueQuit(queue);
+	cuddLevelQueueQuit(localQueue);
+	return(0);
+    }
+    if (Cudd_IsComplement(f)) {
+	item->impactP = 0.0;
+	item->impactN = 1.0;
+    } else {
+	item->impactP = 1.0;
+	item->impactN = 0.0;
+    }
+    while (queue->first != NULL) {
+	/* If the size of the subset is below the threshold, quit. */
+	if (info->size <= threshold)
+	    break;
+	item = (GlobalQueueItem *) queue->first;
+	node = item->node;
+	node = Cudd_Regular(node);
+	(void) st_lookup(info->table, node, &infoN);
+	if (safe && infoN->parity == 3) {
+	    cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+	    continue;
+	}
+	impactP = item->impactP;
+	impactN = item->impactN;
+	numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
+	savings = computeSavings(dd,node,NULL,info,localQueue);
+	if (savings == 0) {
+	    cuddLevelQueueQuit(queue);
+	    cuddLevelQueueQuit(localQueue);
+	    return(0);
+	}
+	cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+#if 0
+	(void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
+		      node, impactP, impactN, numOnset, savings);
+#endif
+	if ((1 - numOnset / info->minterms) >
+	    quality * (1 - (double) savings / info->size)) {
+	    infoN->replace = TRUE;
+	    info->size -= savings;
+	    info->minterms -=numOnset;
+#if 0
+	    (void) printf("replace: new size = %d new minterms = %g\n",
+			  info->size, info->minterms);
+#endif
+	    savings -= updateRefs(dd,node,NULL,info,localQueue);
+	    assert(savings == 0);
+	    continue;
+	}
+	if (!cuddIsConstant(cuddT(node))) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+					 cuddI(dd,cuddT(node)->index));
+	    item->impactP += impactP/2.0;
+	    item->impactN += impactN/2.0;
+	}
+	if (!Cudd_IsConstant(cuddE(node))) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+					 cuddI(dd,Cudd_Regular(cuddE(node))->index));
+	    if (Cudd_IsComplement(cuddE(node))) {
+		item->impactP += impactN/2.0;
+		item->impactN += impactP/2.0;
+	    } else {
+		item->impactP += impactP/2.0;
+		item->impactN += impactN/2.0;
+	    }
+	}
+    }
+
+    cuddLevelQueueQuit(queue);
+    cuddLevelQueueQuit(localQueue);
+    return(1);
+
+} /* end of UAmarkNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the subset BDD.] 
+
+  Description [Builds the subset BDD. Based on the info table,
+  replaces selected nodes by zero. Returns a pointer to the result if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUnderApprox]
+
+******************************************************************************/
+static DdNode *
+UAbuildSubset(
+  DdManager * dd /* DD manager */,
+  DdNode * node /* current node */,
+  ApproxInfo * info /* node info */)
+{
+
+    DdNode *Nt, *Ne, *N, *t, *e, *r;
+    NodeData *infoN;
+
+    if (Cudd_IsConstant(node))
+	return(node);
+
+    N = Cudd_Regular(node);
+
+    if (st_lookup(info->table, N, &infoN)) {
+	if (infoN->replace == TRUE) {
+	    return(info->zero);
+	}
+	if (N == node ) {
+	    if (infoN->resultP != NULL) {
+		return(infoN->resultP);
+	    }
+	} else {
+	    if (infoN->resultN != NULL) {
+		return(infoN->resultN);
+	    }
+	}
+    } else {
+	(void) fprintf(dd->err,
+		       "Something is wrong, ought to be in info table\n");
+	dd->errorCode = CUDD_INTERNAL_ERROR;
+	return(NULL);
+    }
+
+    Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
+    Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
+
+    t = UAbuildSubset(dd, Nt, info);
+    if (t == NULL) {
+	return(NULL);
+    }
+    cuddRef(t);
+
+    e = UAbuildSubset(dd, Ne, info);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(dd,t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+	t = Cudd_Not(t);
+	e = Cudd_Not(e);
+	r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(dd, e);
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+	r = Cudd_Not(r);
+    } else {
+	r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(dd, e);
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    if (N == node) {
+	infoN->resultP = r;
+    } else {
+	infoN->resultN = r;
+    }
+
+    return(r);
+
+} /* end of UAbuildSubset */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Marks nodes for remapping.]
+
+  Description [Marks nodes for remapping. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRemapUnderApprox]
+
+******************************************************************************/
+static int
+RAmarkNodes(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be analyzed */,
+  ApproxInfo * info /* info on BDD */,
+  int  threshold /* when to stop approximating */,
+  double  quality /* minimum improvement for accepted changes */)
+{
+    DdLevelQueue *queue;
+    DdLevelQueue *localQueue;
+    NodeData *infoN, *infoT, *infoE;
+    GlobalQueueItem *item;
+    DdNode *node, *T, *E;
+    DdNode *shared; /* grandchild shared by the two children of node */
+    double numOnset;
+    double impact, impactP, impactN;
+    double minterms;
+    int savings;
+    int replace;
+
+#if 0
+    (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
+		  info->size, info->minterms);
+#endif
+    queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
+    if (queue == NULL) {
+	return(0);
+    }
+    localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
+				    dd->initSlots);
+    if (localQueue == NULL) {
+	cuddLevelQueueQuit(queue);
+	return(0);
+    }
+    /* Enqueue regular pointer to root and initialize impact. */
+    node = Cudd_Regular(f);
+    item = (GlobalQueueItem *)
+	cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL) {
+	cuddLevelQueueQuit(queue);
+	cuddLevelQueueQuit(localQueue);
+	return(0);
+    }
+    if (Cudd_IsComplement(f)) {
+	item->impactP = 0.0;
+	item->impactN = 1.0;
+    } else {
+	item->impactP = 1.0;
+	item->impactN = 0.0;
+    }
+    /* The nodes retrieved here are guaranteed to be non-terminal.
+    ** The initial node is not terminal because constant nodes are
+    ** dealt with in the calling procedure. Subsequent nodes are inserted
+    ** only if they are not terminal. */
+    while (queue->first != NULL) {
+	/* If the size of the subset is below the threshold, quit. */
+	if (info->size <= threshold)
+	    break;
+	item = (GlobalQueueItem *) queue->first;
+	node = item->node;
+#ifdef DD_DEBUG
+	assert(item->impactP >= 0 && item->impactP <= 1.0);
+	assert(item->impactN >= 0 && item->impactN <= 1.0);
+	assert(!Cudd_IsComplement(node));
+	assert(!Cudd_IsConstant(node));
+#endif
+	if (!st_lookup(info->table, node, &infoN)) {
+	    cuddLevelQueueQuit(queue);
+	    cuddLevelQueueQuit(localQueue);
+	    return(0);
+	}
+#ifdef DD_DEBUG
+	assert(infoN->parity >= 1 && infoN->parity <= 3);
+#endif
+	if (infoN->parity == 3) {
+	    /* This node can be reached through paths of different parity.
+	    ** It is not safe to replace it, because remapping will give
+	    ** an incorrect result, while replacement by 0 may cause node
+	    ** splitting. */
+	    cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+	    continue;
+	}
+	T = cuddT(node);
+	E = cuddE(node);
+	shared = NULL;
+	impactP = item->impactP;
+	impactN = item->impactN;
+	if (Cudd_bddLeq(dd,T,E)) {
+	    /* Here we know that E is regular. */
+#ifdef DD_DEBUG
+	    assert(!Cudd_IsComplement(E));
+#endif
+	    (void) st_lookup(info->table, T, &infoT);
+	    (void) st_lookup(info->table, E, &infoE);
+	    if (infoN->parity == 1) {
+		impact = impactP;
+		minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
+		if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+		    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_E;
+	    } else {
+#ifdef DD_DEBUG
+		assert(infoN->parity == 2);
+#endif
+		impact = impactN;
+		minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
+		if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+		    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_T;
+	    }
+	    numOnset = impact * minterms;
+	} else if (Cudd_bddLeq(dd,E,T)) {
+	    /* Here E may be complemented. */
+	    DdNode *Ereg = Cudd_Regular(E);
+	    (void) st_lookup(info->table, T, &infoT);
+	    (void) st_lookup(info->table, Ereg, &infoE);
+	    if (infoN->parity == 1) {
+		impact = impactP;
+		minterms = infoT->mintermsP/2.0 -
+		    ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
+		if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+		    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_T;
+	    } else {
+#ifdef DD_DEBUG
+		assert(infoN->parity == 2);
+#endif
+		impact = impactN;
+		minterms = ((E == Ereg) ? infoE->mintermsN :
+			    infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
+		if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+		    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_E;
+	    }
+	    numOnset = impact * minterms;
+	} else {
+	    DdNode *Ereg = Cudd_Regular(E);
+	    DdNode *TT = cuddT(T);
+	    DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
+	    if (T->index == Ereg->index && TT == ET) {
+		shared = TT;
+		replace = REPLACE_TT;
+	    } else {
+		DdNode *TE = cuddE(T);
+		DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
+		if (T->index == Ereg->index && TE == EE) {
+		    shared = TE;
+		    replace = REPLACE_TE;
+		} else {
+		    replace = REPLACE_N;
+		}
+	    }
+	    numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
+	    savings = computeSavings(dd,node,shared,info,localQueue);
+	    if (shared != NULL) {
+		NodeData *infoS;
+		(void) st_lookup(info->table, Cudd_Regular(shared), &infoS);
+		if (Cudd_IsComplement(shared)) {
+		    numOnset -= (infoS->mintermsN * impactP +
+			infoS->mintermsP * impactN)/2.0;
+		} else {
+		    numOnset -= (infoS->mintermsP * impactP +
+			infoS->mintermsN * impactN)/2.0;
+		}
+		savings--;
+	    }
+	}
+
+	cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+#if 0
+	if (replace == REPLACE_T || replace == REPLACE_E)
+	    (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
+			  node, impact, numOnset, savings);
+	else
+	    (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
+			  node, impactP, impactN, numOnset, savings);
+#endif
+	if ((1 - numOnset / info->minterms) >
+	    quality * (1 - (double) savings / info->size)) {
+	    infoN->replace = replace;
+	    info->size -= savings;
+	    info->minterms -=numOnset;
+#if 0
+	    (void) printf("remap(%d): new size = %d new minterms = %g\n",
+			  replace, info->size, info->minterms);
+#endif
+	    if (replace == REPLACE_N) {
+		savings -= updateRefs(dd,node,NULL,info,localQueue);
+	    } else if (replace == REPLACE_T) {
+		savings -= updateRefs(dd,node,E,info,localQueue);
+	    } else if (replace == REPLACE_E) {
+		savings -= updateRefs(dd,node,T,info,localQueue);
+	    } else {
+#ifdef DD_DEBUG
+		assert(replace == REPLACE_TT || replace == REPLACE_TE);
+#endif
+		savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
+	    }
+	    assert(savings == 0);
+	} else {
+	    replace = NOTHING;
+	}
+	if (replace == REPLACE_N) continue;
+	if ((replace == REPLACE_E || replace == NOTHING) &&
+	    !cuddIsConstant(cuddT(node))) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+					 cuddI(dd,cuddT(node)->index));
+	    if (replace == REPLACE_E) {
+		item->impactP += impactP;
+		item->impactN += impactN;
+	    } else {
+		item->impactP += impactP/2.0;
+		item->impactN += impactN/2.0;
+	    }
+	}
+	if ((replace == REPLACE_T || replace == NOTHING) &&
+	    !Cudd_IsConstant(cuddE(node))) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+					 cuddI(dd,Cudd_Regular(cuddE(node))->index));
+	    if (Cudd_IsComplement(cuddE(node))) {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactN;
+		    item->impactN += impactP;
+		} else {
+		    item->impactP += impactN/2.0;
+		    item->impactN += impactP/2.0;
+		}
+	    } else {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactP;
+		    item->impactN += impactN;
+		} else {
+		    item->impactP += impactP/2.0;
+		    item->impactN += impactN/2.0;
+		}
+	    }
+	}
+	if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
+	    !Cudd_IsConstant(shared)) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
+					 cuddI(dd,Cudd_Regular(shared)->index));
+	    if (Cudd_IsComplement(shared)) {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactN;
+		    item->impactN += impactP;
+		} else {
+		    item->impactP += impactN/2.0;
+		    item->impactN += impactP/2.0;
+		}
+	    } else {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactP;
+		    item->impactN += impactN;
+		} else {
+		    item->impactP += impactP/2.0;
+		    item->impactN += impactN/2.0;
+		}
+	    }
+	}
+    }
+
+    cuddLevelQueueQuit(queue);
+    cuddLevelQueueQuit(localQueue);
+    return(1);
+
+} /* end of RAmarkNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Marks nodes for remapping.]
+
+  Description [Marks nodes for remapping. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRemapUnderApprox]
+
+******************************************************************************/
+static int
+BAmarkNodes(
+  DdManager *dd /* manager */,
+  DdNode *f /* function to be analyzed */,
+  ApproxInfo *info /* info on BDD */,
+  int threshold /* when to stop approximating */,
+  double quality1 /* minimum improvement for accepted changes when b=1 */,
+  double quality0 /* minimum improvement for accepted changes when b=0 */)
+{
+    DdLevelQueue *queue;
+    DdLevelQueue *localQueue;
+    NodeData *infoN, *infoT, *infoE;
+    GlobalQueueItem *item;
+    DdNode *node, *T, *E;
+    DdNode *shared; /* grandchild shared by the two children of node */
+    double numOnset;
+    double impact, impactP, impactN;
+    double minterms;
+    double quality;
+    int savings;
+    int replace;
+
+#if 0
+    (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
+		  info->size, info->minterms);
+#endif
+    queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
+    if (queue == NULL) {
+	return(0);
+    }
+    localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
+				    dd->initSlots);
+    if (localQueue == NULL) {
+	cuddLevelQueueQuit(queue);
+	return(0);
+    }
+    /* Enqueue regular pointer to root and initialize impact. */
+    node = Cudd_Regular(f);
+    item = (GlobalQueueItem *)
+	cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
+    if (item == NULL) {
+	cuddLevelQueueQuit(queue);
+	cuddLevelQueueQuit(localQueue);
+	return(0);
+    }
+    if (Cudd_IsComplement(f)) {
+	item->impactP = 0.0;
+	item->impactN = 1.0;
+    } else {
+	item->impactP = 1.0;
+	item->impactN = 0.0;
+    }
+    /* The nodes retrieved here are guaranteed to be non-terminal.
+    ** The initial node is not terminal because constant nodes are
+    ** dealt with in the calling procedure. Subsequent nodes are inserted
+    ** only if they are not terminal. */
+    while (queue->first != NULL) {
+	/* If the size of the subset is below the threshold, quit. */
+	if (info->size <= threshold)
+	    break;
+	item = (GlobalQueueItem *) queue->first;
+	node = item->node;
+#ifdef DD_DEBUG
+	assert(item->impactP >= 0 && item->impactP <= 1.0);
+	assert(item->impactN >= 0 && item->impactN <= 1.0);
+	assert(!Cudd_IsComplement(node));
+	assert(!Cudd_IsConstant(node));
+#endif
+	if (!st_lookup(info->table, node, &infoN)) {
+	    cuddLevelQueueQuit(queue);
+	    cuddLevelQueueQuit(localQueue);
+	    return(0);
+	}
+	quality = infoN->care ? quality1 : quality0;
+#ifdef DD_DEBUG
+	assert(infoN->parity >= 1 && infoN->parity <= 3);
+#endif
+	if (infoN->parity == 3) {
+	    /* This node can be reached through paths of different parity.
+	    ** It is not safe to replace it, because remapping will give
+	    ** an incorrect result, while replacement by 0 may cause node
+	    ** splitting. */
+	    cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+	    continue;
+	}
+	T = cuddT(node);
+	E = cuddE(node);
+	shared = NULL;
+	impactP = item->impactP;
+	impactN = item->impactN;
+	if (Cudd_bddLeq(dd,T,E)) {
+	    /* Here we know that E is regular. */
+#ifdef DD_DEBUG
+	    assert(!Cudd_IsComplement(E));
+#endif
+	    (void) st_lookup(info->table, T, &infoT);
+	    (void) st_lookup(info->table, E, &infoE);
+	    if (infoN->parity == 1) {
+		impact = impactP;
+		minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
+		if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+		    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_E;
+	    } else {
+#ifdef DD_DEBUG
+		assert(infoN->parity == 2);
+#endif
+		impact = impactN;
+		minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
+		if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+		    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_T;
+	    }
+	    numOnset = impact * minterms;
+	} else if (Cudd_bddLeq(dd,E,T)) {
+	    /* Here E may be complemented. */
+	    DdNode *Ereg = Cudd_Regular(E);
+	    (void) st_lookup(info->table, T, &infoT);
+	    (void) st_lookup(info->table, Ereg, &infoE);
+	    if (infoN->parity == 1) {
+		impact = impactP;
+		minterms = infoT->mintermsP/2.0 -
+		    ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
+		if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
+		    savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_T;
+	    } else {
+#ifdef DD_DEBUG
+		assert(infoN->parity == 2);
+#endif
+		impact = impactN;
+		minterms = ((E == Ereg) ? infoE->mintermsN :
+			    infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
+		if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
+		    savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
+		    if (savings == 1) {
+			cuddLevelQueueQuit(queue);
+			cuddLevelQueueQuit(localQueue);
+			return(0);
+		    }
+		} else {
+		    savings = 1;
+		}
+		replace = REPLACE_E;
+	    }
+	    numOnset = impact * minterms;
+	} else {
+	    DdNode *Ereg = Cudd_Regular(E);
+	    DdNode *TT = cuddT(T);
+	    DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
+	    if (T->index == Ereg->index && TT == ET) {
+		shared = TT;
+		replace = REPLACE_TT;
+	    } else {
+		DdNode *TE = cuddE(T);
+		DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
+		if (T->index == Ereg->index && TE == EE) {
+		    shared = TE;
+		    replace = REPLACE_TE;
+		} else {
+		    replace = REPLACE_N;
+		}
+	    }
+	    numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
+	    savings = computeSavings(dd,node,shared,info,localQueue);
+	    if (shared != NULL) {
+		NodeData *infoS;
+		(void) st_lookup(info->table, Cudd_Regular(shared), &infoS);
+		if (Cudd_IsComplement(shared)) {
+		    numOnset -= (infoS->mintermsN * impactP +
+			infoS->mintermsP * impactN)/2.0;
+		} else {
+		    numOnset -= (infoS->mintermsP * impactP +
+			infoS->mintermsN * impactN)/2.0;
+		}
+		savings--;
+	    }
+	}
+
+	cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
+#if 0
+	if (replace == REPLACE_T || replace == REPLACE_E)
+	    (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
+			  node, impact, numOnset, savings);
+	else
+	    (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
+			  node, impactP, impactN, numOnset, savings);
+#endif
+	if ((1 - numOnset / info->minterms) >
+	    quality * (1 - (double) savings / info->size)) {
+	    infoN->replace = replace;
+	    info->size -= savings;
+	    info->minterms -=numOnset;
+#if 0
+	    (void) printf("remap(%d): new size = %d new minterms = %g\n",
+			  replace, info->size, info->minterms);
+#endif
+	    if (replace == REPLACE_N) {
+		savings -= updateRefs(dd,node,NULL,info,localQueue);
+	    } else if (replace == REPLACE_T) {
+		savings -= updateRefs(dd,node,E,info,localQueue);
+	    } else if (replace == REPLACE_E) {
+		savings -= updateRefs(dd,node,T,info,localQueue);
+	    } else {
+#ifdef DD_DEBUG
+		assert(replace == REPLACE_TT || replace == REPLACE_TE);
+#endif
+		savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
+	    }
+	    assert(savings == 0);
+	} else {
+	    replace = NOTHING;
+	}
+	if (replace == REPLACE_N) continue;
+	if ((replace == REPLACE_E || replace == NOTHING) &&
+	    !cuddIsConstant(cuddT(node))) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
+					 cuddI(dd,cuddT(node)->index));
+	    if (replace == REPLACE_E) {
+		item->impactP += impactP;
+		item->impactN += impactN;
+	    } else {
+		item->impactP += impactP/2.0;
+		item->impactN += impactN/2.0;
+	    }
+	}
+	if ((replace == REPLACE_T || replace == NOTHING) &&
+	    !Cudd_IsConstant(cuddE(node))) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
+					 cuddI(dd,Cudd_Regular(cuddE(node))->index));
+	    if (Cudd_IsComplement(cuddE(node))) {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactN;
+		    item->impactN += impactP;
+		} else {
+		    item->impactP += impactN/2.0;
+		    item->impactN += impactP/2.0;
+		}
+	    } else {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactP;
+		    item->impactN += impactN;
+		} else {
+		    item->impactP += impactP/2.0;
+		    item->impactN += impactN/2.0;
+		}
+	    }
+	}
+	if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
+	    !Cudd_IsConstant(shared)) {
+	    item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
+					 cuddI(dd,Cudd_Regular(shared)->index));
+	    if (Cudd_IsComplement(shared)) {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactN;
+		    item->impactN += impactP;
+		} else {
+		    item->impactP += impactN/2.0;
+		    item->impactN += impactP/2.0;
+		}
+	    } else {
+		if (replace == REPLACE_T) {
+		    item->impactP += impactP;
+		    item->impactN += impactN;
+		} else {
+		    item->impactP += impactP/2.0;
+		    item->impactN += impactN/2.0;
+		}
+	    }
+	}
+    }
+
+    cuddLevelQueueQuit(queue);
+    cuddLevelQueueQuit(localQueue);
+    return(1);
+
+} /* end of BAmarkNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds the subset BDD for cuddRemapUnderApprox.]
+
+  Description [Builds the subset BDDfor cuddRemapUnderApprox.  Based
+  on the info table, performs remapping or replacement at selected
+  nodes. Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRemapUnderApprox]
+
+******************************************************************************/
+static DdNode *
+RAbuildSubset(
+  DdManager * dd /* DD manager */,
+  DdNode * node /* current node */,
+  ApproxInfo * info /* node info */)
+{
+    DdNode *Nt, *Ne, *N, *t, *e, *r;
+    NodeData *infoN;
+
+    if (Cudd_IsConstant(node))
+	return(node);
+
+    N = Cudd_Regular(node);
+
+    Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
+    Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
+
+    if (st_lookup(info->table, N, &infoN)) {
+	if (N == node ) {
+	    if (infoN->resultP != NULL) {
+		return(infoN->resultP);
+	    }
+	} else {
+	    if (infoN->resultN != NULL) {
+		return(infoN->resultN);
+	    }
+	}
+	if (infoN->replace == REPLACE_T) {
+	    r = RAbuildSubset(dd, Ne, info);
+	    return(r);
+	} else if (infoN->replace == REPLACE_E) {
+	    r = RAbuildSubset(dd, Nt, info);
+	    return(r);
+	} else if (infoN->replace == REPLACE_N) {
+	    return(info->zero);
+	} else if (infoN->replace == REPLACE_TT) {
+	    DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)),
+				       Cudd_IsComplement(node));
+	    int index = cuddT(N)->index;
+	    DdNode *e = info->zero;
+	    DdNode *t = RAbuildSubset(dd, Ntt, info);
+	    if (t == NULL) {
+		return(NULL);
+	    }
+	    cuddRef(t);
+	    if (Cudd_IsComplement(t)) {
+		t = Cudd_Not(t);
+		e = Cudd_Not(e);
+		r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+		if (r == NULL) {
+		    Cudd_RecursiveDeref(dd, t);
+		    return(NULL);
+		}
+		r = Cudd_Not(r);
+	    } else {
+		r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+		if (r == NULL) {
+		    Cudd_RecursiveDeref(dd, t);
+		    return(NULL);
+		}
+	    }
+	    cuddDeref(t);
+	    return(r);
+	} else if (infoN->replace == REPLACE_TE) {
+	    DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)),
+				       Cudd_IsComplement(node));
+	    int index = cuddT(N)->index;
+	    DdNode *t = info->one;
+	    DdNode *e = RAbuildSubset(dd, Nte, info);
+	    if (e == NULL) {
+		return(NULL);
+	    }
+	    cuddRef(e);
+	    e = Cudd_Not(e);
+	    r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	    if (r == NULL) {
+		Cudd_RecursiveDeref(dd, e);
+		return(NULL);
+	    }
+	    r =Cudd_Not(r);
+	    cuddDeref(e);
+	    return(r);
+	}
+    } else {
+	(void) fprintf(dd->err,
+		       "Something is wrong, ought to be in info table\n");
+	dd->errorCode = CUDD_INTERNAL_ERROR;
+	return(NULL);
+    }
+
+    t = RAbuildSubset(dd, Nt, info);
+    if (t == NULL) {
+	return(NULL);
+    }
+    cuddRef(t);
+
+    e = RAbuildSubset(dd, Ne, info);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(dd,t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+	t = Cudd_Not(t);
+	e = Cudd_Not(e);
+	r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(dd, e);
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+	r = Cudd_Not(r);
+    } else {
+	r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(dd, e);
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    if (N == node) {
+	infoN->resultP = r;
+    } else {
+	infoN->resultN = r;
+    }
+
+    return(r);
+
+} /* end of RAbuildSubset */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds don't care nodes.]
+
+  Description [Finds don't care nodes by traversing f and b in parallel.
+  Returns the care status of the visited f node if successful; CARE_ERROR
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBiasedUnderApprox]
+
+******************************************************************************/
+static int
+BAapplyBias(
+  DdManager *dd,
+  DdNode *f,
+  DdNode *b,
+  ApproxInfo *info,
+  DdHashTable *cache)
+{
+    DdNode *one, *zero, *res;
+    DdNode *Ft, *Fe, *B, *Bt, *Be;
+    unsigned int topf, topb;
+    NodeData *infoF;
+    int careT, careE;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    if (!st_lookup(info->table, f, &infoF))
+	return(CARE_ERROR);
+    if (f == one) return(TOTAL_CARE);
+    if (b == zero) return(infoF->care);
+    if (infoF->care == TOTAL_CARE) return(TOTAL_CARE);
+
+    if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) &&
+	(res = cuddHashTableLookup2(cache,f,b)) != NULL) {
+	if (res->ref == 0) {
+	    cache->manager->dead++;
+	    cache->manager->constants.dead++;
+	}
+	return(infoF->care);
+    }
+
+    topf = dd->perm[f->index];
+    B = Cudd_Regular(b);
+    topb = cuddI(dd,B->index);
+    if (topf <= topb) {
+	Ft = cuddT(f); Fe = cuddE(f);
+    } else {
+	Ft = Fe = f;
+    }
+    if (topb <= topf) {
+	/* We know that b is not constant because f is not. */
+	Bt = cuddT(B); Be = cuddE(B);
+	if (Cudd_IsComplement(b)) {
+	    Bt = Cudd_Not(Bt);
+	    Be = Cudd_Not(Be);
+	}
+    } else {
+	Bt = Be = b;
+    }
+
+    careT = BAapplyBias(dd, Ft, Bt, info, cache);
+    if (careT == CARE_ERROR)
+	return(CARE_ERROR);
+    careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache);
+    if (careE == CARE_ERROR)
+	return(CARE_ERROR);
+    if (careT == TOTAL_CARE && careE == TOTAL_CARE) {
+	infoF->care = TOTAL_CARE;
+    } else {
+	infoF->care = CARE;
+    }
+
+    if (f->ref != 1 || Cudd_Regular(b)->ref != 1) {
+	ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref;
+	cuddSatDec(fanout);
+	if (!cuddHashTableInsert2(cache,f,b,one,fanout)) {
+	    return(CARE_ERROR);
+	}
+    }
+    return(infoF->care);
+
+} /* end of BAapplyBias */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddBddAbs.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddBddAbs.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddBddAbs.c	(revision 8)
@@ -0,0 +1,715 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBddAbs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Quantification functions for BDDs.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_bddExistAbstract()
+		<li> Cudd_bddXorExistAbstract()
+		<li> Cudd_bddUnivAbstract()
+		<li> Cudd_bddBooleanDiff()
+		<li> Cudd_bddVarIsDependent()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddBddExistAbstractRecur()
+		<li> cuddBddXorExistAbstractRecur()
+		<li> cuddBddBooleanDiffRecur()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> bddCheckPositiveCube()
+		</ul>
+		]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.26 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int bddCheckPositiveCube (DdManager *manager, DdNode *cube);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Existentially abstracts all the variables in cube from f.]
+
+  Description [Existentially abstracts all the variables in cube from f.
+  Returns the abstracted BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddUnivAbstract Cudd_addExistAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddExistAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    if (bddCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,
+		       "Error: Can only abstract positive cubes\n");
+	manager->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    do {
+	manager->reordered = 0;
+	res = cuddBddExistAbstractRecur(manager, f, cube);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddExistAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.  Returns a
+  pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddUnivAbstract Cudd_bddExistAbstract Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddXorExistAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *res;
+
+    if (bddCheckPositiveCube(manager, cube) == 0) {
+        (void) fprintf(manager->err,
+		       "Error: Can only abstract positive cubes\n");
+	manager->errorCode = CUDD_INVALID_ARG;
+        return(NULL);
+    }
+
+    do {
+	manager->reordered = 0;
+	res = cuddBddXorExistAbstractRecur(manager, f, g, cube);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddXorExistAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Universally abstracts all the variables in cube from f.]
+
+  Description [Universally abstracts all the variables in cube from f.
+  Returns the abstracted BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddExistAbstract Cudd_addUnivAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddUnivAbstract(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode	*res;
+
+    if (bddCheckPositiveCube(manager, cube) == 0) {
+	(void) fprintf(manager->err,
+		       "Error: Can only abstract positive cubes\n");
+	manager->errorCode = CUDD_INVALID_ARG;
+	return(NULL);
+    }
+
+    do {
+	manager->reordered = 0;
+	res = cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube);
+    } while (manager->reordered == 1);
+    if (res != NULL) res = Cudd_Not(res);
+
+    return(res);
+
+} /* end of Cudd_bddUnivAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the boolean difference of f with respect to x.]
+
+  Description [Computes the boolean difference of f with respect to the
+  variable with index x.  Returns the BDD of the boolean difference if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_bddBooleanDiff(
+  DdManager * manager,
+  DdNode * f,
+  int  x)
+{
+    DdNode *res, *var;
+
+    /* If the variable is not currently in the manager, f cannot
+    ** depend on it.
+    */
+    if (x >= manager->size) return(Cudd_Not(DD_ONE(manager)));
+    var = manager->vars[x];
+
+    do {
+	manager->reordered = 0;
+	res = cuddBddBooleanDiffRecur(manager, Cudd_Regular(f), var);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddBooleanDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is dependent on others in a
+  function.]
+
+  Description [Checks whether a variable is dependent on others in a
+  function.  Returns 1 if the variable is dependent; 0 otherwise. No
+  new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_bddVarIsDependent(
+  DdManager *dd,		/* manager */
+  DdNode *f,			/* function */
+  DdNode *var			/* variable */)
+{
+    DdNode *F, *res, *zero, *ft, *fe;
+    unsigned topf, level;
+    DD_CTFP cacheOp;
+    int retval;
+
+    zero = Cudd_Not(DD_ONE(dd));
+    if (Cudd_IsConstant(f)) return(f == zero);
+
+    /* From now on f is not constant. */
+    F = Cudd_Regular(f);
+    topf = (unsigned) dd->perm[F->index];
+    level = (unsigned) dd->perm[var->index];
+
+    /* Check terminal case. If topf > index of var, f does not depend on var.
+    ** Therefore, var is not dependent in f. */
+    if (topf > level) {
+	return(0);
+    }
+
+    cacheOp = (DD_CTFP) Cudd_bddVarIsDependent;
+    res = cuddCacheLookup2(dd,cacheOp,f,var);
+    if (res != NULL) {
+	return(res != zero);
+    }
+
+    /* Compute cofactors. */
+    ft = Cudd_NotCond(cuddT(F), f != F);
+    fe = Cudd_NotCond(cuddE(F), f != F);
+
+    if (topf == level) {
+	retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe));
+    } else {
+	retval = Cudd_bddVarIsDependent(dd,ft,var) &&
+	    Cudd_bddVarIsDependent(dd,fe,var);
+    }
+
+    cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval));
+
+    return(retval);
+
+} /* Cudd_bddVarIsDependent */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Cudd_bddExistAbstract.]
+
+  Description [Performs the recursive steps of Cudd_bddExistAbstract.
+  Returns the BDD obtained by abstracting the variables
+  of cube from f if successful; NULL otherwise. It is also used by
+  Cudd_bddUnivAbstract.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddExistAbstract Cudd_bddUnivAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddExistAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * cube)
+{
+    DdNode	*F, *T, *E, *res, *res1, *res2, *one;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    F = Cudd_Regular(f);
+
+    /* Cube is guaranteed to be a cube at this point. */	
+    if (cube == one || F == one) {  
+        return(f);
+    }
+    /* From now on, f and cube are non-constant. */
+
+    /* Abstract a variable that does not appear in f. */
+    while (manager->perm[F->index] > manager->perm[cube->index]) {
+	cube = cuddT(cube);
+	if (cube == one) return(f);
+    }
+
+    /* Check the cache. */
+    if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) {
+	return(res);
+    }
+
+    /* Compute the cofactors of f. */
+    T = cuddT(F); E = cuddE(F);
+    if (f != F) {
+	T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+
+    /* If the two indices are the same, so are their levels. */
+    if (F->index == cube->index) {
+	if (T == one || E == one || T == Cudd_Not(E)) {
+	    return(one);
+	}
+	res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube));
+	if (res1 == NULL) return(NULL);
+	if (res1 == one) {
+	    if (F->ref != 1)
+		cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one);
+	    return(one);
+	}
+        cuddRef(res1);
+	res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube));
+	if (res2 == NULL) {
+	    Cudd_IterDerefBdd(manager,res1);
+	    return(NULL);
+	}
+        cuddRef(res2);
+	res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2));
+	if (res == NULL) {
+	    Cudd_IterDerefBdd(manager, res1);
+	    Cudd_IterDerefBdd(manager, res2);
+	    return(NULL);
+	}
+	res = Cudd_Not(res);
+	cuddRef(res);
+	Cudd_IterDerefBdd(manager, res1);
+	Cudd_IterDerefBdd(manager, res2);
+	if (F->ref != 1)
+	    cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
+	cuddDeref(res);
+        return(res);
+    } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */
+	res1 = cuddBddExistAbstractRecur(manager, T, cube);
+	if (res1 == NULL) return(NULL);
+        cuddRef(res1);
+	res2 = cuddBddExistAbstractRecur(manager, E, cube);
+	if (res2 == NULL) {
+	    Cudd_IterDerefBdd(manager, res1);
+	    return(NULL);
+	}
+        cuddRef(res2);
+	/* ITE takes care of possible complementation of res1 and of the
+        ** case in which res1 == res2. */
+	res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2);
+	if (res == NULL) {
+	    Cudd_IterDerefBdd(manager, res1);
+	    Cudd_IterDerefBdd(manager, res2);
+	    return(NULL);
+	}
+	cuddDeref(res1);
+	cuddDeref(res2);
+	if (F->ref != 1)
+	    cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
+        return(res);
+    }	    
+
+} /* end of cuddBddExistAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
+  the variables in cube. The variables are existentially abstracted.  Returns a
+  pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddXorExistAbstractRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube)
+{
+    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
+    DdNode *one, *zero, *r, *t, *e, *Cube;
+    unsigned int topf, topg, topcube, top, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == g) {
+	return(zero);
+    }
+    if (f == Cudd_Not(g)) {
+	return(one);
+    }
+    if (cube == one) {
+	return(cuddBddXorRecur(manager, f, g));
+    }
+    if (f == one) {
+	return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
+    }
+    if (g == one) {
+	return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
+    }
+    if (f == zero) {
+	return(cuddBddExistAbstractRecur(manager, g, cube));
+    }
+    if (g == zero) {
+	return(cuddBddExistAbstractRecur(manager, f, cube));
+    }
+
+    /* At this point f, g, and cube are not constant. */
+
+    if (f > g) { /* Try to increase cache efficiency. */
+	DdNode *tmp = f;
+	f = g;
+	g = tmp;
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
+    if (r != NULL) {
+	return(r);
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    F = Cudd_Regular(f);
+    topf = manager->perm[F->index];
+    G = Cudd_Regular(g);
+    topg = manager->perm[G->index];
+    top = ddMin(topf, topg);
+    topcube = manager->perm[cube->index];
+
+    if (topcube < top) {
+	return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
+    }
+    /* Now, topcube >= top. */
+
+    if (topf == top) {
+	index = F->index;
+	fv = cuddT(F);
+	fnv = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    fv = Cudd_Not(fv);
+	    fnv = Cudd_Not(fnv);
+	}
+    } else {
+	index = G->index;
+	fv = fnv = f;
+    }
+
+    if (topg == top) {
+	gv = cuddT(G);
+	gnv = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gv = Cudd_Not(gv);
+	    gnv = Cudd_Not(gnv);
+	}
+    } else {
+	gv = gnv = g;
+    }
+
+    if (topcube == top) {
+	Cube = cuddT(cube);
+    } else {
+	Cube = cube;
+    }
+
+    t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
+    if (t == NULL) return(NULL);
+
+    /* Special case: 1 OR anything = 1. Hence, no need to compute
+    ** the else branch if t is 1.
+    */
+    if (t == one && topcube == top) {
+	cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
+	return(one);
+    }
+    cuddRef(t);
+
+    e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
+    if (e == NULL) {
+	Cudd_IterDerefBdd(manager, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (topcube == top) {	/* abstract */
+	r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(manager, t);
+	    Cudd_IterDerefBdd(manager, e);
+	    return(NULL);
+	}
+	r = Cudd_Not(r);
+	cuddRef(r);
+	Cudd_IterDerefBdd(manager, t);
+	Cudd_IterDerefBdd(manager, e);
+	cuddDeref(r);
+    } else if (t == e) {
+	r = t;
+	cuddDeref(t);
+	cuddDeref(e);
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(manager,(int)index,t,e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	}
+	cuddDeref(e);
+	cuddDeref(t);
+    }
+    cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
+    return (r);
+
+} /* end of cuddBddXorExistAbstractRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Cudd_bddBoleanDiff.]
+
+  Description [Performs the recursive steps of Cudd_bddBoleanDiff.
+  Returns the BDD obtained by XORing the cofactors of f with respect to
+  var if successful; NULL otherwise. Exploits the fact that dF/dx =
+  dF'/dx.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddBddBooleanDiffRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * var)
+{
+    DdNode *T, *E, *res, *res1, *res2;
+
+    statLine(manager);
+    if (cuddI(manager,f->index) > manager->perm[var->index]) {
+	/* f does not depend on var. */
+	return(Cudd_Not(DD_ONE(manager)));
+    }
+
+    /* From now on, f is non-constant. */
+
+    /* If the two indices are the same, so are their levels. */
+    if (f->index == var->index) {
+	res = cuddBddXorRecur(manager, cuddT(f), cuddE(f));
+        return(res);
+    }
+
+    /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */
+
+    /* Check the cache. */
+    res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var);
+    if (res != NULL) {
+	return(res);
+    }
+
+    /* Compute the cofactors of f. */
+    T = cuddT(f); E = cuddE(f);
+
+    res1 = cuddBddBooleanDiffRecur(manager, T, var);
+    if (res1 == NULL) return(NULL);
+    cuddRef(res1);
+    res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var);
+    if (res2 == NULL) {
+	Cudd_IterDerefBdd(manager, res1);
+	return(NULL);
+    }
+    cuddRef(res2);
+    /* ITE takes care of possible complementation of res1 and of the
+    ** case in which res1 == res2. */
+    res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(manager, res1);
+	Cudd_IterDerefBdd(manager, res2);
+	return(NULL);
+    }
+    cuddDeref(res1);
+    cuddDeref(res2);
+    cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res);
+    return(res);
+
+} /* end of cuddBddBooleanDiffRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Checks whether cube is an BDD representing the product of
+  positive literals.]
+
+  Description [Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+bddCheckPositiveCube(
+  DdManager * manager,
+  DdNode * cube)
+{
+    if (Cudd_IsComplement(cube)) return(0);
+    if (cube == DD_ONE(manager)) return(1);
+    if (cuddIsConstant(cube)) return(0);
+    if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) {
+        return(bddCheckPositiveCube(manager, cuddT(cube)));
+    }
+    return(0);
+
+} /* end of bddCheckPositiveCube */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddBddCorr.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddBddCorr.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddBddCorr.c	(revision 8)
@@ -0,0 +1,515 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBddCorr.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Correlation between BDDs.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_bddCorrelation()
+		<li> Cudd_bddCorrelationWeights()
+		</ul>
+	    Static procedures included in this module:
+		<ul>
+		<li> bddCorrelationAux()
+		<li> bddCorrelationWeightsAux()
+		<li> CorrelCompare()
+		<li> CorrelHash()
+		<li> CorrelCleanUp()
+		</ul>
+		]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct hashEntry {
+    DdNode *f;
+    DdNode *g;
+} HashEntry;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.14 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+#ifdef CORREL_STATS
+static	int	num_calls;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static double bddCorrelationAux (DdManager *dd, DdNode *f, DdNode *g, st_table *table);
+static double bddCorrelationWeightsAux (DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table);
+static int CorrelCompare (const char *key1, const char *key2);
+static int CorrelHash (char *key, int modulus);
+static enum st_retval CorrelCleanUp (char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the correlation of f and g.]
+
+  Description [Computes the correlation of f and g. If f == g, their
+  correlation is 1. If f == g', their correlation is 0.  Returns the
+  fraction of minterms in the ON-set of the EXNOR of f and g.  If it
+  runs out of memory, returns (double)CUDD_OUT_OF_MEM.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCorrelationWeights]
+
+******************************************************************************/
+double
+Cudd_bddCorrelation(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+
+    st_table	*table;
+    double	correlation;
+
+#ifdef CORREL_STATS
+    num_calls = 0;
+#endif
+
+    table = st_init_table(CorrelCompare,CorrelHash);
+    if (table == NULL) return((double)CUDD_OUT_OF_MEM);
+    correlation = bddCorrelationAux(manager,f,g,table);
+    st_foreach(table, CorrelCleanUp, NIL(char));
+    st_free_table(table);
+    return(correlation);
+
+} /* end of Cudd_bddCorrelation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the correlation of f and g for given input
+  probabilities.]
+
+  Description [Computes the correlation of f and g for given input
+  probabilities. On input, prob\[i\] is supposed to contain the
+  probability of the i-th input variable to be 1.
+  If f == g, their correlation is 1. If f == g', their
+  correlation is 0.  Returns the probability that f and g have the same
+  value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The
+  correlation of f and the constant one gives the probability of f.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCorrelation]
+
+******************************************************************************/
+double
+Cudd_bddCorrelationWeights(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  double * prob)
+{
+
+    st_table	*table;
+    double	correlation;
+
+#ifdef CORREL_STATS
+    num_calls = 0;
+#endif
+
+    table = st_init_table(CorrelCompare,CorrelHash);
+    if (table == NULL) return((double)CUDD_OUT_OF_MEM);
+    correlation = bddCorrelationWeightsAux(manager,f,g,prob,table);
+    st_foreach(table, CorrelCleanUp, NIL(char));
+    st_free_table(table);
+    return(correlation);
+
+} /* end of Cudd_bddCorrelationWeights */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCorrelation.]
+
+  Description [Performs the recursive step of Cudd_bddCorrelation.
+  Returns the fraction of minterms in the ON-set of the EXNOR of f and
+  g.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddCorrelationWeightsAux]
+
+******************************************************************************/
+static double
+bddCorrelationAux(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  st_table * table)
+{
+    DdNode	*Fv, *Fnv, *G, *Gv, *Gnv;
+    double	min, *pmin, min1, min2, *dummy;
+    HashEntry	*entry;
+    unsigned int topF, topG;
+
+    statLine(dd);
+#ifdef CORREL_STATS
+    num_calls++;
+#endif
+
+    /* Terminal cases: only work for BDDs. */
+    if (f == g) return(1.0);
+    if (f == Cudd_Not(g)) return(0.0);
+
+    /* Standardize call using the following properties:
+    **     (f EXNOR g)   = (g EXNOR f)
+    **     (f' EXNOR g') = (f EXNOR g).
+    */
+    if (f > g) {
+	DdNode *tmp = f;
+	f = g; g = tmp;
+    }
+    if (Cudd_IsComplement(f)) {
+	f = Cudd_Not(f);
+	g = Cudd_Not(g);
+    }
+    /* From now on, f is regular. */
+    
+    entry = ALLOC(HashEntry,1);
+    if (entry == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(CUDD_OUT_OF_MEM);
+    }
+    entry->f = f; entry->g = g;
+
+    /* We do not use the fact that
+    ** correlation(f,g') = 1 - correlation(f,g)
+    ** to minimize the risk of cancellation.
+    */
+    if (st_lookup(table, entry, &dummy)) {
+	min = *dummy;
+	FREE(entry);
+	return(min);
+    }
+
+    G = Cudd_Regular(g);
+    topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
+    if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; }
+    if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
+
+    if (g != G) {
+	Gv = Cudd_Not(Gv);
+	Gnv = Cudd_Not(Gnv);
+    }
+
+    min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0;
+    if (min1 == (double)CUDD_OUT_OF_MEM) {
+	FREE(entry);
+	return(CUDD_OUT_OF_MEM);
+    }
+    min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0; 
+    if (min2 == (double)CUDD_OUT_OF_MEM) {
+	FREE(entry);
+	return(CUDD_OUT_OF_MEM);
+    }
+    min = (min1+min2);
+    
+    pmin = ALLOC(double,1);
+    if (pmin == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    *pmin = min;
+
+    if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
+	FREE(entry);
+	FREE(pmin);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    return(min);
+
+} /* end of bddCorrelationAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCorrelationWeigths.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [bddCorrelationAux]
+
+******************************************************************************/
+static double
+bddCorrelationWeightsAux(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  double * prob,
+  st_table * table)
+{
+    DdNode	*Fv, *Fnv, *G, *Gv, *Gnv;
+    double	min, *pmin, min1, min2, *dummy;
+    HashEntry	*entry;
+    int		topF, topG, index;
+
+    statLine(dd);
+#ifdef CORREL_STATS
+    num_calls++;
+#endif
+
+    /* Terminal cases: only work for BDDs. */
+    if (f == g) return(1.0);
+    if (f == Cudd_Not(g)) return(0.0);
+
+    /* Standardize call using the following properties:
+    **     (f EXNOR g)   = (g EXNOR f)
+    **     (f' EXNOR g') = (f EXNOR g).
+    */
+    if (f > g) {
+	DdNode *tmp = f;
+	f = g; g = tmp;
+    }
+    if (Cudd_IsComplement(f)) {
+	f = Cudd_Not(f);
+	g = Cudd_Not(g);
+    }
+    /* From now on, f is regular. */
+    
+    entry = ALLOC(HashEntry,1);
+    if (entry == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    entry->f = f; entry->g = g;
+
+    /* We do not use the fact that
+    ** correlation(f,g') = 1 - correlation(f,g)
+    ** to minimize the risk of cancellation.
+    */
+    if (st_lookup(table, entry, &dummy)) {
+	min = *dummy;
+	FREE(entry);
+	return(min);
+    }
+
+    G = Cudd_Regular(g);
+    topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
+    if (topF <= topG) {
+	Fv = cuddT(f); Fnv = cuddE(f);
+	index = f->index;
+    } else {
+	Fv = Fnv = f;
+	index = G->index;
+    }
+    if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
+
+    if (g != G) {
+	Gv = Cudd_Not(Gv);
+	Gnv = Cudd_Not(Gnv);
+    }
+
+    min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index];
+    if (min1 == (double)CUDD_OUT_OF_MEM) {
+	FREE(entry);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]); 
+    if (min2 == (double)CUDD_OUT_OF_MEM) {
+	FREE(entry);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    min = (min1+min2);
+    
+    pmin = ALLOC(double,1);
+    if (pmin == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    *pmin = min;
+
+    if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
+	FREE(entry);
+	FREE(pmin);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    return(min);
+
+} /* end of bddCorrelationWeightsAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two hash table entries.]
+
+  Description [Compares two hash table entries. Returns 0 if they are
+  identical; 1 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CorrelCompare(
+  const char * key1,
+  const char * key2)
+{
+    HashEntry *entry1;
+    HashEntry *entry2;
+
+    entry1 = (HashEntry *) key1;
+    entry2 = (HashEntry *) key2;
+    if (entry1->f != entry2->f || entry1->g != entry2->g) return(1);
+
+    return(0);
+
+} /* end of CorrelCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hashes a hash table entry.]
+
+  Description [Hashes a hash table entry. It is patterned after
+  st_strhash. Returns a value between 0 and modulus.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+CorrelHash(
+  char * key,
+  int  modulus)
+{
+    HashEntry *entry;
+    int val = 0;
+
+    entry = (HashEntry *) key;
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+    val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g));
+#else
+    val = ((int) entry->f)*997 + ((int) entry->g);
+#endif
+
+    return ((val < 0) ? -val : val) % modulus;
+
+} /* end of CorrelHash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees memory associated with hash table.]
+
+  Description [Frees memory associated with hash table. Returns
+  ST_CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st_retval
+CorrelCleanUp(
+  char * key,
+  char * value,
+  char * arg)
+{
+    double	*d;
+    HashEntry *entry;
+
+    entry = (HashEntry *) key;
+    FREE(entry);
+    d = (double *)value;
+    FREE(d);
+    return ST_CONTINUE;
+
+} /* end of CorrelCleanUp */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddBddIte.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddBddIte.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddBddIte.c	(revision 8)
@@ -0,0 +1,1317 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBddIte.c]
+
+  PackageName [cudd]
+
+  Synopsis    [BDD ITE function and satellites.]
+
+  Description [External procedures included in this module:
+		<ul>
+                <li> Cudd_bddIte()
+       	        <li> Cudd_bddIteConstant()
+		<li> Cudd_bddIntersect()
+		<li> Cudd_bddAnd()
+		<li> Cudd_bddAndLimit()
+		<li> Cudd_bddOr()
+		<li> Cudd_bddNand()
+		<li> Cudd_bddNor()
+		<li> Cudd_bddXor()
+		<li> Cudd_bddXnor()
+		<li> Cudd_bddLeq()
+		</ul>
+       Internal procedures included in this module:
+		<ul>
+		<li> cuddBddIteRecur()
+		<li> cuddBddIntersectRecur()
+		<li> cuddBddAndRecur()
+		<li> cuddBddXorRecur()
+		</ul>
+       Static procedures included in this module:
+		<ul>
+       	        <li> bddVarToConst()
+       	        <li> bddVarToCanonical()
+       	        <li> bddVarToCanonicalSimple()
+		</ul>]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.24 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void bddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one);
+static int bddVarToCanonical (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
+static int bddVarToCanonicalSimple (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITE(f,g,h).]
+
+  Description [Implements ITE(f,g,h). Returns a pointer to the
+  resulting BDD if successful; NULL if the intermediate result blows
+  up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddIteRecur(dd,f,g,h);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddIte */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements ITEconstant(f,g,h).]
+
+  Description [Implements ITEconstant(f,g,h). Returns a pointer to the
+  resulting BDD (which may or may not be constant) or DD_NON_CONSTANT.
+  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIteConstant(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode	 *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
+    DdNode	 *one = DD_ONE(dd);
+    DdNode	 *zero = Cudd_Not(one);
+    int		 comple;
+    unsigned int topf, topg, toph, v;
+
+    statLine(dd);
+    /* Trivial cases. */
+    if (f == one) 			/* ITE(1,G,H) => G */
+	return(g);
+    
+    if (f == zero)			/* ITE(0,G,H) => H */
+	return(h);
+    
+    /* f now not a constant. */
+    bddVarToConst(f, &g, &h, one);	/* possibly convert g or h */
+					/* to constants */
+
+    if (g == h) 			/* ITE(F,G,G) => G */
+	return(g);
+
+    if (Cudd_IsConstant(g) && Cudd_IsConstant(h)) 
+	return(DD_NON_CONSTANT);	/* ITE(F,1,0) or ITE(F,0,1) */
+					/* => DD_NON_CONSTANT */
+    
+    if (g == Cudd_Not(h))
+	return(DD_NON_CONSTANT);	/* ITE(F,G,G') => DD_NON_CONSTANT */
+					/* if F != G and F != G' */
+    
+    comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph);
+
+    /* Cache lookup. */
+    r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h);
+    if (r != NULL) {
+	return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT));
+    }
+
+    v = ddMin(topg, toph);
+
+    /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */
+    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
+	return(DD_NON_CONSTANT);
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+	v = ddMin(topf, v);		/* v = top_var(F,G,H) */
+	Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+	Fv = Fnv = f;
+    }
+
+    if (topg == v) {
+	Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+	Gv = Gnv = g;
+    }
+
+    if (toph == v) {
+	H = Cudd_Regular(h);
+	Hv = cuddT(H); Hnv = cuddE(H);
+	if (Cudd_IsComplement(h)) {
+	    Hv = Cudd_Not(Hv);
+	    Hnv = Cudd_Not(Hnv);
+	}
+    } else {
+	Hv = Hnv = h;
+    }
+
+    /* Recursion. */
+    t = Cudd_bddIteConstant(dd, Fv, Gv, Hv);
+    if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) {
+	cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+	return(DD_NON_CONSTANT);
+    }
+    e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv);
+    if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) {
+	cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
+	return(DD_NON_CONSTANT);
+    }
+    cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t);
+    return(Cudd_NotCond(t,comple));
+
+} /* end of Cudd_bddIteConstant */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a function included in the intersection of f and g.]
+
+  Description [Computes a function included in the intersection of f and
+  g. (That is, a witness that the intersection is not empty.)
+  Cudd_bddIntersect tries to build as few new nodes as possible. If the
+  only result of interest is whether f and g intersect,
+  Cudd_bddLeq should be used instead.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLeq Cudd_bddIteConstant]
+
+******************************************************************************/
+DdNode *
+Cudd_bddIntersect(
+  DdManager * dd /* manager */,
+  DdNode * f /* first operand */,
+  DdNode * g /* second operand */)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddIntersectRecur(dd,f,g);
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddIntersect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the conjunction of two BDDs f and g.]
+
+  Description [Computes the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect
+  Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAnd(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the conjunction of two BDDs f and g.  Returns
+  NULL if too many nodes are required.]
+
+  Description [Computes the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up or more new nodes than <code>limit</code> are
+  required.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAndLimit(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  unsigned int limit)
+{
+    DdNode *res;
+    unsigned int saveLimit = dd->maxLive;
+
+    dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
+    do {
+	dd->reordered = 0;
+	res = cuddBddAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    dd->maxLive = saveLimit;
+    return(res);
+
+} /* end of Cudd_bddAndLimit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the disjunction of two BDDs f and g.]
+
+  Description [Computes the disjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor
+  Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddOr(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
+    } while (dd->reordered == 1);
+    res = Cudd_NotCond(res,res != NULL);
+    return(res);
+
+} /* end of Cudd_bddOr */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the NAND of two BDDs f and g.]
+
+  Description [Computes the NAND of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor
+  Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNand(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    res = Cudd_NotCond(res,res != NULL);
+    return(res);
+
+} /* end of Cudd_bddNand */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the NOR of two BDDs f and g.]
+
+  Description [Computes the NOR of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand
+  Cudd_bddXor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddNor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the exclusive OR of two BDDs f and g.]
+
+  Description [Computes the exclusive OR of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
+  Cudd_bddNand Cudd_bddNor Cudd_bddXnor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddXor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddXorRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddXor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the exclusive NOR of two BDDs f and g.]
+
+  Description [Computes the exclusive NOR of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
+  Cudd_bddNand Cudd_bddNor Cudd_bddXor]
+
+******************************************************************************/
+DdNode *
+Cudd_bddXnor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddXorRecur(dd,f,Cudd_Not(g));
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddXnor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether f is less than or equal to g.]
+
+  Description [Returns 1 if f is less than or equal to g; 0 otherwise.
+  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIteConstant Cudd_addEvalConst]
+
+******************************************************************************/
+int
+Cudd_bddLeq(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn;
+    unsigned int topf, topg, res;
+
+    statLine(dd);
+    /* Terminal cases and normalization. */
+    if (f == g) return(1);
+
+    if (Cudd_IsComplement(g)) {
+	/* Special case: if f is regular and g is complemented,
+	** f(1,...,1) = 1 > 0 = g(1,...,1).
+	*/
+	if (!Cudd_IsComplement(f)) return(0);
+	/* Both are complemented: Swap and complement because
+	** f <= g <=> g' <= f' and we want the second argument to be regular.
+	*/
+	tmp = g;
+	g = Cudd_Not(f);
+	f = Cudd_Not(tmp);
+    } else if (Cudd_IsComplement(f) && g < f) {
+	tmp = g;
+	g = Cudd_Not(f);
+	f = Cudd_Not(tmp);
+    }
+
+    /* Now g is regular and, if f is not regular, f < g. */
+    one = DD_ONE(dd);
+    if (g == one) return(1);	/* no need to test against zero */
+    if (f == one) return(0);	/* since at this point g != one */
+    if (Cudd_Not(f) == g) return(0); /* because neither is constant */
+    zero = Cudd_Not(one);
+    if (f == zero) return(1);
+
+    /* Here neither f nor g is constant. */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_bddLeq,f,g);
+    if (tmp != NULL) {
+	return(tmp == one);
+    }
+
+    /* Compute cofactors. */
+    F = Cudd_Regular(f);
+    topf = dd->perm[F->index];
+    topg = dd->perm[g->index];
+    if (topf <= topg) {
+	fv = cuddT(F); fvn = cuddE(F);
+	if (f != F) {
+	    fv = Cudd_Not(fv);
+	    fvn = Cudd_Not(fvn);
+	}
+    } else {
+	fv = fvn = f;
+    }
+    if (topg <= topf) {
+	gv = cuddT(g); gvn = cuddE(g);
+    } else {
+	gv = gvn = g;
+    }
+
+    /* Recursive calls. Since we want to maximize the probability of
+    ** the special case f(1,...,1) > g(1,...,1), we consider the negative
+    ** cofactors first. Indeed, the complementation parity of the positive
+    ** cofactors is the same as the one of the parent functions.
+    */
+    res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv);
+
+    /* Store result in cache and return. */
+    cuddCacheInsert2(dd,(DD_CTFP)Cudd_bddLeq,f,g,(res ? one : zero));
+    return(res);
+
+} /* end of Cudd_bddLeq */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddIte.]
+
+  Description [Implements the recursive step of Cudd_bddIte. Returns a
+  pointer to the resulting BDD. NULL if the intermediate result blows
+  up or if reordering occurs.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddBddIteRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode	 *one, *zero, *res;
+    DdNode	 *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
+    unsigned int topf, topg, toph, v;
+    int		 index;
+    int		 comple;
+
+    statLine(dd);
+    /* Terminal cases. */
+
+    /* One variable cases. */
+    if (f == (one = DD_ONE(dd))) 	/* ITE(1,G,H) = G */
+	return(g);
+    
+    if (f == (zero = Cudd_Not(one))) 	/* ITE(0,G,H) = H */
+	return(h);
+    
+    /* From now on, f is known not to be a constant. */
+    if (g == one || f == g) {	/* ITE(F,F,H) = ITE(F,1,H) = F + H */
+	if (h == zero) {	/* ITE(F,1,0) = F */
+	    return(f);
+	} else {
+	    res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
+	    return(Cudd_NotCond(res,res != NULL));
+	}
+    } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
+	if (h == one) {		/* ITE(F,0,1) = !F */
+	    return(Cudd_Not(f));
+	} else {
+	    res = cuddBddAndRecur(dd,Cudd_Not(f),h);
+	    return(res);
+	}
+    }
+    if (h == zero || f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+	res = cuddBddAndRecur(dd,f,g);
+	return(res);
+    } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
+	res = cuddBddAndRecur(dd,f,Cudd_Not(g));
+	return(Cudd_NotCond(res,res != NULL));
+    }
+
+    /* Check remaining one variable case. */
+    if (g == h) { 		/* ITE(F,G,G) = G */
+	return(g);
+    } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
+	res = cuddBddXorRecur(dd,f,h);
+	return(res);
+    }
+    
+    /* From here, there are no constants. */
+    comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);
+
+    /* f & g are now regular pointers */
+
+    v = ddMin(topg, toph);
+
+    /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
+    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
+	r = cuddUniqueInter(dd, (int) f->index, g, h);
+	return(Cudd_NotCond(r,comple && r != NULL));
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
+    if (r != NULL) {
+	return(Cudd_NotCond(r,comple));
+    }
+
+    /* Compute cofactors. */
+    if (topf <= v) {
+	v = ddMin(topf, v);	/* v = top_var(F,G,H) */
+	index = f->index;
+	Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+	Fv = Fnv = f;
+    }
+    if (topg == v) {
+	index = g->index;
+	Gv = cuddT(g); Gnv = cuddE(g);
+    } else {
+	Gv = Gnv = g;
+    }
+    if (toph == v) {
+	H = Cudd_Regular(h);
+	index = H->index;
+	Hv = cuddT(H); Hnv = cuddE(H);
+	if (Cudd_IsComplement(h)) {
+	    Hv = Cudd_Not(Hv);
+	    Hnv = Cudd_Not(Hnv);
+	}
+    } else {
+	Hv = Hnv = h;
+    }
+
+    /* Recursive step. */
+    t = cuddBddIteRecur(dd,Fv,Gv,Hv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
+    if (e == NULL) {
+	Cudd_IterDerefBdd(dd,t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+    if (r == NULL) {
+	Cudd_IterDerefBdd(dd,t);
+	Cudd_IterDerefBdd(dd,e);
+	return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddIteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddIntersect.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIntersect]
+
+******************************************************************************/
+DdNode *
+cuddBddIntersectRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+    DdNode *F, *G, *t, *e;
+    DdNode *fv, *fnv, *gv, *gnv;
+    DdNode *one, *zero;
+    unsigned int index, topf, topg;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == g || g == one) return(f);
+    if (f == one) return(g);
+
+    /* At this point f and g are not constant. */
+    if (f > g) { DdNode *tmp = f; f = g; g = tmp; }
+    res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g);
+    if (res != NULL) return(res);
+
+    /* Find splitting variable. Here we can skip the use of cuddI,
+    ** because the operands are known to be non-constant.
+    */
+    F = Cudd_Regular(f);
+    topf = dd->perm[F->index];
+    G = Cudd_Regular(g);
+    topg = dd->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+	index = F->index;
+	fv = cuddT(F);
+	fnv = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    fv = Cudd_Not(fv);
+	    fnv = Cudd_Not(fnv);
+	}
+    } else {
+	index = G->index;
+	fv = fnv = f;
+    }
+
+    if (topg <= topf) {
+	gv = cuddT(G);
+	gnv = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gv = Cudd_Not(gv);
+	    gnv = Cudd_Not(gnv);
+	}
+    } else {
+	gv = gnv = g;
+    }
+
+    /* Compute partial results. */
+    t = cuddBddIntersectRecur(dd,fv,gv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    if (t != zero) {
+	e = zero;
+    } else {
+	e = cuddBddIntersectRecur(dd,fnv,gnv);
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+    }
+    cuddRef(e);
+
+    if (t == e) { /* both equal zero */
+	res = t;
+    } else if (Cudd_IsComplement(t)) {
+	res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e));
+	if (res == NULL) {
+	    Cudd_IterDerefBdd(dd, t);
+	    Cudd_IterDerefBdd(dd, e);
+	    return(NULL);
+	}
+	res = Cudd_Not(res);
+    } else {
+	res = cuddUniqueInter(dd,(int)index,t,e);
+	if (res == NULL) {
+	    Cudd_IterDerefBdd(dd, t);
+	    Cudd_IterDerefBdd(dd, e);
+	    return(NULL);
+	}
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+
+    cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res);
+
+    return(res);
+
+} /* end of cuddBddIntersectRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddAnd.]
+
+  Description [Implements the recursive step of Cudd_bddAnd by taking
+  the conjunction of two BDDs.  Returns a pointer to the result is
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+cuddBddAndRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
+    DdNode *one, *r, *t, *e;
+    unsigned int topf, topg, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+
+    /* Terminal cases. */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    if (F == G) {
+	if (f == g) return(f);
+	else return(Cudd_Not(one));
+    }
+    if (F == one) {
+	if (f == one) return(g);
+	else return(f);
+    }
+    if (G == one) {
+	if (g == one) return(f);
+	else return(g);
+    }
+
+    /* At this point f and g are not constant. */
+    if (f > g) { /* Try to increase cache efficiency. */
+	DdNode *tmp = f;
+	f = g;
+	g = tmp;
+	F = Cudd_Regular(f);
+	G = Cudd_Regular(g);
+    }
+
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+	r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
+	if (r != NULL) return(r);
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+	index = F->index;
+	fv = cuddT(F);
+	fnv = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    fv = Cudd_Not(fv);
+	    fnv = Cudd_Not(fnv);
+	}
+    } else {
+	index = G->index;
+	fv = fnv = f;
+    }
+
+    if (topg <= topf) {
+	gv = cuddT(G);
+	gnv = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gv = Cudd_Not(gv);
+	    gnv = Cudd_Not(gnv);
+	}
+    } else {
+	gv = gnv = g;
+    }
+
+    t = cuddBddAndRecur(manager, fv, gv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddAndRecur(manager, fnv, gnv);
+    if (e == NULL) {
+	Cudd_IterDerefBdd(manager, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+	r = t;
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(manager,(int)index,t,e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	}
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    if (F->ref != 1 || G->ref != 1)
+	cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
+    return(r);
+
+} /* end of cuddBddAndRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddXor.]
+
+  Description [Implements the recursive step of Cudd_bddXor by taking
+  the exclusive OR of two BDDs.  Returns a pointer to the result is
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddXor]
+
+******************************************************************************/
+DdNode *
+cuddBddXorRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *fv, *fnv, *G, *gv, *gnv;
+    DdNode *one, *zero, *r, *t, *e;
+    unsigned int topf, topg, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == g) return(zero);
+    if (f == Cudd_Not(g)) return(one);
+    if (f > g) { /* Try to increase cache efficiency and simplify tests. */
+	DdNode *tmp = f;
+	f = g;
+	g = tmp;
+    }
+    if (g == zero) return(f);
+    if (g == one) return(Cudd_Not(f));
+    if (Cudd_IsComplement(f)) {
+	f = Cudd_Not(f);
+	g = Cudd_Not(g);
+    }
+    /* Now the first argument is regular. */
+    if (f == one) return(Cudd_Not(g));
+
+    /* At this point f and g are not constant. */
+
+    /* Check cache. */
+    r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
+    if (r != NULL) return(r);
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[f->index];
+    G = Cudd_Regular(g);
+    topg = manager->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+	index = f->index;
+	fv = cuddT(f);
+	fnv = cuddE(f);
+    } else {
+	index = G->index;
+	fv = fnv = f;
+    }
+
+    if (topg <= topf) {
+	gv = cuddT(G);
+	gnv = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gv = Cudd_Not(gv);
+	    gnv = Cudd_Not(gnv);
+	}
+    } else {
+	gv = gnv = g;
+    }
+
+    t = cuddBddXorRecur(manager, fv, gv);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddXorRecur(manager, fnv, gnv);
+    if (e == NULL) {
+	Cudd_IterDerefBdd(manager, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+	r = t;
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(manager,(int)index,t,e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	}
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    cuddCacheInsert2(manager, Cudd_bddXor, f, g, r);
+    return(r);
+
+} /* end of cuddBddXorRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Replaces variables with constants if possible.]
+
+  Description [This function performs part of the transformation to
+  standard form by replacing variables with constants if possible.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddVarToCanonical bddVarToCanonicalSimple]
+
+******************************************************************************/
+static void
+bddVarToConst(
+  DdNode * f,
+  DdNode ** gp,
+  DdNode ** hp,
+  DdNode * one)
+{
+    DdNode *g = *gp;
+    DdNode *h = *hp;
+
+    if (f == g) {    /* ITE(F,F,H) = ITE(F,1,H) = F + H */
+	*gp = one;
+    } else if (f == Cudd_Not(g)) {    /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
+	*gp = Cudd_Not(one);
+    }
+    if (f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+	*hp = Cudd_Not(one);
+    } else if (f == Cudd_Not(h)) {    /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
+	*hp = one;
+    }
+
+} /* end of bddVarToConst */
+
+
+/**Function********************************************************************
+
+  Synopsis [Picks unique member from equiv expressions.]
+
+  Description [Reduces 2 variable expressions to canonical form.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddVarToConst bddVarToCanonicalSimple]
+
+******************************************************************************/
+static int
+bddVarToCanonical(
+  DdManager * dd,
+  DdNode ** fp,
+  DdNode ** gp,
+  DdNode ** hp,
+  unsigned int * topfp,
+  unsigned int * topgp,
+  unsigned int * tophp)
+{
+    register DdNode		*F, *G, *H, *r, *f, *g, *h;
+    register unsigned int	topf, topg, toph;
+    DdNode			*one = dd->one;
+    int				comple, change;
+
+    f = *fp;
+    g = *gp;
+    h = *hp;
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    H = Cudd_Regular(h);
+    topf = cuddI(dd,F->index);
+    topg = cuddI(dd,G->index);
+    toph = cuddI(dd,H->index);
+
+    change = 0;
+
+    if (G == one) {			/* ITE(F,c,H) */
+	if ((topf > toph) || (topf == toph && f > h)) {
+	    r = h;
+	    h = f;
+	    f = r;			/* ITE(F,1,H) = ITE(H,1,F) */
+	    if (g != one) {	/* g == zero */
+		f = Cudd_Not(f);		/* ITE(F,0,H) = ITE(!H,0,!F) */
+		h = Cudd_Not(h);
+	    }
+	    change = 1;
+	}
+    } else if (H == one) {		/* ITE(F,G,c) */
+	if ((topf > topg) || (topf == topg && f > g)) {
+	    r = g;
+	    g = f;
+	    f = r;			/* ITE(F,G,0) = ITE(G,F,0) */
+	    if (h == one) {
+		f = Cudd_Not(f);		/* ITE(F,G,1) = ITE(!G,!F,1) */
+		g = Cudd_Not(g);
+	    }
+	    change = 1;
+	}
+    } else if (g == Cudd_Not(h)) {	/* ITE(F,G,!G) = ITE(G,F,!F) */
+	if ((topf > topg) || (topf == topg && f > g)) {
+	    r = f;
+	    f = g;
+	    g = r;
+	    h = Cudd_Not(r);
+	    change = 1;
+	}
+    }
+    /* adjust pointers so that the first 2 arguments to ITE are regular */
+    if (Cudd_IsComplement(f) != 0) {	/* ITE(!F,G,H) = ITE(F,H,G) */
+	f = Cudd_Not(f);
+	r = g;
+	g = h;
+	h = r;
+	change = 1;
+    }
+    comple = 0;
+    if (Cudd_IsComplement(g) != 0) {	/* ITE(F,!G,H) = !ITE(F,G,!H) */
+	g = Cudd_Not(g);
+	h = Cudd_Not(h);
+	change = 1;
+	comple = 1;
+    }
+    if (change != 0) {
+	*fp = f;
+	*gp = g;
+	*hp = h;
+    }
+    *topfp = cuddI(dd,f->index);
+    *topgp = cuddI(dd,g->index);
+    *tophp = cuddI(dd,Cudd_Regular(h)->index);
+
+    return(comple);
+
+} /* end of bddVarToCanonical */
+
+
+/**Function********************************************************************
+
+  Synopsis [Picks unique member from equiv expressions.]
+
+  Description [Makes sure the first two pointers are regular.  This
+  mat require the complementation of the result, which is signaled by
+  returning 1 instead of 0.  This function is simpler than the general
+  case because it assumes that no two arguments are the same or
+  complementary, and no argument is constant.]
+
+  SideEffects [None]
+
+  SeeAlso     [bddVarToConst bddVarToCanonical]
+
+******************************************************************************/
+static int
+bddVarToCanonicalSimple(
+  DdManager * dd,
+  DdNode ** fp,
+  DdNode ** gp,
+  DdNode ** hp,
+  unsigned int * topfp,
+  unsigned int * topgp,
+  unsigned int * tophp)
+{
+    register DdNode		*r, *f, *g, *h;
+    int				comple, change;
+
+    f = *fp;
+    g = *gp;
+    h = *hp;
+
+    change = 0;
+
+    /* adjust pointers so that the first 2 arguments to ITE are regular */
+    if (Cudd_IsComplement(f)) {	/* ITE(!F,G,H) = ITE(F,H,G) */
+	f = Cudd_Not(f);
+	r = g;
+	g = h;
+	h = r;
+	change = 1;
+    }
+    comple = 0;
+    if (Cudd_IsComplement(g)) {	/* ITE(F,!G,H) = !ITE(F,G,!H) */
+	g = Cudd_Not(g);
+	h = Cudd_Not(h);
+	change = 1;
+	comple = 1;
+    }
+    if (change) {
+	*fp = f;
+	*gp = g;
+	*hp = h;
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    *topfp = dd->perm[f->index];
+    *topgp = dd->perm[g->index];
+    *tophp = dd->perm[Cudd_Regular(h)->index];
+
+    return(comple);
+
+} /* end of bddVarToCanonicalSimple */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddBridge.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddBridge.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddBridge.c	(revision 8)
@@ -0,0 +1,1016 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddBridge.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Translation from BDD to ADD and vice versa and transfer between
+  different managers.]
+
+  Description [External procedures included in this file:
+	    <ul>
+	    <li> Cudd_addBddThreshold()
+	    <li> Cudd_addBddStrictThreshold()
+	    <li> Cudd_addBddInterval()
+	    <li> Cudd_addBddIthBit()
+	    <li> Cudd_BddToAdd()
+	    <li> Cudd_addBddPattern()
+	    <li> Cudd_bddTransfer()
+	    </ul>
+	Internal procedures included in this file:
+	    <ul>
+	    <li> cuddBddTransfer()
+	    <li> cuddAddBddDoPattern()
+	    </ul>
+	Static procedures included in this file:
+	    <ul>
+	    <li> addBddDoThreshold()
+	    <li> addBddDoStrictThreshold()
+	    <li> addBddDoInterval()
+	    <li> addBddDoIthBit()
+	    <li> ddBddToAddRecur()
+	    <li> cuddBddTransferRecur()
+	    </ul>
+	    ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddBridge.c,v 1.18 2004/08/13 18:04:46 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addBddDoThreshold (DdManager *dd, DdNode *f, DdNode *val);
+static DdNode * addBddDoStrictThreshold (DdManager *dd, DdNode *f, DdNode *val);
+static DdNode * addBddDoInterval (DdManager *dd, DdNode *f, DdNode *l, DdNode *u);
+static DdNode * addBddDoIthBit (DdManager *dd, DdNode *f, DdNode *index);
+static DdNode * ddBddToAddRecur (DdManager *dd, DdNode *B);
+static DdNode * cuddBddTransferRecur (DdManager *ddS, DdManager *ddD, DdNode *f, st_table *table);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants greater than or equal to value with 1, and all other
+  discriminants with 0. Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd
+  Cudd_addBddStrictThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddThreshold(
+  DdManager * dd,
+  DdNode * f,
+  CUDD_VALUE_TYPE  value)
+{
+    DdNode *res;
+    DdNode *val;
+    
+    val = cuddUniqueConst(dd,value);
+    if (val == NULL) return(NULL);
+    cuddRef(val);
+
+    do {
+	dd->reordered = 0;
+	res = addBddDoThreshold(dd, f, val);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, val);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, val);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants STRICTLY greater than value with 1, and all other
+  discriminants with 0. Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd 
+  Cudd_addBddThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddStrictThreshold(
+  DdManager * dd,
+  DdNode * f,
+  CUDD_VALUE_TYPE  value)
+{
+    DdNode *res;
+    DdNode *val;
+    
+    val = cuddUniqueConst(dd,value);
+    if (val == NULL) return(NULL);
+    cuddRef(val);
+
+    do {
+	dd->reordered = 0;
+	res = addBddDoStrictThreshold(dd, f, val);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, val);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, val);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddStrictThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants greater than or equal to lower and less than or equal to
+  upper with 1, and all other discriminants with 0. Returns a pointer to
+  the resulting BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddThreshold Cudd_addBddStrictThreshold 
+  Cudd_addBddPattern Cudd_BddToAdd]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddInterval(
+  DdManager * dd,
+  DdNode * f,
+  CUDD_VALUE_TYPE  lower,
+  CUDD_VALUE_TYPE  upper)
+{
+    DdNode *res;
+    DdNode *l;
+    DdNode *u;
+    
+    /* Create constant nodes for the interval bounds, so that we can use
+    ** the global cache.
+    */
+    l = cuddUniqueConst(dd,lower);
+    if (l == NULL) return(NULL);
+    cuddRef(l);
+    u = cuddUniqueConst(dd,upper);
+    if (u == NULL) {
+	Cudd_RecursiveDeref(dd,l);
+	return(NULL);
+    }
+    cuddRef(u);
+
+    do {
+	dd->reordered = 0;
+	res = addBddDoInterval(dd, f, l, u);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, l);
+	Cudd_RecursiveDeref(dd, u);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, l);
+    Cudd_RecursiveDeref(dd, u);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddInterval */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD by extracting the i-th bit from
+  the leaves.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants whose i-th bit is equal to 1 with 1, and all other
+  discriminants with 0. The i-th bit refers to the integer
+  representation of the leaf value. If the value is has a fractional
+  part, it is ignored. Repeated calls to this procedure allow one to
+  transform an integer-valued ADD into an array of BDDs, one for each
+  bit of the leaf values. Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddIthBit(
+  DdManager * dd,
+  DdNode * f,
+  int  bit)
+{
+    DdNode *res;
+    DdNode *index;
+    
+    index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit);
+    if (index == NULL) return(NULL);
+    cuddRef(index);
+
+    do {
+	dd->reordered = 0;
+	res = addBddDoIthBit(dd, f, index);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, index);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, index);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addBddIthBit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a BDD to a 0-1 ADD.]
+
+  Description [Converts a BDD to a 0-1 ADD. Returns a pointer to the
+  resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addBddPattern Cudd_addBddThreshold Cudd_addBddInterval
+  Cudd_addBddStrictThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_BddToAdd(
+  DdManager * dd,
+  DdNode * B)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = ddBddToAddRecur(dd, B);
+    } while (dd->reordered ==1);
+    return(res);
+
+} /* end of Cudd_BddToAdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an ADD to a BDD.]
+
+  Description [Converts an ADD to a BDD by replacing all
+  discriminants different from 0 with 1. Returns a pointer to the
+  resulting BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_BddToAdd Cudd_addBddThreshold Cudd_addBddInterval
+  Cudd_addBddStrictThreshold]
+
+******************************************************************************/
+DdNode *
+Cudd_addBddPattern(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+    
+    do {
+	dd->reordered = 0;
+	res = cuddAddBddDoPattern(dd, f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addBddPattern */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. The orders of the
+  variables in the two managers may be different. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_bddTransfer(
+  DdManager * ddSource,
+  DdManager * ddDestination,
+  DdNode * f)
+{
+    DdNode *res;
+    do {
+	ddDestination->reordered = 0;
+	res = cuddBddTransfer(ddSource, ddDestination, f);
+    } while (ddDestination->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddTransfer */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Convert a BDD from a manager to another one.]
+
+  Description [Convert a BDD from a manager to another one. Returns a
+  pointer to the BDD in the destination manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddTransfer]
+
+******************************************************************************/
+DdNode *
+cuddBddTransfer(
+  DdManager * ddS,
+  DdManager * ddD,
+  DdNode * f)
+{
+    DdNode *res;
+    st_table *table = NULL;
+    st_generator *gen = NULL;
+    DdNode *key, *value;
+
+    table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (table == NULL) goto failure;
+    res = cuddBddTransferRecur(ddS, ddD, f, table);
+    if (res != NULL) cuddRef(res);
+
+    /* Dereference all elements in the table and dispose of the table.
+    ** This must be done also if res is NULL to avoid leaks in case of
+    ** reordering. */
+    gen = st_init_gen(table);
+    if (gen == NULL) goto failure;
+    while (st_gen(gen, &key, &value)) {
+	Cudd_RecursiveDeref(ddD, value);
+    }
+    st_free_gen(gen); gen = NULL;
+    st_free_table(table); table = NULL;
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+failure:
+    if (table != NULL) st_free_table(table);
+    if (gen != NULL) st_free_gen(gen);
+    return(NULL);
+
+} /* end of cuddBddTransfer */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddPattern.]
+
+  Description [Performs the recursive step for Cudd_addBddPattern. Returns a
+  pointer to the resulting BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddAddBddDoPattern(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+	return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup1(dd,Cudd_addBddPattern,f);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = cuddAddBddDoPattern(dd,fv);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = cuddAddBddDoPattern(dd,fvn);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+	res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+	res = Cudd_Not(res);
+    } else {
+	res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert1(dd,Cudd_addBddPattern,f,res);
+
+    return(res);
+
+} /* end of cuddAddBddDoPattern */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddThreshold.]
+
+  Description [Performs the recursive step for Cudd_addBddThreshold.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [addBddDoStrictThreshold]
+
+******************************************************************************/
+static DdNode *
+addBddDoThreshold(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * val)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+	return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(val)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addBddDoThreshold,f,val);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoThreshold(dd,fv,val);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoThreshold(dd,fvn,val);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+	res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+	res = Cudd_Not(res);
+    } else {
+	res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addBddDoThreshold,f,val,res);
+
+    return(res);
+
+} /* end of addBddDoThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddStrictThreshold.]
+
+  Description [Performs the recursive step for Cudd_addBddStrictThreshold.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [addBddDoThreshold]
+
+******************************************************************************/
+static DdNode *
+addBddDoStrictThreshold(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * val)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+	return(Cudd_NotCond(DD_ONE(dd),cuddV(f) <= cuddV(val)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoStrictThreshold(dd,fv,val);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoStrictThreshold(dd,fvn,val);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+	res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+	res = Cudd_Not(res);
+    } else {
+	res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res);
+
+    return(res);
+
+} /* end of addBddDoStrictThreshold */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddInterval.]
+
+  Description [Performs the recursive step for Cudd_addBddInterval.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [addBddDoThreshold addBddDoStrictThreshold]
+
+******************************************************************************/
+static DdNode *
+addBddDoInterval(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * l,
+  DdNode * u)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+	return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(l) || cuddV(f) > cuddV(u)));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoInterval(dd,fv,l,u);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoInterval(dd,fvn,l,u);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+	res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+	res = Cudd_Not(res);
+    } else {
+	res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u,res);
+
+    return(res);
+
+} /* end of addBddDoInterval */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_addBddIthBit.]
+
+  Description [Performs the recursive step for Cudd_addBddIthBit.
+  Returns a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+addBddDoIthBit(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * index)
+{
+    DdNode *res, *T, *E;
+    DdNode *fv, *fvn;
+    int mask, value;
+    int v;
+
+    statLine(dd);
+    /* Check terminal case. */
+    if (cuddIsConstant(f)) {
+	mask = 1 << ((int) cuddV(index));
+	value = (int) cuddV(f);
+	return(Cudd_NotCond(DD_ONE(dd),(value & mask) == 0));
+    }
+
+    /* Check cache. */
+    res = cuddCacheLookup2(dd,addBddDoIthBit,f,index);
+    if (res != NULL) return(res);
+
+    /* Recursive step. */
+    v = f->index;
+    fv = cuddT(f); fvn = cuddE(f);
+
+    T = addBddDoIthBit(dd,fv,index);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = addBddDoIthBit(dd,fvn,index);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+    if (Cudd_IsComplement(T)) {
+	res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E));
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+	res = Cudd_Not(res);
+    } else {
+	res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    /* Store result. */
+    cuddCacheInsert2(dd,addBddDoIthBit,f,index,res);
+
+    return(res);
+
+} /* end of addBddDoIthBit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step for Cudd_BddToAdd.]
+
+  Description [Performs the recursive step for Cudd_BddToAdd. Returns a
+  pointer to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+ddBddToAddRecur(
+  DdManager * dd,
+  DdNode * B)
+{
+    DdNode *one;
+    DdNode *res, *res1, *T, *E, *Bt, *Be;
+    int complement = 0;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+
+    if (Cudd_IsConstant(B)) {
+	if (B == one) {
+	    res = one;
+	} else {
+	    res = DD_ZERO(dd);
+	}
+	return(res);
+    }
+    /* Check visited table */
+    res = cuddCacheLookup1(dd,ddBddToAddRecur,B);
+    if (res != NULL) return(res);
+
+    if (Cudd_IsComplement(B)) {
+	complement = 1;
+	Bt = cuddT(Cudd_Regular(B));
+	Be = cuddE(Cudd_Regular(B));
+    } else {
+	Bt = cuddT(B);
+	Be = cuddE(B);
+    }
+
+    T = ddBddToAddRecur(dd, Bt);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+
+    E = ddBddToAddRecur(dd, Be);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    /* No need to check for T == E, because it is guaranteed not to happen. */
+    res = cuddUniqueInter(dd, (int) Cudd_Regular(B)->index, T, E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd ,T);
+	Cudd_RecursiveDeref(dd ,E);
+	return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+
+    if (complement) {
+	cuddRef(res);
+	res1 = cuddAddCmplRecur(dd, res);
+	if (res1 == NULL) {
+	    Cudd_RecursiveDeref(dd, res);
+	    return(NULL);
+	}
+	cuddRef(res1);
+	Cudd_RecursiveDeref(dd, res);
+	res = res1;
+	cuddDeref(res);
+    }
+
+    /* Store result. */
+    cuddCacheInsert1(dd,ddBddToAddRecur,B,res);
+
+    return(res);
+
+} /* end of ddBddToAddRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddTransfer.]
+
+  Description [Performs the recursive step of Cudd_bddTransfer.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBddTransfer]
+
+******************************************************************************/
+static DdNode *
+cuddBddTransferRecur(
+  DdManager * ddS,
+  DdManager * ddD,
+  DdNode * f,
+  st_table * table)
+{
+    DdNode *ft, *fe, *t, *e, *var, *res;
+    DdNode *one, *zero;
+    int	   index;
+    int    comple = 0;
+
+    statLine(ddD);
+    one = DD_ONE(ddD);
+    comple = Cudd_IsComplement(f);
+
+    /* Trivial cases. */
+    if (Cudd_IsConstant(f)) return(Cudd_NotCond(one, comple));
+
+    /* Make canonical to increase the utilization of the cache. */
+    f = Cudd_NotCond(f,comple);
+    /* Now f is a regular pointer to a non-constant node. */
+
+    /* Check the cache. */
+    if(st_lookup(table, f, &res))
+	return(Cudd_NotCond(res,comple));
+    
+    /* Recursive step. */
+    index = f->index;
+    ft = cuddT(f); fe = cuddE(f);
+
+    t = cuddBddTransferRecur(ddS, ddD, ft, table);
+    if (t == NULL) {
+    	return(NULL);
+    }
+    cuddRef(t);
+
+    e = cuddBddTransferRecur(ddS, ddD, fe, table);
+    if (e == NULL) {
+    	Cudd_RecursiveDeref(ddD, t);
+    	return(NULL);
+    }
+    cuddRef(e);
+
+    zero = Cudd_Not(one);
+    var = cuddUniqueInter(ddD,index,one,zero);
+    if (var == NULL) {
+	Cudd_RecursiveDeref(ddD, t);
+	Cudd_RecursiveDeref(ddD, e);
+    	return(NULL);
+    }
+    res = cuddBddIteRecur(ddD,var,t,e);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(ddD, t);
+	Cudd_RecursiveDeref(ddD, e);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(ddD, t);
+    Cudd_RecursiveDeref(ddD, e);
+
+    if (st_add_direct(table, (char *) f, (char *) res) == ST_OUT_OF_MEM) {
+	Cudd_RecursiveDeref(ddD, res);
+	return(NULL);
+    }
+    return(Cudd_NotCond(res,comple));
+
+} /* end of cuddBddTransferRecur */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddCache.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddCache.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddCache.c	(revision 8)
@@ -0,0 +1,1050 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCache.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for cache insertion and lookup.]
+
+  Description [Internal procedures included in this module:
+		<ul>
+		<li> cuddInitCache()
+		<li> cuddCacheInsert()
+		<li> cuddCacheInsert2()
+		<li> cuddCacheLookup()
+		<li> cuddCacheLookupZdd()
+		<li> cuddCacheLookup2()
+		<li> cuddCacheLookup2Zdd()
+		<li> cuddConstantLookup()
+		<li> cuddCacheProfile()
+		<li> cuddCacheResize()
+		<li> cuddCacheFlush()
+		<li> cuddComputeFloorLog2()
+		</ul>
+	    Static procedures included in this module:
+		<ul>
+		</ul> ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifdef DD_CACHE_PROFILE
+#define DD_HYSTO_BINS 8
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.33 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the computed table.]
+
+  Description [Initializes the computed table. It is called by
+  Cudd_Init. Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Init]
+
+******************************************************************************/
+int
+cuddInitCache(
+  DdManager * unique /* unique table */,
+  unsigned int cacheSize /* initial size of the cache */,
+  unsigned int maxCacheSize /* cache size beyond which no resizing occurs */)
+{
+    int i;
+    unsigned int logSize;
+#ifndef DD_CACHE_PROFILE
+    DdNodePtr *mem;
+    ptruint offset;
+#endif
+
+    /* Round cacheSize to largest power of 2 not greater than the requested
+    ** initial cache size. */
+    logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2));
+    cacheSize = 1 << logSize;
+    unique->acache = ALLOC(DdCache,cacheSize+1);
+    if (unique->acache == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    /* If the size of the cache entry is a power of 2, we want to
+    ** enforce alignment to that power of two. This happens when
+    ** DD_CACHE_PROFILE is not defined. */
+#ifdef DD_CACHE_PROFILE
+    unique->cache = unique->acache;
+    unique->memused += (cacheSize) * sizeof(DdCache);
+#else
+    mem = (DdNodePtr *) unique->acache;
+    offset = (ptruint) mem & (sizeof(DdCache) - 1);
+    mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr);
+    unique->cache = (DdCache *) mem;
+    assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0);
+    unique->memused += (cacheSize+1) * sizeof(DdCache);
+#endif
+    unique->cacheSlots = cacheSize;
+    unique->cacheShift = sizeof(int) * 8 - logSize;
+    unique->maxCacheHard = maxCacheSize;
+    /* If cacheSlack is non-negative, we can resize. */
+    unique->cacheSlack = (int) ddMin(maxCacheSize,
+	DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) -
+	2 * (int) cacheSize;
+    Cudd_SetMinHit(unique,DD_MIN_HIT);
+    /* Initialize to avoid division by 0 and immediate resizing. */
+    unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1);
+    unique->cacheHits = 0;
+    unique->totCachehits = 0;
+    /* The sum of cacheMisses and totCacheMisses is always correct,
+    ** even though cacheMisses is larger than it should for the reasons
+    ** explained above. */
+    unique->totCacheMisses = -unique->cacheMisses;
+    unique->cachecollisions = 0;
+    unique->cacheinserts = 0;
+    unique->cacheLastInserts = 0;
+    unique->cachedeletions = 0;
+
+    /* Initialize the cache */
+    for (i = 0; (unsigned) i < cacheSize; i++) {
+	unique->cache[i].h = 0; /* unused slots */
+	unique->cache[i].data = NULL; /* invalid entry */
+#ifdef DD_CACHE_PROFILE
+	unique->cache[i].count = 0;
+#endif
+    }
+
+    return(1);
+
+} /* end of cuddInitCache */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheInsert2 cuddCacheInsert1]
+
+******************************************************************************/
+void
+cuddCacheInsert(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h,
+  DdNode * data)
+{
+    int posn;
+    register DdCache *entry;
+    ptruint uf, ug, uh;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    posn = ddCHash2(uh,uf,ug,table->cacheShift);
+    entry = &table->cache[posn];
+
+    table->cachecollisions += entry->data != NULL;
+    table->cacheinserts++;
+
+    entry->f    = (DdNode *) uf;
+    entry->g    = (DdNode *) ug;
+    entry->h    = uh;
+    entry->data = data;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+
+} /* end of cuddCacheInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in the cache for a function with two
+  operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheInsert cuddCacheInsert1]
+
+******************************************************************************/
+void
+cuddCacheInsert2(
+  DdManager * table,
+  DD_CTFP op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * data)
+{
+    int posn;
+    register DdCache *entry;
+
+    posn = ddCHash2(op,f,g,table->cacheShift);
+    entry = &table->cache[posn];
+
+    if (entry->data != NULL) {
+        table->cachecollisions++;
+    }
+    table->cacheinserts++;
+
+    entry->f = f;
+    entry->g = g;
+    entry->h = (ptruint) op;
+    entry->data = data;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+
+} /* end of cuddCacheInsert2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in the cache for a function with two
+  operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheInsert cuddCacheInsert2]
+
+******************************************************************************/
+void
+cuddCacheInsert1(
+  DdManager * table,
+  DD_CTFP1 op,
+  DdNode * f,
+  DdNode * data)
+{
+    int posn;
+    register DdCache *entry;
+
+    posn = ddCHash2(op,f,f,table->cacheShift);
+    entry = &table->cache[posn];
+
+    if (entry->data != NULL) {
+        table->cachecollisions++;
+    }
+    table->cacheinserts++;
+
+    entry->f = f;
+    entry->g = f;
+    entry->h = (ptruint) op;
+    entry->data = data;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+
+} /* end of cuddCacheInsert1 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up in the cache for the result of op applied to f,
+  g, and h.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup2 cuddCacheLookup1]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+    ptruint uf, ug, uh;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(uh,uf,ug,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
+	en->h==uh) {
+	data = Cudd_Regular(en->data);
+	table->cacheHits++;
+	if (data->ref == 0) {
+	    cuddReclaim(table,data);
+	}
+	return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+	table->cacheHits > table->cacheMisses * table->minHit) {
+	cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up in the cache for the result of op applied to f,
+  g, and h.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup2Zdd cuddCacheLookup1Zdd]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookupZdd(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+    ptruint uf, ug, uh;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(uh,uf,ug,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug &&
+	en->h==uh) {
+	data = Cudd_Regular(en->data);
+	table->cacheHits++;
+	if (data->ref == 0) {
+	    cuddReclaimZdd(table,data);
+	}
+	return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+	table->cacheHits > table->cacheMisses * table->minHit) {
+	cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookupZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up in the cache for the result of op applied to f
+  and g.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup cuddCacheLookup1]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup2(
+  DdManager * table,
+  DD_CTFP op,
+  DdNode * f,
+  DdNode * g)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,f,g,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
+	data = Cudd_Regular(en->data);
+	table->cacheHits++;
+	if (data->ref == 0) {
+	    cuddReclaim(table,data);
+	}
+	return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+	table->cacheHits > table->cacheMisses * table->minHit) {
+	cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup2 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup cuddCacheLookup2]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup1(
+  DdManager * table,
+  DD_CTFP1 op,
+  DdNode * f)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,f,f,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
+	data = Cudd_Regular(en->data);
+	table->cacheHits++;
+	if (data->ref == 0) {
+	    cuddReclaim(table,data);
+	}
+	return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+	table->cacheHits > table->cacheMisses * table->minHit) {
+	cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup1 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f
+  and g.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookupZdd cuddCacheLookup1Zdd]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup2Zdd(
+  DdManager * table,
+  DD_CTFP op,
+  DdNode * f,
+  DdNode * g)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,f,g,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) {
+	data = Cudd_Regular(en->data);
+	table->cacheHits++;
+	if (data->ref == 0) {
+	    cuddReclaimZdd(table,data);
+	}
+	return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+	table->cacheHits > table->cacheMisses * table->minHit) {
+	cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup2Zdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f.]
+
+  Description [Returns the result if found; it returns NULL if no
+  result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookupZdd cuddCacheLookup2Zdd]
+
+******************************************************************************/
+DdNode *
+cuddCacheLookup1Zdd(
+  DdManager * table,
+  DD_CTFP1 op,
+  DdNode * f)
+{
+    int posn;
+    DdCache *en,*cache;
+    DdNode *data;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+
+    posn = ddCHash2(op,f,f,table->cacheShift);
+    en = &cache[posn];
+    if (en->data != NULL && en->f==f && en->h==(ptruint)op) {
+	data = Cudd_Regular(en->data);
+	table->cacheHits++;
+	if (data->ref == 0) {
+	    cuddReclaimZdd(table,data);
+	}
+	return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0  &&
+	table->cacheHits > table->cacheMisses * table->minHit) {
+	cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddCacheLookup1Zdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in the cache for the result of op applied to f,
+  g, and h.]
+
+  Description [Looks up in the cache for the result of op applied to f,
+  g, and h. Assumes that the calling procedure (e.g.,
+  Cudd_bddIteConstant) is only interested in whether the result is
+  constant or not. Returns the result if found (possibly
+  DD_NON_CONSTANT); otherwise it returns NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddCacheLookup]
+
+******************************************************************************/
+DdNode *
+cuddConstantLookup(
+  DdManager * table,
+  ptruint op,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    int posn;
+    DdCache *en,*cache;
+    ptruint uf, ug, uh;
+
+    uf = (ptruint) f | (op & 0xe);
+    ug = (ptruint) g | (op >> 4);
+    uh = (ptruint) h;
+
+    cache = table->cache;
+#ifdef DD_DEBUG
+    if (cache == NULL) {
+        return(NULL);
+    }
+#endif
+    posn = ddCHash2(uh,uf,ug,table->cacheShift);
+    en = &cache[posn];
+
+    /* We do not reclaim here because the result should not be
+     * referenced, but only tested for being a constant.
+     */
+    if (en->data != NULL &&
+	en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) {
+	table->cacheHits++;
+        return(en->data);
+    }
+
+    /* Cache miss: decide whether to resize. */
+    table->cacheMisses++;
+
+    if (table->cacheSlack >= 0 &&
+	table->cacheHits > table->cacheMisses * table->minHit) {
+	cuddCacheResize(table);
+    }
+
+    return(NULL);
+
+} /* end of cuddConstantLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes and prints a profile of the cache usage.]
+
+  Description [Computes and prints a profile of the cache usage.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddCacheProfile(
+  DdManager * table,
+  FILE * fp)
+{
+    DdCache *cache = table->cache;
+    int slots = table->cacheSlots;
+    int nzeroes = 0;
+    int i, retval;
+    double exUsed;
+
+#ifdef DD_CACHE_PROFILE
+    double count, mean, meansq, stddev, expected;
+    long max, min;
+    int imax, imin;
+    double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */
+    int nbins = DD_HYSTO_BINS;
+    int bin;
+    long thiscount;
+    double totalcount, exStddev;
+
+    meansq = mean = expected = 0.0;
+    max = min = (long) cache[0].count;
+    imax = imin = 0;
+    totalcount = 0.0;
+
+    hystogramQ = ALLOC(double, nbins);
+    if (hystogramQ == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    hystogramR = ALLOC(double, nbins);
+    if (hystogramR == NULL) {
+	FREE(hystogramQ);
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < nbins; i++) {
+	hystogramQ[i] = 0;
+	hystogramR[i] = 0;
+    }
+
+    for (i = 0; i < slots; i++) {
+	thiscount = (long) cache[i].count;
+	if (thiscount > max) {
+	    max = thiscount;
+	    imax = i;
+	}
+	if (thiscount < min) {
+	    min = thiscount;
+	    imin = i;
+	}
+	if (thiscount == 0) {
+	    nzeroes++;
+	}
+	count = (double) thiscount;
+	mean += count;
+	meansq += count * count;
+	totalcount += count;
+	expected += count * (double) i;
+	bin = (i * nbins) / slots;
+	hystogramQ[bin] += (double) thiscount;
+	bin = i % nbins;
+	hystogramR[bin] += (double) thiscount;
+    }
+    mean /= (double) slots;
+    meansq /= (double) slots;
+    
+    /* Compute the standard deviation from both the data and the
+    ** theoretical model for a random distribution. */
+    stddev = sqrt(meansq - mean*mean);
+    exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots);
+
+    retval = fprintf(fp,"Cache average accesses = %g\n",  mean);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache access standard deviation = %g ", stddev);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"(expected = %g)\n", exStddev);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
+    if (retval == EOF) return(0);
+    exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots));
+    retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
+		     100.0 - (double) nzeroes * 100.0 / (double) slots,
+		     exUsed);
+    if (retval == EOF) return(0);
+
+    if (totalcount > 0) {
+	expected /= totalcount;
+	retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
+	if (retval == EOF) return(0);
+	retval = fprintf(fp," (expected bin value = %g)\nBy quotient:",
+			 expected);
+	if (retval == EOF) return(0);
+	for (i = nbins - 1; i>=0; i--) {
+	    retval = fprintf(fp," %.0f", hystogramQ[i]);
+	    if (retval == EOF) return(0);
+	}
+	retval = fprintf(fp,"\nBy residue: ");
+	if (retval == EOF) return(0);
+	for (i = nbins - 1; i>=0; i--) {
+	    retval = fprintf(fp," %.0f", hystogramR[i]);
+	    if (retval == EOF) return(0);
+	}
+	retval = fprintf(fp,"\n");
+	if (retval == EOF) return(0);
+    }
+
+    FREE(hystogramQ);
+    FREE(hystogramR);
+#else
+    for (i = 0; i < slots; i++) {
+	nzeroes += cache[i].h == 0;
+    }
+    exUsed = 100.0 *
+	(1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) /
+		   (double) slots));
+    retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n",
+		     100.0 - (double) nzeroes * 100.0 / (double) slots,
+		     exUsed);
+    if (retval == EOF) return(0);
+#endif
+    return(1);
+
+} /* end of cuddCacheProfile */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddCacheResize(
+  DdManager * table)
+{
+    DdCache *cache, *oldcache, *oldacache, *entry, *old;
+    int i;
+    int posn, shift;
+    unsigned int slots, oldslots;
+    double offset;
+    int moved = 0;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+#ifndef DD_CACHE_PROFILE
+    ptruint misalignment;
+    DdNodePtr *mem;
+#endif
+
+    oldcache = table->cache;
+    oldacache = table->acache;
+    oldslots = table->cacheSlots;
+    slots = table->cacheSlots = oldslots << 1;
+
+#ifdef DD_VERBOSE
+    (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n",
+		   oldslots, slots);
+    (void) fprintf(table->err,
+		   "\thits = %g\tmisses = %g\thit ratio = %5.3f\n",
+		   table->cacheHits, table->cacheMisses,
+		   table->cacheHits / (table->cacheHits + table->cacheMisses));
+#endif
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    table->acache = cache = ALLOC(DdCache,slots+1);
+    MMoutOfMemory = saveHandler;
+    /* If we fail to allocate the new table we just give up. */
+    if (cache == NULL) {
+#ifdef DD_VERBOSE
+	(void) fprintf(table->err,"Resizing failed. Giving up.\n");
+#endif
+	table->cacheSlots = oldslots;
+	table->acache = oldacache;
+	/* Do not try to resize again. */
+	table->maxCacheHard = oldslots - 1;
+	table->cacheSlack = - (oldslots + 1);
+	return;
+    }
+    /* If the size of the cache entry is a power of 2, we want to
+    ** enforce alignment to that power of two. This happens when
+    ** DD_CACHE_PROFILE is not defined. */
+#ifdef DD_CACHE_PROFILE
+    table->cache = cache;
+#else
+    mem = (DdNodePtr *) cache;
+    misalignment = (ptruint) mem & (sizeof(DdCache) - 1);
+    mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr);
+    table->cache = cache = (DdCache *) mem;
+    assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0);
+#endif
+    shift = --(table->cacheShift);
+    table->memused += (slots - oldslots) * sizeof(DdCache);
+    table->cacheSlack -= slots; /* need these many slots to double again */
+
+    /* Clear new cache. */
+    for (i = 0; (unsigned) i < slots; i++) {
+	cache[i].data = NULL;
+	cache[i].h = 0;
+#ifdef DD_CACHE_PROFILE
+	cache[i].count = 0;
+#endif
+    }
+
+    /* Copy from old cache to new one. */
+    for (i = 0; (unsigned) i < oldslots; i++) {
+	old = &oldcache[i];
+	if (old->data != NULL) {
+	    posn = ddCHash2(old->h,old->f,old->g,shift);
+	    entry = &cache[posn];
+	    entry->f = old->f;
+	    entry->g = old->g;
+	    entry->h = old->h;
+	    entry->data = old->data;	
+#ifdef DD_CACHE_PROFILE
+	    entry->count = 1;
+#endif
+	    moved++;
+	}
+    }
+
+    FREE(oldacache);
+
+    /* Reinitialize measurements so as to avoid division by 0 and
+    ** immediate resizing.
+    */
+    offset = (double) (int) (slots * table->minHit + 1);
+    table->totCacheMisses += table->cacheMisses - offset;
+    table->cacheMisses = offset;
+    table->totCachehits += table->cacheHits;
+    table->cacheHits = 0;
+    table->cacheLastInserts = table->cacheinserts - (double) moved;
+
+} /* end of cuddCacheResize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Flushes the cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddCacheFlush(
+  DdManager * table)
+{
+    int i, slots;
+    DdCache *cache;
+
+    slots = table->cacheSlots;
+    cache = table->cache;
+    for (i = 0; i < slots; i++) {
+	table->cachedeletions += cache[i].data != NULL;
+	cache[i].data = NULL;
+    }
+    table->cacheLastInserts = table->cacheinserts;
+
+    return;
+
+} /* end of cuddCacheFlush */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the floor of the logarithm to the base 2.]
+
+  Description [Returns the floor of the logarithm to the base 2.
+  The input value is assumed to be greater than 0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddComputeFloorLog2(
+  unsigned int value)
+{
+    int floorLog = 0;
+#ifdef DD_DEBUG
+    assert(value > 0);
+#endif
+    while (value > 1) {
+	floorLog++;
+	value >>= 1;
+    }
+    return(floorLog);
+
+} /* end of cuddComputeFloorLog2 */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: /vis_dev/glu-2.1/src/cuBdd/cuddCheck.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddCheck.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddCheck.c	(revision 8)
@@ -0,0 +1,879 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCheck.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to check consistency of data structures.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_DebugCheck()
+		<li> Cudd_CheckKeys()
+		</ul>
+	       Internal procedures included in this module:
+		<ul>
+		<li> cuddHeapProfile()
+		<li> cuddPrintNode()
+		<li> cuddPrintVarGroups()
+		</ul>
+	       Static procedures included in this module:
+		<ul>
+		<li> debugFindParent()
+		</ul>
+		]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.33 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void debugFindParent (DdManager *table, DdNode *node);
+#if 0
+static void debugCheckParent (DdManager *table, DdNode *node);
+#endif
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for inconsistencies in the DD heap.]
+
+  Description [Checks for inconsistencies in the DD heap:
+  <ul>
+  <li> node has illegal index
+  <li> live node has dead children
+  <li> node has illegal Then or Else pointers
+  <li> BDD/ADD node has identical children
+  <li> ZDD node has zero then child
+  <li> wrong number of total nodes
+  <li> wrong number of dead nodes
+  <li> ref count error at node
+  </ul>
+  Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is
+  not enough memory; 1 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CheckKeys]
+
+******************************************************************************/
+int
+Cudd_DebugCheck(
+  DdManager * table)
+{
+    unsigned int i;
+    int		j,count;
+    int		slots;
+    DdNodePtr	*nodelist;
+    DdNode	*f;
+    DdNode	*sentinel = &(table->sentinel);
+    st_table	*edgeTable;	/* stores internal ref count for each node */
+    st_generator	*gen;
+    int		flag = 0;
+    int		totalNode;
+    int		deadNode;
+    int		index;
+    
+
+    edgeTable = st_init_table(st_ptrcmp,st_ptrhash);
+    if (edgeTable == NULL) return(CUDD_OUT_OF_MEM);
+
+    /* Check the BDD/ADD subtables. */
+    for (i = 0; i < (unsigned) table->size; i++) {
+	index = table->invperm[i];
+	if (i != (unsigned) table->perm[index]) {
+	    (void) fprintf(table->err,
+			   "Permutation corrupted: invperm[%d] = %d\t perm[%d] = %d\n",
+			   i, index, index, table->perm[index]);
+	}
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+
+	totalNode = 0;
+	deadNode = 0;
+	for (j = 0; j < slots; j++) {	/* for each subtable slot */
+	    f = nodelist[j];
+	    while (f != sentinel) {
+		totalNode++;
+		if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { 
+		    if ((int) f->index != index) {
+			(void) fprintf(table->err,
+				       "Error: node has illegal index\n");
+			cuddPrintNode(f,table->err);
+			flag = 1;
+		    }
+		    if ((unsigned) cuddI(table,cuddT(f)->index) <= i ||
+			(unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index)
+			<= i) {
+			(void) fprintf(table->err,
+				       "Error: node has illegal children\n");
+			cuddPrintNode(f,table->err);
+			flag = 1;
+		    }
+		    if (Cudd_Regular(cuddT(f)) != cuddT(f)) {
+			(void) fprintf(table->err,
+				       "Error: node has illegal form\n");
+			cuddPrintNode(f,table->err);
+			flag = 1;
+		    }
+		    if (cuddT(f) == cuddE(f)) {
+			(void) fprintf(table->err,
+				       "Error: node has identical children\n");
+			cuddPrintNode(f,table->err);
+			flag = 1;
+		    }
+		    if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) {
+			(void) fprintf(table->err,
+				       "Error: live node has dead children\n");
+			cuddPrintNode(f,table->err);
+			flag =1;
+		    }
+		    /* Increment the internal reference count for the
+		    ** then child of the current node.
+		    */
+		    if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
+			count++;
+		    } else {
+			count = 1;
+		    }
+		    if (st_insert(edgeTable,(char *)cuddT(f),
+		    (char *)(long)count) == ST_OUT_OF_MEM) {
+			st_free_table(edgeTable);
+			return(CUDD_OUT_OF_MEM);
+		    }
+		
+		    /* Increment the internal reference count for the
+		    ** else child of the current node.
+		    */
+		    if (st_lookup_int(edgeTable,(char *)Cudd_Regular(cuddE(f)),
+				      &count)) {
+			count++;
+		    } else {
+			count = 1;
+		    }
+		    if (st_insert(edgeTable,(char *)Cudd_Regular(cuddE(f)),
+		    (char *)(long)count) == ST_OUT_OF_MEM) {
+			st_free_table(edgeTable);
+			return(CUDD_OUT_OF_MEM);
+		    }
+		} else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
+		    deadNode++;
+#if 0
+		    debugCheckParent(table,f);
+#endif
+		} else {
+		    fprintf(table->err,
+			    "Error: node has illegal Then or Else pointers\n");
+		    cuddPrintNode(f,table->err);
+		    flag = 1;
+		}
+
+		f = f->next;
+	    }	/* for each element of the collision list */
+	}	/* for each subtable slot */
+
+	if ((unsigned) totalNode != table->subtables[i].keys) {
+	    fprintf(table->err,"Error: wrong number of total nodes\n");
+	    flag = 1;
+	}
+	if ((unsigned) deadNode != table->subtables[i].dead) {
+	    fprintf(table->err,"Error: wrong number of dead nodes\n");
+	    flag = 1;
+	}
+    }	/* for each BDD/ADD subtable */
+
+    /* Check the ZDD subtables. */
+    for (i = 0; i < (unsigned) table->sizeZ; i++) {
+	index = table->invpermZ[i];
+	if (i != (unsigned) table->permZ[index]) {
+	    (void) fprintf(table->err,
+			   "Permutation corrupted: invpermZ[%d] = %d\t permZ[%d] = %d in ZDD\n",
+			   i, index, index, table->permZ[index]);
+	}
+	nodelist = table->subtableZ[i].nodelist;
+	slots = table->subtableZ[i].slots;
+
+	totalNode = 0;
+	deadNode = 0;
+	for (j = 0; j < slots; j++) {	/* for each subtable slot */
+	    f = nodelist[j];
+	    while (f != NULL) {
+		totalNode++;
+		if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { 
+		    if ((int) f->index != index) {
+			(void) fprintf(table->err,
+				       "Error: ZDD node has illegal index\n");
+			cuddPrintNode(f,table->err);
+			flag = 1;
+		    }
+		    if (Cudd_IsComplement(cuddT(f)) ||
+			Cudd_IsComplement(cuddE(f))) {
+			(void) fprintf(table->err,
+				       "Error: ZDD node has complemented children\n");
+			cuddPrintNode(f,table->err);
+			flag = 1;
+		    }
+		    if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i ||
+		    (unsigned) cuddIZ(table,cuddE(f)->index) <= i) {
+			(void) fprintf(table->err,
+				       "Error: ZDD node has illegal children\n");
+			cuddPrintNode(f,table->err);
+			cuddPrintNode(cuddT(f),table->err);
+			cuddPrintNode(cuddE(f),table->err);
+			flag = 1;
+		    }
+		    if (cuddT(f) == DD_ZERO(table)) {
+			(void) fprintf(table->err,
+				       "Error: ZDD node has zero then child\n");
+			cuddPrintNode(f,table->err);
+			flag = 1;
+		    }
+		    if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) {
+			(void) fprintf(table->err,
+				       "Error: ZDD live node has dead children\n");
+			cuddPrintNode(f,table->err);
+			flag =1;
+		    }
+		    /* Increment the internal reference count for the
+		    ** then child of the current node.
+		    */
+		    if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
+			count++;
+		    } else {
+			count = 1;
+		    }
+		    if (st_insert(edgeTable,(char *)cuddT(f),
+		    (char *)(long)count) == ST_OUT_OF_MEM) {
+			st_free_table(edgeTable);
+			return(CUDD_OUT_OF_MEM);
+		    }
+		
+		    /* Increment the internal reference count for the
+		    ** else child of the current node.
+		    */
+		    if (st_lookup_int(edgeTable,(char *)cuddE(f),&count)) {
+			count++;
+		    } else {
+			count = 1;
+		    }
+		    if (st_insert(edgeTable,(char *)cuddE(f),
+		    (char *)(long)count) == ST_OUT_OF_MEM) {
+			st_free_table(edgeTable);
+			table->errorCode = CUDD_MEMORY_OUT;
+			return(CUDD_OUT_OF_MEM);
+		    }
+		} else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
+		    deadNode++;
+#if 0
+		    debugCheckParent(table,f);
+#endif
+		} else {
+		    fprintf(table->err,
+			    "Error: ZDD node has illegal Then or Else pointers\n");
+		    cuddPrintNode(f,table->err);
+		    flag = 1;
+		}
+
+		f = f->next;
+	    }	/* for each element of the collision list */
+	}	/* for each subtable slot */
+
+	if ((unsigned) totalNode != table->subtableZ[i].keys) {
+	    fprintf(table->err,
+		    "Error: wrong number of total nodes in ZDD\n");
+	    flag = 1;
+	}
+	if ((unsigned) deadNode != table->subtableZ[i].dead) {
+	    fprintf(table->err,
+		    "Error: wrong number of dead nodes in ZDD\n");
+	    flag = 1;
+	}
+    }	/* for each ZDD subtable */
+
+    /* Check the constant table. */
+    nodelist = table->constants.nodelist;
+    slots = table->constants.slots;
+
+    totalNode = 0;
+    deadNode = 0;
+    for (j = 0; j < slots; j++) {
+	f = nodelist[j];
+	while (f != NULL) {
+	    totalNode++;
+	    if (f->ref != 0) { 
+		if (f->index != CUDD_CONST_INDEX) {
+		    fprintf(table->err,"Error: node has illegal index\n");
+#if SIZEOF_VOID_P == 8
+		    fprintf(table->err,
+			    "       node 0x%lx, id = %d, ref = %d, value = %g\n",
+			    (unsigned long)f,f->index,f->ref,cuddV(f));
+#else
+		    fprintf(table->err,
+			    "       node 0x%x, id = %d, ref = %d, value = %g\n",
+			    (unsigned)f,f->index,f->ref,cuddV(f));
+#endif
+		    flag = 1;
+		}
+	    } else {
+		deadNode++;
+	    }
+	    f = f->next;
+	}
+    }
+    if ((unsigned) totalNode != table->constants.keys) {
+	(void) fprintf(table->err,
+		       "Error: wrong number of total nodes in constants\n");
+	flag = 1;
+    }
+    if ((unsigned) deadNode != table->constants.dead) {
+	(void) fprintf(table->err,
+		       "Error: wrong number of dead nodes in constants\n");
+	flag = 1;
+    }
+    gen = st_init_gen(edgeTable);
+    while (st_gen(gen, &f, &count)) {
+	if (count > (int)(f->ref) && f->ref != DD_MAXREF) {
+#if SIZEOF_VOID_P == 8
+	    fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,count,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f));
+#else
+	    fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,count,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f));
+#endif
+	    debugFindParent(table,f);
+	    flag = 1;
+	}
+    }
+    st_free_gen(gen);
+    st_free_table(edgeTable);
+
+    return (flag);
+
+} /* end of Cudd_DebugCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for several conditions that should not occur.]
+
+  Description [Checks for the following conditions:
+  <ul>
+  <li>Wrong sizes of subtables.
+  <li>Wrong number of keys found in unique subtable.
+  <li>Wrong number of dead found in unique subtable.
+  <li>Wrong number of keys found in the constant table
+  <li>Wrong number of dead found in the constant table
+  <li>Wrong number of total slots found
+  <li>Wrong number of maximum keys found
+  <li>Wrong number of total dead found
+  </ul>
+  Reports the average length of non-empty lists. Returns the number of
+  subtables for which the number of keys is wrong.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DebugCheck]
+
+******************************************************************************/
+int
+Cudd_CheckKeys(
+  DdManager * table)
+{
+    int size;
+    int i,j;
+    DdNodePtr *nodelist;
+    DdNode *node;
+    DdNode *sentinel = &(table->sentinel);
+    DdSubtable *subtable;
+    int keys;
+    int dead;
+    int count = 0;
+    int totalKeys = 0;
+    int totalSlots = 0;
+    int totalDead = 0;
+    int nonEmpty = 0;
+    unsigned int slots;
+    int logSlots;
+    int shift;
+
+    size = table->size;
+
+    for (i = 0; i < size; i++) {
+	subtable = &(table->subtables[i]);
+	nodelist = subtable->nodelist;
+	keys = subtable->keys;
+	dead = subtable->dead;
+	totalKeys += keys;
+	slots = subtable->slots;
+	shift = subtable->shift;
+	logSlots = sizeof(int) * 8 - shift;
+	if (((slots >> logSlots) << logSlots) != slots) {
+	    (void) fprintf(table->err,
+			   "Unique table %d is not the right power of 2\n", i);
+	    (void) fprintf(table->err,
+			   "    slots = %u shift = %d\n", slots, shift);
+	}
+	totalSlots += slots;
+	totalDead += dead;
+	for (j = 0; (unsigned) j < slots; j++) {
+	    node = nodelist[j];
+	    if (node != sentinel) {
+		nonEmpty++;
+	    }
+	    while (node != sentinel) {
+		keys--;
+		if (node->ref == 0) {
+		    dead--;
+		}
+		node = node->next;
+	    }
+	}
+	if (keys != 0) {
+	    (void) fprintf(table->err, "Wrong number of keys found \
+in unique table %d (difference=%d)\n", i, keys);
+	    count++;
+	}
+	if (dead != 0) {
+	    (void) fprintf(table->err, "Wrong number of dead found \
+in unique table no. %d (difference=%d)\n", i, dead);
+	}
+    }	/* for each BDD/ADD subtable */
+
+    /* Check the ZDD subtables. */
+    size = table->sizeZ;
+
+    for (i = 0; i < size; i++) {
+	subtable = &(table->subtableZ[i]);
+	nodelist = subtable->nodelist;
+	keys = subtable->keys;
+	dead = subtable->dead;
+	totalKeys += keys;
+	totalSlots += subtable->slots;
+	totalDead += dead;
+	for (j = 0; (unsigned) j < subtable->slots; j++) {
+	    node = nodelist[j];
+	    if (node != NULL) {
+		nonEmpty++;
+	    }
+	    while (node != NULL) {
+		keys--;
+		if (node->ref == 0) {
+		    dead--;
+		}
+		node = node->next;
+	    }
+	}
+	if (keys != 0) {
+	    (void) fprintf(table->err, "Wrong number of keys found \
+in ZDD unique table no. %d (difference=%d)\n", i, keys);
+	    count++;
+	}
+	if (dead != 0) {
+	    (void) fprintf(table->err, "Wrong number of dead found \
+in ZDD unique table no. %d (difference=%d)\n", i, dead);
+	}
+    }	/* for each ZDD subtable */
+
+    /* Check the constant table. */
+    subtable = &(table->constants);
+    nodelist = subtable->nodelist;
+    keys = subtable->keys;
+    dead = subtable->dead;
+    totalKeys += keys;
+    totalSlots += subtable->slots;
+    totalDead += dead;
+    for (j = 0; (unsigned) j < subtable->slots; j++) {
+	node = nodelist[j];
+	if (node != NULL) {
+	    nonEmpty++;
+	}
+	while (node != NULL) {
+	    keys--;
+	    if (node->ref == 0) {
+		dead--;
+	    }
+	    node = node->next;
+	}
+    }
+    if (keys != 0) {
+	(void) fprintf(table->err, "Wrong number of keys found \
+in the constant table (difference=%d)\n", keys);
+	count++;
+    }
+    if (dead != 0) {
+	(void) fprintf(table->err, "Wrong number of dead found \
+in the constant table (difference=%d)\n", dead);
+    }
+    if ((unsigned) totalKeys != table->keys + table->keysZ) {
+	(void) fprintf(table->err, "Wrong number of total keys found \
+(difference=%d)\n", totalKeys-table->keys);
+    }
+    if ((unsigned) totalSlots != table->slots) {
+	(void) fprintf(table->err, "Wrong number of total slots found \
+(difference=%d)\n", totalSlots-table->slots);
+    }
+    if (table->minDead != (unsigned) (table->gcFrac * table->slots)) {
+	(void) fprintf(table->err, "Wrong number of minimum dead found \
+(%d vs. %d)\n", table->minDead,
+	(unsigned) (table->gcFrac * (double) table->slots));
+    }
+    if ((unsigned) totalDead != table->dead + table->deadZ) {
+	(void) fprintf(table->err, "Wrong number of total dead found \
+(difference=%d)\n", totalDead-table->dead);
+    }
+    (void)printf("Average length of non-empty lists = %g\n",
+    (double) table->keys / (double) nonEmpty);
+
+    return(count);
+
+} /* end of Cudd_CheckKeys */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about the heap.]
+
+  Description [Prints to the manager's stdout the number of live nodes for each
+  level of the DD heap that contains at least one live node.  It also
+  prints a summary containing:
+  <ul>
+  <li> total number of tables;
+  <li> number of tables with live nodes;
+  <li> table with the largest number of live nodes;
+  <li> number of nodes in that table.
+  </ul>
+  If more than one table contains the maximum number of live nodes,
+  only the one of lowest index is reported. Returns 1 in case of success
+  and 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddHeapProfile(
+  DdManager * dd)
+{
+    int ntables = dd->size;
+    DdSubtable *subtables = dd->subtables;
+    int i,		/* loop index */
+	nodes,		/* live nodes in i-th layer */
+	retval,		/* return value of fprintf */
+	largest = -1,	/* index of the table with most live nodes */
+	maxnodes = -1,	/* maximum number of live nodes in a table */
+	nonempty = 0;	/* number of tables with live nodes */
+
+    /* Print header. */
+#if SIZEOF_VOID_P == 8
+    retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n",
+		     (unsigned long) dd);
+#else
+    retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n",
+		     (unsigned) dd);
+#endif
+    if (retval == EOF) return 0;
+
+    /* Print number of live nodes for each nonempty table. */
+    for (i=0; i<ntables; i++) {
+	nodes = subtables[i].keys - subtables[i].dead;
+	if (nodes) {
+	    nonempty++;
+	    retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes);
+	    if (retval == EOF) return 0;
+	    if (nodes > maxnodes) {
+		maxnodes = nodes;
+		largest = i;
+	    }
+	}
+    }
+
+    nodes = dd->constants.keys - dd->constants.dead;
+    if (nodes) {
+	nonempty++;
+	retval = fprintf(dd->out,"const: %5d nodes\n", nodes);
+	if (retval == EOF) return 0;
+	if (nodes > maxnodes) {
+	    maxnodes = nodes;
+	    largest = CUDD_CONST_INDEX;
+	}
+    }
+
+    /* Print summary. */
+    retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ",
+	  ntables+1, nonempty, largest);
+    if (retval == EOF) return 0;
+    retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes);
+    if (retval == EOF) return 0;
+
+    return(1);
+
+} /* end of cuddHeapProfile */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out information on a node.]
+
+  Description [Prints out information on a node.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddPrintNode(
+  DdNode * f,
+  FILE *fp)
+{
+    f = Cudd_Regular(f);
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(fp,"       node 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f));
+#else
+    (void) fprintf(fp,"       node 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f));
+#endif
+
+} /* end of cuddPrintNode */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the variable groups as a parenthesized list.]
+
+  Description [Prints the variable groups as a parenthesized list.
+  For each group the level range that it represents is printed. After
+  each group, the group's flags are printed, preceded by a `|'.  For
+  each flag (except MTR_TERMINAL) a character is printed.
+  <ul>
+  <li>F: MTR_FIXED
+  <li>N: MTR_NEWNODE
+  <li>S: MTR_SOFT
+  </ul>
+  The second argument, silent, if different from 0, causes
+  Cudd_PrintVarGroups to only check the syntax of the group tree.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddPrintVarGroups(
+  DdManager * dd /* manager */,
+  MtrNode * root /* root of the group tree */,
+  int zdd /* 0: BDD; 1: ZDD */,
+  int silent /* flag to check tree syntax only */)
+{
+    MtrNode *node;
+    int level;
+
+    assert(root != NULL);
+    assert(root->younger == NULL || root->younger->elder == root);
+    assert(root->elder == NULL || root->elder->younger == root);
+    if (zdd) {
+	level = dd->permZ[root->index];
+    } else {
+	level = dd->perm[root->index];
+    }
+    if (!silent) (void) printf("(%d",level);
+    if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
+	if (!silent) (void) printf(",");
+    } else {
+	node = root->child;
+	while (node != NULL) {
+	    assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
+	    assert(node->parent == root);
+	    cuddPrintVarGroups(dd,node,zdd,silent);
+	    node = node->younger;
+	}
+    }
+    if (!silent) {
+	(void) printf("%d", level + root->size - 1);
+	if (root->flags != MTR_DEFAULT) {
+	    (void) printf("|");
+	    if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
+	    if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
+	    if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
+	}
+	(void) printf(")");
+	if (root->parent == NULL) (void) printf("\n");
+    }
+    assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
+    return;
+
+} /* end of cuddPrintVarGroups */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Searches the subtables above node for its parents.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+debugFindParent(
+  DdManager * table,
+  DdNode * node)
+{
+    int         i,j;
+    int		slots;
+    DdNodePtr	*nodelist;
+    DdNode	*f;
+	
+    for (i = 0; i < cuddI(table,node->index); i++) {
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+
+	for (j=0;j<slots;j++) {
+	    f = nodelist[j];
+	    while (f != NULL) {
+		if (cuddT(f) == node || Cudd_Regular(cuddE(f)) == node) {
+#if SIZEOF_VOID_P == 8
+		    (void) fprintf(table->out,"parent is at 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",
+			(unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f));
+#else
+		    (void) fprintf(table->out,"parent is at 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",
+			(unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f));
+#endif
+		}
+		f = f->next;
+	    }
+	}
+    }
+
+} /* end of debugFindParent */
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Reports an error if a (dead) node has a non-dead parent.]
+
+  Description [Searches all the subtables above node. Very expensive.
+  The same check is now implemented more efficiently in ddDebugCheck.]
+
+  SideEffects [None]
+
+  SeeAlso     [debugFindParent]
+
+******************************************************************************/
+static void
+debugCheckParent(
+  DdManager * table,
+  DdNode * node)
+{
+    int         i,j;
+    int		slots;
+    DdNode	**nodelist,*f;
+    
+    for (i = 0; i < cuddI(table,node->index); i++) {
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+
+	for (j=0;j<slots;j++) {
+	    f = nodelist[j];
+	    while (f != NULL) {
+		if ((Cudd_Regular(cuddE(f)) == node || cuddT(f) == node) && f->ref != 0) {
+		    (void) fprintf(table->err,
+				   "error with zero ref count\n");
+		    (void) fprintf(table->err,"parent is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f));
+		    (void) fprintf(table->err,"child  is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node));
+		}
+		f = f->next;
+	    }
+	}
+    }
+}
+#endif
Index: /vis_dev/glu-2.1/src/cuBdd/cuddClip.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddClip.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddClip.c	(revision 8)
@@ -0,0 +1,558 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddClip.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Clipping functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_bddClippingAnd()
+		<li> Cudd_bddClippingAndAbstract()
+		</ul>
+       Internal procedures included in this module:
+		<ul>
+		<li> cuddBddClippingAnd()
+		<li> cuddBddClippingAndAbstract()
+		</ul>
+       Static procedures included in this module:
+		<ul>
+		<li> cuddBddClippingAndRecur()
+		<li> cuddBddClipAndAbsRecur()
+		</ul>
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.8 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * cuddBddClippingAndRecur (DdManager *manager, DdNode *f, DdNode *g, int distance, int direction);
+static DdNode * cuddBddClipAndAbsRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g.]
+
+  Description [Approximates the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddClippingAnd(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddClippingAnd(dd,f,g,maxDepth,direction);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddClippingAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube.]
+
+  Description [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube. The variables are
+  existentially abstracted. Returns a pointer to the resulting BDD if
+  successful; NULL if the intermediate result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddAndAbstract Cudd_bddClippingAnd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddClippingAndAbstract(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  DdNode * cube /* cube of variables to be abstracted */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddClippingAndAbstract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g.]
+
+  Description [Approximates the conjunction of two BDDs f and g. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClippingAnd]
+
+******************************************************************************/
+DdNode *
+cuddBddClippingAnd(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction);
+
+    return(res);
+
+} /* end of cuddBddClippingAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube.]
+
+  Description [Approximates the conjunction of two BDDs f and g and
+  simultaneously abstracts the variables in cube. Returns a
+  pointer to the resulting BDD if successful; NULL if the intermediate
+  result blows up.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClippingAndAbstract]
+
+******************************************************************************/
+DdNode *
+cuddBddClippingAndAbstract(
+  DdManager * dd /* manager */,
+  DdNode * f /* first conjunct */,
+  DdNode * g /* second conjunct */,
+  DdNode * cube /* cube of variables to be abstracted */,
+  int  maxDepth /* maximum recursion depth */,
+  int  direction /* under (0) or over (1) approximation */)
+{
+    DdNode *res;
+
+    res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction);
+
+    return(res);
+
+} /* end of cuddBddClippingAndAbstract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddClippingAnd.]
+
+  Description [Implements the recursive step of Cudd_bddClippingAnd by taking
+  the conjunction of two BDDs.  Returns a pointer to the result is
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBddClippingAnd]
+
+******************************************************************************/
+static DdNode *
+cuddBddClippingAndRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  int  distance,
+  int  direction)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *zero, *r, *t, *e;
+    unsigned int topf, topg, index;
+    DD_CTFP cacheOp;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == g || g == one) return(f);
+    if (f == one) return(g);
+    if (distance == 0) {
+	/* One last attempt at returning the right result. We sort of
+	** cheat by calling Cudd_bddLeq. */
+	if (Cudd_bddLeq(manager,f,g)) return(f);
+	if (Cudd_bddLeq(manager,g,f)) return(g);
+	if (direction == 1) {
+	    if (Cudd_bddLeq(manager,f,Cudd_Not(g)) ||
+		Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero);
+	}
+	return(Cudd_NotCond(one,(direction == 0)));
+    }
+
+    /* At this point f and g are not constant. */
+    distance--;
+
+    /* Check cache. Try to increase cache efficiency by sorting the
+    ** pointers. */
+    if (f > g) {
+	DdNode *tmp = f;
+	f = g; g = tmp;
+    }
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    cacheOp = (DD_CTFP)
+	(direction ? Cudd_bddClippingAnd : cuddBddClippingAnd);
+    if (F->ref != 1 || G->ref != 1) {
+	r = cuddCacheLookup2(manager, cacheOp, f, g);
+	if (r != NULL) return(r);
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+	index = F->index;
+	ft = cuddT(F);
+	fe = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    ft = Cudd_Not(ft);
+	    fe = Cudd_Not(fe);
+	}
+    } else {
+	index = G->index;
+	ft = fe = f;
+    }
+
+    if (topg <= topf) {
+	gt = cuddT(G);
+	ge = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gt = Cudd_Not(gt);
+	    ge = Cudd_Not(ge);
+	}
+    } else {
+	gt = ge = g;
+    }
+
+    t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(manager, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+	r = t;
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_RecursiveDeref(manager, t);
+		Cudd_RecursiveDeref(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(manager,(int)index,t,e);
+	    if (r == NULL) {
+		Cudd_RecursiveDeref(manager, t);
+		Cudd_RecursiveDeref(manager, e);
+		return(NULL);
+	    }
+	}
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    if (F->ref != 1 || G->ref != 1)
+	cuddCacheInsert2(manager, cacheOp, f, g, r);
+    return(r);
+
+} /* end of cuddBddClippingAndRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  Description [Approximates the AND of two BDDs and simultaneously
+  abstracts the variables in cube. The variables are existentially
+  abstracted.  Returns a pointer to the result is successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClippingAndAbstract]
+
+******************************************************************************/
+static DdNode *
+cuddBddClipAndAbsRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g,
+  DdNode * cube,
+  int  distance,
+  int  direction)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *zero, *r, *t, *e, *Cube;
+    unsigned int topf, topg, topcube, top, index;
+    ptruint cacheTag;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
+    if (f == one && g == one)	return(one);
+    if (cube == one) {
+	return(cuddBddClippingAndRecur(manager, f, g, distance, direction));
+    }
+    if (f == one || f == g) {
+	return (cuddBddExistAbstractRecur(manager, g, cube));
+    }
+    if (g == one) {
+	return (cuddBddExistAbstractRecur(manager, f, cube));
+    }
+    if (distance == 0) return(Cudd_NotCond(one,(direction == 0)));
+
+    /* At this point f, g, and cube are not constant. */
+    distance--;
+
+    /* Check cache. */
+    if (f > g) { /* Try to increase cache efficiency. */
+	DdNode *tmp = f;
+	f = g; g = tmp;
+    }
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG :
+	DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG;
+    if (F->ref != 1 || G->ref != 1) {
+	r = cuddCacheLookup(manager, cacheTag,
+			    f, g, cube);
+	if (r != NULL) {
+	    return(r);
+	}
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+    top = ddMin(topf, topg);
+    topcube = manager->perm[cube->index];
+
+    if (topcube < top) {
+	return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube),
+				      distance, direction));
+    }
+    /* Now, topcube >= top. */
+
+    if (topf == top) {
+	index = F->index;
+	ft = cuddT(F);
+	fe = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    ft = Cudd_Not(ft);
+	    fe = Cudd_Not(fe);
+	}
+    } else {
+	index = G->index;
+	ft = fe = f;
+    }
+
+    if (topg == top) {
+	gt = cuddT(G);
+	ge = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gt = Cudd_Not(gt);
+	    ge = Cudd_Not(ge);
+	}
+    } else {
+	gt = ge = g;
+    }
+
+    if (topcube == top) {
+	Cube = cuddT(cube);
+    } else {
+	Cube = cube;
+    }
+
+    t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction);
+    if (t == NULL) return(NULL);
+
+    /* Special case: 1 OR anything = 1. Hence, no need to compute
+    ** the else branch if t is 1.
+    */
+    if (t == one && topcube == top) {
+	if (F->ref != 1 || G->ref != 1)
+	    cuddCacheInsert(manager, cacheTag, f, g, cube, one);
+	return(one);
+    }
+    cuddRef(t);
+
+    e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(manager, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (topcube == top) {	/* abstract */
+	r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e),
+				    distance, (direction == 0));
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(manager, t);
+	    Cudd_RecursiveDeref(manager, e);
+	    return(NULL);
+	}
+	r = Cudd_Not(r);
+	cuddRef(r);
+	Cudd_RecursiveDeref(manager, t);
+	Cudd_RecursiveDeref(manager, e);
+	cuddDeref(r);
+    } else if (t == e) {
+	r = t;
+	cuddDeref(t);
+	cuddDeref(e);
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_RecursiveDeref(manager, t);
+		Cudd_RecursiveDeref(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(manager,(int)index,t,e);
+	    if (r == NULL) {
+		Cudd_RecursiveDeref(manager, t);
+		Cudd_RecursiveDeref(manager, e);
+		return(NULL);
+	    }
+	}
+	cuddDeref(e);
+	cuddDeref(t);
+    }
+    if (F->ref != 1 || G->ref != 1)
+	cuddCacheInsert(manager, cacheTag, f, g, cube, r);
+    return (r);
+
+} /* end of cuddBddClipAndAbsRecur */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddCof.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddCof.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddCof.c	(revision 8)
@@ -0,0 +1,327 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCof.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Cofactoring functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_Cofactor()
+		</ul>
+	       Internal procedures included in this module:
+		<ul>
+		<li> cuddGetBranches()
+		<li> cuddCheckCube()
+		<li> cuddCofactorRecur()
+		</ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.9 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cofactor of f with respect to g.]
+
+  Description [Computes the cofactor of f with respect to g; g must be
+  the BDD or the ADD of a cube. Returns a pointer to the cofactor if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_Cofactor(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res,*zero;
+
+    zero = Cudd_Not(DD_ONE(dd));
+    if (g == zero || g == DD_ZERO(dd)) {
+	(void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n");
+	dd->errorCode = CUDD_INVALID_ARG;
+	return(NULL);
+    }
+    do {
+	dd->reordered = 0;
+	res = cuddCofactorRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_Cofactor */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the children of g.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddGetBranches(
+  DdNode * g,
+  DdNode ** g1,
+  DdNode ** g0)
+{
+    DdNode	*G = Cudd_Regular(g);
+
+    *g1 = cuddT(G);
+    *g0 = cuddE(G);
+    if (Cudd_IsComplement(g)) {
+	*g1 = Cudd_Not(*g1);
+	*g0 = Cudd_Not(*g0);
+    }
+
+} /* end of cuddGetBranches */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether g is the BDD of a cube.]
+
+  Description [Checks whether g is the BDD of a cube. Returns 1 in case
+  of success; 0 otherwise. The constant 1 is a valid cube, but all other
+  constant functions cause cuddCheckCube to return 0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddCheckCube(
+  DdManager * dd,
+  DdNode * g)
+{
+    DdNode *g1,*g0,*one,*zero;
+    
+    one = DD_ONE(dd);
+    if (g == one) return(1);
+    if (Cudd_IsConstant(g)) return(0);
+
+    zero = Cudd_Not(one);
+    cuddGetBranches(g,&g1,&g0);
+
+    if (g0 == zero) {
+        return(cuddCheckCube(dd, g1));
+    }
+    if (g1 == zero) {
+        return(cuddCheckCube(dd, g0));
+    }
+    return(0);
+
+} /* end of cuddCheckCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_Cofactor.]
+
+  Description [Performs the recursive step of Cudd_Cofactor. Returns a
+  pointer to the cofactor if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Cofactor]
+
+******************************************************************************/
+DdNode *
+cuddCofactorRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r;
+    unsigned int topf,topg;
+    int comple;
+
+    statLine(dd);
+    F = Cudd_Regular(f);
+    if (cuddIsConstant(F)) return(f);
+
+    one = DD_ONE(dd);
+
+    /* The invariant g != 0 is true on entry to this procedure and is
+    ** recursively maintained by it. Therefore it suffices to test g
+    ** against one to make sure it is not constant.
+    */
+    if (g == one) return(f);
+    /* From now on, f and g are known not to be constants. */
+
+    comple = f != F;
+    r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g);
+    if (r != NULL) {
+	return(Cudd_NotCond(r,comple));
+    }
+
+    topf = dd->perm[F->index];
+    G = Cudd_Regular(g);
+    topg = dd->perm[G->index];
+
+    /* We take the cofactors of F because we are going to rely on
+    ** the fact that the cofactors of the complement are the complements
+    ** of the cofactors to better utilize the cache. Variable comple
+    ** remembers whether we have to complement the result or not.
+    */
+    if (topf <= topg) {
+	f1 = cuddT(F); f0 = cuddE(F);
+    } else {
+	f1 = f0 = F;
+    }
+    if (topg <= topf) {
+	g1 = cuddT(G); g0 = cuddE(G);
+	if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); }
+    } else {
+	g1 = g0 = g;
+    }
+
+    zero = Cudd_Not(one);
+    if (topf >= topg) {
+	if (g0 == zero || g0 == DD_ZERO(dd)) {
+	    r = cuddCofactorRecur(dd, f1, g1);
+	} else if (g1 == zero || g1 == DD_ZERO(dd)) {
+	    r = cuddCofactorRecur(dd, f0, g0);
+	} else {
+	    (void) fprintf(dd->out,
+			   "Cudd_Cofactor: Invalid restriction 2\n");
+	    dd->errorCode = CUDD_INVALID_ARG;
+	    return(NULL);
+	}
+	if (r == NULL) return(NULL);
+    } else /* if (topf < topg) */ {
+	t = cuddCofactorRecur(dd, f1, g);
+	if (t == NULL) return(NULL);
+    	cuddRef(t);
+    	e = cuddCofactorRecur(dd, f0, g);
+	if (e == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+
+	if (t == e) {
+	    r = t;
+	} else if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e));
+	    if (r != NULL)
+		r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(dd,(int)F->index,t,e);
+	}
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(dd ,e);
+	    Cudd_RecursiveDeref(dd ,t);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r);
+
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddCofactorRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddCompose.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddCompose.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddCompose.c	(revision 8)
@@ -0,0 +1,1749 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddCompose.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functional composition and variable permutation of DDs.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_bddCompose()
+		<li> Cudd_addCompose()
+		<li> Cudd_addPermute()
+		<li> Cudd_addSwapVariables()
+		<li> Cudd_bddPermute()
+		<li> Cudd_bddVarMap()
+		<li> Cudd_SetVarMap()
+		<li> Cudd_bddSwapVariables()
+		<li> Cudd_bddAdjPermuteX()
+		<li> Cudd_addVectorCompose()
+		<li> Cudd_addGeneralVectorCompose()
+		<li> Cudd_addNonSimCompose()
+		<li> Cudd_bddVectorCompose()
+		</ul>
+	       Internal procedures included in this module:
+		<ul>
+		<li> cuddBddComposeRecur()
+		<li> cuddAddComposeRecur()
+		</ul>
+	       Static procedures included in this module:
+		<ul>
+		<li> cuddAddPermuteRecur()
+		<li> cuddBddPermuteRecur()
+		<li> cuddBddVarMapRecur()
+		<li> cuddAddVectorComposeRecur()
+		<li> cuddAddGeneralVectorComposeRecur()
+		<li> cuddAddNonSimComposeRecur()
+		<li> cuddBddVectorComposeRecur()
+		<li> ddIsIthAddVar()
+		<li> ddIsIthAddVarPair()
+	       </ul>
+  The permutation functions use a local cache because the results to
+  be remembered depend on the permutation being applied.  Since the
+  permutation is just an array, it cannot be stored in the global
+  cache. There are different procedured for BDDs and ADDs. This is
+  because bddPermuteRecur uses cuddBddIteRecur. If this were changed,
+  the procedures could be merged.]
+
+  Author      [Fabio Somenzi and Kavita Ravi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddCompose.c,v 1.45 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+#ifdef DD_DEBUG
+static int addPermuteRecurHits;
+static int bddPermuteRecurHits;
+static int bddVectorComposeHits;
+static int addVectorComposeHits;
+
+static int addGeneralVectorComposeHits;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * cuddAddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut);
+static DdNode * cuddBddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut);
+static DdNode * cuddBddVarMapRecur (DdManager *manager, DdNode *f);
+static DdNode * cuddAddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest);
+static DdNode * cuddAddNonSimComposeRecur (DdManager *dd, DdNode *f, DdNode **vector, DdNode *key, DdNode *cube, int lastsub);
+static DdNode * cuddBddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest);
+DD_INLINE static int ddIsIthAddVar (DdManager *dd, DdNode *f, unsigned int i);
+
+static DdNode * cuddAddGeneralVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vectorOn, DdNode **vectorOff, int deepest);
+DD_INLINE static int ddIsIthAddVarPair (DdManager *dd, DdNode *f, DdNode *g, unsigned int i);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes g for x_v in the BDD for f.]
+
+  Description [Substitutes g for x_v in the BDD for f. v is the index of the
+  variable to be substituted. Cudd_bddCompose passes the corresponding
+  projection function to the recursive procedure, so that the cache may
+  be used.  Returns the composed BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_bddCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  int  v)
+{
+    DdNode *proj, *res;
+
+    /* Sanity check. */
+    if (v < 0 || v >= dd->size) return(NULL);
+
+    proj =  dd->vars[v];
+    do {
+	dd->reordered = 0;
+	res = cuddBddComposeRecur(dd,f,g,proj);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes g for x_v in the ADD for f.]
+
+  Description [Substitutes g for x_v in the ADD for f. v is the index of the
+  variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes
+  the corresponding projection function to the recursive procedure, so
+  that the cache may be used.  Returns the composed ADD if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  int  v)
+{
+    DdNode *proj, *res;
+
+    /* Sanity check. */
+    if (v < 0 || v >= dd->size) return(NULL);
+
+    proj =  dd->vars[v];
+    do {
+	dd->reordered = 0;
+	res = cuddAddComposeRecur(dd,f,g,proj);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables of an ADD.]
+
+  Description [Given a permutation in array permut, creates a new ADD
+  with permuted variables. There should be an entry in array permut
+  for each variable in the manager. The i-th entry of permut holds the
+  index of the variable that is to substitute the i-th
+  variable. Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_addSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_addPermute(
+  DdManager * manager,
+  DdNode * node,
+  int * permut)
+{
+    DdHashTable		*table;
+    DdNode		*res;
+
+    do {
+	manager->reordered = 0;
+	table = cuddHashTableInit(manager,1,2);
+	if (table == NULL) return(NULL);
+	/* Recursively solve the problem. */
+	res = cuddAddPermuteRecur(manager,table,node,permut);
+	if (res != NULL) cuddRef(res);
+	/* Dispose of local cache. */
+	cuddHashTableQuit(table);
+    } while (manager->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addPermute */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swaps two sets of variables of the same size (x and y) in
+  the ADD f.]
+
+  Description [Swaps two sets of variables of the same size (x and y) in
+  the ADD f.  The size is given by n. The two sets of variables are
+  assumed to be disjoint. Returns a pointer to the resulting ADD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_addSwapVariables(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *swapped;
+    int	 i, j, k;
+    int	 *permut;
+
+    permut = ALLOC(int,dd->size);
+    if (permut == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) permut[i] = i;
+    for (i = 0; i < n; i++) {
+	j = x[i]->index;
+	k = y[i]->index;
+	permut[j] = k;
+	permut[k] = j;
+    }
+
+    swapped = Cudd_addPermute(dd,f,permut);
+    FREE(permut);
+
+    return(swapped);
+
+} /* end of Cudd_addSwapVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables of a BDD.]
+
+  Description [Given a permutation in array permut, creates a new BDD
+  with permuted variables. There should be an entry in array permut
+  for each variable in the manager. The i-th entry of permut holds the
+  index of the variable that is to substitute the i-th variable.
+  Returns a pointer to the resulting BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_bddPermute(
+  DdManager * manager,
+  DdNode * node,
+  int * permut)
+{
+    DdHashTable		*table;
+    DdNode		*res;
+
+    do {
+	manager->reordered = 0;
+	table = cuddHashTableInit(manager,1,2);
+	if (table == NULL) return(NULL);
+	res = cuddBddPermuteRecur(manager,table,node,permut);
+	if (res != NULL) cuddRef(res);
+	/* Dispose of local cache. */
+	cuddHashTableQuit(table);
+
+    } while (manager->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddPermute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Remaps the variables of a BDD using the default variable map.]
+
+  Description [Remaps the variables of a BDD using the default
+  variable map.  A typical use of this function is to swap two sets of
+  variables.  The variable map must be registered with Cudd_SetVarMap.
+  Returns a pointer to the resulting BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_bddSwapVariables Cudd_SetVarMap]
+
+******************************************************************************/
+DdNode *
+Cudd_bddVarMap(
+  DdManager * manager /* DD manager */,
+  DdNode * f /* function in which to remap variables */)
+{
+    DdNode *res;
+
+    if (manager->map == NULL) return(NULL);
+    do {
+	manager->reordered = 0;
+	res = cuddBddVarMapRecur(manager, f);
+    } while (manager->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_bddVarMap */
+
+
+/**Function********************************************************************
+
+  Synopsis [Registers a variable mapping with the manager.]
+
+  Description [Registers with the manager a variable mapping described
+  by two sets of variables.  This variable mapping is then used by
+  functions like Cudd_bddVarMap.  This function is convenient for
+  those applications that perform the same mapping several times.
+  However, if several different permutations are used, it may be more
+  efficient not to rely on the registered mapping, because changing
+  mapping causes the cache to be cleared.  (The initial setting,
+  however, does not clear the cache.) The two sets of variables (x and
+  y) must have the same size (x and y).  The size is given by n. The
+  two sets of variables are normally disjoint, but this restriction is
+  not imposeded by the function. When new variables are created, the
+  map is automatically extended (each new variable maps to
+  itself). The typical use, however, is to wait until all variables
+  are created, and then create the map.  Returns 1 if the mapping is
+  successfully registered with the manager; 0 otherwise.]
+
+  SideEffects [Modifies the manager. May clear the cache.]
+
+  SeeAlso     [Cudd_bddVarMap Cudd_bddPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+int
+Cudd_SetVarMap (
+  DdManager *manager /* DD manager */,
+  DdNode **x /* first array of variables */,
+  DdNode **y /* second array of variables */,
+  int n /* length of both arrays */)
+{
+    int i;
+
+    if (manager->map != NULL) {
+	cuddCacheFlush(manager);
+    } else {
+	manager->map = ALLOC(int,manager->maxSize);
+	if (manager->map == NULL) {
+	    manager->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	manager->memused += sizeof(int) * manager->maxSize;
+    }
+    /* Initialize the map to the identity. */
+    for (i = 0; i < manager->size; i++) {
+	manager->map[i] = i;
+    }
+    /* Create the map. */
+    for (i = 0; i < n; i++) {
+	manager->map[x[i]->index] = y[i]->index;
+	manager->map[y[i]->index] = x[i]->index;
+    }
+    return(1);
+
+} /* end of Cudd_SetVarMap */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swaps two sets of variables of the same size (x and y) in
+  the BDD f.]
+
+  Description [Swaps two sets of variables of the same size (x and y)
+  in the BDD f. The size is given by n. The two sets of variables are
+  assumed to be disjoint.  Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_addSwapVariables]
+
+******************************************************************************/
+DdNode *
+Cudd_bddSwapVariables(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** x,
+  DdNode ** y,
+  int  n)
+{
+    DdNode *swapped;
+    int	 i, j, k;
+    int	 *permut;
+
+    permut = ALLOC(int,dd->size);
+    if (permut == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) permut[i] = i;
+    for (i = 0; i < n; i++) {
+	j = x[i]->index;
+	k = y[i]->index;
+	permut[j] = k;
+	permut[k] = j;
+    }
+
+    swapped = Cudd_bddPermute(dd,f,permut);
+    FREE(permut);
+
+    return(swapped);
+
+} /* end of Cudd_bddSwapVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Rearranges a set of variables in the BDD B.]
+
+  Description [Rearranges a set of variables in the BDD B. The size of
+  the set is given by n. This procedure is intended for the
+  `randomization' of the priority functions. Returns a pointer to the
+  BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_bddSwapVariables
+  Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAdjPermuteX(
+  DdManager * dd,
+  DdNode * B,
+  DdNode ** x,
+  int  n)
+{
+    DdNode *swapped;
+    int	 i, j, k;
+    int	 *permut;
+
+    permut = ALLOC(int,dd->size);
+    if (permut == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) permut[i] = i;
+    for (i = 0; i < n-2; i += 3) {
+	j = x[i]->index;
+	k = x[i+1]->index;
+	permut[j] = k;
+	permut[k] = j;
+    }
+
+    swapped = Cudd_bddPermute(dd,B,permut);
+    FREE(permut);
+
+    return(swapped);
+
+} /* end of Cudd_bddAdjPermuteX */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes an ADD with a vector of 0-1 ADDs.]
+
+  Description [Given a vector of 0-1 ADDs, creates a new ADD by
+  substituting the 0-1 ADDs for the variables of the ADD f.  There
+  should be an entry in vector for each variable in the manager.
+  If no substitution is sought for a given variable, the corresponding
+  projection function should be specified in the vector.
+  This function implements simultaneous composition.
+  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose
+  Cudd_bddVectorCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addVectorCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector)
+{
+    DdHashTable		*table;
+    DdNode		*res;
+    int			deepest;
+    int                 i;
+
+    do {
+	dd->reordered = 0;
+	/* Initialize local cache. */
+	table = cuddHashTableInit(dd,1,2);
+	if (table == NULL) return(NULL);
+
+	/* Find deepest real substitution. */
+	for (deepest = dd->size - 1; deepest >= 0; deepest--) {
+	    i = dd->invperm[deepest];
+	    if (!ddIsIthAddVar(dd,vector[i],i)) {
+		break;
+	    }
+	}
+
+	/* Recursively solve the problem. */
+	res = cuddAddVectorComposeRecur(dd,table,f,vector,deepest);
+	if (res != NULL) cuddRef(res);
+
+	/* Dispose of local cache. */
+	cuddHashTableQuit(table);
+    } while (dd->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addVectorCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes an ADD with a vector of ADDs.]
+
+  Description [Given a vector of ADDs, creates a new ADD by substituting the
+  ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted
+  for the x_v and vectorOff the ADDs to be substituted for x_v'. There should
+  be an entry in vector for each variable in the manager.  If no substitution
+  is sought for a given variable, the corresponding projection function should
+  be specified in the vector.  This function implements simultaneous
+  composition.  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_addVectorCompose Cudd_addNonSimCompose Cudd_addPermute
+  Cudd_addCompose Cudd_bddVectorCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addGeneralVectorCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vectorOn,
+  DdNode ** vectorOff)
+{
+    DdHashTable		*table;
+    DdNode		*res;
+    int			deepest;
+    int                 i;
+
+    do {
+	dd->reordered = 0;
+	/* Initialize local cache. */
+	table = cuddHashTableInit(dd,1,2);
+	if (table == NULL) return(NULL);
+
+	/* Find deepest real substitution. */
+	for (deepest = dd->size - 1; deepest >= 0; deepest--) {
+	    i = dd->invperm[deepest];
+	    if (!ddIsIthAddVarPair(dd,vectorOn[i],vectorOff[i],i)) {
+		break;
+	    }
+	}
+
+	/* Recursively solve the problem. */
+	res = cuddAddGeneralVectorComposeRecur(dd,table,f,vectorOn,
+					       vectorOff,deepest);
+	if (res != NULL) cuddRef(res);
+
+	/* Dispose of local cache. */
+	cuddHashTableQuit(table);
+    } while (dd->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addGeneralVectorCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes an ADD with a vector of 0-1 ADDs.]
+
+  Description [Given a vector of 0-1 ADDs, creates a new ADD by
+  substituting the 0-1 ADDs for the variables of the ADD f.  There
+  should be an entry in vector for each variable in the manager.
+  This function implements non-simultaneous composition. If any of the
+  functions being composed depends on any of the variables being
+  substituted, then the result depends on the order of composition,
+  which in turn depends on the variable order: The variables farther from
+  the roots in the order are substituted first.
+  Returns a pointer to the resulting ADD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addVectorCompose Cudd_addPermute Cudd_addCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_addNonSimCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector)
+{
+    DdNode		*cube, *key, *var, *tmp, *piece;
+    DdNode		*res;
+    int			i, lastsub;
+
+    /* The cache entry for this function is composed of three parts:
+    ** f itself, the replacement relation, and the cube of the
+    ** variables being substituted.
+    ** The replacement relation is the product of the terms (yi EXNOR gi).
+    ** This apporach allows us to use the global cache for this function,
+    ** with great savings in memory with respect to using arrays for the
+    ** cache entries.
+    ** First we build replacement relation and cube of substituted
+    ** variables from the vector specifying the desired composition.
+    */
+    key = DD_ONE(dd);
+    cuddRef(key);
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    for (i = (int) dd->size - 1; i >= 0; i--) {
+	if (ddIsIthAddVar(dd,vector[i],(unsigned int)i)) {
+	    continue;
+	}
+	var = Cudd_addIthVar(dd,i);
+	if (var == NULL) {
+	    Cudd_RecursiveDeref(dd,key);
+	    Cudd_RecursiveDeref(dd,cube);
+	    return(NULL);
+	}
+	cuddRef(var);
+	/* Update cube. */
+	tmp = Cudd_addApply(dd,Cudd_addTimes,var,cube);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDeref(dd,key);
+	    Cudd_RecursiveDeref(dd,cube);
+	    Cudd_RecursiveDeref(dd,var);
+	    return(NULL);
+	}
+	cuddRef(tmp);
+	Cudd_RecursiveDeref(dd,cube);
+	cube = tmp;
+	/* Update replacement relation. */
+	piece = Cudd_addApply(dd,Cudd_addXnor,var,vector[i]);
+	if (piece == NULL) {
+	    Cudd_RecursiveDeref(dd,key);
+	    Cudd_RecursiveDeref(dd,var);
+	    return(NULL);
+	}
+	cuddRef(piece);
+	Cudd_RecursiveDeref(dd,var);
+	tmp = Cudd_addApply(dd,Cudd_addTimes,key,piece);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDeref(dd,key);
+	    Cudd_RecursiveDeref(dd,piece);
+	    return(NULL);
+	}
+	cuddRef(tmp);
+	Cudd_RecursiveDeref(dd,key);
+	Cudd_RecursiveDeref(dd,piece);
+	key = tmp;
+    }
+
+    /* Now try composition, until no reordering occurs. */
+    do {
+	/* Find real substitution with largest index. */
+	for (lastsub = dd->size - 1; lastsub >= 0; lastsub--) {
+	    if (!ddIsIthAddVar(dd,vector[lastsub],(unsigned int)lastsub)) {
+		break;
+	    }
+	}
+
+	/* Recursively solve the problem. */
+	dd->reordered = 0;
+	res = cuddAddNonSimComposeRecur(dd,f,vector,key,cube,lastsub+1);
+	if (res != NULL) cuddRef(res);
+
+    } while (dd->reordered == 1);
+
+    Cudd_RecursiveDeref(dd,key);
+    Cudd_RecursiveDeref(dd,cube);
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_addNonSimCompose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Composes a BDD with a vector of BDDs.]
+
+  Description [Given a vector of BDDs, creates a new BDD by
+  substituting the BDDs for the variables of the BDD f.  There
+  should be an entry in vector for each variable in the manager.
+  If no substitution is sought for a given variable, the corresponding
+  projection function should be specified in the vector.
+  This function implements simultaneous composition.
+  Returns a pointer to the resulting BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute Cudd_bddCompose Cudd_addVectorCompose]
+
+******************************************************************************/
+DdNode *
+Cudd_bddVectorCompose(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector)
+{
+    DdHashTable		*table;
+    DdNode		*res;
+    int			deepest;
+    int                 i;
+
+    do {
+	dd->reordered = 0;
+	/* Initialize local cache. */
+	table = cuddHashTableInit(dd,1,2);
+	if (table == NULL) return(NULL);
+
+	/* Find deepest real substitution. */
+	for (deepest = dd->size - 1; deepest >= 0; deepest--) {
+	    i = dd->invperm[deepest];
+	    if (vector[i] != dd->vars[i]) {
+		break;
+	    }
+	}
+
+	/* Recursively solve the problem. */
+	res = cuddBddVectorComposeRecur(dd,table,f,vector, deepest);
+	if (res != NULL) cuddRef(res);
+
+	/* Dispose of local cache. */
+	cuddHashTableQuit(table);
+    } while (dd->reordered == 1);
+
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddVectorCompose */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCompose.]
+
+  Description [Performs the recursive step of Cudd_bddCompose.
+  Exploits the fact that the composition of f' with g
+  produces the complement of the composition of f with g to better
+  utilize the cache.  Returns the composed BDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCompose]
+
+******************************************************************************/
+DdNode *
+cuddBddComposeRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * proj)
+{
+    DdNode	*F, *G, *f1, *f0, *g1, *g0, *r, *t, *e;
+    unsigned int v, topf, topg, topindex;
+    int		comple;
+
+    statLine(dd);
+    v = dd->perm[proj->index];
+    F = Cudd_Regular(f);
+    topf = cuddI(dd,F->index);
+
+    /* Terminal case. Subsumes the test for constant f. */
+    if (topf > v) return(f);
+
+    /* We solve the problem for a regular pointer, and then complement
+    ** the result if the pointer was originally complemented.
+    */
+    comple = Cudd_IsComplement(f);
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj);
+    if (r != NULL) {
+	return(Cudd_NotCond(r,comple));
+    }
+
+    if (topf == v) {
+	/* Compose. */
+	f1 = cuddT(F);
+	f0 = cuddE(F);
+	r = cuddBddIteRecur(dd, g, f1, f0);
+	if (r == NULL) return(NULL);
+    } else {
+	/* Compute cofactors of f and g. Remember the index of the top
+	** variable.
+	*/
+	G = Cudd_Regular(g);
+	topg = cuddI(dd,G->index);
+	if (topf > topg) {
+	    topindex = G->index;
+	    f1 = f0 = F;
+	} else {
+	    topindex = F->index;
+	    f1 = cuddT(F);
+	    f0 = cuddE(F);
+	}
+	if (topg > topf) {
+	    g1 = g0 = g;
+	} else {
+	    g1 = cuddT(G);
+	    g0 = cuddE(G);
+	    if (g != G) {
+		g1 = Cudd_Not(g1);
+		g0 = Cudd_Not(g0);
+	    }
+	}
+	/* Recursive step. */
+	t = cuddBddComposeRecur(dd, f1, g1, proj);
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddBddComposeRecur(dd, f0, g0, proj);
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+
+	r = cuddBddIteRecur(dd, dd->vars[topindex], t, e);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, t);
+	    Cudd_IterDerefBdd(dd, e);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */
+	Cudd_IterDerefBdd(dd, e);
+	cuddDeref(r);
+    }
+
+    cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r);
+
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addCompose.]
+
+  Description [Performs the recursive step of Cudd_addCompose.
+  Returns the composed BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addCompose]
+
+******************************************************************************/
+DdNode *
+cuddAddComposeRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * proj)
+{
+    DdNode *f1, *f0, *g1, *g0, *r, *t, *e;
+    unsigned int v, topf, topg, topindex;
+
+    statLine(dd);
+    v = dd->perm[proj->index];
+    topf = cuddI(dd,f->index);
+
+    /* Terminal case. Subsumes the test for constant f. */
+    if (topf > v) return(f);
+
+    /* Check cache. */
+    r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj);
+    if (r != NULL) {
+	return(r);
+    }
+
+    if (topf == v) {
+	/* Compose. */
+	f1 = cuddT(f);
+	f0 = cuddE(f);
+	r = cuddAddIteRecur(dd, g, f1, f0);
+	if (r == NULL) return(NULL);
+    } else {
+	/* Compute cofactors of f and g. Remember the index of the top
+	** variable.
+	*/
+	topg = cuddI(dd,g->index);
+	if (topf > topg) {
+	    topindex = g->index;
+	    f1 = f0 = f;
+	} else {
+	    topindex = f->index;
+	    f1 = cuddT(f);
+	    f0 = cuddE(f);
+	}
+	if (topg > topf) {
+	    g1 = g0 = g;
+	} else {
+	    g1 = cuddT(g);
+	    g0 = cuddE(g);
+	}
+	/* Recursive step. */
+	t = cuddAddComposeRecur(dd, f1, g1, proj);
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddAddComposeRecur(dd, f0, g0, proj);
+	if (e == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+
+	if (t == e) {
+	    r = t;
+	} else {
+	    r = cuddUniqueInter(dd, (int) topindex, t, e);
+	    if (r == NULL) {
+		Cudd_RecursiveDeref(dd, t);
+		Cudd_RecursiveDeref(dd, e);
+		return(NULL);
+	    }
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r);
+
+    return(r);
+
+} /* end of cuddAddComposeRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_addPermute.]
+
+  Description [ Recursively puts the ADD in the order given in the
+  array permut. Checks for trivial cases to terminate recursion, then
+  splits on the children of this node.  Once the solutions for the
+  children are obtained, it puts into the current position the node
+  from the rest of the ADD that should be here. Then returns this ADD.
+  The key here is that the node being visited is NOT put in its proper
+  place by this instance, but rather is switched when its proper
+  position is reached in the recursion tree.<p>
+  The DdNode * that is returned is the same ADD as passed in as node,
+  but in the new order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addPermute cuddBddPermuteRecur]
+
+******************************************************************************/
+static DdNode *
+cuddAddPermuteRecur(
+  DdManager * manager /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * node /* ADD to be reordered */,
+  int * permut /* permutation array */)
+{
+    DdNode	*T,*E;
+    DdNode	*res,*var;
+    int		index;
+    
+    statLine(manager);
+    /* Check for terminal case of constant node. */
+    if (cuddIsConstant(node)) {
+	return(node);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
+#ifdef DD_DEBUG
+	addPermuteRecurHits++;
+#endif
+	return(res);
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddAddPermuteRecur(manager,table,cuddT(node),permut);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddAddPermuteRecur(manager,table,cuddE(node),permut);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(manager, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    /* Move variable that should be in this position to this position
+    ** by creating a single var ADD for that variable, and calling
+    ** cuddAddIteRecur with the T and E we just created.
+    */
+    index = permut[node->index];
+    var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager));
+    if (var == NULL) return(NULL);
+    cuddRef(var);
+    res = cuddAddIteRecur(manager,var,T,E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(manager,var);
+	Cudd_RecursiveDeref(manager, T);
+	Cudd_RecursiveDeref(manager, E);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(manager,var);
+    Cudd_RecursiveDeref(manager, T);
+    Cudd_RecursiveDeref(manager, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (node->ref != 1) {
+	ptrint fanout = (ptrint) node->ref;
+	cuddSatDec(fanout);
+	if (!cuddHashTableInsert1(table,node,res,fanout)) {
+	    Cudd_RecursiveDeref(manager, res);
+	    return(NULL);
+	}
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddAddPermuteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddPermute.]
+
+  Description [ Recursively puts the BDD in the order given in the array permut.
+  Checks for trivial cases to terminate recursion, then splits on the
+  children of this node.  Once the solutions for the children are
+  obtained, it puts into the current position the node from the rest of
+  the BDD that should be here. Then returns this BDD.
+  The key here is that the node being visited is NOT put in its proper
+  place by this instance, but rather is switched when its proper position
+  is reached in the recursion tree.<p>
+  The DdNode * that is returned is the same BDD as passed in as node,
+  but in the new order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPermute cuddAddPermuteRecur]
+
+******************************************************************************/
+static DdNode *
+cuddBddPermuteRecur(
+  DdManager * manager /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * node /* BDD to be reordered */,
+  int * permut /* permutation array */)
+{
+    DdNode	*N,*T,*E;
+    DdNode	*res;
+    int		index;
+
+    statLine(manager);
+    N = Cudd_Regular(node);
+
+    /* Check for terminal case of constant node. */
+    if (cuddIsConstant(N)) {
+	return(node);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) {
+#ifdef DD_DEBUG
+	bddPermuteRecurHits++;
+#endif
+	return(Cudd_NotCond(res,N != node));
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddBddPermuteRecur(manager,table,cuddT(N),permut);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddBddPermuteRecur(manager,table,cuddE(N),permut);
+    if (E == NULL) {
+	Cudd_IterDerefBdd(manager, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    /* Move variable that should be in this position to this position
+    ** by retrieving the single var BDD for that variable, and calling
+    ** cuddBddIteRecur with the T and E we just created.
+    */
+    index = permut[N->index];
+    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(manager, T);
+	Cudd_IterDerefBdd(manager, E);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(manager, T);
+    Cudd_IterDerefBdd(manager, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (N->ref != 1) {
+	ptrint fanout = (ptrint) N->ref;
+	cuddSatDec(fanout);
+	if (!cuddHashTableInsert1(table,N,res,fanout)) {
+	    Cudd_IterDerefBdd(manager, res);
+	    return(NULL);
+	}
+    }
+    cuddDeref(res);
+    return(Cudd_NotCond(res,N != node));
+
+} /* end of cuddBddPermuteRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_bddVarMap.]
+
+  Description [Implements the recursive step of Cudd_bddVarMap.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddVarMap]
+
+******************************************************************************/
+static DdNode *
+cuddBddVarMapRecur(
+  DdManager *manager /* DD manager */,
+  DdNode *f /* BDD to be remapped */)
+{
+    DdNode	*F, *T, *E;
+    DdNode	*res;
+    int		index;
+
+    statLine(manager);
+    F = Cudd_Regular(f);
+
+    /* Check for terminal case of constant node. */
+    if (cuddIsConstant(F)) {
+	return(f);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if (F->ref != 1 &&
+	(res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) {
+	return(Cudd_NotCond(res,F != f));
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddBddVarMapRecur(manager,cuddT(F));
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddBddVarMapRecur(manager,cuddE(F));
+    if (E == NULL) {
+	Cudd_IterDerefBdd(manager, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    /* Move variable that should be in this position to this position
+    ** by retrieving the single var BDD for that variable, and calling
+    ** cuddBddIteRecur with the T and E we just created.
+    */
+    index = manager->map[F->index];
+    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(manager, T);
+	Cudd_IterDerefBdd(manager, E);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(manager, T);
+    Cudd_IterDerefBdd(manager, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (F->ref != 1) {
+	cuddCacheInsert1(manager,Cudd_bddVarMap,F,res);
+    }
+    cuddDeref(res);
+    return(Cudd_NotCond(res,F != f));
+
+} /* end of cuddBddVarMapRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addVectorCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddVectorComposeRecur(
+  DdManager * dd /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * f /* ADD in which to compose */,
+  DdNode ** vector /* functions to substitute */,
+  int  deepest /* depth of deepest substitution */)
+{
+    DdNode	*T,*E;
+    DdNode	*res;
+
+    statLine(dd);
+    /* If we are past the deepest substitution, return f. */
+    if (cuddI(dd,f->index) > deepest) {
+	return(f);
+    }
+
+    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
+#ifdef DD_DEBUG
+	addVectorComposeHits++;
+#endif
+	return(res);
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest);
+    if (T == NULL)  return(NULL);
+    cuddRef(T);
+    E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    /* Retrieve the 0-1 ADD for the current top variable and call
+    ** cuddAddIteRecur with the T and E we just created.
+    */
+    res = cuddAddIteRecur(dd,vector[f->index],T,E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	Cudd_RecursiveDeref(dd, E);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, T);
+    Cudd_RecursiveDeref(dd, E);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again
+    */
+    if (f->ref != 1) {
+	ptrint fanout = (ptrint) f->ref;
+	cuddSatDec(fanout);
+	if (!cuddHashTableInsert1(table,f,res,fanout)) {
+	    Cudd_RecursiveDeref(dd, res);
+	    return(NULL);
+	}
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddAddVectorComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addGeneralVectorCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddGeneralVectorComposeRecur(
+  DdManager * dd /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * f /* ADD in which to compose */,
+  DdNode ** vectorOn /* functions to substitute for x_i */,
+  DdNode ** vectorOff /* functions to substitute for x_i' */,
+  int  deepest /* depth of deepest substitution */)
+{
+    DdNode	*T,*E,*t,*e;
+    DdNode	*res;
+
+    /* If we are past the deepest substitution, return f. */
+    if (cuddI(dd,f->index) > deepest) {
+	return(f);
+    }
+
+    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
+#ifdef DD_DEBUG
+	addGeneralVectorComposeHits++;
+#endif
+	return(res);
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f),
+					 vectorOn,vectorOff,deepest);
+    if (T == NULL)  return(NULL);
+    cuddRef(T);
+    E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f),
+					 vectorOn,vectorOff,deepest);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    /* Retrieve the compose ADDs for the current top variable and call
+    ** cuddAddApplyRecur with the T and E we just created.
+    */
+    t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T);
+    if (t == NULL) {
+      Cudd_RecursiveDeref(dd,T);
+      Cudd_RecursiveDeref(dd,E);
+      return(NULL);
+    }
+    cuddRef(t);
+    e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E);
+    if (e == NULL) {
+      Cudd_RecursiveDeref(dd,T);
+      Cudd_RecursiveDeref(dd,E);
+      Cudd_RecursiveDeref(dd,t);
+      return(NULL);
+    }
+    cuddRef(e);
+    res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
+    if (res == NULL) {
+      Cudd_RecursiveDeref(dd,T);
+      Cudd_RecursiveDeref(dd,E);
+      Cudd_RecursiveDeref(dd,t);
+      Cudd_RecursiveDeref(dd,e);
+      return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,T);
+    Cudd_RecursiveDeref(dd,E);
+    Cudd_RecursiveDeref(dd,t);
+    Cudd_RecursiveDeref(dd,e);
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again
+    */
+    if (f->ref != 1) {
+	ptrint fanout = (ptrint) f->ref;
+	cuddSatDec(fanout);
+	if (!cuddHashTableInsert1(table,f,res,fanout)) {
+	    Cudd_RecursiveDeref(dd, res);
+	    return(NULL);
+	}
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddAddGeneralVectorComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addNonSimCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddNonSimComposeRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** vector,
+  DdNode * key,
+  DdNode * cube,
+  int  lastsub)
+{
+    DdNode *f1, *f0, *key1, *key0, *cube1, *var;
+    DdNode *T,*E;
+    DdNode *r;
+    unsigned int top, topf, topk, topc;
+    unsigned int index;
+    int i;
+    DdNode **vect1;
+    DdNode **vect0;
+
+    statLine(dd);
+    /* If we are past the deepest substitution, return f. */
+    if (cube == DD_ONE(dd) || cuddIsConstant(f)) {
+	return(f);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube);
+    if (r != NULL) {
+	return(r);
+    }
+
+    /* Find top variable. we just need to look at f, key, and cube,
+    ** because all the varibles in the gi are in key.
+    */
+    topf = cuddI(dd,f->index);
+    topk = cuddI(dd,key->index);
+    top = ddMin(topf,topk);
+    topc = cuddI(dd,cube->index);
+    top = ddMin(top,topc);
+    index = dd->invperm[top];
+
+    /* Compute the cofactors. */
+    if (topf == top) {
+	f1 = cuddT(f);
+	f0 = cuddE(f);
+    } else {
+	f1 = f0 = f;
+    }
+    if (topc == top) {
+	cube1 = cuddT(cube);
+	/* We want to eliminate vector[index] from key. Otherwise
+	** cache performance is severely affected. Hence we
+	** existentially quantify the variable with index "index" from key.
+	*/
+	var = Cudd_addIthVar(dd, (int) index);
+	if (var == NULL) {
+	    return(NULL);
+	}
+	cuddRef(var);
+	key1 = cuddAddExistAbstractRecur(dd, key, var);
+	if (key1 == NULL) {
+	    Cudd_RecursiveDeref(dd,var);
+	    return(NULL);
+	}
+	cuddRef(key1);
+	Cudd_RecursiveDeref(dd,var);
+	key0 = key1;
+    } else {
+	cube1 = cube;
+	if (topk == top) {
+	    key1 = cuddT(key);
+	    key0 = cuddE(key);
+	} else {
+	    key1 = key0 = key;
+	}
+	cuddRef(key1);
+    }
+
+    /* Allocate two new vectors for the cofactors of vector. */
+    vect1 = ALLOC(DdNode *,lastsub);
+    if (vect1 == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	Cudd_RecursiveDeref(dd,key1);
+	return(NULL);
+    }
+    vect0 = ALLOC(DdNode *,lastsub);
+    if (vect0 == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	Cudd_RecursiveDeref(dd,key1);
+	FREE(vect1);
+	return(NULL);
+    }
+
+    /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because
+    ** we do not need them.
+    */
+    for (i = 0; i < lastsub; i++) {
+	DdNode *gi = vector[i];
+	if (gi == NULL) {
+	    vect1[i] = vect0[i] = NULL;
+	} else if (gi->index == index) {
+	    vect1[i] = cuddT(gi);
+	    vect0[i] = cuddE(gi);
+	} else {
+	    vect1[i] = vect0[i] = gi;
+	}
+    }
+    vect1[index] = vect0[index] = NULL;
+
+    /* Recur on children. */
+    T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub);
+    FREE(vect1);
+    if (T == NULL) {
+	Cudd_RecursiveDeref(dd,key1);
+	FREE(vect0);
+	return(NULL);
+    }
+    cuddRef(T);
+    E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub);
+    FREE(vect0);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd,key1);
+	Cudd_RecursiveDeref(dd,T);
+	return(NULL);
+    }
+    cuddRef(E);
+    Cudd_RecursiveDeref(dd,key1);
+
+    /* Retrieve the 0-1 ADD for the current top variable from vector,
+    ** and call cuddAddIteRecur with the T and E we just created.
+    */
+    r = cuddAddIteRecur(dd,vector[index],T,E);
+    if (r == NULL) {
+	Cudd_RecursiveDeref(dd,T);
+	Cudd_RecursiveDeref(dd,E);
+	return(NULL);
+    }
+    cuddRef(r);
+    Cudd_RecursiveDeref(dd,T);
+    Cudd_RecursiveDeref(dd,E);
+    cuddDeref(r);
+
+    /* Store answer to trim recursion. */
+    cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r);
+
+    return(r);
+
+} /* end of cuddAddNonSimComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddVectorCompose.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddBddVectorComposeRecur(
+  DdManager * dd /* DD manager */,
+  DdHashTable * table /* computed table */,
+  DdNode * f /* BDD in which to compose */,
+  DdNode ** vector /* functions to be composed */,
+  int deepest /* depth of the deepest substitution */)
+{
+    DdNode	*F,*T,*E;
+    DdNode	*res;
+
+    statLine(dd);
+    F = Cudd_Regular(f);
+
+    /* If we are past the deepest substitution, return f. */
+    if (cuddI(dd,F->index) > deepest) {
+	return(f);
+    }
+
+    /* If problem already solved, look up answer and return. */
+    if ((res = cuddHashTableLookup1(table,F)) != NULL) {
+#ifdef DD_DEBUG
+	bddVectorComposeHits++;
+#endif
+	return(Cudd_NotCond(res,F != f));
+    }
+
+    /* Split and recur on children of this node. */
+    T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest);
+    if (T == NULL) return(NULL);
+    cuddRef(T);
+    E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest);
+    if (E == NULL) {
+	Cudd_IterDerefBdd(dd, T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    /* Call cuddBddIteRecur with the BDD that replaces the current top
+    ** variable and the T and E we just created.
+    */
+    res = cuddBddIteRecur(dd,vector[F->index],T,E);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(dd, T);
+	Cudd_IterDerefBdd(dd, E);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd, T);
+    Cudd_IterDerefBdd(dd, E);	
+
+    /* Do not keep the result if the reference count is only 1, since
+    ** it will not be visited again.
+    */
+    if (F->ref != 1) {
+	ptrint fanout = (ptrint) F->ref;
+	cuddSatDec(fanout);
+	if (!cuddHashTableInsert1(table,F,res,fanout)) {
+	    Cudd_IterDerefBdd(dd, res);
+	    return(NULL);
+	}
+    }
+    cuddDeref(res);
+    return(Cudd_NotCond(res,F != f));
+
+} /* end of cuddBddVectorComposeRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison of a function to the i-th ADD variable.]
+
+  Description [Comparison of a function to the i-th ADD variable. Returns 1 if
+  the function is the i-th ADD variable; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static int
+ddIsIthAddVar(
+  DdManager * dd,
+  DdNode * f,
+  unsigned int  i)
+{
+    return(f->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd));
+
+} /* end of ddIsIthAddVar */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison of a pair of functions to the i-th ADD variable.]
+
+  Description [Comparison of a pair of functions to the i-th ADD
+  variable. Returns 1 if the functions are the i-th ADD variable and its
+  complement; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static int
+ddIsIthAddVarPair(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  unsigned int  i)
+{
+    return(f->index == i && g->index == i && 
+	   cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd) &&
+	   cuddT(g) == DD_ZERO(dd) && cuddE(g) == DD_ONE(dd));
+
+} /* end of ddIsIthAddVarPair */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddDecomp.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddDecomp.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddDecomp.c	(revision 8)
@@ -0,0 +1,2177 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddDecomp.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for BDD decomposition.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_bddApproxConjDecomp()
+		<li> Cudd_bddApproxDisjDecomp()
+		<li> Cudd_bddIterConjDecomp()
+		<li> Cudd_bddIterDisjDecomp()
+		<li> Cudd_bddGenConjDecomp()
+		<li> Cudd_bddGenDisjDecomp()
+		<li> Cudd_bddVarConjDecomp()
+		<li> Cudd_bddVarDisjDecomp()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> cuddConjunctsAux()
+		<li> CreateBotDist()
+		<li> BuildConjuncts()
+		<li> ConjunctsFree()
+		</ul>]
+
+  Author      [Kavita Ravi, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define DEPTH 5
+#define THRESHOLD 10
+#define NONE 0
+#define PAIR_ST 1
+#define PAIR_CR 2
+#define G_ST 3
+#define G_CR 4
+#define H_ST 5
+#define H_CR 6
+#define BOTH_G 7
+#define BOTH_H 8
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct Conjuncts {
+    DdNode *g;
+    DdNode *h;
+} Conjuncts;
+
+typedef struct  NodeStat {
+    int distance;
+    int localRef;
+} NodeStat;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddDecomp.c,v 1.44 2004/08/13 18:04:47 fabio Exp $";
+#endif
+
+static	DdNode	*one, *zero;
+long lastTimeG;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+#define FactorsNotStored(factors)  ((int)((long)(factors) & 01))
+
+#define FactorsComplement(factors) ((Conjuncts *)((long)(factors) | 01))
+
+#define FactorsUncomplement(factors) ((Conjuncts *)((long)(factors) ^ 01))
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static NodeStat * CreateBotDist (DdNode * node, st_table * distanceTable);
+static double CountMinterms (DdNode * node, double max, st_table * mintermTable, FILE *fp);
+static void ConjunctsFree (DdManager * dd, Conjuncts * factors);
+static int PairInTables (DdNode * g, DdNode * h, st_table * ghTable);
+static Conjuncts * CheckTablesCacheAndReturn (DdNode * node, DdNode * g, DdNode * h, st_table * ghTable, st_table * cacheTable);
+static Conjuncts * PickOnePair (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable);
+static Conjuncts * CheckInTables (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable, int * outOfMem);
+static Conjuncts * ZeroCase (DdManager * dd, DdNode * node, Conjuncts * factorsNv, st_table * ghTable, st_table * cacheTable, int switched);
+static Conjuncts * BuildConjuncts (DdManager * dd, DdNode * node, st_table * distanceTable, st_table * cacheTable, int approxDistance, int maxLocalRef, st_table * ghTable, st_table * mintermTable);
+static int cuddConjunctsAux (DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Performs two-way conjunctive decomposition of a
+  BDD. This procedure owes its name to the use of supersetting to
+  obtain an initial factor of the given function. Returns the number
+  of conjuncts produced, that is, 2 if successful; 1 if no meaningful
+  decomposition was found; 0 otherwise. The conjuncts produced by this
+  procedure tend to be imbalanced.]
+
+  SideEffects [The factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddApproxDisjDecomp Cudd_bddIterConjDecomp
+  Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox
+  Cudd_bddSqueeze Cudd_bddLICompaction]
+
+******************************************************************************/
+int
+Cudd_bddApproxConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the first factor */)
+{
+    DdNode *superset1, *superset2, *glocal, *hlocal;
+    int nvars = Cudd_SupportSize(dd,f);
+
+    /* Find a tentative first factor by overapproximation and minimization. */
+    superset1 = Cudd_RemapOverApprox(dd,f,nvars,0,1.0);
+    if (superset1 == NULL) return(0);
+    cuddRef(superset1);
+    superset2 = Cudd_bddSqueeze(dd,f,superset1);
+    if (superset2 == NULL) {
+	Cudd_RecursiveDeref(dd,superset1);
+	return(0);
+    }
+    cuddRef(superset2);
+    Cudd_RecursiveDeref(dd,superset1);
+
+    /* Compute the second factor by minimization. */
+    hlocal = Cudd_bddLICompaction(dd,f,superset2);
+    if (hlocal == NULL) {
+	Cudd_RecursiveDeref(dd,superset2);
+	return(0);
+    }
+    cuddRef(hlocal);
+
+    /* Refine the first factor by minimization. If h turns out to be f, this
+    ** step guarantees that g will be 1. */
+    glocal = Cudd_bddLICompaction(dd,superset2,hlocal);
+    if (glocal == NULL) {
+	Cudd_RecursiveDeref(dd,superset2);
+	Cudd_RecursiveDeref(dd,hlocal);
+	return(0);
+    }
+    cuddRef(glocal);
+    Cudd_RecursiveDeref(dd,superset2);
+
+    if (glocal != DD_ONE(dd)) {
+	if (hlocal != DD_ONE(dd)) {
+	    *conjuncts = ALLOC(DdNode *,2);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,glocal);
+		Cudd_RecursiveDeref(dd,hlocal);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = glocal;
+	    (*conjuncts)[1] = hlocal;
+	    return(2);
+	} else {
+	    Cudd_RecursiveDeref(dd,hlocal);
+	    *conjuncts = ALLOC(DdNode *,1);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,glocal);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = glocal;
+	    return(1);
+	}
+    } else {
+	Cudd_RecursiveDeref(dd,glocal);
+	*conjuncts = ALLOC(DdNode *,1);
+	if (*conjuncts == NULL) {
+	    Cudd_RecursiveDeref(dd,hlocal);
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	(*conjuncts)[0] = hlocal;
+	return(1);
+    }
+
+} /* end of Cudd_bddApproxConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD.
+  Returns the number of disjuncts produced, that is, 2 if successful;
+  1 if no meaningful decomposition was found; 0 otherwise. The
+  disjuncts produced by this procedure tend to be imbalanced.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddApproxConjDecomp Cudd_bddIterDisjDecomp
+  Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddApproxDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddApproxConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+	(*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddApproxDisjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Performs two-way conjunctive decomposition of a
+  BDD. This procedure owes its name to the iterated use of
+  supersetting to obtain a factor of the given function. Returns the
+  number of conjuncts produced, that is, 2 if successful; 1 if no
+  meaningful decomposition was found; 0 otherwise. The conjuncts
+  produced by this procedure tend to be imbalanced.]
+
+  SideEffects [The factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddIterDisjDecomp Cudd_bddApproxConjDecomp
+  Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox
+  Cudd_bddSqueeze Cudd_bddLICompaction]
+
+******************************************************************************/
+int
+Cudd_bddIterConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the array of conjuncts */)
+{
+    DdNode *superset1, *superset2, *old[2], *res[2];
+    int sizeOld, sizeNew;
+    int nvars = Cudd_SupportSize(dd,f);
+
+    old[0] = DD_ONE(dd);
+    cuddRef(old[0]);
+    old[1] = f;
+    cuddRef(old[1]);
+    sizeOld = Cudd_SharingSize(old,2);
+
+    do {
+	/* Find a tentative first factor by overapproximation and
+	** minimization. */
+	superset1 = Cudd_RemapOverApprox(dd,old[1],nvars,0,1.0);
+	if (superset1 == NULL) {
+	    Cudd_RecursiveDeref(dd,old[0]);
+	    Cudd_RecursiveDeref(dd,old[1]);
+	    return(0);
+	}
+	cuddRef(superset1);
+	superset2 = Cudd_bddSqueeze(dd,old[1],superset1);
+	if (superset2 == NULL) {
+	    Cudd_RecursiveDeref(dd,old[0]);
+	    Cudd_RecursiveDeref(dd,old[1]);
+	    Cudd_RecursiveDeref(dd,superset1);
+	    return(0);
+	}
+	cuddRef(superset2);
+	Cudd_RecursiveDeref(dd,superset1);
+	res[0] = Cudd_bddAnd(dd,old[0],superset2);
+	if (res[0] == NULL) {
+	    Cudd_RecursiveDeref(dd,superset2);
+	    Cudd_RecursiveDeref(dd,old[0]);
+	    Cudd_RecursiveDeref(dd,old[1]);
+	    return(0);
+	}
+	cuddRef(res[0]);
+	Cudd_RecursiveDeref(dd,superset2);
+	if (res[0] == old[0]) {
+	    Cudd_RecursiveDeref(dd,res[0]);
+	    break;	/* avoid infinite loop */
+	}
+
+	/* Compute the second factor by minimization. */
+	res[1] = Cudd_bddLICompaction(dd,old[1],res[0]);
+	if (res[1] == NULL) {
+	    Cudd_RecursiveDeref(dd,old[0]);
+	    Cudd_RecursiveDeref(dd,old[1]);
+	    return(0);
+	}
+	cuddRef(res[1]);
+
+	sizeNew = Cudd_SharingSize(res,2);
+	if (sizeNew <= sizeOld) {
+	    Cudd_RecursiveDeref(dd,old[0]);
+	    old[0] = res[0];
+	    Cudd_RecursiveDeref(dd,old[1]);
+	    old[1] = res[1];
+	    sizeOld = sizeNew;
+	} else {
+	    Cudd_RecursiveDeref(dd,res[0]);
+	    Cudd_RecursiveDeref(dd,res[1]);
+	    break;
+	}
+
+    } while (1);
+
+    /* Refine the first factor by minimization. If h turns out to
+    ** be f, this step guarantees that g will be 1. */
+    superset1 = Cudd_bddLICompaction(dd,old[0],old[1]);
+    if (superset1 == NULL) {
+	Cudd_RecursiveDeref(dd,old[0]);
+	Cudd_RecursiveDeref(dd,old[1]);
+	return(0);
+    }
+    cuddRef(superset1);
+    Cudd_RecursiveDeref(dd,old[0]);
+    old[0] = superset1;
+
+    if (old[0] != DD_ONE(dd)) {
+	if (old[1] != DD_ONE(dd)) {
+	    *conjuncts = ALLOC(DdNode *,2);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,old[0]);
+		Cudd_RecursiveDeref(dd,old[1]);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = old[0];
+	    (*conjuncts)[1] = old[1];
+	    return(2);
+	} else {
+	    Cudd_RecursiveDeref(dd,old[1]);
+	    *conjuncts = ALLOC(DdNode *,1);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,old[0]);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = old[0];
+	    return(1);
+	}
+    } else {
+	Cudd_RecursiveDeref(dd,old[0]);
+	*conjuncts = ALLOC(DdNode *,1);
+	if (*conjuncts == NULL) {
+	    Cudd_RecursiveDeref(dd,old[1]);
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	(*conjuncts)[0] = old[1];
+	return(1);
+    }
+
+} /* end of Cudd_bddIterConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD.
+  Returns the number of disjuncts produced, that is, 2 if successful;
+  1 if no meaningful decomposition was found; 0 otherwise. The
+  disjuncts produced by this procedure tend to be imbalanced.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddIterConjDecomp Cudd_bddApproxDisjDecomp
+  Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddIterDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddIterConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+	(*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddIterDisjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Performs two-way conjunctive decomposition of a
+  BDD. This procedure owes its name to the fact tht it generalizes the
+  decomposition based on the cofactors with respect to one
+  variable. Returns the number of conjuncts produced, that is, 2 if
+  successful; 1 if no meaningful decomposition was found; 0
+  otherwise. The conjuncts produced by this procedure tend to be
+  balanced.]
+
+  SideEffects [The two factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddGenDisjDecomp Cudd_bddApproxConjDecomp
+  Cudd_bddIterConjDecomp Cudd_bddVarConjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddGenConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the array of conjuncts */)
+{
+    int result;
+    DdNode *glocal, *hlocal;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+    
+    do {
+	dd->reordered = 0;
+	result = cuddConjunctsAux(dd, f, &glocal, &hlocal);
+    } while (dd->reordered == 1);
+
+    if (result == 0) {
+	return(0);
+    }
+
+    if (glocal != one) {
+	if (hlocal != one) {
+	    *conjuncts = ALLOC(DdNode *,2);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,glocal);
+		Cudd_RecursiveDeref(dd,hlocal);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = glocal;
+	    (*conjuncts)[1] = hlocal;
+	    return(2);
+	} else {
+	    Cudd_RecursiveDeref(dd,hlocal);
+	    *conjuncts = ALLOC(DdNode *,1);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,glocal);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = glocal;
+	    return(1);
+	}
+    } else {
+	Cudd_RecursiveDeref(dd,glocal);
+	*conjuncts = ALLOC(DdNode *,1);
+	if (*conjuncts == NULL) {
+	    Cudd_RecursiveDeref(dd,hlocal);
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	(*conjuncts)[0] = hlocal;
+	return(1);
+    }
+
+} /* end of Cudd_bddGenConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD.
+  Returns the number of disjuncts produced, that is, 2 if successful;
+  1 if no meaningful decomposition was found; 0 otherwise. The
+  disjuncts produced by this procedure tend to be balanced.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddGenConjDecomp Cudd_bddApproxDisjDecomp
+  Cudd_bddIterDisjDecomp Cudd_bddVarDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddGenDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddGenConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+	(*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddGenDisjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way conjunctive decomposition of a BDD.]
+
+  Description [Conjunctively decomposes one BDD according to a
+  variable.  If <code>f</code> is the function of the BDD and
+  <code>x</code> is the variable, the decomposition is
+  <code>(f+x)(f+x')</code>.  The variable is chosen so as to balance
+  the sizes of the two conjuncts and to keep them small.  Returns the
+  number of conjuncts produced, that is, 2 if successful; 1 if no
+  meaningful decomposition was found; 0 otherwise.]
+
+  SideEffects [The two factors are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the conjuncts are already
+  referenced. If the function returns 0, the array for the conjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddVarDisjDecomp Cudd_bddGenConjDecomp
+  Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp]
+
+*****************************************************************************/
+int
+Cudd_bddVarConjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** conjuncts /* address of the array of conjuncts */)
+{
+    int best;
+    int min;
+    DdNode *support, *scan, *var, *glocal, *hlocal;
+
+    /* Find best cofactoring variable. */
+    support = Cudd_Support(dd,f);
+    if (support == NULL) return(0);
+    if (Cudd_IsConstant(support)) {
+	*conjuncts = ALLOC(DdNode *,1);
+	if (*conjuncts == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	(*conjuncts)[0] = f;
+	cuddRef((*conjuncts)[0]);
+	return(1);
+    }
+    cuddRef(support);
+    min = 1000000000;
+    best = -1;
+    scan = support;
+    while (!Cudd_IsConstant(scan)) {
+	int i = scan->index;
+	int est1 = Cudd_EstimateCofactor(dd,f,i,1);
+	int est0 = Cudd_EstimateCofactor(dd,f,i,0);
+	/* Minimize the size of the larger of the two cofactors. */
+	int est = (est1 > est0) ? est1 : est0;
+	if (est < min) {
+	    min = est;
+	    best = i;
+	}
+	scan = cuddT(scan);
+    }
+#ifdef DD_DEBUG
+    assert(best >= 0 && best < dd->size);
+#endif
+    Cudd_RecursiveDeref(dd,support);
+
+    var = Cudd_bddIthVar(dd,best);
+    glocal = Cudd_bddOr(dd,f,var);
+    if (glocal == NULL) {
+	return(0);
+    }
+    cuddRef(glocal);
+    hlocal = Cudd_bddOr(dd,f,Cudd_Not(var));
+    if (hlocal == NULL) {
+	Cudd_RecursiveDeref(dd,glocal);
+	return(0);
+    }
+    cuddRef(hlocal);
+
+    if (glocal != DD_ONE(dd)) {
+	if (hlocal != DD_ONE(dd)) {
+	    *conjuncts = ALLOC(DdNode *,2);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,glocal);
+		Cudd_RecursiveDeref(dd,hlocal);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = glocal;
+	    (*conjuncts)[1] = hlocal;
+	    return(2);
+	} else {
+	    Cudd_RecursiveDeref(dd,hlocal);
+	    *conjuncts = ALLOC(DdNode *,1);
+	    if (*conjuncts == NULL) {
+		Cudd_RecursiveDeref(dd,glocal);
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    (*conjuncts)[0] = glocal;
+	    return(1);
+	}
+    } else {
+	Cudd_RecursiveDeref(dd,glocal);
+	*conjuncts = ALLOC(DdNode *,1);
+	if (*conjuncts == NULL) {
+	    Cudd_RecursiveDeref(dd,hlocal);
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	(*conjuncts)[0] = hlocal;
+	return(1);
+    }
+
+} /* end of Cudd_bddVarConjDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs two-way disjunctive decomposition of a BDD.]
+
+  Description [Performs two-way disjunctive decomposition of a BDD
+  according to a variable. If <code>f</code> is the function of the
+  BDD and <code>x</code> is the variable, the decomposition is
+  <code>f*x + f*x'</code>.  The variable is chosen so as to balance
+  the sizes of the two disjuncts and to keep them small.  Returns the
+  number of disjuncts produced, that is, 2 if successful; 1 if no
+  meaningful decomposition was found; 0 otherwise.]
+
+  SideEffects [The two disjuncts are returned in an array as side effects.
+  The array is allocated by this function. It is the caller's responsibility
+  to free it. On successful completion, the disjuncts are already
+  referenced. If the function returns 0, the array for the disjuncts is
+  not allocated. If the function returns 1, the only factor equals the
+  function to be decomposed.]
+
+  SeeAlso     [Cudd_bddVarConjDecomp Cudd_bddApproxDisjDecomp
+  Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp]
+
+******************************************************************************/
+int
+Cudd_bddVarDisjDecomp(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be decomposed */,
+  DdNode *** disjuncts /* address of the array of the disjuncts */)
+{
+    int result, i;
+
+    result = Cudd_bddVarConjDecomp(dd,Cudd_Not(f),disjuncts);
+    for (i = 0; i < result; i++) {
+	(*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
+    }
+    return(result);
+
+} /* end of Cudd_bddVarDisjDecomp */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get longest distance of node from constant.]
+
+  Description [Get longest distance of node from constant. Returns the
+  distance of the root from the constant if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static NodeStat *
+CreateBotDist(
+  DdNode * node,
+  st_table * distanceTable)
+{
+    DdNode *N, *Nv, *Nnv;
+    int distance, distanceNv, distanceNnv;
+    NodeStat *nodeStat, *nodeStatNv, *nodeStatNnv;
+
+#if 0
+    if (Cudd_IsConstant(node)) {
+	return(0);
+    }
+#endif
+    
+    /* Return the entry in the table if found. */
+    N = Cudd_Regular(node);
+    if (st_lookup(distanceTable, N, &nodeStat)) {
+	nodeStat->localRef++;
+	return(nodeStat);
+    }
+
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* Recur on the children. */
+    nodeStatNv = CreateBotDist(Nv, distanceTable);
+    if (nodeStatNv == NULL) return(NULL);
+    distanceNv = nodeStatNv->distance;
+
+    nodeStatNnv = CreateBotDist(Nnv, distanceTable);
+    if (nodeStatNnv == NULL) return(NULL);
+    distanceNnv = nodeStatNnv->distance;
+    /* Store max distance from constant; note sometimes this distance
+    ** may be to 0.
+    */
+    distance = (distanceNv > distanceNnv) ? (distanceNv+1) : (distanceNnv + 1);
+
+    nodeStat = ALLOC(NodeStat, 1);
+    if (nodeStat == NULL) {
+	return(0);
+    }
+    nodeStat->distance = distance;
+    nodeStat->localRef = 1;
+    
+    if (st_insert(distanceTable, (char *)N, (char *)nodeStat) ==
+	ST_OUT_OF_MEM) {
+	return(0);
+
+    }
+    return(nodeStat);
+
+} /* end of CreateBotDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Count the number of minterms of each node ina a BDD and
+  store it in a hash table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double
+CountMinterms(
+  DdNode * node,
+  double  max,
+  st_table * mintermTable,
+  FILE *fp)
+{
+    DdNode *N, *Nv, *Nnv;
+    double min, minNv, minNnv;
+    double *dummy;
+
+    N = Cudd_Regular(node);
+
+    if (cuddIsConstant(N)) {
+	if (node == zero) {
+	    return(0);
+	} else {
+	    return(max);
+	}
+    }
+
+    /* Return the entry in the table if found. */
+    if (st_lookup(mintermTable, node, &dummy)) {
+	min = *dummy;
+	return(min);
+    }
+
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* Recur on the children. */
+    minNv = CountMinterms(Nv, max, mintermTable, fp);
+    if (minNv == -1.0) return(-1.0);
+    minNnv = CountMinterms(Nnv, max, mintermTable, fp);
+    if (minNnv == -1.0) return(-1.0);
+    min = minNv / 2.0 + minNnv / 2.0;
+    /* store 
+     */
+
+    dummy = ALLOC(double, 1);
+    if (dummy == NULL) return(-1.0);
+    *dummy = min;
+    if (st_insert(mintermTable, (char *)node, (char *)dummy) == ST_OUT_OF_MEM) {
+	(void) fprintf(fp, "st table insert failed\n");
+    }
+    return(min);
+
+} /* end of CountMinterms */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free factors structure]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ConjunctsFree(
+  DdManager * dd,
+  Conjuncts * factors)
+{
+    Cudd_RecursiveDeref(dd, factors->g);
+    Cudd_RecursiveDeref(dd, factors->h);
+    FREE(factors);
+    return;
+
+} /* end of ConjunctsFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether the given pair is in the tables.]
+
+  Description [.Check whether the given pair is in the tables.  gTable
+  and hTable are combined.
+  absence in both is indicated by 0,
+  presence in gTable is indicated by 1,
+  presence in hTable by 2 and
+  presence in both by 3.
+  The values returned by this function are PAIR_ST,
+  PAIR_CR, G_ST, G_CR, H_ST, H_CR, BOTH_G, BOTH_H, NONE.
+  PAIR_ST implies g in gTable and h in hTable
+  PAIR_CR implies g in hTable and h in gTable
+  G_ST implies g in gTable and h not in any table
+  G_CR implies g in hTable and h not in any table
+  H_ST implies h in hTable and g not in any table
+  H_CR implies h in gTable and g not in any table
+  BOTH_G implies both in gTable
+  BOTH_H implies both in hTable
+  NONE implies none in table; ]
+
+  SideEffects []
+
+  SeeAlso     [CheckTablesCacheAndReturn CheckInTables]
+
+******************************************************************************/
+static int
+PairInTables(
+  DdNode * g,
+  DdNode * h,
+  st_table * ghTable)
+{
+    int valueG, valueH, gPresent, hPresent;
+
+    valueG = valueH = gPresent = hPresent = 0;
+    
+    gPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(g), &valueG);
+    hPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(h), &valueH);
+
+    if (!gPresent && !hPresent) return(NONE);
+
+    if (!hPresent) {
+	if (valueG & 1) return(G_ST);
+	if (valueG & 2) return(G_CR);
+    }
+    if (!gPresent) {
+	if (valueH & 1) return(H_CR);
+	if (valueH & 2) return(H_ST);
+    }
+    /* both in tables */
+    if ((valueG & 1) && (valueH & 2)) return(PAIR_ST);
+    if ((valueG & 2) && (valueH & 1)) return(PAIR_CR);
+    
+    if (valueG & 1) {
+	return(BOTH_G);
+    } else {
+	return(BOTH_H);
+    }
+    
+} /* end of PairInTables */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check the tables for the existence of pair and return one
+  combination, cache the result.]
+
+  Description [Check the tables for the existence of pair and return
+  one combination, cache the result. The assumption is that one of the
+  conjuncts is already in the tables.]
+
+  SideEffects [g and h referenced for the cache]
+
+  SeeAlso     [ZeroCase]
+
+******************************************************************************/
+static Conjuncts *
+CheckTablesCacheAndReturn(
+  DdNode * node,
+  DdNode * g,
+  DdNode * h,
+  st_table * ghTable,
+  st_table * cacheTable)
+{
+    int pairValue;
+    int value;
+    Conjuncts *factors;
+    
+    value = 0;
+    /* check tables */
+    pairValue = PairInTables(g, h, ghTable);
+    assert(pairValue != NONE);
+    /* if both dont exist in table, we know one exists(either g or h).
+     * Therefore store the other and proceed
+     */
+    factors = ALLOC(Conjuncts, 1);
+    if (factors == NULL) return(NULL);
+    if ((pairValue == BOTH_H) || (pairValue == H_ST)) {
+	if (g != one) {
+	    value = 0;
+	    if (st_lookup_int(ghTable, (char *)Cudd_Regular(g), &value)) {
+		value |= 1;
+	    } else {
+		value = 1;
+	    }
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		return(NULL);
+	    }
+	}
+	factors->g = g;
+	factors->h = h;
+    } else  if ((pairValue == BOTH_G) || (pairValue == G_ST)) {
+	if (h != one) {
+	    value = 0;
+	    if (st_lookup_int(ghTable, (char *)Cudd_Regular(h), &value)) {
+		value |= 2;
+	    } else {
+		value = 2;
+	    }
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		return(NULL);
+	    }
+	}
+	factors->g = g;
+	factors->h = h;
+    } else if (pairValue == H_CR) {
+	if (g != one) {
+	    value = 2;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		return(NULL);
+	    }
+	}
+	factors->g = h;
+	factors->h = g;
+    } else if (pairValue == G_CR) {
+	if (h != one) {
+	    value = 1;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		return(NULL);
+	    }
+	}
+	factors->g = h;
+	factors->h = g;
+    } else if (pairValue == PAIR_CR) {
+    /* pair exists in table */
+	factors->g = h;
+	factors->h = g;
+    } else if (pairValue == PAIR_ST) {
+	factors->g = g;
+	factors->h = h;
+    }
+	    
+    /* cache the result for this node */
+    if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) {
+	FREE(factors);
+	return(NULL);
+    }
+
+    return(factors);
+
+} /* end of CheckTablesCacheAndReturn */
+	
+/**Function********************************************************************
+
+  Synopsis    [Check the tables for the existence of pair and return one
+  combination, store in cache.]
+
+  Description [Check the tables for the existence of pair and return
+  one combination, store in cache. The pair that has more pointers to
+  it is picked. An approximation of the number of local pointers is
+  made by taking the reference count of the pairs sent. ]
+
+  SideEffects []
+
+  SeeAlso     [ZeroCase BuildConjuncts]
+
+******************************************************************************/
+static Conjuncts *
+PickOnePair(
+  DdNode * node,
+  DdNode * g1,
+  DdNode * h1,
+  DdNode * g2,
+  DdNode * h2,
+  st_table * ghTable,
+  st_table * cacheTable)
+{
+    int value;
+    Conjuncts *factors;
+    int oneRef, twoRef;
+    
+    factors = ALLOC(Conjuncts, 1);
+    if (factors == NULL) return(NULL);
+
+    /* count the number of pointers to pair 2 */
+    if (h2 == one) {
+	twoRef = (Cudd_Regular(g2))->ref;
+    } else if (g2 == one) {
+	twoRef = (Cudd_Regular(h2))->ref;
+    } else {
+	twoRef = ((Cudd_Regular(g2))->ref + (Cudd_Regular(h2))->ref)/2;
+    }
+
+    /* count the number of pointers to pair 1 */
+    if (h1 == one) {
+	oneRef  = (Cudd_Regular(g1))->ref;
+    } else if (g1 == one) {
+	oneRef  = (Cudd_Regular(h1))->ref;
+    } else {
+	oneRef = ((Cudd_Regular(g1))->ref + (Cudd_Regular(h1))->ref)/2;
+    }
+
+    /* pick the pair with higher reference count */
+    if (oneRef >= twoRef) {
+	factors->g = g1;
+	factors->h = h1;
+    } else {
+	factors->g = g2;
+	factors->h = h2;
+    }
+    
+    /*
+     * Store computed factors in respective tables to encourage
+     * recombination.
+     */
+    if (factors->g != one) {
+	/* insert g in htable */
+	value = 0;
+	if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->g), &value)) {
+	    if (value == 2) {
+		value |= 1;
+		if (st_insert(ghTable, (char *)Cudd_Regular(factors->g),
+			      (char *)(long)value) == ST_OUT_OF_MEM) {
+		    FREE(factors);
+		    return(NULL);
+		}
+	    }
+	} else {
+	    value = 1;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(factors->g),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    }
+
+    if (factors->h != one) {
+	/* insert h in htable */
+	value = 0;
+	if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->h), &value)) {
+	    if (value == 1) {
+		value |= 2;
+		if (st_insert(ghTable, (char *)Cudd_Regular(factors->h),
+			      (char *)(long)value) == ST_OUT_OF_MEM) {
+		    FREE(factors);
+		    return(NULL);
+		}
+	    }	    
+	} else {
+	    value = 2;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(factors->h),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    }
+    
+    /* Store factors in cache table for later use. */
+    if (st_insert(cacheTable, (char *)node, (char *)factors) ==
+	    ST_OUT_OF_MEM) {
+	FREE(factors);
+	return(NULL);
+    }
+
+    return(factors);
+
+} /* end of PickOnePair */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check if the two pairs exist in the table, If any of the
+  conjuncts do exist, store in the cache and return the corresponding pair.]
+
+  Description [Check if the two pairs exist in the table. If any of
+  the conjuncts do exist, store in the cache and return the
+  corresponding pair.]
+
+  SideEffects []
+
+  SeeAlso     [ZeroCase BuildConjuncts]
+
+******************************************************************************/
+static Conjuncts *
+CheckInTables(
+  DdNode * node,
+  DdNode * g1,
+  DdNode * h1,
+  DdNode * g2,
+  DdNode * h2,
+  st_table * ghTable,
+  st_table * cacheTable,
+  int * outOfMem)
+{
+    int pairValue1,  pairValue2;
+    Conjuncts *factors;
+    int value;
+    
+    *outOfMem = 0;
+
+    /* check existence of pair in table */
+    pairValue1 = PairInTables(g1, h1, ghTable);
+    pairValue2 = PairInTables(g2, h2, ghTable);
+
+    /* if none of the 4 exist in the gh tables, return NULL */
+    if ((pairValue1 == NONE) && (pairValue2 == NONE)) {
+	return NULL;
+    }
+    
+    factors = ALLOC(Conjuncts, 1);
+    if (factors == NULL) {
+	*outOfMem = 1;
+	return NULL;
+    }
+
+    /* pairs that already exist in the table get preference. */
+    if (pairValue1 == PAIR_ST) {
+	factors->g = g1;
+	factors->h = h1;
+    } else if (pairValue2 == PAIR_ST) {
+	factors->g = g2;
+	factors->h = h2;
+    } else if (pairValue1 == PAIR_CR) {
+	factors->g = h1;
+	factors->h = g1;
+    } else if (pairValue2 == PAIR_CR) {
+	factors->g = h2;
+	factors->h = g2;
+    } else if (pairValue1 == G_ST) {
+	/* g exists in the table, h is not found in either table */
+	factors->g = g1;
+	factors->h = h1;
+	if (h1 != one) {
+	    value = 2;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h1),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue1 == BOTH_G) {
+	/* g and h are  found in the g table */
+	factors->g = g1;
+	factors->h = h1;
+	if (h1 != one) {
+	    value = 3;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h1),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue1 == H_ST) {
+	/* h exists in the table, g is not found in either table */
+	factors->g = g1;
+	factors->h = h1;
+	if (g1 != one) {
+	    value = 1;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g1),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue1 == BOTH_H) {
+	/* g and h are  found in the h table */
+	factors->g = g1;
+	factors->h = h1;
+	if (g1 != one) {
+	    value = 3;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g1),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue2 == G_ST) {
+	/* g exists in the table, h is not found in either table */
+	factors->g = g2;
+	factors->h = h2;
+	if (h2 != one) {
+	    value = 2;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h2),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if  (pairValue2 == BOTH_G) {
+	/* g and h are  found in the g table */
+	factors->g = g2;
+	factors->h = h2;
+	if (h2 != one) {
+	    value = 3;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h2),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue2 == H_ST) { 
+	/* h exists in the table, g is not found in either table */
+	factors->g = g2;
+	factors->h = h2;
+	if (g2 != one) {
+	    value = 1;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g2),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue2 == BOTH_H) {
+	/* g and h are  found in the h table */
+	factors->g = g2;
+	factors->h = h2;
+	if (g2 != one) {
+	    value = 3;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g2),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue1 == G_CR) {
+	/* g found in h table and h in none */
+	factors->g = h1;
+	factors->h = g1;
+	if (h1 != one) {
+	    value = 1;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h1),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue1 == H_CR) {
+	/* h found in g table and g in none */
+	factors->g = h1;
+	factors->h = g1;
+	if (g1 != one) {
+	    value = 2;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g1),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue2 == G_CR) {
+	/* g found in h table and h in none */
+	factors->g = h2;
+	factors->h = g2;
+	if (h2 != one) {
+	    value = 1;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(h2),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    } else if (pairValue2 == H_CR) {
+	/* h found in g table and g in none */
+	factors->g = h2;
+	factors->h = g2;
+	if (g2 != one) {
+	    value = 2;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(g2),
+			  (char *)(long)value) == ST_OUT_OF_MEM) {
+		*outOfMem = 1;
+		FREE(factors);
+		return(NULL);
+	    }
+	}
+    }
+    
+    /* Store factors in cache table for later use. */
+    if (st_insert(cacheTable, (char *)node, (char *)factors) ==
+	    ST_OUT_OF_MEM) {
+	*outOfMem = 1;
+	FREE(factors);
+	return(NULL);
+    }
+    return factors;
+} /* end of CheckInTables */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [If one child is zero, do explicitly what Restrict does or better]
+
+  Description [If one child is zero, do explicitly what Restrict does or better.
+  First separate a variable and its child in the base case. In case of a cube
+  times a function, separate the cube and function. As a last resort, look in
+  tables.]
+
+  SideEffects [Frees the BDDs in factorsNv. factorsNv itself is not freed
+  because it is freed above.]
+
+  SeeAlso     [BuildConjuncts]
+
+******************************************************************************/
+static Conjuncts *
+ZeroCase(
+  DdManager * dd,
+  DdNode * node,
+  Conjuncts * factorsNv,
+  st_table * ghTable,
+  st_table * cacheTable,
+  int switched)
+{
+    int topid;
+    DdNode *g, *h, *g1, *g2, *h1, *h2, *x, *N, *G, *H, *Gv, *Gnv;
+    DdNode *Hv, *Hnv;
+    int value;
+    int outOfMem;
+    Conjuncts *factors;
+    
+    /* get var at this node */
+    N = Cudd_Regular(node);
+    topid = N->index;
+    x = dd->vars[topid];
+    x = (switched) ? Cudd_Not(x): x;
+    cuddRef(x);
+
+    /* Seprate variable and child */
+    if (factorsNv->g == one) {
+	Cudd_RecursiveDeref(dd, factorsNv->g);
+	factors = ALLOC(Conjuncts, 1);
+	if (factors == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    Cudd_RecursiveDeref(dd, factorsNv->h);
+	    Cudd_RecursiveDeref(dd, x);
+	    return(NULL);
+	}
+	factors->g = x;
+	factors->h = factorsNv->h;
+	/* cache the result*/
+	if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    Cudd_RecursiveDeref(dd, factorsNv->h); 
+	    Cudd_RecursiveDeref(dd, x);
+	    FREE(factors);
+	    return NULL;
+	}
+	
+	/* store  x in g table, the other node is already in the table */
+	if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) {
+	    value |= 1;
+	} else {
+	    value = 1;
+	}
+	if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return NULL;
+	}
+	return(factors);
+    }
+    
+    /* Seprate variable and child */
+    if (factorsNv->h == one) {
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	factors = ALLOC(Conjuncts, 1);
+	if (factors == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    Cudd_RecursiveDeref(dd, factorsNv->g);
+	    Cudd_RecursiveDeref(dd, x);
+	    return(NULL);
+	}
+	factors->g = factorsNv->g;
+	factors->h = x;
+	/* cache the result. */
+ 	if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    Cudd_RecursiveDeref(dd, factorsNv->g);
+	    Cudd_RecursiveDeref(dd, x);
+	    FREE(factors);
+	    return(NULL);
+	}
+	/* store x in h table,  the other node is already in the table */
+	if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) {
+	    value |= 2;
+	} else {
+	    value = 2;
+	}
+	if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return NULL;
+	}
+	return(factors);
+    }
+
+    G = Cudd_Regular(factorsNv->g);
+    Gv = cuddT(G);
+    Gnv = cuddE(G);
+    Gv = Cudd_NotCond(Gv, Cudd_IsComplement(node));
+    Gnv = Cudd_NotCond(Gnv, Cudd_IsComplement(node));
+    /* if the child below is a variable */
+    if ((Gv == zero) || (Gnv == zero)) {
+	h = factorsNv->h;
+	g = cuddBddAndRecur(dd, x, factorsNv->g);
+	if (g != NULL) 	cuddRef(g);
+	Cudd_RecursiveDeref(dd, factorsNv->g); 
+	Cudd_RecursiveDeref(dd, x);
+	if (g == NULL) {
+	    Cudd_RecursiveDeref(dd, factorsNv->h); 
+	    return NULL;
+	}
+	/* CheckTablesCacheAndReturn responsible for allocating
+	 * factors structure., g,h referenced for cache store  the
+	 */
+	factors = CheckTablesCacheAndReturn(node,
+					    g,
+					    h,
+					    ghTable,
+					    cacheTable);
+	if (factors == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    Cudd_RecursiveDeref(dd, g);
+	    Cudd_RecursiveDeref(dd, h);
+	}
+	return(factors); 
+    }
+
+    H = Cudd_Regular(factorsNv->h);
+    Hv = cuddT(H);
+    Hnv = cuddE(H);
+    Hv = Cudd_NotCond(Hv, Cudd_IsComplement(node));
+    Hnv = Cudd_NotCond(Hnv, Cudd_IsComplement(node));
+    /* if the child below is a variable */
+    if ((Hv == zero) || (Hnv == zero)) {
+	g = factorsNv->g;
+	h = cuddBddAndRecur(dd, x, factorsNv->h);
+	if (h!= NULL) cuddRef(h);
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	Cudd_RecursiveDeref(dd, x);
+	if (h == NULL) {
+	    Cudd_RecursiveDeref(dd, factorsNv->g);
+	    return NULL;
+	}
+	/* CheckTablesCacheAndReturn responsible for allocating
+	 * factors structure.g,h referenced for table store 
+	 */
+	factors = CheckTablesCacheAndReturn(node,
+					    g,
+					    h,
+					    ghTable,
+					    cacheTable);
+	if (factors == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    Cudd_RecursiveDeref(dd, g);
+	    Cudd_RecursiveDeref(dd, h);
+	}
+	return(factors); 
+    }
+
+    /* build g1 = x*g; h1 = h */
+    /* build g2 = g; h2 = x*h */
+    Cudd_RecursiveDeref(dd, x);
+    h1 = factorsNv->h;
+    g1 = cuddBddAndRecur(dd, x, factorsNv->g);
+    if (g1 != NULL) cuddRef(g1);
+    if (g1 == NULL) {
+	Cudd_RecursiveDeref(dd, factorsNv->g); 
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	return NULL;
+    }
+    
+    g2 = factorsNv->g;
+    h2 = cuddBddAndRecur(dd, x, factorsNv->h);
+    if (h2 != NULL) cuddRef(h2);
+    if (h2 == NULL) {
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	Cudd_RecursiveDeref(dd, factorsNv->g);
+	return NULL;
+    }
+
+    /* check whether any pair is in tables */
+    factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem);
+    if (outOfMem) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	Cudd_RecursiveDeref(dd, g1);
+	Cudd_RecursiveDeref(dd, h1);
+	Cudd_RecursiveDeref(dd, g2);
+	Cudd_RecursiveDeref(dd, h2);
+	return NULL;
+    }
+    if (factors != NULL) {
+	if ((factors->g == g1) || (factors->g == h1)) {
+	    Cudd_RecursiveDeref(dd, g2);
+	    Cudd_RecursiveDeref(dd, h2);
+	} else {
+	    Cudd_RecursiveDeref(dd, g1);
+	    Cudd_RecursiveDeref(dd, h1);
+	}
+	return factors;
+    }
+
+    /* check for each pair in tables and choose one */
+    factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable);
+    if (factors == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	Cudd_RecursiveDeref(dd, g1);
+	Cudd_RecursiveDeref(dd, h1);
+	Cudd_RecursiveDeref(dd, g2);
+	Cudd_RecursiveDeref(dd, h2);
+    } else {
+	/* now free what was created and not used */
+	if ((factors->g == g1) || (factors->g == h1)) {
+	    Cudd_RecursiveDeref(dd, g2);
+	    Cudd_RecursiveDeref(dd, h2);
+	} else {
+	    Cudd_RecursiveDeref(dd, g1);
+	    Cudd_RecursiveDeref(dd, h1);
+	}
+    }
+	
+    return(factors);
+} /* end of ZeroCase */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the conjuncts recursively, bottom up.]
+
+  Description [Builds the conjuncts recursively, bottom up. Constants
+  are returned as (f, f). The cache is checked for previously computed
+  result. The decomposition points are determined by the local
+  reference count of this node and the longest distance from the
+  constant. At the decomposition point, the factors returned are (f,
+  1). Recur on the two children. The order is determined by the
+  heavier branch. Combine the factors of the two children and pick the
+  one that already occurs in the gh table. Occurence in g is indicated
+  by value 1, occurence in h by 2, occurence in both 3.]
+
+  SideEffects []
+
+  SeeAlso     [cuddConjunctsAux]
+
+******************************************************************************/
+static Conjuncts *
+BuildConjuncts(
+  DdManager * dd,
+  DdNode * node,
+  st_table * distanceTable,
+  st_table * cacheTable,
+  int approxDistance,
+  int maxLocalRef,
+  st_table * ghTable,
+  st_table * mintermTable)
+{
+    int topid, distance;
+    Conjuncts *factorsNv, *factorsNnv, *factors;
+    Conjuncts *dummy;
+    DdNode *N, *Nv, *Nnv, *temp, *g1, *g2, *h1, *h2, *topv;
+    double minNv = 0.0, minNnv = 0.0;
+    double *doubleDummy;
+    int switched =0;
+    int outOfMem;
+    int freeNv = 0, freeNnv = 0, freeTemp;
+    NodeStat *nodeStat;
+    int value;
+
+    /* if f is constant, return (f,f) */
+    if (Cudd_IsConstant(node)) {
+	factors = ALLOC(Conjuncts, 1);
+	if (factors == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(NULL);
+	}
+	factors->g = node;
+	factors->h = node;
+	return(FactorsComplement(factors));
+    }
+
+    /* If result (a pair of conjuncts) in cache, return the factors. */
+    if (st_lookup(cacheTable, node, &dummy)) {
+	factors = dummy;
+	return(factors);
+    }
+    
+    /* check distance and local reference count of this node */
+    N = Cudd_Regular(node);
+    if (!st_lookup(distanceTable, N, &nodeStat)) {
+	(void) fprintf(dd->err, "Not in table, Something wrong\n");
+	dd->errorCode = CUDD_INTERNAL_ERROR;
+	return(NULL);
+    }
+    distance = nodeStat->distance;
+
+    /* at or below decomposition point, return (f, 1) */
+    if (((nodeStat->localRef > maxLocalRef*2/3) &&
+	 (distance < approxDistance*2/3)) ||
+	    (distance <= approxDistance/4)) {
+	factors = ALLOC(Conjuncts, 1);
+	if (factors == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(NULL);
+	}
+	/* alternate assigning (f,1) */
+	value = 0;
+	if (st_lookup_int(ghTable, (char *)Cudd_Regular(node), &value)) {
+	    if (value == 3) {
+		if (!lastTimeG) {
+		    factors->g = node;
+		    factors->h = one;
+		    lastTimeG = 1;
+		} else {
+		    factors->g = one;
+		    factors->h = node;
+		    lastTimeG = 0; 
+		}
+	    } else if (value == 1) {
+		factors->g = node;
+		factors->h = one;
+	    } else {
+		factors->g = one;
+		factors->h = node;
+	    }
+	} else if (!lastTimeG) {
+	    factors->g = node;
+	    factors->h = one;
+	    lastTimeG = 1;
+	    value = 1;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) {
+		dd->errorCode = CUDD_MEMORY_OUT;
+		FREE(factors);
+		return NULL;
+	    }
+	} else {
+	    factors->g = one;
+	    factors->h = node;
+	    lastTimeG = 0;
+	    value = 2;
+	    if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) {
+		dd->errorCode = CUDD_MEMORY_OUT;
+		FREE(factors);
+		return NULL;
+	    }
+	}
+	return(FactorsComplement(factors));
+    }
+    
+    /* get the children and recur */
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* Choose which subproblem to solve first based on the number of
+     * minterms. We go first where there are more minterms.
+     */
+    if (!Cudd_IsConstant(Nv)) {
+	if (!st_lookup(mintermTable, Nv, &doubleDummy)) {
+	    (void) fprintf(dd->err, "Not in table: Something wrong\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+	}
+	minNv = *doubleDummy;
+    }
+    
+    if (!Cudd_IsConstant(Nnv)) {
+	if (!st_lookup(mintermTable, Nnv, &doubleDummy)) {
+	    (void) fprintf(dd->err, "Not in table: Something wrong\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+	}
+	minNnv = *doubleDummy;
+    }
+    
+    if (minNv < minNnv) {
+	temp = Nv;
+	Nv = Nnv;
+	Nnv = temp;
+	switched = 1;
+    }
+
+    /* build gt, ht recursively */
+    if (Nv != zero) {
+	factorsNv = BuildConjuncts(dd, Nv, distanceTable,
+				   cacheTable, approxDistance, maxLocalRef, 
+				   ghTable, mintermTable);
+	if (factorsNv == NULL) return(NULL);
+	freeNv = FactorsNotStored(factorsNv);
+	factorsNv = (freeNv) ? FactorsUncomplement(factorsNv) : factorsNv;
+	cuddRef(factorsNv->g);
+	cuddRef(factorsNv->h);
+	
+	/* Deal with the zero case */
+	if (Nnv == zero) {
+	    /* is responsible for freeing factorsNv */
+	    factors = ZeroCase(dd, node, factorsNv, ghTable,
+			       cacheTable, switched);
+	    if (freeNv) FREE(factorsNv);
+	    return(factors);
+	}
+    }
+
+    /* build ge, he recursively */
+    if (Nnv != zero) {
+	factorsNnv = BuildConjuncts(dd, Nnv, distanceTable,
+				    cacheTable, approxDistance, maxLocalRef,
+				    ghTable, mintermTable);
+	if (factorsNnv == NULL) {
+	    Cudd_RecursiveDeref(dd, factorsNv->g);
+	    Cudd_RecursiveDeref(dd, factorsNv->h);
+	    if (freeNv) FREE(factorsNv);
+	    return(NULL);
+	}
+	freeNnv = FactorsNotStored(factorsNnv);
+	factorsNnv = (freeNnv) ? FactorsUncomplement(factorsNnv) : factorsNnv;
+	cuddRef(factorsNnv->g);
+	cuddRef(factorsNnv->h);
+	
+	/* Deal with the zero case */
+	if (Nv == zero) {
+	    /* is responsible for freeing factorsNv */
+	    factors = ZeroCase(dd, node, factorsNnv, ghTable,
+			       cacheTable, switched);
+	    if (freeNnv) FREE(factorsNnv);
+	    return(factors);
+	}
+    }
+
+    /* construct the 2 pairs */
+    /* g1 = x*gt + x'*ge; h1 = x*ht + x'*he; */
+    /* g2 = x*gt + x'*he; h2 = x*ht + x'*ge */
+    if (switched) {
+	factors = factorsNnv;
+	factorsNnv = factorsNv;
+	factorsNv = factors;
+	freeTemp = freeNv;
+	freeNv = freeNnv;
+	freeNnv = freeTemp;
+    }
+
+    /* Build the factors for this node. */
+    topid = N->index;
+    topv = dd->vars[topid];
+    
+    g1 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->g);
+    if (g1 == NULL) {
+	Cudd_RecursiveDeref(dd, factorsNv->g);
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	Cudd_RecursiveDeref(dd, factorsNnv->g);
+	Cudd_RecursiveDeref(dd, factorsNnv->h);
+	if (freeNv) FREE(factorsNv);
+	if (freeNnv) FREE(factorsNnv);
+	return(NULL);
+    }
+
+    cuddRef(g1);
+
+    h1 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->h);
+    if (h1 == NULL) {
+	Cudd_RecursiveDeref(dd, factorsNv->g);
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	Cudd_RecursiveDeref(dd, factorsNnv->g);
+	Cudd_RecursiveDeref(dd, factorsNnv->h);
+	Cudd_RecursiveDeref(dd, g1);
+	if (freeNv) FREE(factorsNv);
+	if (freeNnv) FREE(factorsNnv);
+	return(NULL);
+    }
+
+    cuddRef(h1);
+
+    g2 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->h);
+    if (g2 == NULL) {
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	Cudd_RecursiveDeref(dd, factorsNv->g);
+	Cudd_RecursiveDeref(dd, factorsNnv->g);
+	Cudd_RecursiveDeref(dd, factorsNnv->h);
+	Cudd_RecursiveDeref(dd, g1);
+	Cudd_RecursiveDeref(dd, h1);
+	if (freeNv) FREE(factorsNv);
+	if (freeNnv) FREE(factorsNnv);
+	return(NULL);
+    }
+    cuddRef(g2);
+    Cudd_RecursiveDeref(dd, factorsNv->g);
+    Cudd_RecursiveDeref(dd, factorsNnv->h);
+
+    h2 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->g);
+    if (h2 == NULL) {
+	Cudd_RecursiveDeref(dd, factorsNv->g);
+	Cudd_RecursiveDeref(dd, factorsNv->h);
+	Cudd_RecursiveDeref(dd, factorsNnv->g);
+	Cudd_RecursiveDeref(dd, factorsNnv->h);
+	Cudd_RecursiveDeref(dd, g1);
+	Cudd_RecursiveDeref(dd, h1);
+	Cudd_RecursiveDeref(dd, g2);
+	if (freeNv) FREE(factorsNv);
+	if (freeNnv) FREE(factorsNnv);
+	return(NULL);
+    }
+    cuddRef(h2);
+    Cudd_RecursiveDeref(dd, factorsNv->h);
+    Cudd_RecursiveDeref(dd, factorsNnv->g);
+    if (freeNv) FREE(factorsNv);
+    if (freeNnv) FREE(factorsNnv);
+
+    /* check for each pair in tables and choose one */
+    factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem);
+    if (outOfMem) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	Cudd_RecursiveDeref(dd, g1);
+	Cudd_RecursiveDeref(dd, h1);
+	Cudd_RecursiveDeref(dd, g2);
+	Cudd_RecursiveDeref(dd, h2);
+	return(NULL);
+    }
+    if (factors != NULL) {
+	if ((factors->g == g1) || (factors->g == h1)) {
+	    Cudd_RecursiveDeref(dd, g2);
+	    Cudd_RecursiveDeref(dd, h2);
+	} else {
+	    Cudd_RecursiveDeref(dd, g1);
+	    Cudd_RecursiveDeref(dd, h1);
+	}
+	return(factors);
+    }
+
+    /* if not in tables, pick one pair */
+    factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable);
+    if (factors == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	Cudd_RecursiveDeref(dd, g1);
+	Cudd_RecursiveDeref(dd, h1);
+	Cudd_RecursiveDeref(dd, g2);
+	Cudd_RecursiveDeref(dd, h2);
+    } else {
+	/* now free what was created and not used */
+	if ((factors->g == g1) || (factors->g == h1)) {
+	    Cudd_RecursiveDeref(dd, g2);
+	    Cudd_RecursiveDeref(dd, h2);
+	} else {
+	    Cudd_RecursiveDeref(dd, g1);
+	    Cudd_RecursiveDeref(dd, h1);
+	}
+    }
+	
+    return(factors);
+    
+} /* end of BuildConjuncts */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Procedure to compute two conjunctive factors of f and place in *c1 and *c2.]
+
+  Description [Procedure to compute two conjunctive factors of f and
+  place in *c1 and *c2. Sets up the required data - table of distances
+  from the constant and local reference count. Also minterm table. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddConjunctsAux(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** c1,
+  DdNode ** c2)
+{
+    st_table *distanceTable = NULL;
+    st_table *cacheTable = NULL;
+    st_table *mintermTable = NULL;
+    st_table *ghTable = NULL;
+    st_generator *stGen;
+    char *key, *value;
+    Conjuncts *factors;
+    int distance, approxDistance;
+    double max, minterms;
+    int freeFactors;
+    NodeStat *nodeStat;
+    int maxLocalRef;
+    
+    /* initialize */
+    *c1 = NULL;
+    *c2 = NULL;
+
+    /* initialize distances table */
+    distanceTable = st_init_table(st_ptrcmp,st_ptrhash);
+    if (distanceTable == NULL) goto outOfMem;
+    
+    /* make the entry for the constant */
+    nodeStat = ALLOC(NodeStat, 1);
+    if (nodeStat == NULL) goto outOfMem;
+    nodeStat->distance = 0;
+    nodeStat->localRef = 1;
+    if (st_insert(distanceTable, (char *)one, (char *)nodeStat) == ST_OUT_OF_MEM) {
+	goto outOfMem;
+    }
+
+    /* Count node distances from constant. */
+    nodeStat = CreateBotDist(f, distanceTable);
+    if (nodeStat == NULL) goto outOfMem;
+
+    /* set the distance for the decomposition points */
+    approxDistance = (DEPTH < nodeStat->distance) ? nodeStat->distance : DEPTH;
+    distance = nodeStat->distance;
+
+    if (distance < approxDistance) {
+	/* Too small to bother. */
+	*c1 = f;
+	*c2 = DD_ONE(dd);
+	cuddRef(*c1); cuddRef(*c2);
+	stGen = st_init_gen(distanceTable);
+	if (stGen == NULL) goto outOfMem;
+	while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	    FREE(value);
+	}
+	st_free_gen(stGen); stGen = NULL;
+	st_free_table(distanceTable);
+	return(1);
+    }
+
+    /* record the maximum local reference count */
+    maxLocalRef = 0;
+    stGen = st_init_gen(distanceTable);
+    if (stGen == NULL) goto outOfMem;
+    while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	nodeStat = (NodeStat *)value;
+	maxLocalRef = (nodeStat->localRef > maxLocalRef) ?
+	    nodeStat->localRef : maxLocalRef;
+    }
+    st_free_gen(stGen); stGen = NULL;
+
+	    
+    /* Count minterms for each node. */
+    max = pow(2.0, (double)Cudd_SupportSize(dd,f)); /* potential overflow */
+    mintermTable = st_init_table(st_ptrcmp,st_ptrhash);
+    if (mintermTable == NULL) goto outOfMem;
+    minterms = CountMinterms(f, max, mintermTable, dd->err);
+    if (minterms == -1.0) goto outOfMem;
+    
+    lastTimeG = Cudd_Random() & 1;
+    cacheTable = st_init_table(st_ptrcmp, st_ptrhash);
+    if (cacheTable == NULL) goto outOfMem;
+    ghTable = st_init_table(st_ptrcmp, st_ptrhash);
+    if (ghTable == NULL) goto outOfMem;
+
+    /* Build conjuncts. */
+    factors = BuildConjuncts(dd, f, distanceTable, cacheTable,
+			     approxDistance, maxLocalRef, ghTable, mintermTable);
+    if (factors == NULL) goto outOfMem;
+
+    /* free up tables */
+    stGen = st_init_gen(distanceTable);
+    if (stGen == NULL) goto outOfMem;
+    while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	FREE(value);
+    }
+    st_free_gen(stGen); stGen = NULL;
+    st_free_table(distanceTable); distanceTable = NULL;
+    st_free_table(ghTable); ghTable = NULL;
+    
+    stGen = st_init_gen(mintermTable);
+    if (stGen == NULL) goto outOfMem;
+    while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	FREE(value);
+    }
+    st_free_gen(stGen); stGen = NULL;
+    st_free_table(mintermTable); mintermTable = NULL;
+
+    freeFactors = FactorsNotStored(factors);
+    factors = (freeFactors) ? FactorsUncomplement(factors) : factors;
+    if (factors != NULL) {
+	*c1 = factors->g;
+	*c2 = factors->h;
+	cuddRef(*c1);
+	cuddRef(*c2);
+	if (freeFactors) FREE(factors);
+	
+#if 0    
+	if ((*c1 == f) && (!Cudd_IsConstant(f))) {
+	    assert(*c2 == one);
+	}
+	if ((*c2 == f) && (!Cudd_IsConstant(f))) {
+	    assert(*c1 == one);
+	}
+	
+	if ((*c1 != one) && (!Cudd_IsConstant(f))) {
+	    assert(!Cudd_bddLeq(dd, *c2, *c1));
+	}
+	if ((*c2 != one) && (!Cudd_IsConstant(f))) {
+	    assert(!Cudd_bddLeq(dd, *c1, *c2));
+	}
+#endif
+    }
+
+    stGen = st_init_gen(cacheTable);
+    if (stGen == NULL) goto outOfMem;
+    while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	ConjunctsFree(dd, (Conjuncts *)value);
+    }
+    st_free_gen(stGen); stGen = NULL;
+
+    st_free_table(cacheTable); cacheTable = NULL;
+
+    return(1);
+
+outOfMem:
+    if (distanceTable != NULL) {
+	stGen = st_init_gen(distanceTable);
+	if (stGen == NULL) goto outOfMem;
+	while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	    FREE(value);
+	}
+	st_free_gen(stGen); stGen = NULL;
+	st_free_table(distanceTable); distanceTable = NULL;
+    }
+    if (mintermTable != NULL) {
+	stGen = st_init_gen(mintermTable);
+	if (stGen == NULL) goto outOfMem;
+	while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	    FREE(value);
+	}
+	st_free_gen(stGen); stGen = NULL;
+	st_free_table(mintermTable); mintermTable = NULL;
+    }
+    if (ghTable != NULL) st_free_table(ghTable);
+    if (cacheTable != NULL) {
+	stGen = st_init_gen(cacheTable);
+	if (stGen == NULL) goto outOfMem;
+	while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	    ConjunctsFree(dd, (Conjuncts *)value);
+	}
+	st_free_gen(stGen); stGen = NULL;
+	st_free_table(cacheTable); cacheTable = NULL;
+    }
+    dd->errorCode = CUDD_MEMORY_OUT;
+    return(0);
+
+} /* end of cuddConjunctsAux */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddEssent.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddEssent.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddEssent.c	(revision 8)
@@ -0,0 +1,1468 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddEssent.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for the detection of essential variables.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_FindEssential()
+		<li> Cudd_bddIsVarEssential()
+		<li> Cudd_FindTwoLiteralClauses()
+		<li> Cudd_ReadIthClause()
+		<li> Cudd_PrintTwoLiteralClauses()
+		<li> Cudd_tlcInfoFree()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddFindEssentialRecur()
+		<li> ddFindTwoLiteralClausesRecur()
+		<li> computeClauses()
+		<li> computeClausesWithUniverse()
+		<li> emptyClauseSet()
+		<li> sentinelp()
+		<li> equalp()
+		<li> beforep()
+		<li> oneliteralp()
+		<li> impliedp()
+		<li> bitVectorAlloc()
+		<li> bitVectorClear()
+		<li> bitVectorFree()
+		<li> bitVectorRead()
+		<li> bitVectorSet()
+		<li> tlcInfoAlloc()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* These definitions are for the bit vectors. */
+#if SIZEOF_LONG == 8
+#define BPL 64
+#define LOGBPL 6
+#else
+#define BPL 32
+#define LOGBPL 5
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* This structure holds the set of clauses for a node.  Each clause consists
+** of two literals.  For one-literal clauses, the second lietral is FALSE.
+** Each literal is composed of a variable and a phase.  A variable is a node
+** index, and requires sizeof(DdHalfWord) bytes.  The constant literals use
+** CUDD_MAXINDEX as variable indicator.  Each phase is a bit: 0 for positive
+** phase, and 1 for negative phase.
+** Variables and phases are stored separately for the sake of compactness.
+** The variables are stored in an array of DdHalfWord's terminated by a
+** sentinel (a pair of zeroes).  The phases are stored in a bit vector.
+** The cnt field holds, at the end, the number of clauses.
+** The clauses of the set are kept sorted.  For each clause, the first literal
+** is the one of least index.  So, the clause with literals +2 and -4 is stored
+** as (+2,-4).  A one-literal clause with literal +3 is stored as
+** (+3,-CUDD_MAXINDEX).  Clauses are sorted in decreasing order as follows:
+**      (+5,-7)
+**      (+5,+6)
+**      (-5,+7)
+**      (-4,FALSE)
+**      (-4,+8)
+**      ...
+** That is, one first looks at the variable of the first literal, then at the
+** phase of the first litral, then at the variable of the second literal,
+** and finally at the phase of the second literal.
+*/
+struct DdTlcInfo {
+    DdHalfWord *vars;
+    long *phases;
+    DdHalfWord cnt;
+};
+
+/* This structure is for temporary representation of sets of clauses.  It is
+** meant to be used in link lists, when the number of clauses is not yet
+** known. The encoding of a clause is the same as in DdTlcInfo, though
+** the phase information is not stored in a bit array. */
+struct TlClause {
+    DdHalfWord v1, v2;
+    short p1, p2;
+    struct TlClause *next;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef long BitVector;
+typedef struct TlClause TlClause;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddEssent.c,v 1.21 2004/08/13 18:04:48 fabio Exp $";
+#endif
+
+static BitVector *Tolv;
+static BitVector *Tolp;
+static BitVector *Eolv;
+static BitVector *Eolp;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * ddFindEssentialRecur (DdManager *dd, DdNode *f);
+static DdTlcInfo * ddFindTwoLiteralClausesRecur (DdManager * dd, DdNode * f, st_table *table);
+static DdTlcInfo * computeClauses (DdTlcInfo *Tres, DdTlcInfo *Eres, DdHalfWord label, int size);
+static DdTlcInfo * computeClausesWithUniverse (DdTlcInfo *Cres, DdHalfWord label, short phase, int size);
+static DdTlcInfo * emptyClauseSet (void);
+static int sentinelp (DdHalfWord var1, DdHalfWord var2);
+static int equalp (DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b);
+static int beforep (DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b);
+static int oneliteralp (DdHalfWord var);
+static int impliedp (DdHalfWord var1, short phase1, DdHalfWord var2, short phase2, BitVector *olv, BitVector *olp);
+static BitVector * bitVectorAlloc (int size);
+DD_INLINE static void bitVectorClear (BitVector *vector, int size);
+static void bitVectorFree (BitVector *vector);
+DD_INLINE static short bitVectorRead (BitVector *vector, int i);
+DD_INLINE static void bitVectorSet (BitVector * vector, int i, short val);
+static DdTlcInfo * tlcInfoAlloc (void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the essential variables of a DD.]
+
+  Description [Returns the cube of the essential variables. A positive
+  literal means that the variable must be set to 1 for the function to be
+  1. A negative literal means that the variable must be set to 0 for the
+  function to be 1. Returns a pointer to the cube BDD if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIsVarEssential]
+
+******************************************************************************/
+DdNode *
+Cudd_FindEssential(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = ddFindEssentialRecur(dd,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_FindEssential */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether a given variable is essential with a
+  given phase in a BDD.]
+
+  Description [Determines whether a given variable is essential with a
+  given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1
+  and f-->x_id, or if phase == 0 and f-->x_id'.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindEssential]
+
+******************************************************************************/
+int
+Cudd_bddIsVarEssential(
+  DdManager * manager,
+  DdNode * f,
+  int  id,
+  int  phase)
+{
+    DdNode	*var;
+    int		res;
+
+    var = Cudd_bddIthVar(manager, id);
+
+    var = Cudd_NotCond(var,phase == 0);
+
+    res = Cudd_bddLeq(manager, f, var);
+
+    return(res);
+
+} /* end of Cudd_bddIsVarEssential */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the two literal clauses of a DD.]
+
+  Description [Returns the one- and two-literal clauses of a DD.
+  Returns a pointer to the structure holding the clauses if
+  successful; NULL otherwise.  For a constant DD, the empty set of clauses
+  is returned.  This is obviously correct for a non-zero constant.  For the
+  constant zero, it is based on the assumption that only those clauses
+  containing variables in the support of the function are considered.  Since
+  the support of a constant function is empty, no clauses are returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindEssential]
+
+******************************************************************************/
+DdTlcInfo *
+Cudd_FindTwoLiteralClauses(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdTlcInfo *res;
+    st_table *table;
+    st_generator *gen;
+    DdTlcInfo *tlc;
+    DdNode *node;
+    int size = dd->size;
+
+    if (Cudd_IsConstant(f)) {
+	res = emptyClauseSet();
+	return(res);
+    }
+    table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (table == NULL) return(NULL);
+    Tolv = bitVectorAlloc(size);
+    if (Tolv == NULL) {
+	st_free_table(table);
+	return(NULL);
+    }
+    Tolp = bitVectorAlloc(size);
+    if (Tolp == NULL) {
+	st_free_table(table);
+	bitVectorFree(Tolv);
+        return(NULL);
+    }
+    Eolv = bitVectorAlloc(size);
+    if (Eolv == NULL) {
+	st_free_table(table);
+	bitVectorFree(Tolv);
+	bitVectorFree(Tolp);
+        return(NULL);
+    }
+    Eolp = bitVectorAlloc(size);
+    if (Eolp == NULL) {
+	st_free_table(table);
+	bitVectorFree(Tolv);
+	bitVectorFree(Tolp);
+	bitVectorFree(Eolv);
+        return(NULL);
+    }
+
+    res = ddFindTwoLiteralClausesRecur(dd,f,table);
+    /* Dispose of table contents and free table. */
+    st_foreach_item(table, gen, &node, &tlc) {
+	if (node != f) {
+	    Cudd_tlcInfoFree(tlc);
+	}
+    }
+    st_free_table(table);
+    bitVectorFree(Tolv);
+    bitVectorFree(Tolp);
+    bitVectorFree(Eolv);
+    bitVectorFree(Eolp);
+
+    if (res != NULL) {
+	int i;
+	for (i = 0; !sentinelp(res->vars[i], res->vars[i+1]); i += 2);
+	res->cnt = i >> 1;
+    }
+
+    return(res);
+
+} /* end of Cudd_FindTwoLiteralClauses */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Accesses the i-th clause of a DD.]
+
+  Description [Accesses the i-th clause of a DD given the clause set which
+  must be already computed.  Returns 1 if successful; 0 if i is out of range,
+  or in case of error.]
+
+  SideEffects [the four components of a clause are returned as side effects.]
+
+  SeeAlso     [Cudd_FindTwoLiteralClauses]
+
+******************************************************************************/
+int
+Cudd_ReadIthClause(
+  DdTlcInfo * tlc,
+  int i,
+  DdHalfWord *var1,
+  DdHalfWord *var2,
+  int *phase1,
+  int *phase2)
+{
+    if (tlc == NULL) return(0);
+    if (tlc->vars == NULL || tlc->phases == NULL) return(0);
+    if (i >= tlc->cnt) return(0);
+    *var1 = tlc->vars[2*i];
+    *var2 = tlc->vars[2*i+1];
+    *phase1 = (int) bitVectorRead(tlc->phases, 2*i);
+    *phase2 = (int) bitVectorRead(tlc->phases, 2*i+1);
+    return(1);
+
+} /* end of Cudd_ReadIthClause */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the two literal clauses of a DD.]
+
+  Description [Prints the one- and two-literal clauses. Returns 1 if
+  successful; 0 otherwise.  The argument "names" can be NULL, in which case
+  the variable indices are printed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindTwoLiteralClauses]
+
+******************************************************************************/
+int
+Cudd_PrintTwoLiteralClauses(
+  DdManager * dd,
+  DdNode * f,
+  char **names,
+  FILE *fp)
+{
+    DdHalfWord *vars;
+    BitVector *phases;
+    int i;
+    DdTlcInfo *res = Cudd_FindTwoLiteralClauses(dd, f);
+    FILE *ifp = fp == NULL ? dd->out : fp;
+    
+    if (res == NULL) return(0);
+    vars = res->vars;
+    phases = res->phases;
+    for (i = 0; !sentinelp(vars[i], vars[i+1]); i += 2) {
+	if (names != NULL) {
+	    if (vars[i+1] == CUDD_MAXINDEX) {
+		(void) fprintf(ifp, "%s%s\n",
+			       bitVectorRead(phases, i) ? "~" : " ",
+			       names[vars[i]]);
+	    } else {
+		(void) fprintf(ifp, "%s%s | %s%s\n",
+			       bitVectorRead(phases, i) ? "~" : " ",
+			       names[vars[i]],
+			       bitVectorRead(phases, i+1) ? "~" : " ",
+			       names[vars[i+1]]);
+	    }
+	} else {
+	    if (vars[i+1] == CUDD_MAXINDEX) {
+		(void) fprintf(ifp, "%s%d\n",
+			       bitVectorRead(phases, i) ? "~" : " ",
+			       (int) vars[i]);
+	    } else {
+		(void) fprintf(ifp, "%s%d | %s%d\n",
+			       bitVectorRead(phases, i) ? "~" : " ",
+			       (int) vars[i],
+			       bitVectorRead(phases, i+1) ? "~" : " ",
+			       (int) vars[i+1]);
+	    }
+	}
+    }
+    Cudd_tlcInfoFree(res);
+
+    return(1);
+    
+} /* end of Cudd_PrintTwoLiteralClauses */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a DdTlcInfo Structure.]
+
+  Description [Frees a DdTlcInfo Structure as well as the memory pointed
+  by it.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_tlcInfoFree(
+  DdTlcInfo * t)
+{
+    if (t->vars != NULL) FREE(t->vars);
+    if (t->phases != NULL) FREE(t->phases);
+    FREE(t);
+
+} /* end of Cudd_tlcInfoFree */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_FindEssential.]
+
+  Description [Implements the recursive step of Cudd_FindEssential.
+  Returns a pointer to the cube BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+ddFindEssentialRecur(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode	*T, *E, *F;
+    DdNode	*essT, *essE, *res;
+    int		index;
+    DdNode	*one, *lzero, *azero;
+
+    one = DD_ONE(dd);
+    F = Cudd_Regular(f);
+    /* If f is constant the set of essential variables is empty. */
+    if (cuddIsConstant(F)) return(one);
+
+    res = cuddCacheLookup1(dd,Cudd_FindEssential,f);
+    if (res != NULL) {
+	return(res);
+    }
+
+    lzero = Cudd_Not(one);
+    azero = DD_ZERO(dd);
+    /* Find cofactors: here f is non-constant. */
+    T = cuddT(F);
+    E = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+	T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+
+    index = F->index;
+    if (Cudd_IsConstant(T) && T != lzero && T != azero) {
+	/* if E is zero, index is essential, otherwise there are no
+	** essentials, because index is not essential and no other variable
+	** can be, since setting index = 1 makes the function constant and
+	** different from 0.
+	*/
+	if (E == lzero || E == azero) {
+	    res = dd->vars[index];
+	} else {
+	    res = one;
+	}
+    } else if (T == lzero || T == azero) {
+	if (Cudd_IsConstant(E)) { /* E cannot be zero here */
+	    res = Cudd_Not(dd->vars[index]);
+	} else { /* E == non-constant */
+	    /* find essentials in the else branch */
+	    essE = ddFindEssentialRecur(dd,E);
+	    if (essE == NULL) {
+		return(NULL);
+	    }
+	    cuddRef(essE);
+
+	    /* add index to the set with negative phase */
+	    res = cuddUniqueInter(dd,index,one,Cudd_Not(essE));
+	    if (res == NULL) {
+		Cudd_RecursiveDeref(dd,essE);
+		return(NULL);
+	    }
+	    res = Cudd_Not(res);
+	    cuddDeref(essE);
+	}
+    } else { /* T == non-const */
+	if (E == lzero || E == azero) {
+	    /* find essentials in the then branch */
+	    essT = ddFindEssentialRecur(dd,T);
+	    if (essT == NULL) {
+		return(NULL);
+	    }
+	    cuddRef(essT);
+
+	    /* add index to the set with positive phase */
+	    /* use And because essT may be complemented */
+	    res = cuddBddAndRecur(dd,dd->vars[index],essT);
+	    if (res == NULL) {
+		Cudd_RecursiveDeref(dd,essT);
+		return(NULL);
+	    }
+	    cuddDeref(essT);
+	} else if (!Cudd_IsConstant(E)) {
+	    /* if E is a non-zero constant there are no essentials
+	    ** because T is non-constant.
+	    */
+	    essT = ddFindEssentialRecur(dd,T);
+	    if (essT == NULL) {
+		return(NULL);
+	    }
+	    if (essT == one) {
+		res = one;
+	    } else {
+		cuddRef(essT);
+		essE = ddFindEssentialRecur(dd,E);
+		if (essE == NULL) {
+		    Cudd_RecursiveDeref(dd,essT);
+		    return(NULL);
+		}
+		cuddRef(essE);
+
+		/* res = intersection(essT, essE) */
+		res = cuddBddLiteralSetIntersectionRecur(dd,essT,essE);
+		if (res == NULL) {
+		    Cudd_RecursiveDeref(dd,essT);
+		    Cudd_RecursiveDeref(dd,essE);
+		    return(NULL);
+		}
+		cuddRef(res);
+		Cudd_RecursiveDeref(dd,essT);
+		Cudd_RecursiveDeref(dd,essE);
+		cuddDeref(res);
+	    }
+	} else {	/* E is a non-zero constant */
+	    res = one;
+	}
+    }
+
+    cuddCacheInsert1(dd,Cudd_FindEssential, f, res);
+    return(res);
+
+} /* end of ddFindEssentialRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_FindTwoLiteralClauses.]
+
+  Description [Implements the recursive step of
+  Cudd_FindTwoLiteralClauses.  The DD node is assumed to be not
+  constant.  Returns a pointer to a set of clauses if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_FindTwoLiteralClauses]
+
+******************************************************************************/
+static DdTlcInfo *
+ddFindTwoLiteralClausesRecur(
+  DdManager * dd,
+  DdNode * f,
+  st_table *table)
+{
+    DdNode *T, *E, *F;
+    DdNode *one, *lzero, *azero;
+    DdTlcInfo *res, *Tres, *Eres;
+    DdHalfWord index;
+
+    F = Cudd_Regular(f);
+
+    assert(!cuddIsConstant(F));
+
+    /* Check computed table.  Separate entries are necessary for
+    ** a node and its complement.  We should update the counter here. */
+    if (st_lookup(table, f, &res)) {
+	return(res);
+    }
+
+    /* Easy access to the constants for BDDs and ADDs. */
+    one = DD_ONE(dd);
+    lzero = Cudd_Not(one);
+    azero = DD_ZERO(dd);
+
+    /* Find cofactors and variable labeling the top node. */
+    T = cuddT(F); E = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+	T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+    index = F->index;
+
+    if (Cudd_IsConstant(T) && T != lzero && T != azero) {
+	/* T is a non-zero constant.  If E is zero, then this node's index
+        ** is a one-literal clause.  Otherwise, if E is a non-zero
+	** constant, there are no clauses for this node.  Finally,
+	** if E is not constant, we recursively compute its clauses, and then
+	** merge using the empty set for T. */
+	if (E == lzero || E == azero) {
+	    /* Create the clause (index + 0). */
+	    res = tlcInfoAlloc();
+	    if (res == NULL) return(NULL);
+	    res->vars = ALLOC(DdHalfWord,4);
+	    if (res->vars == NULL) {
+		FREE(res);
+		return(NULL);
+	    }
+	    res->phases = bitVectorAlloc(2);
+	    if (res->phases == NULL) {
+		FREE(res->vars);
+		FREE(res);
+		return(NULL);
+	    }
+	    res->vars[0] = index;
+	    res->vars[1] = CUDD_MAXINDEX;
+	    res->vars[2] = 0;
+	    res->vars[3] = 0;
+	    bitVectorSet(res->phases, 0, 0); /* positive phase */
+	    bitVectorSet(res->phases, 1, 1); /* negative phase */
+	} else if (Cudd_IsConstant(E)) {
+	    /* If E is a non-zero constant, no clauses. */
+	    res = emptyClauseSet();
+	} else {
+	    /* E is non-constant */
+	    Tres = emptyClauseSet();
+	    if (Tres == NULL) return(NULL);
+	    Eres = ddFindTwoLiteralClausesRecur(dd, E, table);
+	    if (Eres == NULL) {
+	        Cudd_tlcInfoFree(Tres);
+	        return(NULL);
+	    }
+	    res = computeClauses(Tres, Eres, index, dd->size);
+	    Cudd_tlcInfoFree(Tres);
+	}
+    } else if (T == lzero || T == azero) {
+	/* T is zero.  If E is a non-zero constant, then the
+        ** complement of this node's index is a one-literal clause.
+        ** Otherwise, if E is not constant, we recursively compute its
+        ** clauses, and then merge using the universal set for T. */
+	if (Cudd_IsConstant(E)) { /* E cannot be zero here */
+	    /* Create the clause (!index + 0). */
+	    res = tlcInfoAlloc();
+	    if (res == NULL) return(NULL);
+	    res->vars = ALLOC(DdHalfWord,4);
+	    if (res->vars == NULL) {
+		FREE(res);
+		return(NULL);
+	    }
+	    res->phases = bitVectorAlloc(2);
+	    if (res->phases == NULL) {
+		FREE(res->vars);
+		FREE(res);
+		return(NULL);
+	    }
+	    res->vars[0] = index;
+	    res->vars[1] = CUDD_MAXINDEX;
+	    res->vars[2] = 0;
+	    res->vars[3] = 0;
+	    bitVectorSet(res->phases, 0, 1); /* negative phase */
+	    bitVectorSet(res->phases, 1, 1); /* negative phase */
+	} else { /* E == non-constant */
+	    Eres = ddFindTwoLiteralClausesRecur(dd, E, table);
+	    if (Eres == NULL) return(NULL);
+	    res = computeClausesWithUniverse(Eres, index, 1, dd->size);
+	}
+    } else { /* T == non-const */
+	Tres = ddFindTwoLiteralClausesRecur(dd, T, table);
+	if (Tres == NULL) return(NULL);
+	if (Cudd_IsConstant(E)) {
+	    if (E == lzero || E == azero) {
+		res = computeClausesWithUniverse(Tres, index, 0, dd->size);
+	    } else {
+		Eres = emptyClauseSet();
+		if (Eres == NULL) return(NULL);
+		res = computeClauses(Tres, Eres, index, dd->size);
+		Cudd_tlcInfoFree(Eres);
+	    }
+	} else {
+	    Eres = ddFindTwoLiteralClausesRecur(dd, E, table);
+	    if (Eres == NULL) return(NULL);
+	    res = computeClauses(Tres, Eres, index, dd->size);
+	}
+    }
+
+    /* Cache results. */
+    if (st_add_direct(table, (char *)f, (char *)res) == ST_OUT_OF_MEM) {
+	FREE(res);
+	return(NULL);
+    }
+    return(res);
+
+} /* end of ddFindTwoLiteralClausesRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the two-literal clauses for a node.]
+
+  Description [Computes the two-literal clauses for a node given the
+  clauses for its children and the label of the node.  Returns a
+  pointer to a TclInfo structure if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [computeClausesWithUniverse]
+
+******************************************************************************/
+static DdTlcInfo *
+computeClauses(
+  DdTlcInfo *Tres /* list of clauses for T child */,
+  DdTlcInfo *Eres /* list of clauses for E child */,
+  DdHalfWord label /* variable labeling the current node */,
+  int size /* number of variables in the manager */)
+{
+    DdHalfWord *Tcv = Tres->vars; /* variables of clauses for the T child */
+    BitVector *Tcp = Tres->phases; /* phases of clauses for the T child */
+    DdHalfWord *Ecv = Eres->vars; /* variables of clauses for the E child */
+    BitVector *Ecp = Eres->phases; /* phases of clauses for the E child */
+    DdHalfWord *Vcv = NULL; /* pointer to variables of the clauses for v */
+    BitVector *Vcp = NULL; /* pointer to phases of the clauses for v */
+    DdTlcInfo *res = NULL; /* the set of clauses to be returned */
+    int pt = 0; /* index in the list of clauses of T */
+    int pe = 0; /* index in the list of clauses of E */
+    int cv = 0; /* counter of the clauses for this node */
+    TlClause *iclauses = NULL; /* list of inherited clauses */
+    TlClause *tclauses = NULL; /* list of 1-literal clauses of T */
+    TlClause *eclauses = NULL; /* list of 1-literal clauses of E */
+    TlClause *nclauses = NULL; /* list of new (non-inherited) clauses */
+    TlClause *lnclause = NULL; /* pointer to last new clause */
+    TlClause *newclause; /* temporary pointer to new clauses */
+
+    /* Initialize sets of one-literal clauses.  The one-literal clauses
+    ** are stored redundantly.  These sets allow constant-time lookup, which
+    ** we need when we check for implication of a two-literal clause by a
+    ** one-literal clause.  The linked lists allow fast sequential
+    ** processing. */
+    bitVectorClear(Tolv, size);
+    bitVectorClear(Tolp, size);
+    bitVectorClear(Eolv, size);
+    bitVectorClear(Eolp, size);
+
+    /* Initialize result structure. */
+    res = tlcInfoAlloc();
+    if (res == NULL) goto cleanup;
+
+    /* Scan the two input list.  Extract inherited two-literal clauses
+    ** and set aside one-literal clauses from each list.  The incoming lists
+    ** are sorted in the order defined by beforep.  The three linked list
+    ** produced by this loop are sorted in the reverse order because we
+    ** always append to the front of the lists.
+    ** The inherited clauses are those clauses (both one- and two-literal)
+    ** that are common to both children; and the two-literal clauses of
+    ** one child that are implied by a one-literal clause of the other
+    ** child. */
+    while (!sentinelp(Tcv[pt], Tcv[pt+1]) || !sentinelp(Ecv[pe], Ecv[pe+1])) {
+	if (equalp(Tcv[pt], bitVectorRead(Tcp, pt),
+		   Tcv[pt+1], bitVectorRead(Tcp, pt+1),
+		   Ecv[pe], bitVectorRead(Ecp, pe),
+		   Ecv[pe+1], bitVectorRead(Ecp, pe+1))) {
+	    /* Add clause to inherited list. */
+	    newclause = ALLOC(TlClause,1);
+	    if (newclause == NULL) goto cleanup;
+	    newclause->v1 = Tcv[pt];
+	    newclause->v2 = Tcv[pt+1];
+	    newclause->p1 = bitVectorRead(Tcp, pt);
+	    newclause->p2 = bitVectorRead(Tcp, pt+1);
+	    newclause->next = iclauses;
+	    iclauses = newclause;
+	    pt += 2; pe += 2; cv++;
+	} else if (beforep(Tcv[pt], bitVectorRead(Tcp, pt),
+		   Tcv[pt+1], bitVectorRead(Tcp, pt+1),
+		   Ecv[pe], bitVectorRead(Ecp, pe),
+		   Ecv[pe+1], bitVectorRead(Ecp, pe+1))) {
+	    if (oneliteralp(Tcv[pt+1])) {
+		/* Add this one-literal clause to the T set. */
+		newclause = ALLOC(TlClause,1);
+		if (newclause == NULL) goto cleanup;
+		newclause->v1 = Tcv[pt];
+		newclause->v2 = CUDD_MAXINDEX;
+		newclause->p1 = bitVectorRead(Tcp, pt);
+		newclause->p2 = 1;
+		newclause->next = tclauses;
+		tclauses = newclause;
+		bitVectorSet(Tolv, Tcv[pt], 1);
+		bitVectorSet(Tolp, Tcv[pt], bitVectorRead(Tcp, pt));
+	    } else {
+		if (impliedp(Tcv[pt], bitVectorRead(Tcp, pt),
+			     Tcv[pt+1], bitVectorRead(Tcp, pt+1),
+			     Eolv, Eolp)) {
+		    /* Add clause to inherited list. */
+		    newclause = ALLOC(TlClause,1);
+		    if (newclause == NULL) goto cleanup;
+		    newclause->v1 = Tcv[pt];
+		    newclause->v2 = Tcv[pt+1];
+		    newclause->p1 = bitVectorRead(Tcp, pt);
+		    newclause->p2 = bitVectorRead(Tcp, pt+1);
+		    newclause->next = iclauses;
+		    iclauses = newclause;
+		    cv++;
+		}
+	    }
+	    pt += 2;
+	} else { /* !beforep() */
+	    if (oneliteralp(Ecv[pe+1])) {
+		/* Add this one-literal clause to the E set. */
+		newclause = ALLOC(TlClause,1);
+		if (newclause == NULL) goto cleanup;
+		newclause->v1 = Ecv[pe];
+		newclause->v2 = CUDD_MAXINDEX;
+		newclause->p1 = bitVectorRead(Ecp, pe);
+		newclause->p2 = 1;
+		newclause->next = eclauses;
+		eclauses = newclause;
+		bitVectorSet(Eolv, Ecv[pe], 1);
+		bitVectorSet(Eolp, Ecv[pe], bitVectorRead(Ecp, pe));
+	    } else {
+		if (impliedp(Ecv[pe], bitVectorRead(Ecp, pe),
+			     Ecv[pe+1], bitVectorRead(Ecp, pe+1),
+			     Tolv, Tolp)) {
+		    /* Add clause to inherited list. */
+		    newclause = ALLOC(TlClause,1);
+		    if (newclause == NULL) goto cleanup;
+		    newclause->v1 = Ecv[pe];
+		    newclause->v2 = Ecv[pe+1];
+		    newclause->p1 = bitVectorRead(Ecp, pe);
+		    newclause->p2 = bitVectorRead(Ecp, pe+1);
+		    newclause->next = iclauses;
+		    iclauses = newclause;
+		    cv++;
+		}
+	    }
+	    pe += 2;
+	}
+    }
+
+    /* Add one-literal clauses for the label variable to the front of
+    ** the two lists. */
+    newclause = ALLOC(TlClause,1);
+    if (newclause == NULL) goto cleanup;
+    newclause->v1 = label;
+    newclause->v2 = CUDD_MAXINDEX;
+    newclause->p1 = 0;
+    newclause->p2 = 1;
+    newclause->next = tclauses;
+    tclauses = newclause;
+    newclause = ALLOC(TlClause,1);
+    if (newclause == NULL) goto cleanup;
+    newclause->v1 = label;
+    newclause->v2 = CUDD_MAXINDEX;
+    newclause->p1 = 1;
+    newclause->p2 = 1;
+    newclause->next = eclauses;
+    eclauses = newclause;
+
+    /* Produce the non-inherited clauses.  We preserve the "reverse"
+    ** order of the two input lists by appending to the end of the
+    ** list.  In this way, iclauses and nclauses are consistent. */
+    while (tclauses != NULL && eclauses != NULL) {
+	if (beforep(eclauses->v1, eclauses->p1, eclauses->v2, eclauses->p2,
+		    tclauses->v1, tclauses->p1, tclauses->v2, tclauses->p2)) {
+	    TlClause *nextclause = tclauses->next;
+	    TlClause *otherclauses = eclauses;
+	    while (otherclauses != NULL) {
+		if (tclauses->v1 != otherclauses->v1) {
+		    newclause = ALLOC(TlClause,1);
+		    if (newclause == NULL) goto cleanup;
+		    newclause->v1 = tclauses->v1;
+		    newclause->v2 = otherclauses->v1;
+		    newclause->p1 = tclauses->p1;
+		    newclause->p2 = otherclauses->p1;
+		    newclause->next = NULL;
+		    if (nclauses == NULL) {
+			nclauses = newclause;
+			lnclause = newclause;
+		    } else {
+			lnclause->next = newclause;
+			lnclause = newclause;
+		    }
+		    cv++;
+		}
+		otherclauses = otherclauses->next;
+	    }
+	    FREE(tclauses);
+	    tclauses = nextclause;
+	} else {
+	    TlClause *nextclause = eclauses->next;
+	    TlClause *otherclauses = tclauses;
+	    while (otherclauses != NULL) {
+		if (eclauses->v1 != otherclauses->v1) {
+		    newclause = ALLOC(TlClause,1);
+		    if (newclause == NULL) goto cleanup;
+		    newclause->v1 = eclauses->v1;
+		    newclause->v2 = otherclauses->v1;
+		    newclause->p1 = eclauses->p1;
+		    newclause->p2 = otherclauses->p1;
+		    newclause->next = NULL;
+		    if (nclauses == NULL) {
+			nclauses = newclause;
+			lnclause = newclause;
+		    } else {
+			lnclause->next = newclause;
+			lnclause = newclause;
+		    }
+		    cv++;
+		}
+		otherclauses = otherclauses->next;
+	    }
+	    FREE(eclauses);
+	    eclauses = nextclause;
+	}
+    }
+    while (tclauses != NULL) {
+	TlClause *nextclause = tclauses->next;
+	FREE(tclauses);
+	tclauses = nextclause;
+    }
+    while (eclauses != NULL) {
+	TlClause *nextclause = eclauses->next;
+	FREE(eclauses);
+	eclauses = nextclause;
+    }
+
+    /* Merge inherited and non-inherited clauses.  Now that we know the
+    ** total number, we allocate the arrays, and we fill them bottom-up
+    ** to restore the proper ordering. */
+    Vcv = ALLOC(DdHalfWord, 2*(cv+1));
+    if (Vcv == NULL) goto cleanup;
+    if (cv > 0) {
+	Vcp = bitVectorAlloc(2*cv);
+	if (Vcp == NULL) goto cleanup;
+    } else {
+	Vcp = NULL;
+    }
+    res->vars = Vcv;
+    res->phases = Vcp;
+    /* Add sentinel. */
+    Vcv[2*cv] = 0;
+    Vcv[2*cv+1] = 0;
+    while (iclauses != NULL || nclauses != NULL) {
+	TlClause *nextclause;
+	cv--;
+	if (nclauses == NULL || (iclauses != NULL &&
+	    beforep(nclauses->v1, nclauses->p1, nclauses->v2, nclauses->p2,
+		    iclauses->v1, iclauses->p1, iclauses->v2, iclauses->p2))) {
+	    Vcv[2*cv] = iclauses->v1;
+	    Vcv[2*cv+1] = iclauses->v2;
+	    bitVectorSet(Vcp, 2*cv, iclauses->p1);
+	    bitVectorSet(Vcp, 2*cv+1, iclauses->p2);
+	    nextclause = iclauses->next;
+	    FREE(iclauses);
+	    iclauses = nextclause;
+	} else {
+	    Vcv[2*cv] = nclauses->v1;
+	    Vcv[2*cv+1] = nclauses->v2;
+	    bitVectorSet(Vcp, 2*cv, nclauses->p1);
+	    bitVectorSet(Vcp, 2*cv+1, nclauses->p2);
+	    nextclause = nclauses->next;
+	    FREE(nclauses);
+	    nclauses = nextclause;
+	}
+    }
+    assert(cv == 0);
+
+    return(res);
+
+ cleanup:
+    if (res != NULL) Cudd_tlcInfoFree(res);
+    while (iclauses != NULL) {
+	TlClause *nextclause = iclauses->next;
+	FREE(iclauses);
+	iclauses = nextclause;
+    }
+    while (nclauses != NULL) {
+	TlClause *nextclause = nclauses->next;
+	FREE(nclauses);
+	nclauses = nextclause;
+    }
+    while (tclauses != NULL) {
+	TlClause *nextclause = tclauses->next;
+	FREE(tclauses);
+	tclauses = nextclause;
+    }
+    while (eclauses != NULL) {
+	TlClause *nextclause = eclauses->next;
+	FREE(eclauses);
+	eclauses = nextclause;
+    }
+
+    return(NULL);
+
+} /* end of computeClauses */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the two-literal clauses for a node.]
+
+  Description [Computes the two-literal clauses for a node with a zero
+  child, given the clauses for its other child and the label of the
+  node.  Returns a pointer to a TclInfo structure if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [computeClauses]
+
+******************************************************************************/
+static DdTlcInfo *
+computeClausesWithUniverse(
+  DdTlcInfo *Cres /* list of clauses for child */,
+  DdHalfWord label /* variable labeling the current node */,
+  short phase /* 0 if E child is zero; 1 if T child is zero */,
+  int size /* number of variables in the manager */)
+{
+    DdHalfWord *Ccv = Cres->vars; /* variables of clauses for child */
+    BitVector *Ccp = Cres->phases; /* phases of clauses for child */
+    DdHalfWord *Vcv = NULL; /* pointer to the variables of the clauses for v */
+    BitVector *Vcp = NULL; /* pointer to the phases of the clauses for v */
+    DdTlcInfo *res = NULL; /* the set of clauses to be returned */
+    int i;
+
+    /* Initialize result. */
+    res = tlcInfoAlloc();
+    if (res == NULL) goto cleanup;
+    /* Count entries for new list and allocate accordingly. */
+    for (i = 0; !sentinelp(Ccv[i], Ccv[i+1]); i += 2);
+    /* At this point, i is twice the number of clauses in the child's
+    ** list.  We need four more entries for this node: 2 for the one-literal
+    ** clause for the label, and 2 for the sentinel. */
+    Vcv = ALLOC(DdHalfWord,i+4);
+    if (Vcv == NULL) goto cleanup;
+    Vcp = bitVectorAlloc(i+4);
+    if (Vcp == NULL) goto cleanup;
+    res->vars = Vcv;
+    res->phases = Vcp;
+    /* Copy old list into new. */
+    for (i = 0; !sentinelp(Ccv[i], Ccv[i+1]); i += 2) {
+	Vcv[i] = Ccv[i];
+	Vcv[i+1] = Ccv[i+1];
+	bitVectorSet(Vcp, i, bitVectorRead(Ccp, i));
+	bitVectorSet(Vcp, i+1, bitVectorRead(Ccp, i+1));
+    }
+    /* Add clause corresponding to label. */
+    Vcv[i] = label;
+    bitVectorSet(Vcp, i, phase);
+    i++;
+    Vcv[i] = CUDD_MAXINDEX;
+    bitVectorSet(Vcp, i, 1);
+    i++;
+    /* Add sentinel. */
+    Vcv[i] = 0;
+    Vcv[i+1] = 0;
+    bitVectorSet(Vcp, i, 0);
+    bitVectorSet(Vcp, i+1, 0);
+
+    return(res);
+
+ cleanup:
+    if (Vcv != NULL) FREE(Vcv);
+    if (Vcp != NULL) bitVectorFree(Vcp);
+    if (res != NULL) Cudd_tlcInfoFree(res);
+
+    return(NULL);
+
+} /* end of computeClausesWithUniverse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an enpty set of clauses.]
+
+  Description [Returns a pointer to an empty set of clauses if
+  successful; NULL otherwise.  No bit vector for the phases is
+  allocated.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdTlcInfo *
+emptyClauseSet(void)
+{
+    DdTlcInfo *eset;
+
+    eset = ALLOC(DdTlcInfo,1);
+    if (eset == NULL) return(NULL);
+    eset->vars = ALLOC(DdHalfWord,2);
+    if (eset->vars == NULL) {
+	FREE(eset);
+	return(NULL);
+    }
+    /* Sentinel */
+    eset->vars[0] = 0;
+    eset->vars[1] = 0;
+    eset->phases = NULL; /* does not matter */
+    eset->cnt = 0;
+    return(eset);
+
+} /* end of emptyClauseSet */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the argument is the sentinel clause.]
+
+  Description [Returns true iff the argument is the sentinel clause.
+  A sentinel clause has both variables equal to 0.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+sentinelp(
+  DdHalfWord var1,
+  DdHalfWord var2)
+{
+    return(var1 == 0 && var2 == 0);
+
+} /* end of sentinelp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the two arguments are identical clauses.]
+
+  Description [Returns true iff the two arguments are identical
+  clauses.  Since literals are sorted, we only need to compare
+  literals in the same position.]
+
+  SideEffects [None]
+
+  SeeAlso     [beforep]
+
+******************************************************************************/
+static int
+equalp(
+  DdHalfWord var1a,
+  short phase1a,
+  DdHalfWord var1b,
+  short phase1b,
+  DdHalfWord var2a,
+  short phase2a,
+  DdHalfWord var2b,
+  short phase2b)
+{
+    return(var1a == var2a && phase1a == phase2a &&
+	   var1b == var2b && phase1b == phase2b);
+
+} /* end of equalp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the first argument precedes the second in
+  the clause order.]
+
+  Description [Returns true iff the first argument precedes the second
+  in the clause order.  A clause precedes another if its first lieral
+  precedes the first literal of the other, or if the first literals
+  are the same, and its second literal precedes the second literal of
+  the other clause.  A literal precedes another if it has a higher
+  index, of if it has the same index, but it has lower phase.  Phase 0
+  is the positive phase, and it is lower than Phase 1 (negative
+  phase).]
+
+  SideEffects [None]
+
+  SeeAlso     [equalp]
+
+******************************************************************************/
+static int
+beforep(
+  DdHalfWord var1a,
+  short phase1a,
+  DdHalfWord var1b,
+  short phase1b,
+  DdHalfWord var2a,
+  short phase2a,
+  DdHalfWord var2b,
+  short phase2b)
+{
+    return(var1a > var2a || (var1a == var2a &&
+	   (phase1a < phase2a || (phase1a == phase2a &&
+	    (var1b > var2b || (var1b == var2b && phase1b < phase2b))))));
+
+} /* end of beforep */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true iff the argument is a one-literal clause.]
+
+  Description [Returns true iff the argument is a one-literal clause.
+  A one-litaral clause has the constant FALSE as second literal.
+  Since the constant TRUE is never used, it is sufficient to test for
+  a constant.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+oneliteralp(
+  DdHalfWord var)
+{
+    return(var == CUDD_MAXINDEX);
+
+} /* end of oneliteralp */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns true iff either literal of a clause is in a set of
+  literals.]
+
+  Description [Returns true iff either literal of a clause is in a set
+  of literals.  The first four arguments specify the clause.  The
+  remaining two arguments specify the literal set.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+impliedp(
+  DdHalfWord var1,
+  short phase1,
+  DdHalfWord var2,
+  short phase2,
+  BitVector *olv,
+  BitVector *olp)
+{
+    return((bitVectorRead(olv, var1) &&
+	    bitVectorRead(olp, var1) == phase1) ||
+	   (bitVectorRead(olv, var2) &&
+	    bitVectorRead(olp, var2) == phase2));
+
+} /* end of impliedp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a bit vector.]
+
+  Description [Allocates a bit vector.  The parameter size gives the
+  number of bits.  This procedure allocates enough long's to hold the
+  specified number of bits.  Returns a pointer to the allocated vector
+  if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorClear bitVectorFree]
+
+******************************************************************************/
+static BitVector *
+bitVectorAlloc(
+  int size)
+{
+    int allocSize;
+    BitVector *vector;
+
+    /* Find out how many long's we need.
+    ** There are sizeof(long) * 8 bits in a long.
+    ** The ceiling of the ratio of two integers m and n is given
+    ** by ((n-1)/m)+1.  Putting all this together, we get... */
+    allocSize = ((size - 1) / (sizeof(BitVector) * 8)) + 1;
+    vector = ALLOC(BitVector, allocSize);
+    if (vector == NULL) return(NULL);
+    /* Clear the whole array. */
+    (void) memset(vector, 0, allocSize * sizeof(BitVector));
+    return(vector);
+    
+} /* end of bitVectorAlloc */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clears a bit vector.]
+
+  Description [Clears a bit vector.  The parameter size gives the
+  number of bits.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorAlloc]
+
+******************************************************************************/
+DD_INLINE
+static void
+bitVectorClear(
+  BitVector *vector,
+  int size)
+{
+    int allocSize;
+
+    /* Find out how many long's we need.
+    ** There are sizeof(long) * 8 bits in a long.
+    ** The ceiling of the ratio of two integers m and n is given
+    ** by ((n-1)/m)+1.  Putting all this together, we get... */
+    allocSize = ((size - 1) / (sizeof(BitVector) * 8)) + 1;
+    /* Clear the whole array. */
+    (void) memset(vector, 0, allocSize * sizeof(BitVector));
+    return;
+    
+} /* end of bitVectorClear */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a bit vector.]
+
+  Description [Frees a bit vector.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorAlloc]
+
+******************************************************************************/
+static void
+bitVectorFree(
+  BitVector *vector)
+{
+    FREE(vector);
+
+} /* end of bitVectorFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the i-th entry of a bit vector.]
+
+  Description [Returns the i-th entry of a bit vector.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorSet]
+
+******************************************************************************/
+DD_INLINE
+static short
+bitVectorRead(
+  BitVector *vector,
+  int i)
+{
+    int word, bit;
+    short result;
+
+    if (vector == NULL) return((short) 0);
+
+    word = i >> LOGBPL;
+    bit = i & (BPL - 1);
+    result = (short) ((vector[word] >> bit) & 1L);
+    return(result);
+
+} /* end of bitVectorRead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the i-th entry of a bit vector to a value.]
+
+  Description [Sets the i-th entry of a bit vector to a value.]
+
+  SideEffects [None]
+
+  SeeAlso     [bitVectorRead]
+
+******************************************************************************/
+DD_INLINE
+static void
+bitVectorSet(
+  BitVector * vector,
+  int i,
+  short val)
+{
+    int word, bit;
+
+    word = i >> LOGBPL;
+    bit = i & (BPL - 1);
+    vector[word] &= ~(1L << bit);
+    vector[word] |= (((long) val) << bit);
+
+} /* end of bitVectorSet */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a DdTlcInfo Structure.]
+
+  Description [Returns a pointer to a DdTlcInfo Structure if successful;
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_tlcInfoFree]
+
+******************************************************************************/
+static DdTlcInfo *
+tlcInfoAlloc(void)
+{
+    DdTlcInfo *res = ALLOC(DdTlcInfo,1);
+    if (res == NULL) return(NULL);
+    res->vars = NULL;
+    res->phases = NULL;
+    res->cnt = 0;
+    return(res);
+
+} /* end of tlcInfoAlloc */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddExact.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddExact.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddExact.c	(revision 8)
@@ -0,0 +1,1018 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddExact.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for exact variable reordering.]
+
+  Description [External procedures included in this file:
+		<ul>
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddExact()
+		</ul>
+	Static procedures included in this module:
+		<ul> 
+                <li> getMaxBinomial()
+		<li> gcd()
+                <li> getMatrix()
+		<li> freeMatrix()
+                <li> getLevelKeys()
+                <li> ddShuffle()
+                <li> ddSiftUp()
+		<li> updateUB()
+		<li> ddCountRoots()
+		<li> ddClearGlobal()
+		<li> computeLB()
+		<li> updateEntry()
+		<li> pushDown()
+		<li> initSymmInfo()
+                </ul>]
+
+  Author      [Cheng Hua, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.26 2004/08/13 18:04:48 fabio Exp $";
+#endif
+
+#ifdef DD_STATS
+static int ddTotalShuffles;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int getMaxBinomial (int n);
+static DdHalfWord ** getMatrix (int rows, int cols);
+static void freeMatrix (DdHalfWord **matrix);
+static int getLevelKeys (DdManager *table, int l);
+static int ddShuffle (DdManager *table, DdHalfWord *permutation, int lower, int upper);
+static int ddSiftUp (DdManager *table, int x, int xLow);
+static int updateUB (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper);
+static int ddCountRoots (DdManager *table, int lower, int upper);
+static void ddClearGlobal (DdManager *table, int lower, int maxlevel);
+static int computeLB (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level);
+static int updateEntry (DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper);
+static void pushDown (DdHalfWord *order, int j, int level);
+static DdHalfWord * initSymmInfo (DdManager *table, int lower, int upper);
+static int checkSymmInfo (DdManager *table, DdHalfWord *symmInfo, int index, int level);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Exact variable ordering algorithm.]
+
+  Description [Exact variable ordering algorithm. Finds an optimum
+  order for the variables between lower and upper.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddExact(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int k, i, j;
+    int maxBinomial, oldSubsets, newSubsets;
+    int subsetCost;
+    int size;			/* number of variables to be reordered */
+    int unused, nvars, level, result;
+    int upperBound, lowerBound, cost;
+    int roots;
+    char *mask = NULL;
+    DdHalfWord  *symmInfo = NULL;
+    DdHalfWord **newOrder = NULL;
+    DdHalfWord **oldOrder = NULL;
+    int *newCost = NULL;
+    int *oldCost = NULL;
+    DdHalfWord **tmpOrder;
+    int *tmpCost;
+    DdHalfWord *bestOrder = NULL;
+    DdHalfWord *order;
+#ifdef DD_STATS
+    int  ddTotalSubsets;
+#endif
+
+    /* Restrict the range to be reordered by excluding unused variables
+    ** at the two ends. */
+    while (table->subtables[lower].keys == 1 &&
+	   table->vars[table->invperm[lower]]->ref == 1 &&
+	   lower < upper)
+	lower++;
+    while (table->subtables[upper].keys == 1 &&
+	   table->vars[table->invperm[upper]]->ref == 1 &&
+	   lower < upper)
+	upper--;
+    if (lower == upper) return(1); /* trivial problem */
+
+    /* Apply symmetric sifting to get a good upper bound and to extract
+    ** symmetry information. */
+    result = cuddSymmSiftingConv(table,lower,upper);
+    if (result == 0) goto cuddExactOutOfMem;
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    ddTotalShuffles = 0;
+    ddTotalSubsets = 0;
+#endif
+
+    /* Initialization. */
+    nvars = table->size;
+    size = upper - lower + 1;
+    /* Count unused variable among those to be reordered.  This is only
+    ** used to compute maxBinomial. */
+    unused = 0;
+    for (i = lower + 1; i < upper; i++) {
+	if (table->subtables[i].keys == 1 &&
+	    table->vars[table->invperm[i]]->ref == 1)
+	    unused++;
+    }
+
+    /* Find the maximum number of subsets we may have to store. */
+    maxBinomial = getMaxBinomial(size - unused);
+    if (maxBinomial == -1) goto cuddExactOutOfMem;
+
+    newOrder = getMatrix(maxBinomial, size);
+    if (newOrder == NULL) goto cuddExactOutOfMem;
+
+    newCost = ALLOC(int, maxBinomial);
+    if (newCost == NULL) goto cuddExactOutOfMem;
+
+    oldOrder = getMatrix(maxBinomial, size);
+    if (oldOrder == NULL) goto cuddExactOutOfMem;
+
+    oldCost = ALLOC(int, maxBinomial);
+    if (oldCost == NULL) goto cuddExactOutOfMem;
+
+    bestOrder = ALLOC(DdHalfWord, size);
+    if (bestOrder == NULL) goto cuddExactOutOfMem;
+
+    mask = ALLOC(char, nvars);
+    if (mask == NULL) goto cuddExactOutOfMem;
+
+    symmInfo = initSymmInfo(table, lower, upper);
+    if (symmInfo == NULL) goto cuddExactOutOfMem;
+
+    roots = ddCountRoots(table, lower, upper);
+
+    /* Initialize the old order matrix for the empty subset and the best
+    ** order to the current order. The cost for the empty subset includes
+    ** the cost of the levels between upper and the constants. These levels
+    ** are not going to change. Hence, we count them only once.
+    */
+    oldSubsets = 1;
+    for (i = 0; i < size; i++) {
+	oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower];
+    }
+    subsetCost = table->constants.keys;
+    for (i = upper + 1; i < nvars; i++)
+	subsetCost += getLevelKeys(table,i);
+    oldCost[0] = subsetCost;
+    /* The upper bound is initialized to the current size of the BDDs. */
+    upperBound = table->keys - table->isolated;
+
+    /* Now consider subsets of increasing size. */
+    for (k = 1; k <= size; k++) {
+#if DD_STATS
+	(void) fprintf(table->out,"Processing subsets of size %d\n", k);
+	fflush(table->out);
+#endif
+	newSubsets = 0;
+	level = size - k;		/* offset of first bottom variable */
+
+	for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */
+	    order = oldOrder[i];
+	    cost = oldCost[i];
+	    lowerBound = computeLB(table, order, roots, cost, lower, upper,
+				   level);
+	    if (lowerBound >= upperBound)
+		continue;
+	    /* Impose new order. */
+	    result = ddShuffle(table, order, lower, upper);
+	    if (result == 0) goto cuddExactOutOfMem;
+	    upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
+	    /* For each top bottom variable. */
+	    for (j = level; j >= 0; j--) {
+		/* Skip unused variables. */
+		if (table->subtables[j+lower-1].keys == 1 &&
+		    table->vars[table->invperm[j+lower-1]]->ref == 1) continue;
+		/* Find cost under this order. */
+		subsetCost = cost + getLevelKeys(table, lower + level);
+		newSubsets = updateEntry(table, order, level, subsetCost,
+					 newOrder, newCost, newSubsets, mask,
+					 lower, upper);
+		if (j == 0)
+		    break;
+		if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0)
+		    continue;
+		pushDown(order,j-1,level);
+		/* Impose new order. */
+		result = ddShuffle(table, order, lower, upper);
+		if (result == 0) goto cuddExactOutOfMem;
+		upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
+	    } /* for each bottom variable */
+	} /* for each subset of size k */
+
+	/* New orders become old orders in preparation for next iteration. */
+	tmpOrder = oldOrder; tmpCost = oldCost;
+	oldOrder = newOrder; oldCost = newCost;
+	newOrder = tmpOrder; newCost = tmpCost;
+#ifdef DD_STATS
+	ddTotalSubsets += newSubsets;
+#endif
+	oldSubsets = newSubsets;
+    }
+    result = ddShuffle(table, bestOrder, lower, upper);
+    if (result == 0) goto cuddExactOutOfMem;
+#ifdef DD_STATS
+#ifdef DD_VERBOSE
+    (void) fprintf(table->out,"\n");
+#endif
+    (void) fprintf(table->out,"#:S_EXACT   %8d: total subsets\n",
+		   ddTotalSubsets);
+    (void) fprintf(table->out,"#:H_EXACT   %8d: total shuffles",
+		   ddTotalShuffles);
+#endif
+
+    freeMatrix(newOrder);
+    freeMatrix(oldOrder);
+    FREE(bestOrder);
+    FREE(oldCost);
+    FREE(newCost);
+    FREE(symmInfo);
+    FREE(mask);
+    return(1);
+
+cuddExactOutOfMem:
+
+    if (newOrder != NULL) freeMatrix(newOrder);
+    if (oldOrder != NULL) freeMatrix(oldOrder);
+    if (bestOrder != NULL) FREE(bestOrder);
+    if (oldCost != NULL) FREE(oldCost);
+    if (newCost != NULL) FREE(newCost);
+    if (symmInfo != NULL) FREE(symmInfo);
+    if (mask != NULL) FREE(mask);
+    table->errorCode = CUDD_MEMORY_OUT;
+    return(0);
+
+} /* end of cuddExact */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the maximum value of (n choose k) for a given n.]
+
+  Description [Computes the maximum value of (n choose k) for a given
+  n.  The maximum value occurs for k = n/2 when n is even, or k =
+  (n-1)/2 when n is odd.  The algorithm used in this procedure avoids
+  intermediate overflow problems.  It is based on the identity
+  <pre>
+    binomial(n,k) = n/k * binomial(n-1,k-1).
+  </pre>
+  Returns the computed value if successful; -1 if out of range.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+getMaxBinomial(
+  int n)
+{
+    double i, j, result;
+
+    if (n < 0 || n > 33) return(-1); /* error */
+    if (n < 2) return(1);
+
+    for (result = (double)((n+3)/2), i = result+1, j=2; i <= n; i++, j++) {
+	result *= i;
+	result /= j;
+    }
+
+    return((int)result);
+
+} /* end of getMaxBinomial */
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Returns the gcd of two integers.]
+
+  Description [Returns the gcd of two integers. Uses the binary GCD
+  algorithm described in Cormen, Leiserson, and Rivest.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+gcd(
+  int  x,
+  int  y)
+{
+    int a;
+    int b;
+    int lsbMask;
+
+    /* GCD(n,0) = n. */
+    if (x == 0) return(y);
+    if (y == 0) return(x);
+
+    a = x; b = y; lsbMask = 1;
+    
+    /* Here both a and b are != 0. The iteration maintains this invariant.
+    ** Hence, we only need to check for when they become equal.
+    */
+    while (a != b) {
+	if (a & lsbMask) {
+	    if (b & lsbMask) {	/* both odd */
+		if (a < b) {
+		    b = (b - a) >> 1;
+		} else {
+		    a = (a - b) >> 1;
+		}
+	    } else {		/* a odd, b even */
+		b >>= 1;
+	    }
+	} else {
+	    if (b & lsbMask) {	/* a even, b odd */
+		a >>= 1;
+	    } else {		/* both even */
+		lsbMask <<= 1;
+	    }
+	}
+    }
+
+    return(a);
+
+} /* end of gcd */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a two-dimensional matrix of ints.]
+
+  Description [Allocates a two-dimensional matrix of ints.
+  Returns the pointer to the matrix if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [freeMatrix]
+
+******************************************************************************/
+static DdHalfWord **
+getMatrix(
+  int  rows /* number of rows */,
+  int  cols /* number of columns */)
+{
+    DdHalfWord **matrix;
+    int i;
+
+    if (cols*rows == 0) return(NULL);
+    matrix = ALLOC(DdHalfWord *, rows);
+    if (matrix == NULL) return(NULL);
+    matrix[0] = ALLOC(DdHalfWord, cols*rows);
+    if (matrix[0] == NULL) return(NULL);
+    for (i = 1; i < rows; i++) {
+	matrix[i] = matrix[i-1] + cols;
+    }
+    return(matrix);
+
+} /* end of getMatrix */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a two-dimensional matrix allocated by getMatrix.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [getMatrix]
+
+******************************************************************************/
+static void
+freeMatrix(
+  DdHalfWord ** matrix)
+{
+    FREE(matrix[0]);
+    FREE(matrix);
+    return;
+
+} /* end of freeMatrix */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes at one level of a unique table.]
+
+  Description [Returns the number of nodes at one level of a unique table.
+  The projection function, if isolated, is not counted.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+getLevelKeys(
+  DdManager * table,
+  int  l)
+{
+    int isolated;
+    int x;        /* x is an index */
+
+    x = table->invperm[l];
+    isolated = table->vars[x]->ref == 1;
+
+    return(table->subtables[l].keys - isolated);
+
+} /* end of getLevelKeys */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables according to a given permutation.]
+
+  Description [Reorders variables according to a given permutation.
+  The i-th permutation array contains the index of the variable that
+  should be brought to the i-th level. ddShuffle assumes that no
+  dead nodes are present and that the interaction matrix is properly
+  initialized.  The reordering is achieved by a series of upward sifts.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+ddShuffle(
+  DdManager * table,
+  DdHalfWord * permutation,
+  int  lower,
+  int  upper)
+{
+    DdHalfWord	index;
+    int		level;
+    int		position;
+#if 0
+    int		numvars;
+#endif
+    int		result;
+#ifdef DD_STATS
+    long	localTime;
+    int		initialSize;
+#ifdef DD_VERBOSE
+    int		finalSize;
+#endif
+    int		previousSize;
+#endif
+
+#ifdef DD_STATS
+    localTime = util_cpu_time();
+    initialSize = table->keys - table->isolated;
+#endif
+
+#if 0
+    numvars = table->size;
+
+    (void) fprintf(table->out,"%d:", ddTotalShuffles);
+    for (level = 0; level < numvars; level++) {
+	(void) fprintf(table->out," %d", table->invperm[level]);
+    }
+    (void) fprintf(table->out,"\n");
+#endif
+
+    for (level = 0; level <= upper - lower; level++) {
+	index = permutation[level];
+	position = table->perm[index];
+#ifdef DD_STATS
+	previousSize = table->keys - table->isolated;
+#endif
+	result = ddSiftUp(table,position,level+lower);
+	if (!result) return(0);
+    }
+
+#ifdef DD_STATS
+    ddTotalShuffles++;
+#ifdef DD_VERBOSE
+    finalSize = table->keys - table->isolated;
+    if (finalSize < initialSize) {
+	(void) fprintf(table->out,"-");
+    } else if (finalSize > initialSize) {
+	(void) fprintf(table->out,"+");
+    } else {
+	(void) fprintf(table->out,"=");
+    }
+    if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n");
+    fflush(table->out);
+#endif
+#endif
+
+    return(1);
+
+} /* end of ddShuffle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one variable up.]
+
+  Description [Takes a variable from position x and sifts it up to
+  position xLow;  xLow should be less than or equal to x.
+  Returns 1 if successful; 0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddSiftUp(
+  DdManager * table,
+  int  x,
+  int  xLow)
+{
+    int        y;
+    int        size;
+
+    y = cuddNextLow(table,x);
+    while (y >= xLow) {
+	size = cuddSwapInPlace(table,y,x);
+	if (size == 0) {
+	    return(0);
+	}
+	x = y;
+	y = cuddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of ddSiftUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the upper bound and saves the best order seen so far.]
+
+  Description [Updates the upper bound and saves the best order seen so far.
+  Returns the current value of the upper bound.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+updateUB(
+  DdManager * table,
+  int  oldBound,
+  DdHalfWord * bestOrder,
+  int  lower,
+  int  upper)
+{
+    int i;
+    int newBound = table->keys - table->isolated;
+
+    if (newBound < oldBound) {
+#ifdef DD_STATS
+	(void) fprintf(table->out,"New upper bound = %d\n", newBound);
+	fflush(table->out);
+#endif
+	for (i = lower; i <= upper; i++)
+	    bestOrder[i-lower] = (DdHalfWord) table->invperm[i];
+	return(newBound);
+    } else {
+	return(oldBound);
+    }
+
+} /* end of updateUB */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of roots.]
+
+  Description [Counts the number of roots at the levels between lower and
+  upper.  The computation is based on breadth-first search.
+  A node is a root if it is not reachable from any previously visited node.
+  (All the nodes at level lower are therefore considered roots.)
+  The visited flag uses the LSB of the next pointer.  Returns the root
+  count. The roots that are constant nodes are always ignored.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddClearGlobal]
+
+******************************************************************************/
+static int
+ddCountRoots(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int i,j;
+    DdNode *f;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(table->sentinel);
+    int slots;
+    int roots = 0;
+    int maxlevel = lower;
+
+    for (i = lower; i <= upper; i++) {
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+	for (j = 0; j < slots; j++) {
+	    f = nodelist[j];
+	    while (f != sentinel) {
+		/* A node is a root of the DAG if it cannot be
+		** reached by nodes above it. If a node was never
+		** reached during the previous depth-first searches,
+		** then it is a root, and we start a new depth-first
+		** search from it.
+		*/
+		if (!Cudd_IsComplement(f->next)) {
+		    if (f != table->vars[f->index]) {
+			roots++;
+		    }
+		}
+		if (!Cudd_IsConstant(cuddT(f))) {
+		    cuddT(f)->next = Cudd_Complement(cuddT(f)->next);
+		    if (table->perm[cuddT(f)->index] > maxlevel)
+			maxlevel = table->perm[cuddT(f)->index];
+		}
+		if (!Cudd_IsConstant(cuddE(f))) {
+		    Cudd_Regular(cuddE(f))->next =
+			Cudd_Complement(Cudd_Regular(cuddE(f))->next);
+		    if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel)
+			maxlevel = table->perm[Cudd_Regular(cuddE(f))->index];
+		}
+		f = Cudd_Regular(f->next);
+	    }
+	}
+    }
+    ddClearGlobal(table, lower, maxlevel);
+
+    return(roots);
+
+} /* end of ddCountRoots */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Scans the DD and clears the LSB of the next pointers.]
+
+  Description [Scans the DD and clears the LSB of the next pointers.
+  The LSB of the next pointers are used as markers to tell whether a
+  node was reached. Once the roots are counted, these flags are
+  reset.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddCountRoots]
+
+******************************************************************************/
+static void
+ddClearGlobal(
+  DdManager * table,
+  int  lower,
+  int  maxlevel)
+{
+    int i,j;
+    DdNode *f;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(table->sentinel);
+    int slots;
+
+    for (i = lower; i <= maxlevel; i++) {
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+	for (j = 0; j < slots; j++) {
+	    f = nodelist[j];
+	    while (f != sentinel) {
+		f->next = Cudd_Regular(f->next);
+		f = f->next;
+	    }
+	}
+    }
+
+} /* end of ddClearGlobal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a lower bound on the size of a BDD.]
+
+  Description [Computes a lower bound on the size of a BDD from the
+  following factors:
+  <ul>
+  <li> size of the lower part of it;
+  <li> size of the part of the upper part not subjected to reordering;
+  <li> number of roots in the part of the BDD subjected to reordering;
+  <li> variable in the support of the roots in the upper part of the
+       BDD subjected to reordering.
+  <ul/>]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+computeLB(
+  DdManager * table		/* manager */,
+  DdHalfWord * order		/* optimal order for the subset */,
+  int  roots			/* roots between lower and upper */,
+  int  cost			/* minimum cost for the subset */,
+  int  lower			/* lower level to be reordered */,
+  int  upper			/* upper level to be reordered */,
+  int  level			/* offset for the current top bottom var */
+  )
+{
+    int i;
+    int lb = cost;
+    int lb1 = 0;
+    int lb2;
+    int support;
+    DdHalfWord ref;
+
+    /* The levels not involved in reordering are not going to change.
+    ** Add their sizes to the lower bound.
+    */
+    for (i = 0; i < lower; i++) {
+	lb += getLevelKeys(table,i);
+    }
+    /* If a variable is in the support, then there is going
+    ** to be at least one node labeled by that variable.
+    */
+    for (i = lower; i <= lower+level; i++) {
+	support = table->subtables[i].keys > 1 ||
+	    table->vars[order[i-lower]]->ref > 1;
+	lb1 += support;
+    }
+
+    /* Estimate the number of nodes required to connect the roots to
+    ** the nodes in the bottom part. */
+    if (lower+level+1 < table->size) {
+	if (lower+level < upper)
+	    ref = table->vars[order[level+1]]->ref;
+	else
+	    ref = table->vars[table->invperm[upper+1]]->ref;
+	lb2 = table->subtables[lower+level+1].keys -
+	    (ref > (DdHalfWord) 1) - roots;
+    } else {
+	lb2 = 0;
+    }
+
+    lb += lb1 > lb2 ? lb1 : lb2;
+
+    return(lb);
+
+} /* end of computeLB */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates entry for a subset.]
+
+  Description [Updates entry for a subset. Finds the subset, if it exists.
+  If the new order for the subset has lower cost, or if the subset did not
+  exist, it stores the new order and cost. Returns the number of subsets
+  currently in the table.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+updateEntry(
+  DdManager * table,
+  DdHalfWord * order,
+  int  level,
+  int  cost,
+  DdHalfWord ** orders,
+  int * costs,
+  int  subsets,
+  char * mask,
+  int  lower,
+  int  upper)
+{
+    int i, j;
+    int size = upper - lower + 1;
+
+    /* Build a mask that says what variables are in this subset. */
+    for (i = lower; i <= upper; i++)
+	mask[table->invperm[i]] = 0;
+    for (i = level; i < size; i++)
+	mask[order[i]] = 1;
+
+    /* Check each subset until a match is found or all subsets are examined. */
+    for (i = 0; i < subsets; i++) {
+	DdHalfWord *subset = orders[i];
+	for (j = level; j < size; j++) {
+	    if (mask[subset[j]] == 0)
+		break;
+	}
+	if (j == size)		/* no mismatches: success */
+	    break;
+    }
+    if (i == subsets || cost < costs[i]) {		/* add or replace */
+	for (j = 0; j < size; j++)
+	    orders[i][j] = order[j];
+	costs[i] = cost;
+	subsets += (i == subsets);
+    }
+    return(subsets);
+
+} /* end of updateEntry */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Pushes a variable in the order down to position "level."]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+pushDown(
+  DdHalfWord * order,
+  int  j,
+  int  level)
+{
+    int i;
+    DdHalfWord tmp;
+
+    tmp = order[j];
+    for (i = j; i < level; i++) {
+	order[i] = order[i+1];
+    }
+    order[level] = tmp;
+    return;
+
+} /* end of pushDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gathers symmetry information.]
+
+  Description [Translates the symmetry information stored in the next
+  field of each subtable from level to indices. This procedure is called
+  immediately after symmetric sifting, so that the next fields are correct.
+  By translating this informaton in terms of indices, we make it independent
+  of subsequent reorderings. The format used is that of the next fields:
+  a circular list where each variable points to the next variable in the
+  same symmetry group. Only the entries between lower and upper are
+  considered.  The procedure returns a pointer to an array
+  holding the symmetry information if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [checkSymmInfo]
+
+******************************************************************************/
+static DdHalfWord *
+initSymmInfo(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int level, index, next, nextindex;
+    DdHalfWord *symmInfo;
+
+    symmInfo =  ALLOC(DdHalfWord, table->size);
+    if (symmInfo == NULL) return(NULL);
+
+    for (level = lower; level <= upper; level++) {
+	index = table->invperm[level];
+	next =  table->subtables[level].next;
+	nextindex = table->invperm[next];
+	symmInfo[index] = nextindex;
+    }
+    return(symmInfo);
+
+} /* end of initSymmInfo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check symmetry condition.]
+
+  Description [Returns 1 if a variable is the one with the highest index
+  among those belonging to a symmetry group that are in the top part of
+  the BDD.  The top part is given by level.]
+
+  SideEffects [None]
+
+  SeeAlso     [initSymmInfo]
+
+******************************************************************************/
+static int
+checkSymmInfo(
+  DdManager * table,
+  DdHalfWord * symmInfo,
+  int  index,
+  int  level)
+{
+    int i;
+
+    i = symmInfo[index];
+    while (i != index) {
+	if (index < i && table->perm[i] <= level)
+	    return(0);
+	i = symmInfo[i];
+    }
+    return(1);
+
+} /* end of checkSymmInfo */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddExport.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddExport.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddExport.c	(revision 8)
@@ -0,0 +1,1328 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddExport.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Export functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_DumpBlif()
+		<li> Cudd_DumpBlifBody()
+		<li> Cudd_DumpDot()
+		<li> Cudd_DumpDaVinci()
+		<li> Cudd_DumpDDcal()
+		<li> Cudd_DumpFactoredForm()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddDoDumpBlif()
+		<li> ddDoDumpDaVinci()
+		<li> ddDoDumpDDcal()
+		<li> ddDoDumpFactoredForm()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.18 2004/08/13 18:04:48 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddDoDumpBlif (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names);
+static int ddDoDumpDaVinci (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, unsigned long mask);
+static int ddDoDumpDDcal (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, unsigned long mask);
+static int ddDoDumpFactoredForm (DdManager *dd, DdNode *f, FILE *fp, char **names);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a blif file representing the argument BDDs.]
+
+  Description [Writes a blif file representing the argument BDDs as a
+  network of multiplexers. One multiplexer is written for each BDD
+  node. It returns 1 in case of success; 0 otherwise (e.g.,
+  out-of-memory, file system full, or an ADD with constants different
+  from 0 and 1).  Cudd_DumpBlif does not close the file: This is the
+  caller responsibility. Cudd_DumpBlif uses a minimal unique subset of
+  the hexadecimal address of a node as name for it.  If the argument
+  inames is non-null, it is assumed to hold the pointers to the names
+  of the inputs. Similarly for onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal
+  Cudd_DumpDaVinci Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpBlif(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  char * mname /* model name (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode	*support = NULL;
+    DdNode	*scan;
+    int		*sorted = NULL;
+    int		nvars = dd->size;
+    int		retval;
+    int		i;
+
+    /* Build a bit array with the support of f. */
+    sorted = ALLOC(int,nvars);
+    if (sorted == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    support = Cudd_VectorSupport(dd,f,n);
+    if (support == NULL) goto failure;
+    cuddRef(support);
+    scan = support;
+    while (!cuddIsConstant(scan)) {
+	sorted[scan->index] = 1;
+	scan = cuddT(scan);
+    }
+    Cudd_RecursiveDeref(dd,support);
+    support = NULL; /* so that we do not try to free it in case of failure */
+
+    /* Write the header (.model .inputs .outputs). */
+    if (mname == NULL) {
+	retval = fprintf(fp,".model DD\n.inputs");
+    } else {
+	retval = fprintf(fp,".model %s\n.inputs",mname);
+    }
+    if (retval == EOF) return(0);
+
+    /* Write the input list by scanning the support array. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[i]) {
+	    if (inames == NULL) {
+		retval = fprintf(fp," %d", i);
+	    } else {
+		retval = fprintf(fp," %s", inames[i]);
+	    }
+            if (retval == EOF) goto failure;
+        }
+    }
+    FREE(sorted);
+    sorted = NULL;
+
+    /* Write the .output line. */
+    retval = fprintf(fp,"\n.outputs");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp," f%d", i);
+	} else {
+	    retval = fprintf(fp," %s", onames[i]);
+	}
+	if (retval == EOF) goto failure;
+    }
+    retval = fprintf(fp,"\n");
+    if (retval == EOF) goto failure;
+
+    retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp);
+    if (retval == 0) goto failure;
+
+    /* Write trailer and return. */
+    retval = fprintf(fp,".end\n");
+    if (retval == EOF) goto failure;
+
+    return(1);
+
+failure:
+    if (sorted != NULL) FREE(sorted);
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    return(0);
+
+} /* end of Cudd_DumpBlif */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a blif body representing the argument BDDs.]
+
+  Description [Writes a blif body representing the argument BDDs as a
+  network of multiplexers.  No header (.model, .inputs, and .outputs) and
+  footer (.end) are produced by this function.  One multiplexer is written
+  for each BDD node. It returns 1 in case of success; 0 otherwise (e.g.,
+  out-of-memory, file system full, or an ADD with constants different
+  from 0 and 1).  Cudd_DumpBlifBody does not close the file: This is the
+  caller responsibility. Cudd_DumpBlifBody uses a minimal unique subset of
+  the hexadecimal address of a node as name for it.  If the argument
+  inames is non-null, it is assumed to hold the pointers to the names
+  of the inputs. Similarly for onames. This function prints out only
+  .names part.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpBlif Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal
+  Cudd_DumpDaVinci Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpBlifBody(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    st_table	*visited = NULL;
+    int		retval;
+    int		i;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+	retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames);
+	if (retval == 0) goto failure;
+    }
+
+    /* To account for the possible complement on the root,
+    ** we put either a buffer or an inverter at the output of
+    ** the multiplexer representing the top node.
+    */
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp,
+#if SIZEOF_VOID_P == 8
+		".names %lx f%d\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), i);
+#else
+		".names %x f%d\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), i);
+#endif
+	} else {
+	    retval = fprintf(fp,
+#if SIZEOF_VOID_P == 8
+		".names %lx %s\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), onames[i]);
+#else
+		".names %x %s\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), onames[i]);
+#endif
+	}
+	if (retval == EOF) goto failure;
+	if (Cudd_IsComplement(f[i])) {
+	    retval = fprintf(fp,"0 1\n");
+	} else {
+	    retval = fprintf(fp,"1 1\n");
+	}
+	if (retval == EOF) goto failure;
+    }
+
+    st_free_table(visited);
+    return(1);
+
+failure:
+    if (visited != NULL) st_free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpBlifBody */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a dot file representing the argument DDs.]
+
+  Description [Writes a file representing the argument DDs in a format
+  suitable for the graph drawing program dot.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory,
+  file system full).
+  Cudd_DumpDot does not close the file: This is the caller
+  responsibility. Cudd_DumpDot uses a minimal unique subset of the
+  hexadecimal address of a node as name for it.
+  If the argument inames is non-null, it is assumed to hold the pointers
+  to the names of the inputs. Similarly for onames.
+  Cudd_DumpDot uses the following convention to draw arcs:
+    <ul>
+    <li> solid line: THEN arcs;
+    <li> dotted line: complement arcs;
+    <li> dashed line: regular ELSE arcs.
+    </ul>
+  The dot options are chosen so that the drawing fits on a letter-size
+  sheet.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal
+  Cudd_DumpDaVinci Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpDot(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode	*support = NULL;
+    DdNode	*scan;
+    int		*sorted = NULL;
+    int		nvars = dd->size;
+    st_table	*visited = NULL;
+    st_generator *gen = NULL;
+    int		retval;
+    int		i, j;
+    int		slots;
+    DdNodePtr	*nodelist;
+    long	refAddr, diff, mask;
+
+    /* Build a bit array with the support of f. */
+    sorted = ALLOC(int,nvars);
+    if (sorted == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    support = Cudd_VectorSupport(dd,f,n);
+    if (support == NULL) goto failure;
+    cuddRef(support);
+    scan = support;
+    while (!cuddIsConstant(scan)) {
+	sorted[scan->index] = 1;
+	scan = cuddT(scan);
+    }
+    Cudd_RecursiveDeref(dd,support);
+    support = NULL; /* so that we do not try to free it in case of failure */
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+	retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
+	if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (long) Cudd_Regular(f[0]);
+    diff = 0;
+    gen = st_init_gen(visited);
+    if (gen == NULL) goto failure;
+    while (st_gen(gen, &scan, NULL)) {
+	diff |= refAddr ^ (long) scan;
+    }
+    st_free_gen(gen); gen = NULL;
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) {
+	mask = (1 << i) - 1;
+	if (diff <= mask) break;
+    }
+
+    /* Write the header and the global attributes. */
+    retval = fprintf(fp,"digraph \"DD\" {\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+	"size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
+    if (retval == EOF) return(0);
+
+    /* Write the input name subgraph by scanning the support array. */
+    retval = fprintf(fp,"{ node [shape = plaintext];\n");
+    if (retval == EOF) goto failure;
+    retval = fprintf(fp,"  edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    /* We use a name ("CONST NODES") with an embedded blank, because
+    ** it is unlikely to appear as an input name.
+    */
+    retval = fprintf(fp,"  \"CONST NODES\" [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+	    if (inames == NULL || inames[dd->invperm[i]] == NULL) {
+		retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]);
+	    } else {
+		retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[i]]);
+	    }
+            if (retval == EOF) goto failure;
+        }
+    }
+    retval = fprintf(fp,"\"CONST NODES\"; \n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write the output node subgraph. */
+    retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp,"\"F%d\"", i);
+	} else {
+	    retval = fprintf(fp,"\"  %s  \"", onames[i]);
+	}
+	if (retval == EOF) goto failure;
+	if (i == n - 1) {
+	    retval = fprintf(fp,"; }\n");
+	} else {
+	    retval = fprintf(fp," -> ");
+	}
+	if (retval == EOF) goto failure;
+    }
+
+    /* Write rank info: All nodes with the same index have the same rank. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+	    retval = fprintf(fp,"{ rank = same; ");
+	    if (retval == EOF) goto failure;
+	    if (inames == NULL || inames[dd->invperm[i]] == NULL) {
+		retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]);
+	    } else {
+		retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]);
+	    }
+            if (retval == EOF) goto failure;
+	    nodelist = dd->subtables[i].nodelist;
+	    slots = dd->subtables[i].slots;
+	    for (j = 0; j < slots; j++) {
+		scan = nodelist[j];
+		while (scan != NULL) {
+		    if (st_is_member(visited,(char *) scan)) {
+			retval = fprintf(fp,"\"%lx\";\n",
+			    (unsigned long) ((mask & (long) scan) /
+			    sizeof(DdNode)));
+			if (retval == EOF) goto failure;
+		    }
+		    scan = scan->next;
+		}
+	    }
+	    retval = fprintf(fp,"}\n");
+	    if (retval == EOF) goto failure;
+	}
+    }
+
+    /* All constants have the same rank. */
+    retval = fprintf(fp,
+	"{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
+    if (retval == EOF) goto failure;
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+	scan = nodelist[j];
+	while (scan != NULL) {
+	    if (st_is_member(visited,(char *) scan)) {
+		retval = fprintf(fp,"\"%lx\";\n",
+		    (unsigned long) ((mask & (long) scan) / sizeof(DdNode)));
+		if (retval == EOF) goto failure;
+	    }
+	    scan = scan->next;
+	}
+    }
+    retval = fprintf(fp,"}\n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write edge info. */
+    /* Edges from the output nodes. */
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp,"\"F%d\"", i);
+	} else {
+	    retval = fprintf(fp,"\"  %s  \"", onames[i]);
+	}
+	if (retval == EOF) goto failure;
+	/* Account for the possible complement on the root. */
+	if (Cudd_IsComplement(f[i])) {
+	    retval = fprintf(fp," -> \"%lx\" [style = dotted];\n",
+		(unsigned long) ((mask & (long) f[i]) / sizeof(DdNode)));
+	} else {
+	    retval = fprintf(fp," -> \"%lx\" [style = solid];\n",
+		(unsigned long) ((mask & (long) f[i]) / sizeof(DdNode)));
+	}
+	if (retval == EOF) goto failure;
+    }
+
+    /* Edges from internal nodes. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+	    nodelist = dd->subtables[i].nodelist;
+	    slots = dd->subtables[i].slots;
+	    for (j = 0; j < slots; j++) {
+		scan = nodelist[j];
+		while (scan != NULL) {
+		    if (st_is_member(visited,(char *) scan)) {
+			retval = fprintf(fp,
+			    "\"%lx\" -> \"%lx\";\n",
+			    (unsigned long) ((mask & (long) scan) /
+			    sizeof(DdNode)),
+			    (unsigned long) ((mask & (long) cuddT(scan)) /
+			    sizeof(DdNode)));
+			if (retval == EOF) goto failure;
+			if (Cudd_IsComplement(cuddE(scan))) {
+			    retval = fprintf(fp,
+				"\"%lx\" -> \"%lx\" [style = dotted];\n",
+				(unsigned long) ((mask & (long) scan) /
+				sizeof(DdNode)),
+				(unsigned long) ((mask & (long) cuddE(scan)) /
+				sizeof(DdNode)));
+			} else {
+			    retval = fprintf(fp,
+				"\"%lx\" -> \"%lx\" [style = dashed];\n",
+				(unsigned long) ((mask & (long) scan) /
+				sizeof(DdNode)),
+				(unsigned long) ((mask & (long) cuddE(scan)) /
+				sizeof(DdNode)));
+			}
+			if (retval == EOF) goto failure;
+		    }
+		    scan = scan->next;
+		}
+	    }
+	}
+    }
+
+    /* Write constant labels. */
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+	scan = nodelist[j];
+	while (scan != NULL) {
+	    if (st_is_member(visited,(char *) scan)) {
+		retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n",
+		    (unsigned long) ((mask & (long) scan) / sizeof(DdNode)),
+		    cuddV(scan));
+		if (retval == EOF) goto failure;
+	    }
+	    scan = scan->next;
+	}
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp,"}\n");
+    if (retval == EOF) goto failure;
+
+    st_free_table(visited);
+    FREE(sorted);
+    return(1);
+
+failure:
+    if (sorted != NULL) FREE(sorted);
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    if (visited != NULL) st_free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpDot */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a daVinci file representing the argument BDDs.]
+
+  Description [Writes a daVinci file representing the argument BDDs.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or
+  file system full).  Cudd_DumpDaVinci does not close the file: This
+  is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique
+  subset of the hexadecimal address of a node as name for it.  If the
+  argument inames is non-null, it is assumed to hold the pointers to
+  the names of the inputs. Similarly for onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal
+  Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpDaVinci(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode	  *support = NULL;
+    DdNode	  *scan;
+    st_table	  *visited = NULL;
+    int		  retval;
+    int		  i;
+    st_generator  *gen;
+    unsigned long refAddr, diff, mask;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+	retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
+	if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (unsigned long) Cudd_Regular(f[0]);
+    diff = 0;
+    gen = st_init_gen(visited);
+    while (st_gen(gen, &scan, NULL)) {
+	diff |= refAddr ^ (unsigned long) scan;
+    }
+    st_free_gen(gen);
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(long unsigned); i += 4) {
+	mask = (1 << i) - 1;
+	if (diff <= mask) break;
+    }
+    st_free_table(visited);
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (visited == NULL) goto failure;
+
+    retval = fprintf(fp, "[");
+    if (retval == EOF) goto failure;
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp,
+			     "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],",
+			     i,i);
+	} else {
+	    retval = fprintf(fp,
+			     "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],",
+			     onames[i], onames[i]);
+	}
+	if (retval == EOF) goto failure;
+	retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],",
+			 Cudd_IsComplement(f[i]) ? "red" : "blue");
+	if (retval == EOF) goto failure;
+	retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask);
+	if (retval == 0) goto failure;
+	retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ",");
+	if (retval == EOF) goto failure;
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp, "]\n");
+    if (retval == EOF) goto failure;
+
+    st_free_table(visited);
+    return(1);
+
+failure:
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    if (visited != NULL) st_free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpDaVinci */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a DDcal file representing the argument BDDs.]
+
+  Description [Writes a DDcal file representing the argument BDDs.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or
+  file system full).  Cudd_DumpDDcal does not close the file: This
+  is the caller responsibility. Cudd_DumpDDcal uses a minimal unique
+  subset of the hexadecimal address of a node as name for it.  If the
+  argument inames is non-null, it is assumed to hold the pointers to
+  the names of the inputs. Similarly for onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci
+  Cudd_DumpFactoredForm]
+
+******************************************************************************/
+int
+Cudd_DumpDDcal(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode	  *support = NULL;
+    DdNode	  *scan;
+    int		  *sorted = NULL;
+    int		  nvars = dd->size;
+    st_table	  *visited = NULL;
+    int		  retval;
+    int		  i;
+    st_generator  *gen;
+    unsigned long refAddr, diff, mask;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+	retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
+	if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (unsigned long) Cudd_Regular(f[0]);
+    diff = 0;
+    gen = st_init_gen(visited);
+    while (st_gen(gen, &scan, NULL)) {
+	diff |= refAddr ^ (unsigned long) scan;
+    }
+    st_free_gen(gen);
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(unsigned long); i += 4) {
+	mask = (1 << i) - 1;
+	if (diff <= mask) break;
+    }
+    st_free_table(visited);
+
+    /* Build a bit array with the support of f. */
+    sorted = ALLOC(int,nvars);
+    if (sorted == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    support = Cudd_VectorSupport(dd,f,n);
+    if (support == NULL) goto failure;
+    cuddRef(support);
+    scan = support;
+    while (!cuddIsConstant(scan)) {
+	sorted[scan->index] = 1;
+	scan = cuddT(scan);
+    }
+    Cudd_RecursiveDeref(dd,support);
+    support = NULL; /* so that we do not try to free it in case of failure */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invperm[i]]) {
+	    if (inames == NULL || inames[dd->invperm[i]] == NULL) {
+		retval = fprintf(fp,"v%d", dd->invperm[i]);
+	    } else {
+		retval = fprintf(fp,"%s", inames[dd->invperm[i]]);
+	    }
+            if (retval == EOF) goto failure;
+        }
+	retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * ");
+	if (retval == EOF) goto failure;
+    }
+    FREE(sorted);
+    sorted = NULL;
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+	retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask);
+	if (retval == 0) goto failure;
+	if (onames == NULL) {
+	    retval = fprintf(fp, "f%d = ", i);
+	} else {
+	    retval = fprintf(fp, "%s = ", onames[i]);
+	}
+	if (retval == EOF) goto failure;
+	retval = fprintf(fp, "n%lx%s\n",
+			 ((unsigned long) f[i] & mask) /
+			 (unsigned long) sizeof(DdNode),
+			 Cudd_IsComplement(f[i]) ? "'" : "");
+	if (retval == EOF) goto failure;
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp, "[");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp, "f%d", i);
+	} else {
+	    retval = fprintf(fp, "%s", onames[i]);
+	}
+	retval = fprintf(fp, "%s", i == n-1 ? "" : " ");
+	if (retval == EOF) goto failure;
+    }
+    retval = fprintf(fp, "]\n");
+    if (retval == EOF) goto failure;
+
+    st_free_table(visited);
+    return(1);
+
+failure:
+    if (sorted != NULL) FREE(sorted);
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    if (visited != NULL) st_free_table(visited);
+    return(0);
+
+} /* end of Cudd_DumpDDcal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes factored forms representing the argument BDDs.]
+
+  Description [Writes factored forms representing the argument BDDs.
+  The format of the factored form is the one used in the genlib files
+  for technology mapping in sis.  It returns 1 in case of success; 0
+  otherwise (e.g., file system full).  Cudd_DumpFactoredForm does not
+  close the file: This is the caller responsibility. Caution must be
+  exercised because a factored form may be exponentially larger than
+  the argument BDD.  If the argument inames is non-null, it is assumed
+  to hold the pointers to the names of the inputs. Similarly for
+  onames.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci
+  Cudd_DumpDDcal]
+
+******************************************************************************/
+int
+Cudd_DumpFactoredForm(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    int		retval;
+    int		i;
+
+    /* Call the function that really gets the job done. */
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp, "f%d = ", i);
+	} else {
+	    retval = fprintf(fp, "%s = ", onames[i]);
+	}
+	if (retval == EOF) return(0);
+	if (f[i] == DD_ONE(dd)) {
+	    retval = fprintf(fp, "CONST1");
+	    if (retval == EOF) return(0);
+	} else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) {
+	    retval = fprintf(fp, "CONST0");
+	    if (retval == EOF) return(0);
+	} else {
+	    retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : "");
+	    if (retval == EOF) return(0);
+	    retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames);
+	    if (retval == 0) return(0);
+	    retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : "");
+	    if (retval == EOF) return(0);
+	}
+	retval = fprintf(fp, "%s", i == n-1 ? "" : "\n");
+	if (retval == EOF) return(0);
+    }
+
+    return(1);
+
+} /* end of Cudd_DumpFactoredForm */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpBlif.]
+
+  Description [Performs the recursive step of Cudd_DumpBlif. Traverses
+  the BDD f and writes a multiplexer-network description to the file
+  pointed by fp in blif format. f is assumed to be a regular pointer
+  and ddDoDumpBlif guarantees this assumption in the recursive calls.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddDoDumpBlif(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  st_table * visited,
+  char ** names)
+{
+    DdNode	*T, *E;
+    int		retval;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    /* If already visited, nothing to do. */
+    if (st_is_member(visited, (char *) f) == 1)
+        return(1);
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
+        return(0);
+
+    /* Check for special case: If constant node, generate constant 1. */
+    if (f == DD_ONE(dd)) {
+#if SIZEOF_VOID_P == 8
+        retval = fprintf(fp, ".names %lx\n1\n",(unsigned long) f / (unsigned long) sizeof(DdNode));
+#else
+        retval = fprintf(fp, ".names %x\n1\n",(unsigned) f / (unsigned) sizeof(DdNode));
+#endif
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Check whether this is an ADD. We deal with 0-1 ADDs, but not
+    ** with the general case.
+    */
+    if (f == DD_ZERO(dd)) {
+#if SIZEOF_VOID_P == 8
+        retval = fprintf(fp, ".names %lx\n",(unsigned long) f / (unsigned long) sizeof(DdNode));
+#else
+        retval = fprintf(fp, ".names %x\n",(unsigned) f / (unsigned) sizeof(DdNode));
+#endif
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+    if (cuddIsConstant(f))
+	return(0);
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    retval = ddDoDumpBlif(dd,T,fp,visited,names);
+    if (retval != 1) return(retval);
+    E = Cudd_Regular(cuddE(f));
+    retval = ddDoDumpBlif(dd,E,fp,visited,names);
+    if (retval != 1) return(retval);
+
+    /* Write multiplexer taking complement arc into account. */
+    if (names != NULL) {
+	retval = fprintf(fp,".names %s", names[f->index]);
+    } else {
+	retval = fprintf(fp,".names %d", f->index);
+    }
+    if (retval == EOF)
+	return(0);
+
+#if SIZEOF_VOID_P == 8
+    if (Cudd_IsComplement(cuddE(f))) {
+        retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n",
+	    (unsigned long) T / (unsigned long) sizeof(DdNode),
+	    (unsigned long) E / (unsigned long) sizeof(DdNode),
+	    (unsigned long) f / (unsigned long) sizeof(DdNode));
+    } else {
+        retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n",
+	    (unsigned long) T / (unsigned long) sizeof(DdNode),
+	    (unsigned long) E / (unsigned long) sizeof(DdNode),
+	    (unsigned long) f / (unsigned long) sizeof(DdNode));
+    }
+#else
+    if (Cudd_IsComplement(cuddE(f))) {
+        retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n",
+	    (unsigned) T / (unsigned) sizeof(DdNode),
+	    (unsigned) E / (unsigned) sizeof(DdNode),
+	    (unsigned) f / (unsigned) sizeof(DdNode));
+    } else {
+        retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n",
+	    (unsigned) T / (unsigned) sizeof(DdNode),
+	    (unsigned) E / (unsigned) sizeof(DdNode),
+	    (unsigned) f / (unsigned) sizeof(DdNode));
+    }
+#endif
+    if (retval == EOF) {
+        return(0);
+    } else {
+        return(1);
+    }
+
+} /* end of ddDoDumpBlif */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpDaVinci.]
+
+  Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses
+  the BDD f and writes a term expression to the file
+  pointed by fp in daVinci format. f is assumed to be a regular pointer
+  and ddDoDumpDaVinci guarantees this assumption in the recursive calls.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddDoDumpDaVinci(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  st_table * visited,
+  char ** names,
+  unsigned long mask)
+{
+    DdNode	  *T, *E;
+    int		  retval;
+    unsigned long id;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    id = ((unsigned long) f & mask) / sizeof(DdNode);
+
+    /* If already visited, insert a reference. */
+    if (st_is_member(visited, (char *) f) == 1) {
+	retval = fprintf(fp,"r(\"%lx\")", id);
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
+        return(0);
+
+    /* Check for special case: If constant node, generate constant 1. */
+    if (Cudd_IsConstant(f)) {
+        retval = fprintf(fp, "l(\"%lx\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))", id, cuddV(f));
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Recursive calls. */
+    if (names != NULL) {
+	retval = fprintf(fp,
+			 "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%s\"),",
+			 id, names[f->index]);
+    } else {
+	retval = fprintf(fp,
+			 "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%d\"),",
+			 id, f->index);
+    }
+    retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],");
+    if (retval == EOF) return(0);
+    T = cuddT(f);
+    retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+    retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],",
+		     Cudd_IsComplement(cuddE(f)) ? "red" : "green");
+    if (retval == EOF) return(0);
+    E = Cudd_Regular(cuddE(f));
+    retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+
+    retval = fprintf(fp,")]))");
+    if (retval == EOF) {
+        return(0);
+    } else {
+        return(1);
+    }
+
+} /* end of ddDoDumpDaVinci */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpDDcal.]
+
+  Description [Performs the recursive step of Cudd_DumpDDcal. Traverses
+  the BDD f and writes a line for each node to the file
+  pointed by fp in DDcal format. f is assumed to be a regular pointer
+  and ddDoDumpDDcal guarantees this assumption in the recursive calls.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddDoDumpDDcal(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  st_table * visited,
+  char ** names,
+  unsigned long mask)
+{
+    DdNode	  *T, *E;
+    int		  retval;
+    unsigned long id, idT, idE;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    id = ((unsigned long) f & mask) / sizeof(DdNode);
+
+    /* If already visited, do nothing. */
+    if (st_is_member(visited, (char *) f) == 1) {
+	return(1);
+    }
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
+        return(0);
+
+    /* Check for special case: If constant node, assign constant. */
+    if (Cudd_IsConstant(f)) {
+	if (f != DD_ONE(dd) && f != DD_ZERO(dd))
+	    return(0);
+	retval = fprintf(fp, "n%lx = %g\n", id, cuddV(f));
+        if (retval == EOF) {
+            return(0);
+        } else {
+            return(1);
+        }
+    }
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+    E = Cudd_Regular(cuddE(f));
+    retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask);
+    if (retval != 1) return(retval);
+    idT = ((unsigned long) T & mask) / sizeof(DdNode);
+    idE = ((unsigned long) E & mask) / sizeof(DdNode);
+    if (names != NULL) {
+	retval = fprintf(fp, "n%lx = %s * n%lx + %s' * n%lx%s\n",
+			 id, names[f->index], idT, names[f->index],
+			 idE, Cudd_IsComplement(cuddE(f)) ? "'" : "");
+    } else {
+	retval = fprintf(fp, "n%lx = v%d * n%lx + v%d' * n%lx%s\n",
+			 id, f->index, idT, f->index,
+			 idE, Cudd_IsComplement(cuddE(f)) ? "'" : "");
+    }
+    if (retval == EOF) {
+        return(0);
+    } else {
+        return(1);
+    }
+
+} /* end of ddDoDumpDDcal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DumpFactoredForm.]
+
+  Description [Performs the recursive step of
+  Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored
+  form for each node to the file pointed by fp in terms of the
+  factored forms of the children. Constants are propagated, and
+  absorption is applied.  f is assumed to be a regular pointer and
+  ddDoDumpFActoredForm guarantees this assumption in the recursive
+  calls.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpFactoredForm]
+
+******************************************************************************/
+static int
+ddDoDumpFactoredForm(
+  DdManager * dd,
+  DdNode * f,
+  FILE * fp,
+  char ** names)
+{
+    DdNode	*T, *E;
+    int		retval;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+    assert(!Cudd_IsConstant(f));
+#endif
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    E = cuddE(f);
+    if (T != DD_ZERO(dd)) {
+	if (E != DD_ONE(dd)) {
+	    if (names != NULL) {
+		retval = fprintf(fp, "%s", names[f->index]);
+	    } else {
+		retval = fprintf(fp, "x%d", f->index);
+	    }
+	    if (retval == EOF) return(0);
+	}
+	if (T != DD_ONE(dd)) {
+	    retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : "");
+	    if (retval == EOF) return(0);
+	    retval = ddDoDumpFactoredForm(dd,T,fp,names);
+	    if (retval != 1) return(retval);
+	    retval = fprintf(fp, ")");
+	    if (retval == EOF) return(0);
+	}
+	if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1);
+	retval = fprintf(fp, " + ");
+	if (retval == EOF) return(0);
+    }
+    E = Cudd_Regular(E);
+    if (T != DD_ONE(dd)) {
+	if (names != NULL) {
+	    retval = fprintf(fp, "!%s", names[f->index]);
+	} else {
+	    retval = fprintf(fp, "!x%d", f->index);
+	}
+	if (retval == EOF) return(0);
+    }
+    if (E != DD_ONE(dd)) {
+	retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "",
+			 E != cuddE(f) ? "!" : "");
+	if (retval == EOF) return(0);
+	retval = ddDoDumpFactoredForm(dd,E,fp,names);
+	if (retval != 1) return(retval);
+	retval = fprintf(fp, ")");
+	if (retval == EOF) return(0);
+    }
+    return(1);
+
+} /* end of ddDoDumpFactoredForm */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddGenCof.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddGenCof.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddGenCof.c	(revision 8)
@@ -0,0 +1,2175 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddGenCof.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Generalized cofactors for BDDs and ADDs.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_bddConstrain()
+		<li> Cudd_bddRestrict()
+		<li> Cudd_bddNPAnd()
+		<li> Cudd_addConstrain()
+		<li> Cudd_bddConstrainDecomp()
+		<li> Cudd_addRestrict()
+		<li> Cudd_bddCharToVect()
+		<li> Cudd_bddLICompaction()
+		<li> Cudd_bddSqueeze()
+		<li> Cudd_SubsetCompress()
+		<li> Cudd_SupersetCompress()
+		</ul>
+	    Internal procedures included in this module:
+		<ul>
+		<li> cuddBddConstrainRecur()
+		<li> cuddBddRestrictRecur()
+		<li> cuddBddNPAndRecur()
+		<li> cuddAddConstrainRecur()
+		<li> cuddAddRestrictRecur()
+		<li> cuddBddLICompaction()
+		</ul>
+	    Static procedures included in this module:
+	        <ul>
+		<li> cuddBddConstrainDecomp()
+		<li> cuddBddCharToVect()
+		<li> cuddBddLICMarkEdges()
+		<li> cuddBddLICBuildResult()
+		<li> cuddBddSqueeze()
+		</ul>
+		]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Codes for edge markings in Cudd_bddLICompaction.  The codes are defined
+** so that they can be bitwise ORed to implement the code priority scheme.
+*/
+#define DD_LIC_DC 0
+#define DD_LIC_1  1
+#define DD_LIC_0  2
+#define DD_LIC_NL 3
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/* Key for the cache used in the edge marking phase. */
+typedef struct MarkCacheKey {
+    DdNode *f;
+    DdNode *c;
+} MarkCacheKey;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.38 2005/05/14 17:27:11 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddBddConstrainDecomp (DdManager *dd, DdNode *f, DdNode **decomp);
+static DdNode * cuddBddCharToVect (DdManager *dd, DdNode *f, DdNode *x);
+static int cuddBddLICMarkEdges (DdManager *dd, DdNode *f, DdNode *c, st_table *table, st_table *cache);
+static DdNode * cuddBddLICBuildResult (DdManager *dd, DdNode *f, st_table *cache, st_table *table);
+static int MarkCacheHash (char *ptr, int modulus);
+static int MarkCacheCompare (const char *ptr1, const char *ptr2);
+static enum st_retval MarkCacheCleanUp (char *key, char *value, char *arg);
+static DdNode * cuddBddSqueeze (DdManager *dd, DdNode *l, DdNode *u);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes f constrain c.]
+
+  Description [Computes f constrain c (f @ c).
+  Uses a canonical form: (f' @ c) = ( f @ c)'.  (Note: this is not true
+  for c.)  List of special cases:
+    <ul>
+    <li> f @ 0 = 0
+    <li> f @ 1 = f
+    <li> 0 @ c = 0
+    <li> 1 @ c = 1
+    <li> f @ f = 1
+    <li> f @ f'= 0
+    </ul>
+  Returns a pointer to the result if successful; NULL otherwise. Note that if
+  F=(f1,...,fn) and reordering takes place while computing F @ c, then the
+  image restriction property (Img(F,c) = Img(F @ c)) is lost.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict Cudd_addConstrain]
+
+******************************************************************************/
+DdNode *
+Cudd_bddConstrain(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddConstrainRecur(dd,f,c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddConstrain */
+
+
+/**Function********************************************************************
+
+  Synopsis [BDD restrict according to Coudert and Madre's algorithm
+  (ICCAD90).]
+
+  Description [BDD restrict according to Coudert and Madre's algorithm
+  (ICCAD90). Returns the restricted BDD if successful; otherwise NULL.
+  If application of restrict results in a BDD larger than the input
+  BDD, the input BDD is returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_addRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_bddRestrict(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *suppF, *suppC, *commonSupport;
+    DdNode *cplus, *res;
+    int retval;
+    int sizeF, sizeRes;
+
+    /* Check terminal cases here to avoid computing supports in trivial cases.
+    ** This also allows us notto check later for the case c == 0, in which
+    ** there is no common support. */
+    if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd)));
+    if (Cudd_IsConstant(f)) return(f);
+    if (f == c) return(DD_ONE(dd));
+    if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
+
+    /* Check if supports intersect. */
+    retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC);
+    if (retval == 0) {
+	return(NULL);
+    }
+    cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC);
+    Cudd_IterDerefBdd(dd,suppF);
+
+    if (commonSupport == DD_ONE(dd)) {
+	Cudd_IterDerefBdd(dd,commonSupport);
+	Cudd_IterDerefBdd(dd,suppC);
+	return(f);
+    }
+    Cudd_IterDerefBdd(dd,commonSupport);
+
+    /* Abstract from c the variables that do not appear in f. */
+    cplus = Cudd_bddExistAbstract(dd, c, suppC);
+    if (cplus == NULL) {
+	Cudd_IterDerefBdd(dd,suppC);
+	return(NULL);
+    }
+    cuddRef(cplus);
+    Cudd_IterDerefBdd(dd,suppC);
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddRestrictRecur(dd, f, cplus);
+    } while (dd->reordered == 1);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(dd,cplus);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd,cplus);
+    /* Make restric safe by returning the smaller of the input and the
+    ** result. */
+    sizeF = Cudd_DagSize(f);
+    sizeRes = Cudd_DagSize(res);
+    if (sizeF <= sizeRes) {
+	Cudd_IterDerefBdd(dd, res);
+	return(f);
+    } else {
+	cuddDeref(res);
+	return(res);
+    }
+
+} /* end of Cudd_bddRestrict */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes f non-polluting-and g.]
+
+  Description [Computes f non-polluting-and g.  The non-polluting AND
+  of f and g is a hybrid of AND and Restrict.  From Restrict, this
+  operation takes the idea of existentially quantifying the top
+  variable of the second operand if it does not appear in the first.
+  Therefore, the variables that appear in the result also appear in f.
+  For the rest, the function behaves like AND.  Since the two operands
+  play different roles, non-polluting AND is not commutative.
+
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_bddNPAnd(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddNPAndRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddNPAnd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes f constrain c for ADDs.]
+
+  Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1
+  ADD.  List of special cases:
+    <ul>
+    <li> F @ 0 = 0
+    <li> F @ 1 = F
+    <li> 0 @ c = 0
+    <li> 1 @ c = 1
+    <li> F @ F = 1
+    </ul>
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain]
+
+******************************************************************************/
+DdNode *
+Cudd_addConstrain(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddAddConstrainRecur(dd,f,c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addConstrain */
+
+
+/**Function********************************************************************
+
+  Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.]
+
+  Description [BDD conjunctive decomposition as in McMillan's CAV96
+  paper.  The decomposition is canonical only for a given variable
+  order. If canonicity is required, variable ordering must be disabled
+  after the decomposition has been computed. Returns an array with one
+  entry for each BDD variable in the manager if successful; otherwise
+  NULL. The components of the solution have their reference counts
+  already incremented (unlike the results of most other functions in
+  the package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain Cudd_bddExistAbstract]
+
+******************************************************************************/
+DdNode **
+Cudd_bddConstrainDecomp(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode **decomp;
+    int res;
+    int i;
+
+    /* Create an initialize decomposition array. */
+    decomp = ALLOC(DdNode *,dd->size);
+    if (decomp == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < dd->size; i++) {
+	decomp[i] = NULL;
+    }
+    do {
+	dd->reordered = 0;
+	/* Clean up the decomposition array in case reordering took place. */
+	for (i = 0; i < dd->size; i++) {
+	    if (decomp[i] != NULL) {
+		Cudd_IterDerefBdd(dd, decomp[i]);
+		decomp[i] = NULL;
+	    }
+	}
+	res = cuddBddConstrainDecomp(dd,f,decomp);
+    } while (dd->reordered == 1);
+    if (res == 0) {
+	FREE(decomp);
+	return(NULL);
+    }
+    /* Missing components are constant ones. */
+    for (i = 0; i < dd->size; i++) {
+	if (decomp[i] == NULL) {
+	    decomp[i] = DD_ONE(dd);
+	    cuddRef(decomp[i]);
+	}
+    }
+    return(decomp);
+
+} /* end of Cudd_bddConstrainDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis [ADD restrict according to Coudert and Madre's algorithm
+  (ICCAD90).]
+
+  Description [ADD restrict according to Coudert and Madre's algorithm
+  (ICCAD90). Returns the restricted ADD if successful; otherwise NULL.
+  If application of restrict results in an ADD larger than the input
+  ADD, the input ADD is returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addConstrain Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_addRestrict(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *supp_f, *supp_c;
+    DdNode *res, *commonSupport;
+    int intersection;
+    int sizeF, sizeRes;
+
+    /* Check if supports intersect. */
+    supp_f = Cudd_Support(dd, f);
+    if (supp_f == NULL) {
+	return(NULL);
+    }
+    cuddRef(supp_f);
+    supp_c = Cudd_Support(dd, c);
+    if (supp_c == NULL) {
+	Cudd_RecursiveDeref(dd,supp_f);
+	return(NULL);
+    }
+    cuddRef(supp_c);
+    commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c);
+    if (commonSupport == NULL) {
+	Cudd_RecursiveDeref(dd,supp_f);
+	Cudd_RecursiveDeref(dd,supp_c);
+	return(NULL);
+    }
+    cuddRef(commonSupport);
+    Cudd_RecursiveDeref(dd,supp_f);
+    Cudd_RecursiveDeref(dd,supp_c);
+    intersection = commonSupport != DD_ONE(dd);
+    Cudd_RecursiveDeref(dd,commonSupport);
+
+    if (intersection) {
+	do {
+	    dd->reordered = 0;
+	    res = cuddAddRestrictRecur(dd, f, c);
+	} while (dd->reordered == 1);
+	sizeF = Cudd_DagSize(f);
+	sizeRes = Cudd_DagSize(res);
+	if (sizeF <= sizeRes) {
+	    cuddRef(res);
+	    Cudd_RecursiveDeref(dd, res);
+	    return(f);
+	} else {
+	    return(res);
+	}
+    } else {
+	return(f);
+    }
+
+} /* end of Cudd_addRestrict */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a vector whose image equals a non-zero function.]
+
+  Description [Computes a vector of BDDs whose image equals a non-zero
+  function.
+  The result depends on the variable order. The i-th component of the vector
+  depends only on the first i variables in the order.  Each BDD in the vector
+  is not larger than the BDD of the given characteristic function.  This
+  function is based on the description of char-to-vect in "Verification of
+  Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C.
+  Berthet and J. C. Madre.
+  Returns a pointer to an array containing the result if successful; NULL
+  otherwise. The size of the array equals the number of variables in the
+  manager. The components of the solution have their reference counts 
+  already incremented (unlike the results of most other functions in 
+  the package).]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain]
+
+******************************************************************************/
+DdNode **
+Cudd_bddCharToVect(
+  DdManager * dd,
+  DdNode * f)
+{
+    int i, j;
+    DdNode **vect;
+    DdNode *res = NULL;
+
+    if (f == Cudd_Not(DD_ONE(dd))) return(NULL);
+
+    vect = ALLOC(DdNode *, dd->size);
+    if (vect == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    do {
+	dd->reordered = 0;
+	for (i = 0; i < dd->size; i++) {
+	    res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]);
+	    if (res == NULL) {
+		/* Clean up the vector array in case reordering took place. */
+		for (j = 0; j < i; j++) {
+		    Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]);
+		}
+		break;
+	    }
+	    cuddRef(res);
+	    vect[dd->invperm[i]] = res;
+	}
+    } while (dd->reordered == 1);
+    if (res == NULL) {
+	FREE(vect);
+	return(NULL);
+    }
+    return(vect);
+
+} /* end of Cudd_bddCharToVect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs safe minimization of a BDD.]
+
+  Description [Performs safe minimization of a BDD. Given the BDD
+  <code>f</code> of a function to be minimized and a BDD
+  <code>c</code> representing the care set, Cudd_bddLICompaction
+  produces the BDD of a function that agrees with <code>f</code>
+  wherever <code>c</code> is 1.  Safe minimization means that the size
+  of the result is guaranteed not to exceed the size of
+  <code>f</code>. This function is based on the DAC97 paper by Hong et
+  al..  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+Cudd_bddLICompaction(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be minimized */,
+  DdNode * c /* constraint (care set) */)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddLICompaction(dd,f,c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddLICompaction */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a small BDD in a function interval.]
+
+  Description [Finds a small BDD in a function interval. Given BDDs
+  <code>l</code> and <code>u</code>, representing the lower bound and
+  upper bound of a function interval, Cudd_bddSqueeze produces the BDD
+  of a function within the interval with a small BDD.  Returns a
+  pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict Cudd_bddLICompaction]
+
+******************************************************************************/
+DdNode *
+Cudd_bddSqueeze(
+  DdManager * dd /* manager */,
+  DdNode * l /* lower bound */,
+  DdNode * u /* upper bound */)
+{
+    DdNode *res;
+    int sizeRes, sizeL, sizeU;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddSqueeze(dd,l,u);
+    } while (dd->reordered == 1);
+    if (res == NULL) return(NULL);
+    /* We now compare the result with the bounds and return the smallest.
+    ** We first compare to u, so that in case l == 0 and u == 1, we return
+    ** 0 as in other minimization algorithms. */
+    sizeRes = Cudd_DagSize(res);
+    sizeU = Cudd_DagSize(u);
+    if (sizeU <= sizeRes) {
+	cuddRef(res);
+	Cudd_IterDerefBdd(dd,res);
+	res = u;
+	sizeRes = sizeU;
+    }
+    sizeL = Cudd_DagSize(l);
+    if (sizeL <= sizeRes) {
+	cuddRef(res);
+	Cudd_IterDerefBdd(dd,res);
+	res = l;
+	sizeRes = sizeL;
+    }
+    return(res);
+
+} /* end of Cudd_bddSqueeze */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a small BDD that agrees with <code>f</code> over
+  <code>c</code>.]
+
+  Description [Finds a small BDD that agrees with <code>f</code> over
+  <code>c</code>.  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze]
+
+******************************************************************************/
+DdNode *
+Cudd_bddMinimize(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode *cplus, *res;
+
+    if (c == Cudd_Not(DD_ONE(dd))) return(c);
+    if (Cudd_IsConstant(f)) return(f);
+    if (f == c) return(DD_ONE(dd));
+    if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
+
+    cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0);
+    if (cplus == NULL) return(NULL);
+    cuddRef(cplus);
+    res = Cudd_bddLICompaction(dd,f,cplus);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(dd,cplus);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd,cplus);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddMinimize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find a dense subset of BDD <code>f</code>.]
+
+  Description [Finds a dense subset of BDD <code>f</code>. Density is
+  the ratio of number of minterms to number of nodes.  Uses several
+  techniques in series. It is more expensive than other subsetting
+  procedures, but often produces better results. See
+  Cudd_SubsetShortPaths for a description of the threshold and nvars
+  parameters.  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch
+  Cudd_bddSqueeze]
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetCompress(
+  DdManager * dd /* manager */,
+  DdNode * f /* BDD whose subset is sought */,
+  int  nvars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */)
+{
+    DdNode *res, *tmp1, *tmp2;
+
+    tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0);
+    if (tmp1 == NULL) return(NULL);
+    cuddRef(tmp1);
+    tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,1.0);
+    if (tmp2 == NULL) {
+	Cudd_IterDerefBdd(dd,tmp1);
+	return(NULL);
+    }
+    cuddRef(tmp2);
+    Cudd_IterDerefBdd(dd,tmp1);
+    res = Cudd_bddSqueeze(dd,tmp2,f);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(dd,tmp2);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_IterDerefBdd(dd,tmp2);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_SubsetCompress */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find a dense superset of BDD <code>f</code>.]
+
+  Description [Finds a dense superset of BDD <code>f</code>. Density is
+  the ratio of number of minterms to number of nodes.  Uses several
+  techniques in series. It is more expensive than other supersetting
+  procedures, but often produces better results. See
+  Cudd_SupersetShortPaths for a description of the threshold and nvars
+  parameters.  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths
+  Cudd_SupersetHeavyBranch Cudd_bddSqueeze]
+
+******************************************************************************/
+DdNode *
+Cudd_SupersetCompress(
+  DdManager * dd /* manager */,
+  DdNode * f /* BDD whose superset is sought */,
+  int  nvars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the superset */)
+{
+    DdNode *subset;
+
+    subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold);
+
+    return(Cudd_NotCond(subset, (subset != NULL)));
+
+} /* end of Cudd_SupersetCompress */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddConstrain.]
+
+  Description [Performs the recursive step of Cudd_bddConstrain.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrain]
+
+******************************************************************************/
+DdNode *
+cuddBddConstrainRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
+    DdNode	 *one, *zero;
+    unsigned int topf, topc;
+    int		 index;
+    int          comple = 0;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Trivial cases. */
+    if (c == one)		return(f);
+    if (c == zero)		return(zero);
+    if (Cudd_IsConstant(f))	return(f);
+    if (f == c)			return(one);
+    if (f == Cudd_Not(c))	return(zero);
+
+    /* Make canonical to increase the utilization of the cache. */
+    if (Cudd_IsComplement(f)) {
+	f = Cudd_Not(f);
+	comple = 1;
+    }
+    /* Now f is a regular pointer to a non-constant node; c is also
+    ** non-constant, but may be complemented.
+    */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c);
+    if (r != NULL) {
+	return(Cudd_NotCond(r,comple));
+    }
+    
+    /* Recursive step. */
+    topf = dd->perm[f->index];
+    topc = dd->perm[Cudd_Regular(c)->index];
+    if (topf <= topc) {
+	index = f->index;
+	Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+	index = Cudd_Regular(c)->index;
+	Fv = Fnv = f;
+    }
+    if (topc <= topf) {
+	Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
+	if (Cudd_IsComplement(c)) {
+	    Cv = Cudd_Not(Cv);
+	    Cnv = Cudd_Not(Cnv);
+	}
+    } else {
+	Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+	t = cuddBddConstrainRecur(dd, Fv, Cv);
+	if (t == NULL)
+	    return(NULL);
+    } else if (Cv == one) {
+	t = Fv;
+    } else {		/* Cv == zero: return Fnv @ Cnv */
+	if (Cnv == one) {
+	    r = Fnv;
+	} else {
+	    r = cuddBddConstrainRecur(dd, Fnv, Cnv);
+	    if (r == NULL)
+		return(NULL);
+	}
+	return(Cudd_NotCond(r,comple));
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+	e = cuddBddConstrainRecur(dd, Fnv, Cnv);
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+    } else if (Cnv == one) {
+	e = Fnv;
+    } else {		/* Cnv == zero: return Fv @ Cv previously computed */
+	cuddDeref(t);
+	return(Cudd_NotCond(t,comple));
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+	t = Cudd_Not(t);
+	e = Cudd_Not(e);
+	r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, e);
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+	r = Cudd_Not(r);
+    } else {
+	r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, e);
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddConstrainRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddRestrict.]
+
+  Description [Performs the recursive step of Cudd_bddRestrict.
+  Returns the restricted BDD if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddRestrict]
+
+******************************************************************************/
+DdNode *
+cuddBddRestrictRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode	 *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
+    unsigned int topf, topc;
+    int		 index;
+    int		 comple = 0;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Trivial cases */
+    if (c == one)		return(f);
+    if (c == zero)		return(zero);
+    if (Cudd_IsConstant(f))	return(f);
+    if (f == c)			return(one);
+    if (f == Cudd_Not(c))	return(zero);
+
+    /* Make canonical to increase the utilization of the cache. */
+    if (Cudd_IsComplement(f)) {
+	f = Cudd_Not(f);
+	comple = 1;
+    }
+    /* Now f is a regular pointer to a non-constant node; c is also
+    ** non-constant, but may be complemented.
+    */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c);
+    if (r != NULL) {
+	return(Cudd_NotCond(r,comple));
+    }
+
+    topf = dd->perm[f->index];
+    topc = dd->perm[Cudd_Regular(c)->index];
+
+    if (topc < topf) {	/* abstract top variable from c */
+	DdNode *d, *s1, *s2;
+
+	/* Find complements of cofactors of c. */
+	if (Cudd_IsComplement(c)) {
+	    s1 = cuddT(Cudd_Regular(c));
+	    s2 = cuddE(Cudd_Regular(c));
+	} else {
+	    s1 = Cudd_Not(cuddT(c));
+	    s2 = Cudd_Not(cuddE(c));
+	}
+	/* Take the OR by applying DeMorgan. */
+	d = cuddBddAndRecur(dd, s1, s2);
+	if (d == NULL) return(NULL);
+	d = Cudd_Not(d);
+	cuddRef(d);
+	r = cuddBddRestrictRecur(dd, f, d);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, d);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_IterDerefBdd(dd, d);
+	cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
+	cuddDeref(r);
+	return(Cudd_NotCond(r,comple));
+    }
+
+    /* Recursive step. Here topf <= topc. */
+    index = f->index;
+    Fv = cuddT(f); Fnv = cuddE(f);
+    if (topc == topf) {
+	Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
+	if (Cudd_IsComplement(c)) {
+	    Cv = Cudd_Not(Cv);
+	    Cnv = Cudd_Not(Cnv);
+	}
+    } else {
+	Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+	t = cuddBddRestrictRecur(dd, Fv, Cv);
+	if (t == NULL) return(NULL);
+    } else if (Cv == one) {
+	t = Fv;
+    } else {		/* Cv == zero: return(Fnv @ Cnv) */
+	if (Cnv == one) {
+	    r = Fnv;
+	} else {
+	    r = cuddBddRestrictRecur(dd, Fnv, Cnv);
+	    if (r == NULL) return(NULL);
+	}
+	return(Cudd_NotCond(r,comple));
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+	e = cuddBddRestrictRecur(dd, Fnv, Cnv);
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+    } else if (Cnv == one) {
+	e = Fnv;
+    } else {		/* Cnv == zero: return (Fv @ Cv) previously computed */
+	cuddDeref(t);
+	return(Cudd_NotCond(t,comple));
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+	t = Cudd_Not(t);
+	e = Cudd_Not(e);
+	r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, e);
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+	r = Cudd_Not(r);
+    } else {
+	r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, e);
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddRestrictRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive step of Cudd_bddAnd.]
+
+  Description [Implements the recursive step of Cudd_bddNPAnd.
+  Returns a pointer to the result is successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddNPAnd]
+
+******************************************************************************/
+DdNode *
+cuddBddNPAndRecur(
+  DdManager * manager,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *F, *ft, *fe, *G, *gt, *ge;
+    DdNode *one, *r, *t, *e;
+    unsigned int topf, topg, index;
+
+    statLine(manager);
+    one = DD_ONE(manager);
+
+    /* Terminal cases. */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    if (F == G) {
+	if (f == g) return(one);
+	else return(Cudd_Not(one));
+    }
+    if (G == one) {
+	if (g == one) return(f);
+	else return(g);
+    }
+    if (F == one) {
+	return(f);
+    }
+
+    /* At this point f and g are not constant. */
+    /* Check cache. */
+    if (F->ref != 1 || G->ref != 1) {
+	r = cuddCacheLookup2(manager, Cudd_bddNPAnd, f, g);
+	if (r != NULL) return(r);
+    }
+
+    /* Here we can skip the use of cuddI, because the operands are known
+    ** to be non-constant.
+    */
+    topf = manager->perm[F->index];
+    topg = manager->perm[G->index];
+
+    if (topg < topf) {	/* abstract top variable from g */
+	DdNode *d;
+
+	/* Find complements of cofactors of g. */
+	if (Cudd_IsComplement(g)) {
+	    gt = cuddT(G);
+	    ge = cuddE(G);
+	} else {
+	    gt = Cudd_Not(cuddT(g));
+	    ge = Cudd_Not(cuddE(g));
+	}
+	/* Take the OR by applying DeMorgan. */
+	d = cuddBddAndRecur(manager, gt, ge);
+	if (d == NULL) return(NULL);
+	d = Cudd_Not(d);
+	cuddRef(d);
+	r = cuddBddNPAndRecur(manager, f, d);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(manager, d);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_IterDerefBdd(manager, d);
+	cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
+	cuddDeref(r);
+	return(r);
+    }
+
+    /* Compute cofactors. */
+    index = F->index;
+    ft = cuddT(F);
+    fe = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+      ft = Cudd_Not(ft);
+      fe = Cudd_Not(fe);
+    }
+
+    if (topg == topf) {
+	gt = cuddT(G);
+	ge = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gt = Cudd_Not(gt);
+	    ge = Cudd_Not(ge);
+	}
+    } else {
+	gt = ge = g;
+    }
+
+    t = cuddBddAndRecur(manager, ft, gt);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+
+    e = cuddBddAndRecur(manager, fe, ge);
+    if (e == NULL) {
+	Cudd_IterDerefBdd(manager, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (t == e) {
+	r = t;
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(manager,(int)index,t,e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(manager, t);
+		Cudd_IterDerefBdd(manager, e);
+		return(NULL);
+	    }
+	}
+    }
+    cuddDeref(e);
+    cuddDeref(t);
+    if (F->ref != 1 || G->ref != 1)
+	cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
+    return(r);
+
+} /* end of cuddBddNPAndRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addConstrain.]
+
+  Description [Performs the recursive step of Cudd_addConstrain.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addConstrain]
+
+******************************************************************************/
+DdNode *
+cuddAddConstrainRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode       *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
+    DdNode	 *one, *zero;
+    unsigned int topf, topc;
+    int		 index;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Trivial cases. */
+    if (c == one)		return(f);
+    if (c == zero)		return(zero);
+    if (Cudd_IsConstant(f))	return(f);
+    if (f == c)			return(one);
+
+    /* Now f and c are non-constant. */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c);
+    if (r != NULL) {
+	return(r);
+    }
+    
+    /* Recursive step. */
+    topf = dd->perm[f->index];
+    topc = dd->perm[c->index];
+    if (topf <= topc) {
+	index = f->index;
+	Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+	index = c->index;
+	Fv = Fnv = f;
+    }
+    if (topc <= topf) {
+	Cv = cuddT(c); Cnv = cuddE(c);
+    } else {
+	Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+	t = cuddAddConstrainRecur(dd, Fv, Cv);
+	if (t == NULL)
+	    return(NULL);
+    } else if (Cv == one) {
+	t = Fv;
+    } else {		/* Cv == zero: return Fnv @ Cnv */
+	if (Cnv == one) {
+	    r = Fnv;
+	} else {
+	    r = cuddAddConstrainRecur(dd, Fnv, Cnv);
+	    if (r == NULL)
+		return(NULL);
+	}
+	return(r);
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+	e = cuddAddConstrainRecur(dd, Fnv, Cnv);
+	if (e == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+    } else if (Cnv == one) {
+	e = Fnv;
+    } else {		/* Cnv == zero: return Fv @ Cv previously computed */
+	cuddDeref(t);
+	return(t);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+    if (r == NULL) {
+	Cudd_RecursiveDeref(dd, e);
+	Cudd_RecursiveDeref(dd, t);
+	return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r);
+    return(r);
+
+} /* end of cuddAddConstrainRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addRestrict.]
+
+  Description [Performs the recursive step of Cudd_addRestrict.
+  Returns the restricted ADD if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addRestrict]
+
+******************************************************************************/
+DdNode *
+cuddAddRestrictRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c)
+{
+    DdNode	 *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
+    unsigned int topf, topc;
+    int		 index;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Trivial cases */
+    if (c == one)		return(f);
+    if (c == zero)		return(zero);
+    if (Cudd_IsConstant(f))	return(f);
+    if (f == c)			return(one);
+
+    /* Now f and c are non-constant. */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c);
+    if (r != NULL) {
+	return(r);
+    }
+
+    topf = dd->perm[f->index];
+    topc = dd->perm[c->index];
+
+    if (topc < topf) {	/* abstract top variable from c */
+	DdNode *d, *s1, *s2;
+
+	/* Find cofactors of c. */
+	s1 = cuddT(c);
+	s2 = cuddE(c);
+	/* Take the OR by applying DeMorgan. */
+	d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2);
+	if (d == NULL) return(NULL);
+	cuddRef(d);
+	r = cuddAddRestrictRecur(dd, f, d);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(dd, d);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_RecursiveDeref(dd, d);
+	cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
+	cuddDeref(r);
+	return(r);
+    }
+
+    /* Recursive step. Here topf <= topc. */
+    index = f->index;
+    Fv = cuddT(f); Fnv = cuddE(f);
+    if (topc == topf) {
+	Cv = cuddT(c); Cnv = cuddE(c);
+    } else {
+	Cv = Cnv = c;
+    }
+
+    if (!Cudd_IsConstant(Cv)) {
+	t = cuddAddRestrictRecur(dd, Fv, Cv);
+	if (t == NULL) return(NULL);
+    } else if (Cv == one) {
+	t = Fv;
+    } else {		/* Cv == zero: return(Fnv @ Cnv) */
+	if (Cnv == one) {
+	    r = Fnv;
+	} else {
+	    r = cuddAddRestrictRecur(dd, Fnv, Cnv);
+	    if (r == NULL) return(NULL);
+	}
+	return(r);
+    }
+    cuddRef(t);
+
+    if (!Cudd_IsConstant(Cnv)) {
+	e = cuddAddRestrictRecur(dd, Fnv, Cnv);
+	if (e == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    return(NULL);
+	}
+    } else if (Cnv == one) {
+	e = Fnv;
+    } else {		/* Cnv == zero: return (Fv @ Cv) previously computed */
+	cuddDeref(t);
+	return(t);
+    }
+    cuddRef(e);
+
+    r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+    if (r == NULL) {
+	Cudd_RecursiveDeref(dd, e);
+	Cudd_RecursiveDeref(dd, t);
+	return(NULL);
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
+    return(r);
+
+} /* end of cuddAddRestrictRecur */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs safe minimization of a BDD.]
+
+  Description [Performs safe minimization of a BDD. Given the BDD
+  <code>f</code> of a function to be minimized and a BDD
+  <code>c</code> representing the care set, Cudd_bddLICompaction
+  produces the BDD of a function that agrees with <code>f</code>
+  wherever <code>c</code> is 1.  Safe minimization means that the size
+  of the result is guaranteed not to exceed the size of
+  <code>f</code>. This function is based on the DAC97 paper by Hong et
+  al..  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+DdNode *
+cuddBddLICompaction(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be minimized */,
+  DdNode * c /* constraint (care set) */)
+{
+    st_table *marktable, *markcache, *buildcache;
+    DdNode *res, *zero;
+
+    zero = Cudd_Not(DD_ONE(dd));
+    if (c == zero) return(zero);
+
+    /* We need to use local caches for both steps of this operation.
+    ** The results of the edge marking step are only valid as long as the
+    ** edge markings themselves are available. However, the edge markings
+    ** are lost at the end of one invocation of Cudd_bddLICompaction.
+    ** Hence, the cache entries for the edge marking step must be
+    ** invalidated at the end of this function.
+    ** For the result of the building step we argue as follows. The result
+    ** for a node and a given constrain depends on the BDD in which the node
+    ** appears. Hence, the same node and constrain may give different results
+    ** in successive invocations.
+    */
+    marktable = st_init_table(st_ptrcmp,st_ptrhash);
+    if (marktable == NULL) {
+	return(NULL);
+    }
+    markcache = st_init_table(MarkCacheCompare,MarkCacheHash);
+    if (markcache == NULL) {
+	st_free_table(marktable);
+	return(NULL);
+    }
+    if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) {
+	st_foreach(markcache, MarkCacheCleanUp, NULL);
+	st_free_table(marktable);
+	st_free_table(markcache);
+	return(NULL);
+    }
+    st_foreach(markcache, MarkCacheCleanUp, NULL);
+    st_free_table(markcache);
+    buildcache = st_init_table(st_ptrcmp,st_ptrhash);
+    if (buildcache == NULL) {
+	st_free_table(marktable);
+	return(NULL);
+    }
+    res = cuddBddLICBuildResult(dd,f,buildcache,marktable);
+    st_free_table(buildcache);
+    st_free_table(marktable);
+    return(res);
+
+} /* end of cuddBddLICompaction */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddConstrainDecomp.]
+
+  Description [Performs the recursive step of Cudd_bddConstrainDecomp.
+  Returns f super (i) if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddConstrainDecomp]
+
+******************************************************************************/
+static int
+cuddBddConstrainDecomp(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** decomp)
+{
+    DdNode *F, *fv, *fvn;
+    DdNode *fAbs;
+    DdNode *result;
+    int ok;
+
+    if (Cudd_IsConstant(f)) return(1);
+    /* Compute complements of cofactors. */
+    F = Cudd_Regular(f);
+    fv = cuddT(F);
+    fvn = cuddE(F);
+    if (F == f) {
+	fv = Cudd_Not(fv);
+	fvn = Cudd_Not(fvn);
+    }
+    /* Compute abstraction of top variable. */
+    fAbs = cuddBddAndRecur(dd, fv, fvn);
+    if (fAbs == NULL) {
+	return(0);
+    }
+    cuddRef(fAbs);
+    fAbs = Cudd_Not(fAbs);
+    /* Recursively find the next abstraction and the components of the
+    ** decomposition. */
+    ok = cuddBddConstrainDecomp(dd, fAbs, decomp);
+    if (ok == 0) {
+	Cudd_IterDerefBdd(dd,fAbs);
+	return(0);
+    }
+    /* Compute the component of the decomposition corresponding to the
+    ** top variable and store it in the decomposition array. */
+    result = cuddBddConstrainRecur(dd, f, fAbs);
+    if (result == NULL) {
+	Cudd_IterDerefBdd(dd,fAbs);
+	return(0);
+    }
+    cuddRef(result);
+    decomp[F->index] = result;
+    Cudd_IterDerefBdd(dd, fAbs);
+    return(1);
+
+} /* end of cuddBddConstrainDecomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddCharToVect.]
+
+  Description [Performs the recursive step of Cudd_bddCharToVect.
+  This function maintains the invariant that f is non-zero.
+  Returns the i-th component of the vector if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddCharToVect]
+
+******************************************************************************/
+static DdNode *
+cuddBddCharToVect(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * x)
+{
+    unsigned int topf;
+    unsigned int level;
+    int comple;
+
+    DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E;
+
+    statLine(dd);
+    /* Check the cache. */
+    res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x);
+    if (res != NULL) {
+	return(res);
+    }
+
+    F = Cudd_Regular(f);
+
+    topf = cuddI(dd,F->index);
+    level = dd->perm[x->index];
+
+    if (topf > level) return(x);
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    comple = F != f;
+    fT = Cudd_NotCond(cuddT(F),comple);
+    fE = Cudd_NotCond(cuddE(F),comple);
+
+    if (topf == level) {
+	if (fT == zero) return(zero);
+	if (fE == zero) return(one);
+	return(x);
+    }
+
+    /* Here topf < level. */
+    if (fT == zero) return(cuddBddCharToVect(dd, fE, x));
+    if (fE == zero) return(cuddBddCharToVect(dd, fT, x));
+
+    T = cuddBddCharToVect(dd, fT, x);
+    if (T == NULL) {
+	return(NULL);
+    }
+    cuddRef(T);
+    E = cuddBddCharToVect(dd, fE, x);
+    if (E == NULL) {
+	Cudd_IterDerefBdd(dd,T);
+	return(NULL);
+    }
+    cuddRef(E);
+    res = cuddBddIteRecur(dd, dd->vars[F->index], T, E);
+    if (res == NULL) {
+	Cudd_IterDerefBdd(dd,T);
+	Cudd_IterDerefBdd(dd,E);
+	return(NULL);
+    }
+    cuddDeref(T);
+    cuddDeref(E);
+    cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res);
+    return(res);
+
+} /* end of cuddBddCharToVect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the edge marking step of Cudd_bddLICompaction.]
+
+  Description [Performs the edge marking step of Cudd_bddLICompaction.
+  Returns the LUB of the markings of the two outgoing edges of <code>f</code>
+  if successful; otherwise CUDD_OUT_OF_MEM.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction cuddBddLICBuildResult]
+
+******************************************************************************/
+static int
+cuddBddLICMarkEdges(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * c,
+  st_table * table,
+  st_table * cache)
+{
+    DdNode *Fv, *Fnv, *Cv, *Cnv;
+    DdNode *one, *zero;
+    unsigned int topf, topc;
+    int comple;
+    int resT, resE, res, retval;
+    char **slot;
+    MarkCacheKey *key;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Terminal cases. */
+    if (c == zero) return(DD_LIC_DC);
+    if (f == one)  return(DD_LIC_1);
+    if (f == zero) return(DD_LIC_0);
+
+    /* Make canonical to increase the utilization of the cache. */
+    comple = Cudd_IsComplement(f);
+    f = Cudd_Regular(f);
+    /* Now f is a regular pointer to a non-constant node; c may be
+    ** constant, or it may be complemented.
+    */
+
+    /* Check the cache. */
+    key = ALLOC(MarkCacheKey, 1);
+    if (key == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(CUDD_OUT_OF_MEM);
+    }
+    key->f = f; key->c = c;
+    if (st_lookup_int(cache, (char *)key, &res)) {
+	FREE(key);
+	if (comple) {
+	    if (res == DD_LIC_0) res = DD_LIC_1;
+	    else if (res == DD_LIC_1) res = DD_LIC_0;
+	}
+	return(res);
+    }
+
+    /* Recursive step. */
+    topf = dd->perm[f->index];
+    topc = cuddI(dd,Cudd_Regular(c)->index);
+    if (topf <= topc) {
+	Fv = cuddT(f); Fnv = cuddE(f);
+    } else {
+	Fv = Fnv = f;
+    }
+    if (topc <= topf) {
+	/* We know that c is not constant because f is not. */
+	Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
+	if (Cudd_IsComplement(c)) {
+	    Cv = Cudd_Not(Cv);
+	    Cnv = Cudd_Not(Cnv);
+	}
+    } else {
+	Cv = Cnv = c;
+    }
+
+    resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache);
+    if (resT == CUDD_OUT_OF_MEM) {
+	FREE(key);
+	return(CUDD_OUT_OF_MEM);
+    }
+    resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache);
+    if (resE == CUDD_OUT_OF_MEM) {
+	FREE(key);
+	return(CUDD_OUT_OF_MEM);
+    }
+
+    /* Update edge markings. */
+    if (topf <= topc) {
+	retval = st_find_or_add(table, (char *)f, (char ***)&slot);
+	if (retval == 0) {
+	    *slot = (char *) (ptrint)((resT << 2) | resE);
+	} else if (retval == 1) {
+	    *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE);
+	} else {
+	    FREE(key);
+	    return(CUDD_OUT_OF_MEM);
+	}
+    }
+
+    /* Cache result. */
+    res = resT | resE;
+    if (st_insert(cache, (char *)key, (char *)(ptrint)res) == ST_OUT_OF_MEM) {
+	FREE(key);
+	return(CUDD_OUT_OF_MEM);
+    }
+
+    /* Take into account possible complementation. */
+    if (comple) {
+	if (res == DD_LIC_0) res = DD_LIC_1;
+	else if (res == DD_LIC_1) res = DD_LIC_0;
+    }
+    return(res);
+
+} /* end of cuddBddLICMarkEdges */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the result of Cudd_bddLICompaction.]
+
+  Description [Builds the results of Cudd_bddLICompaction.
+  Returns a pointer to the minimized BDD if successful; otherwise NULL.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction cuddBddLICMarkEdges]
+
+******************************************************************************/
+static DdNode *
+cuddBddLICBuildResult(
+  DdManager * dd,
+  DdNode * f,
+  st_table * cache,
+  st_table * table)
+{
+    DdNode *Fv, *Fnv, *r, *t, *e;
+    DdNode *one, *zero;
+    int	index;
+    int comple;
+    int markT, markE, markings;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    if (Cudd_IsConstant(f)) return(f);
+    /* Make canonical to increase the utilization of the cache. */
+    comple = Cudd_IsComplement(f);
+    f = Cudd_Regular(f);
+
+    /* Check the cache. */
+    if (st_lookup(cache, f, &r)) {
+	return(Cudd_NotCond(r,comple));
+    }
+
+    /* Retrieve the edge markings. */
+    if (st_lookup_int(table, (char *)f, &markings) == 0)
+	return(NULL);
+    markT = markings >> 2;
+    markE = markings & 3;
+
+    index = f->index;
+    Fv = cuddT(f); Fnv = cuddE(f);
+
+    if (markT == DD_LIC_NL) {
+	t = cuddBddLICBuildResult(dd,Fv,cache,table);
+	if (t == NULL) {
+	    return(NULL);
+	}
+    } else if (markT == DD_LIC_1) {
+	t = one;
+    } else {
+	t = zero;
+    }
+    cuddRef(t);
+    if (markE == DD_LIC_NL) {
+	e = cuddBddLICBuildResult(dd,Fnv,cache,table);
+	if (e == NULL) {
+	    Cudd_IterDerefBdd(dd,t);
+	    return(NULL);
+	}
+    } else if (markE == DD_LIC_1) {
+	e = one;
+    } else {
+	e = zero;
+    }
+    cuddRef(e);
+
+    if (markT == DD_LIC_DC && markE != DD_LIC_DC) {
+	r = e;
+    } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) {
+	r = t;
+    } else {
+	if (Cudd_IsComplement(t)) {
+	    t = Cudd_Not(t);
+	    e = Cudd_Not(e);
+	    r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(dd, e);
+		Cudd_IterDerefBdd(dd, t);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(dd, e);
+		Cudd_IterDerefBdd(dd, t);
+		return(NULL);
+	    }
+	}
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+    if (st_insert(cache, (char *)f, (char *)r) == ST_OUT_OF_MEM) {
+	cuddRef(r);
+	Cudd_IterDerefBdd(dd,r);
+	return(NULL);
+    }
+
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddLICBuildResult */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hash function for the computed table of cuddBddLICMarkEdges.]
+
+  Description [Hash function for the computed table of
+  cuddBddLICMarkEdges.  Returns the bucket number.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+static int
+MarkCacheHash(
+  char * ptr,
+  int  modulus)
+{
+    int val = 0;
+    MarkCacheKey *entry;
+
+    entry = (MarkCacheKey *) ptr;
+
+    val = (int) (ptrint) entry->f;
+    val = val * 997 + (int) (ptrint) entry->c;
+
+    return ((val < 0) ? -val : val) % modulus;
+
+} /* end of MarkCacheHash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function for the computed table of
+  cuddBddLICMarkEdges.]
+
+  Description [Comparison function for the computed table of
+  cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+static int
+MarkCacheCompare(
+  const char * ptr1,
+  const char * ptr2)
+{
+    MarkCacheKey *entry1, *entry2;
+
+    entry1 = (MarkCacheKey *) ptr1;
+    entry2 = (MarkCacheKey *) ptr2;
+    
+    return((entry1->f != entry2->f) || (entry1->c != entry2->c));
+
+} /* end of MarkCacheCompare */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees memory associated with computed table of
+  cuddBddLICMarkEdges.]
+
+  Description [Frees memory associated with computed table of
+  cuddBddLICMarkEdges. Returns ST_CONTINUE.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLICompaction]
+
+******************************************************************************/
+static enum st_retval
+MarkCacheCleanUp(
+  char * key,
+  char * value,
+  char * arg)
+{
+    MarkCacheKey *entry;
+
+    entry = (MarkCacheKey *) key;
+    FREE(entry);
+    return ST_CONTINUE;
+
+} /* end of MarkCacheCleanUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddSqueeze.]
+
+  Description [Performs the recursive step of Cudd_bddSqueeze.  This
+  procedure exploits the fact that if we complement and swap the
+  bounds of the interval we obtain a valid solution by taking the
+  complement of the solution to the original problem. Therefore, we
+  can enforce the condition that the upper bound is always regular.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddSqueeze]
+
+******************************************************************************/
+static DdNode *
+cuddBddSqueeze(
+  DdManager * dd,
+  DdNode * l,
+  DdNode * u)
+{
+    DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e;
+#if 0
+    DdNode *ar;
+#endif
+    int comple = 0;
+    unsigned int topu, topl;
+    int index;
+
+    statLine(dd);
+    if (l == u) {
+	return(l);
+    }
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+    /* The only case when l == zero && u == one is at the top level,
+    ** where returning either one or zero is OK. In all other cases
+    ** the procedure will detect such a case and will perform
+    ** remapping. Therefore the order in which we test l and u at this
+    ** point is immaterial. */
+    if (l == zero) return(l);
+    if (u == one)  return(u);
+
+    /* Make canonical to increase the utilization of the cache. */
+    if (Cudd_IsComplement(u)) {
+	DdNode *temp;
+	temp = Cudd_Not(l);
+	l = Cudd_Not(u);
+	u = temp;
+	comple = 1;
+    }
+    /* At this point u is regular and non-constant; l is non-constant, but
+    ** may be complemented. */
+
+    /* Here we could check the relative sizes. */
+
+    /* Check the cache. */
+    r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u);
+    if (r != NULL) {
+	return(Cudd_NotCond(r,comple));
+    }
+
+    /* Recursive step. */
+    topu = dd->perm[u->index];
+    topl = dd->perm[Cudd_Regular(l)->index];
+    if (topu <= topl) {
+	index = u->index;
+	ut = cuddT(u); ue = cuddE(u);
+    } else {
+	index = Cudd_Regular(l)->index;
+	ut = ue = u;
+    }
+    if (topl <= topu) {
+	lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l));
+	if (Cudd_IsComplement(l)) {
+	    lt = Cudd_Not(lt);
+	    le = Cudd_Not(le);
+	}
+    } else {
+	lt = le = l;
+    }
+
+    /* If one interval is contained in the other, use the smaller
+    ** interval. This corresponds to one-sided matching. */
+    if ((lt == zero || Cudd_bddLeq(dd,lt,le)) &&
+	(ut == one  || Cudd_bddLeq(dd,ue,ut))) { /* remap */
+	r = cuddBddSqueeze(dd, le, ue);
+	if (r == NULL)
+	    return(NULL);
+	return(Cudd_NotCond(r,comple));
+    } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) &&
+	       (ue == one  || Cudd_bddLeq(dd,ut,ue))) { /* remap */
+	r = cuddBddSqueeze(dd, lt, ut);
+	if (r == NULL)
+	    return(NULL);
+	return(Cudd_NotCond(r,comple));
+    } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) &&
+	       (ue == one  || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */
+	t = cuddBddSqueeze(dd, lt, ut);
+	cuddRef(t);
+	if (Cudd_IsComplement(t)) {
+	    r = cuddUniqueInter(dd, index, Cudd_Not(t), t);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(dd, t);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	} else {
+	    r = cuddUniqueInter(dd, index, t, Cudd_Not(t));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(dd, t);
+		return(NULL);
+	    }
+	}
+	cuddDeref(t);
+	if (r == NULL)
+	    return(NULL);
+	cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
+	return(Cudd_NotCond(r,comple));
+    } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) &&
+	       (ut == one  || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */
+	e = cuddBddSqueeze(dd, le, ue);
+	cuddRef(e);
+	if (Cudd_IsComplement(e)) {
+	    r = cuddUniqueInter(dd, index, Cudd_Not(e), e);
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(dd, e);
+		return(NULL);
+	    }
+	} else {
+	    r = cuddUniqueInter(dd, index, e, Cudd_Not(e));
+	    if (r == NULL) {
+		Cudd_IterDerefBdd(dd, e);
+		return(NULL);
+	    }
+	    r = Cudd_Not(r);
+	}
+	cuddDeref(e);
+	if (r == NULL)
+	    return(NULL);
+	cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
+	return(Cudd_NotCond(r,comple));
+    }
+
+#if 0
+    /* If the two intervals intersect, take a solution from
+    ** the intersection of the intervals. This guarantees that the
+    ** splitting variable will not appear in the result.
+    ** This approach corresponds to two-sided matching, and is very
+    ** expensive. */
+    if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) {
+	DdNode *au, *al;
+	au = cuddBddAndRecur(dd,ut,ue);
+	if (au == NULL)
+	    return(NULL);
+	cuddRef(au);
+	al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le));
+	if (al == NULL) {
+	    Cudd_IterDerefBdd(dd,au);
+	    return(NULL);
+	}
+	cuddRef(al);
+	al = Cudd_Not(al);
+	ar = cuddBddSqueeze(dd, al, au);
+	if (ar == NULL) {
+	    Cudd_IterDerefBdd(dd,au);
+	    Cudd_IterDerefBdd(dd,al);
+	    return(NULL);
+	}
+	cuddRef(ar);
+	Cudd_IterDerefBdd(dd,au);
+	Cudd_IterDerefBdd(dd,al);
+    } else {
+	ar = NULL;
+    }
+#endif
+
+    t = cuddBddSqueeze(dd, lt, ut);
+    if (t == NULL) {
+	return(NULL);
+    }
+    cuddRef(t);
+    e = cuddBddSqueeze(dd, le, ue);
+    if (e == NULL) {
+	Cudd_IterDerefBdd(dd,t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    if (Cudd_IsComplement(t)) {
+	t = Cudd_Not(t);
+	e = Cudd_Not(e);
+	r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, e);
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+	r = Cudd_Not(r);
+    } else {
+	r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
+	if (r == NULL) {
+	    Cudd_IterDerefBdd(dd, e);
+	    Cudd_IterDerefBdd(dd, t);
+	    return(NULL);
+	}
+    }
+    cuddDeref(t);
+    cuddDeref(e);
+
+#if 0
+    /* Check whether there is a result obtained by abstraction and whether
+    ** it is better than the one obtained by recursion. */
+    cuddRef(r);
+    if (ar != NULL) {
+	if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) {
+	    Cudd_IterDerefBdd(dd, r);
+	    r = ar;
+	} else {
+	    Cudd_IterDerefBdd(dd, ar);
+	}
+    }
+    cuddDeref(r);
+#endif
+
+    cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
+    return(Cudd_NotCond(r,comple));
+
+} /* end of cuddBddSqueeze */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddGenetic.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddGenetic.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddGenetic.c	(revision 8)
@@ -0,0 +1,957 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddGenetic.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Genetic algorithm for variable reordering.]
+
+  Description [Internal procedures included in this file:
+		<ul>
+		<li> cuddGa()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> make_random()
+		<li> sift_up()
+		<li> build_dd()
+		<li> largest()
+		<li> rand_int()
+		<li> array_hash()
+		<li> array_compare()
+		<li> find_best()
+		<li> find_average_fitness()
+		<li> PMX()
+		<li> roulette()
+		</ul>
+
+  The genetic algorithm implemented here is as follows.  We start with
+  the current DD order.  We sift this order and use this as the
+  reference DD.  We only keep 1 DD around for the entire process and
+  simply rearrange the order of this DD, storing the various orders
+  and their corresponding DD sizes.  We generate more random orders to
+  build an initial population. This initial population is 3 times the
+  number of variables, with a maximum of 120. Each random order is
+  built (from the reference DD) and its size stored.  Each random
+  order is also sifted to keep the DD sizes fairly small.  Then a
+  crossover is performed between two orders (picked randomly) and the
+  two resulting DDs are built and sifted.  For each new order, if its
+  size is smaller than any DD in the population, it is inserted into
+  the population and the DD with the largest number of nodes is thrown
+  out. The crossover process happens up to 50 times, and at this point
+  the DD in the population with the smallest size is chosen as the
+  result.  This DD must then be built from the reference DD.]
+
+  SeeAlso     []
+
+  Author      [Curt Musfeldt, Alan Shuler, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.28 2004/08/13 18:04:48 fabio Exp $";
+#endif
+
+static int popsize;		/* the size of the population */
+static int numvars;		/* the number of input variables in the ckt. */
+/* storedd stores the population orders and sizes. This table has two
+** extra rows and one extras column. The two extra rows are used for the
+** offspring produced by a crossover. Each row stores one order and its
+** size. The order is stored by storing the indices of variables in the
+** order in which they appear in the order. The table is in reality a
+** one-dimensional array which is accessed via a macro to give the illusion
+** it is a two-dimensional structure.
+*/
+static int *storedd;
+static st_table *computed;	/* hash table to identify existing orders */
+static int *repeat;		/* how many times an order is present */
+static int large;		/* stores the index of the population with
+				** the largest number of nodes in the DD */
+static int result;
+static int cross;		/* the number of crossovers to perform */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/* macro used to access the population table as if it were a
+** two-dimensional structure.
+*/
+#define STOREDD(i,j)	storedd[(i)*(numvars+1)+(j)]
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int make_random (DdManager *table, int lower);
+static int sift_up (DdManager *table, int x, int x_low);
+static int build_dd (DdManager *table, int num, int lower, int upper);
+static int largest (void);
+static int rand_int (int a);
+static int array_hash (char *array, int modulus);
+static int array_compare (const char *array1, const char *array2);
+static int find_best (void);
+#ifdef DD_STATS
+static double find_average_fitness (void);
+#endif
+static int PMX (int maxvar);
+static int roulette (int *p1, int *p2);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Genetic algorithm for DD reordering.]
+
+  Description [Genetic algorithm for DD reordering.
+  The two children of a crossover will be stored in
+  storedd[popsize] and storedd[popsize+1] --- the last two slots in the
+  storedd array.  (This will make comparisons and replacement easy.)
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddGa(
+  DdManager * table /* manager */,
+  int  lower /* lowest level to be reordered */,
+  int  upper /* highest level to be reorderded */)
+{
+    int 	i,n,m;		/* dummy/loop vars */
+    int		index;
+#ifdef DD_STATS
+    double	average_fitness;
+#endif
+    int		small;		/* index of smallest DD in population */
+
+    /* Do an initial sifting to produce at least one reasonable individual. */
+    if (!cuddSifting(table,lower,upper)) return(0);
+
+    /* Get the initial values. */
+    numvars = upper - lower + 1; /* number of variables to be reordered */
+    if (table->populationSize == 0) {
+	popsize = 3 * numvars;  /* population size is 3 times # of vars */
+	if (popsize > 120) {
+	    popsize = 120;	/* Maximum population size is 120 */
+	}
+    } else {
+	popsize = table->populationSize;  /* user specified value */
+    }
+    if (popsize < 4) popsize = 4;	/* enforce minimum population size */
+
+    /* Allocate population table. */
+    storedd = ALLOC(int,(popsize+2)*(numvars+1));
+    if (storedd == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+
+    /* Initialize the computed table. This table is made up of two data
+    ** structures: A hash table with the key given by the order, which says
+    ** if a given order is present in the population; and the repeat
+    ** vector, which says how many copies of a given order are stored in
+    ** the population table. If there are multiple copies of an order, only
+    ** one has a repeat count greater than 1. This copy is the one pointed
+    ** by the computed table.
+    */
+    repeat = ALLOC(int,popsize);
+    if (repeat == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	FREE(storedd);
+	return(0);
+    }
+    for (i = 0; i < popsize; i++) {
+	repeat[i] = 0;
+    }
+    computed = st_init_table(array_compare,array_hash);
+    if (computed == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	FREE(storedd);
+	FREE(repeat);
+	return(0);
+    }
+
+    /* Copy the current DD and its size to the population table. */
+    for (i = 0; i < numvars; i++) {
+	STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */
+    }
+    STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */
+
+    /* Store the initial order in the computed table. */
+    if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) {
+	FREE(storedd);
+	FREE(repeat);
+	st_free_table(computed);
+	return(0);
+    }
+    repeat[0]++;
+
+    /* Insert the reverse order as second element of the population. */
+    for (i = 0; i < numvars; i++) {
+	STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */
+    }
+
+    /* Now create the random orders. make_random fills the population
+    ** table with random permutations. The successive loop builds and sifts
+    ** the DDs for the reverse order and each random permutation, and stores
+    ** the results in the computed table.
+    */
+    if (!make_random(table,lower)) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	FREE(storedd);
+	FREE(repeat);
+	st_free_table(computed);
+	return(0);
+    }
+    for (i = 1; i < popsize; i++) {
+	result = build_dd(table,i,lower,upper);	/* build and sift order */
+	if (!result) {
+	    FREE(storedd);
+	    FREE(repeat);
+	    st_free_table(computed);
+	    return(0);
+	}
+	if (st_lookup_int(computed,(char *)&STOREDD(i,0),&index)) {
+	    repeat[index]++;
+	} else {
+	    if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) ==
+	    ST_OUT_OF_MEM) {
+		FREE(storedd);
+		FREE(repeat);
+		st_free_table(computed);
+		return(0);
+	    }
+	    repeat[i]++;
+	}
+    }
+
+#if 0
+#ifdef DD_STATS
+    /* Print the initial population. */
+    (void) fprintf(table->out,"Initial population after sifting\n");
+    for (m = 0; m < popsize; m++) {
+	for (i = 0; i < numvars; i++) {
+	    (void) fprintf(table->out," %2d",STOREDD(m,i));
+	}
+	(void) fprintf(table->out," : %3d (%d)\n",
+		       STOREDD(m,numvars),repeat[m]);
+    }
+#endif
+#endif
+
+    small = find_best();
+#ifdef DD_STATS
+    average_fitness = find_average_fitness();
+    (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
+#endif
+
+    /* Decide how many crossovers should be tried. */
+    if (table->numberXovers == 0) {
+	cross = 3*numvars;
+	if (cross > 60) {	/* do a maximum of 50 crossovers */
+	    cross = 60;
+	}
+    } else {
+	cross = table->numberXovers;      /* use user specified value */
+    }
+
+    /* Perform the crossovers to get the best order. */
+    for (m = 0; m < cross; m++) {
+	if (!PMX(table->size)) {	/* perform one crossover */
+	    table->errorCode = CUDD_MEMORY_OUT;
+	    FREE(storedd);
+	    FREE(repeat);
+	    st_free_table(computed);
+	    return(0);
+	}
+	/* The offsprings are left in the last two entries of the
+	** population table. These are now considered in turn.
+	*/
+	for (i = popsize; i <= popsize+1; i++) {
+	    result = build_dd(table,i,lower,upper); /* build and sift child */
+	    if (!result) {
+		FREE(storedd);
+		FREE(repeat);
+		st_free_table(computed);
+		return(0);
+	    }
+	    large = largest();	/* find the largest DD in population */
+
+	    /* If the new child is smaller than the largest DD in the current
+	    ** population, enter it into the population in place of the
+	    ** largest DD.
+	    */
+	    if (STOREDD(i,numvars) < STOREDD(large,numvars)) {
+		/* Look up the largest DD in the computed table.
+		** Decrease its repetition count. If the repetition count
+		** goes to 0, remove the largest DD from the computed table.
+		*/
+		result = st_lookup_int(computed,(char *)&STOREDD(large,0),
+				       &index);
+		if (!result) {
+		    FREE(storedd);
+		    FREE(repeat);
+		    st_free_table(computed);
+		    return(0);
+		}
+		repeat[index]--;
+		if (repeat[index] == 0) {
+		    int *pointer = &STOREDD(index,0);
+		    result = st_delete(computed, &pointer, NULL);
+		    if (!result) {
+			FREE(storedd);
+			FREE(repeat);
+			st_free_table(computed);
+			return(0);
+		    }
+		}
+		/* Copy the new individual to the entry of the
+		** population table just made available and update the
+		** computed table.
+		*/
+		for (n = 0; n <= numvars; n++) {
+		    STOREDD(large,n) = STOREDD(i,n);
+		}
+		if (st_lookup_int(computed,(char *)&STOREDD(large,0),
+				  &index)) {
+		    repeat[index]++;
+		} else {
+		    if (st_insert(computed,(char *)&STOREDD(large,0),
+		    (char *)(long)large) == ST_OUT_OF_MEM) {
+			FREE(storedd);
+			FREE(repeat);
+			st_free_table(computed);
+			return(0);
+		    }
+		    repeat[large]++;
+		}
+	    }
+	}
+    }
+
+    /* Find the smallest DD in the population and build it;
+    ** that will be the result.
+    */
+    small = find_best();
+
+    /* Print stats on the final population. */
+#ifdef DD_STATS
+    average_fitness = find_average_fitness();
+    (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
+#endif
+
+    /* Clean up, build the result DD, and return. */
+    st_free_table(computed);
+    computed = NULL;
+    result = build_dd(table,small,lower,upper);
+    FREE(storedd);
+    FREE(repeat);
+    return(result);
+
+} /* end of cuddGa */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the random sequences for the initial population.]
+
+  Description [Generates the random sequences for the initial population.
+  The sequences are permutations of the indices between lower and
+  upper in the current order.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+make_random(
+  DdManager * table,
+  int  lower)
+{
+    int i,j;		/* loop variables */
+    int	*used;		/* is a number already in a permutation */
+    int	next;		/* next random number without repetitions */
+
+    used = ALLOC(int,numvars);
+    if (used == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+#if 0
+#ifdef DD_STATS
+    (void) fprintf(table->out,"Initial population before sifting\n");
+    for (i = 0; i < 2; i++) {
+	for (j = 0; j < numvars; j++) {
+	    (void) fprintf(table->out," %2d",STOREDD(i,j));
+	}
+	(void) fprintf(table->out,"\n");
+    }
+#endif
+#endif
+    for (i = 2; i < popsize; i++) {
+       	for (j = 0; j < numvars; j++) {
+	    used[j] = 0;
+	}
+	/* Generate a permutation of {0...numvars-1} and use it to
+	** permute the variables in the layesr from lower to upper.
+	*/
+       	for (j = 0; j < numvars; j++) {
+	    do {
+		next = rand_int(numvars-1);
+	    } while (used[next] != 0);
+	    used[next] = 1;
+	    STOREDD(i,j) = table->invperm[next+lower];
+       	}
+#if 0
+#ifdef DD_STATS
+	/* Print the order just generated. */
+	for (j = 0; j < numvars; j++) {
+	    (void) fprintf(table->out," %2d",STOREDD(i,j));
+	}
+	(void) fprintf(table->out,"\n");
+#endif
+#endif
+    }
+    FREE(used);
+    return(1);
+
+} /* end of make_random */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one variable up.]
+
+  Description [Takes a variable from position x and sifts it up to
+  position x_low;  x_low should be less than x. Returns 1 if successful;
+  0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+sift_up(
+  DdManager * table,
+  int  x,
+  int  x_low)
+{
+    int        y;
+    int        size;
+
+    y = cuddNextLow(table,x);
+    while (y >= x_low) {
+	size = cuddSwapInPlace(table,y,x);
+	if (size == 0) {
+	    return(0);
+	}
+	x = y;
+	y = cuddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of sift_up */
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds a DD from a given order.]
+
+  Description [Builds a DD from a given order.  This procedure also
+  sifts the final order and inserts into the array the size in nodes
+  of the result. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+build_dd(
+  DdManager * table,
+  int  num /* the index of the individual to be built */,
+  int  lower,
+  int  upper)
+{
+    int 	i,j;		/* loop vars */
+    int 	position;
+    int		index;
+    int		limit;		/* how large the DD for this order can grow */
+    int		size;
+
+    /* Check the computed table. If the order already exists, it
+    ** suffices to copy the size from the existing entry.
+    */
+    if (computed && st_lookup_int(computed,(char *)&STOREDD(num,0),&index)) {
+	STOREDD(num,numvars) = STOREDD(index,numvars);
+#ifdef DD_STATS
+	(void) fprintf(table->out,"\nCache hit for index %d", index);
+#endif
+	return(1);
+    }
+
+    /* Stop if the DD grows 20 times larges than the reference size. */
+    limit = 20 * STOREDD(0,numvars);
+
+    /* Sift up the variables so as to build the desired permutation.
+    ** First the variable that has to be on top is sifted to the top.
+    ** Then the variable that has to occupy the secon position is sifted
+    ** up to the second position, and so on.
+    */
+    for (j = 0; j < numvars; j++) {
+	i = STOREDD(num,j);
+	position = table->perm[i];
+	result = sift_up(table,position,j+lower);
+	if (!result) return(0);
+	size = table->keys - table->isolated;
+	if (size > limit) break;
+    }
+
+    /* Sift the DD just built. */
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+#endif
+    result = cuddSifting(table,lower,upper);
+    if (!result) return(0);
+
+    /* Copy order and size to table. */
+    for (j = 0; j < numvars; j++) {
+	STOREDD(num,j) = table->invperm[lower+j];
+    }
+    STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */
+    return(1);
+
+} /* end of build_dd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the largest DD in the population.]
+
+  Description [Finds the largest DD in the population. If an order is
+  repeated, it avoids choosing the copy that is in the computed table
+  (it has repeat[i] > 1).]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+largest(void)
+{
+    int i;	/* loop var */
+    int big;	/* temporary holder to return result */
+
+    big = 0;
+    while (repeat[big] > 1) big++;
+    for (i = big + 1; i < popsize; i++) {
+	if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) {
+	    big = i;
+	}
+    }
+    return(big);
+
+} /* end of largest */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a random number between 0 and the integer a.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+rand_int(
+  int  a)
+{
+    return(Cudd_Random() % (a+1));
+
+} /* end of rand_int */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hash function for the computed table.]
+
+  Description [Hash function for the computed table. Returns the bucket
+  number.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+array_hash(
+  char * array,
+  int  modulus)
+{
+    int val = 0;
+    int i;
+    int *intarray;
+
+    intarray = (int *) array;
+
+    for (i = 0; i < numvars; i++) {
+	val = val * 997 + intarray[i];
+    }
+
+    return ((val < 0) ? -val : val) % modulus;
+
+} /* end of array_hash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function for the computed table.]
+
+  Description [Comparison function for the computed table. Returns 0 if
+  the two arrays are equal; 1 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+array_compare(
+  const char * array1,
+  const char * array2)
+{
+    int i;
+    int *intarray1, *intarray2;
+
+    intarray1 = (int *) array1;
+    intarray2 = (int *) array2;
+
+    for (i = 0; i < numvars; i++) {
+	if (intarray1[i] != intarray2[i]) return(1);
+    }
+    return(0);
+
+} /* end of array_compare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the fittest individual.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+find_best(void)
+{
+    int i,small;
+
+    small = 0;
+    for (i = 1; i < popsize; i++) {
+	if (STOREDD(i,numvars) < STOREDD(small,numvars)) {
+	    small = i;
+	}
+    }
+    return(small);
+
+} /* end of find_best */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the average fitness of the population.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef DD_STATS
+static double
+find_average_fitness(void)
+{
+    int i;
+    int total_fitness = 0;
+    double average_fitness;
+
+    for (i = 0; i < popsize; i++) {
+	total_fitness += STOREDD(i,numvars);
+    }
+    average_fitness = (double) total_fitness / (double) popsize;
+    return(average_fitness);
+
+} /* end of find_average_fitness */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the crossover between two parents.]
+
+  Description [Performs the crossover between two randomly chosen
+  parents, and creates two children, x1 and x2. Uses the Partially
+  Matched Crossover operator.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+PMX(
+  int  maxvar)
+{
+    int 	cut1,cut2;	/* the two cut positions (random) */
+    int 	mom,dad;	/* the two randomly chosen parents */
+    int		*inv1;		/* inverse permutations for repair algo */
+    int		*inv2;
+    int 	i;		/* loop vars */
+    int		u,v;		/* aux vars */
+
+    inv1 = ALLOC(int,maxvar);
+    if (inv1 == NULL) {
+	return(0);
+    }
+    inv2 = ALLOC(int,maxvar);
+    if (inv2 == NULL) {
+	FREE(inv1);
+	return(0);
+    }
+
+    /* Choose two orders from the population using roulette wheel. */
+    if (!roulette(&mom,&dad)) {
+	FREE(inv1);
+	FREE(inv2);
+	return(0);
+    }
+
+    /* Choose two random cut positions. A cut in position i means that
+    ** the cut immediately precedes position i.  If cut1 < cut2, we
+    ** exchange the middle of the two orderings; otherwise, we
+    ** exchange the beginnings and the ends.
+    */
+    cut1 = rand_int(numvars-1);
+    do {
+	cut2 = rand_int(numvars-1);
+    } while (cut1 == cut2);
+
+#if 0
+    /* Print out the parents. */
+    (void) fprintf(table->out,
+		   "Crossover of %d (mom) and %d (dad) between %d and %d\n",
+		   mom,dad,cut1,cut2);
+    for (i = 0; i < numvars; i++) {
+	if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+	(void) fprintf(table->out,"%2d ",STOREDD(mom,i));
+    }
+    (void) fprintf(table->out,"\n");
+    for (i = 0; i < numvars; i++) {
+	if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+	(void) fprintf(table->out,"%2d ",STOREDD(dad,i));
+    }
+    (void) fprintf(table->out,"\n");
+#endif
+
+    /* Initialize the inverse permutations: -1 means yet undetermined. */
+    for (i = 0; i < maxvar; i++) {
+	inv1[i] = -1;
+	inv2[i] = -1;
+    }
+
+    /* Copy the portions whithin the cuts. */
+    for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) {
+	STOREDD(popsize,i) = STOREDD(dad,i);
+	inv1[STOREDD(popsize,i)] = i;
+	STOREDD(popsize+1,i) = STOREDD(mom,i);
+	inv2[STOREDD(popsize+1,i)] = i;
+    }
+
+    /* Now apply the repair algorithm outside the cuts. */
+    for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) {
+	v = i;
+	do {
+	    u = STOREDD(mom,v);
+	    v = inv1[u];
+	} while (v != -1);
+	STOREDD(popsize,i) = u;
+	inv1[u] = i;
+	v = i;
+	do {
+	    u = STOREDD(dad,v);
+	    v = inv2[u];
+	} while (v != -1);
+	STOREDD(popsize+1,i) = u;
+	inv2[u] = i;
+    }
+
+#if 0
+    /* Print the results of crossover. */
+    for (i = 0; i < numvars; i++) {
+	if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+	(void) fprintf(table->out,"%2d ",STOREDD(popsize,i));
+    }
+    (void) fprintf(table->out,"\n");
+    for (i = 0; i < numvars; i++) {
+	if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
+	(void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i));
+    }
+    (void) fprintf(table->out,"\n");
+#endif
+
+    FREE(inv1);
+    FREE(inv2);
+    return(1);
+
+} /* end of PMX */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Selects two parents with the roulette wheel method.]
+
+  Description [Selects two distinct parents with the roulette wheel method.]
+
+  SideEffects [The indices of the selected parents are returned as side
+  effects.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+roulette(
+  int * p1,
+  int * p2)
+{
+    double *wheel;
+    double spin;
+    int i;
+
+    wheel = ALLOC(double,popsize);
+    if (wheel == NULL) {
+	return(0);
+    }
+
+    /* The fitness of an individual is the reciprocal of its size. */
+    wheel[0] = 1.0 / (double) STOREDD(0,numvars);
+
+    for (i = 1; i < popsize; i++) {
+	wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars);
+    }
+
+    /* Get a random number between 0 and wheel[popsize-1] (that is,
+    ** the sum of all fitness values. 2147483561 is the largest number
+    ** returned by Cudd_Random.
+    */
+    spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0;
+
+    /* Find the lucky element by scanning the wheel. */
+    for (i = 0; i < popsize; i++) {
+	if (spin <= wheel[i]) break;
+    }
+    *p1 = i;
+
+    /* Repeat the process for the second parent, making sure it is
+    ** distinct from the first.
+    */
+    do {
+	spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0;
+	for (i = 0; i < popsize; i++) {
+	    if (spin <= wheel[i]) break;
+	}
+    } while (i == *p1);
+    *p2 = i;
+
+    FREE(wheel);
+    return(1);
+
+} /* end of roulette */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddGroup.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddGroup.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddGroup.c	(revision 8)
@@ -0,0 +1,2177 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddGroup.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for group sifting.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_MakeTreeNode()
+		</ul>
+	Internal procedures included in this file:
+		<ul>
+		<li> cuddTreeSifting()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddTreeSiftingAux()
+		<li> ddCountInternalMtrNodes()
+		<li> ddReorderChildren()
+		<li> ddFindNodeHiLo()
+		<li> ddUniqueCompareGroup()
+		<li> ddGroupSifting()
+		<li> ddCreateGroup()
+		<li> ddGroupSiftingAux()
+		<li> ddGroupSiftingUp()
+		<li> ddGroupSiftingDown()
+		<li> ddGroupMove()
+		<li> ddGroupMoveBackward()
+		<li> ddGroupSiftingBackward()
+		<li> ddMergeGroups()
+		<li> ddDissolveGroup()
+		<li> ddNoCheck()
+		<li> ddSecDiffCheck()
+		<li> ddExtSymmCheck()
+		<li> ddVarGroupCheck()
+		<li> ddSetVarHandled()
+		<li> ddResetVarHandled()
+		<li> ddIsVarHandled()
+		</ul>]
+
+  Author      [Shipra Panda, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Constants for lazy sifting */
+#define	DD_NORMAL_SIFT	0
+#define	DD_LAZY_SIFT	1
+
+/* Constants for sifting up and down */
+#define	DD_SIFT_DOWN	0
+#define	DD_SIFT_UP	1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    typedef int (*DD_CHKFP)(DdManager *, int, int);
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.42 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+static	int	*entry;
+extern	int	ddTotalNumberSwapping;
+#ifdef DD_STATS
+extern	int	ddTotalNISwaps;
+static  int     extsymmcalls;
+static  int     extsymm;
+static  int     secdiffcalls;
+static  int     secdiff;
+static  int     secdiffmisfire;
+#endif
+#ifdef DD_DEBUG
+static	int	pr = 0;	/* flag to enable printing while debugging */
+			/* by depositing a 1 into it */
+#endif
+static unsigned int originalSize;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+#ifdef DD_STATS
+static int ddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
+#endif
+static int ddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+static void ddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
+static int ddUniqueCompareGroup (int *ptrX, int *ptrY);
+static int ddGroupSifting (DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag);
+static void ddCreateGroup (DdManager *table, int x, int y);
+static int ddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag);
+static int ddGroupSiftingUp (DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves);
+static int ddGroupSiftingDown (DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves);
+static int ddGroupMove (DdManager *table, int x, int y, Move **moves);
+static int ddGroupMoveBackward (DdManager *table, int x, int y);
+static int ddGroupSiftingBackward (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag);
+static void ddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
+static void ddDissolveGroup (DdManager *table, int x, int y);
+static int ddNoCheck (DdManager *table, int x, int y);
+static int ddSecDiffCheck (DdManager *table, int x, int y);
+static int ddExtSymmCheck (DdManager *table, int x, int y);
+static int ddVarGroupCheck (DdManager * table, int x, int y);
+static int ddSetVarHandled (DdManager *dd, int index);
+static int ddResetVarHandled (DdManager *dd, int index);
+static int ddIsVarHandled (DdManager *dd, int index);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new variable group.]
+
+  Description [Creates a new variable group. The group starts at
+  variable and contains size variables. The parameter low is the index
+  of the first variable. If the variable already exists, its current
+  position in the order is known to the manager. If the variable does
+  not exist yet, the position is assumed to be the same as the index.
+  The group tree is created if it does not exist yet.
+  Returns a pointer to the group if successful; NULL otherwise.]
+
+  SideEffects [The variable tree is changed.]
+
+  SeeAlso     [Cudd_MakeZddTreeNode]
+
+******************************************************************************/
+MtrNode *
+Cudd_MakeTreeNode(
+  DdManager * dd /* manager */,
+  unsigned int  low /* index of the first group variable */,
+  unsigned int  size /* number of variables in the group */,
+  unsigned int  type /* MTR_DEFAULT or MTR_FIXED */)
+{
+    MtrNode *group;
+    MtrNode *tree;
+    unsigned int level;
+
+    /* If the variable does not exist yet, the position is assumed to be
+    ** the same as the index. Therefore, applications that rely on
+    ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
+    ** variables have to create the variables before they group them.
+    */
+    level = (low < (unsigned int) dd->size) ? dd->perm[low] : low;
+
+    if (level + size - 1> (int) MTR_MAXHIGH)
+	return(NULL);
+
+    /* If the tree does not exist yet, create it. */
+    tree = dd->tree;
+    if (tree == NULL) {
+	dd->tree = tree = Mtr_InitGroupTree(0, dd->size);
+	if (tree == NULL)
+	    return(NULL);
+	tree->index = dd->invperm[0];
+    }
+
+    /* Extend the upper bound of the tree if necessary. This allows the
+    ** application to create groups even before the variables are created.
+    */
+    tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size));
+
+    /* Create the group. */
+    group = Mtr_MakeGroup(tree, level, size, type);
+    if (group == NULL)
+	return(NULL);
+
+    /* Initialize the index field to the index of the variable currently
+    ** in position low. This field will be updated by the reordering
+    ** procedure to provide a handle to the group once it has been moved.
+    */
+    group->index = (MtrHalfWord) low;
+
+    return(group);
+
+} /* end of Cudd_MakeTreeNode */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tree sifting algorithm.]
+
+  Description [Tree sifting algorithm. Assumes that a tree representing
+  a group hierarchy is passed as a parameter. It then reorders each
+  group in postorder fashion by calling ddTreeSiftingAux.  Assumes that
+  no dead nodes are present.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddTreeSifting(
+  DdManager * table /* DD table */,
+  Cudd_ReorderingType method /* reordering method for the groups of leaves */)
+{
+    int i;
+    int nvars;
+    int result;
+    int tempTree;
+
+    /* If no tree is provided we create a temporary one in which all
+    ** variables are in a single group. After reordering this tree is
+    ** destroyed.
+    */
+    tempTree = table->tree == NULL;
+    if (tempTree) {
+	table->tree = Mtr_InitGroupTree(0,table->size);
+	table->tree->index = table->invperm[0];
+    }
+    nvars = table->size;
+
+#ifdef DD_DEBUG
+    if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:");
+    Mtr_PrintGroups(table->tree,pr <= 0);
+#endif
+
+#ifdef DD_STATS
+    extsymmcalls = 0;
+    extsymm = 0;
+    secdiffcalls = 0;
+    secdiff = 0;
+    secdiffmisfire = 0;
+
+    (void) fprintf(table->out,"\n");
+    if (!tempTree)
+	(void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
+		       ddCountInternalMtrNodes(table,table->tree));
+#endif
+
+    /* Initialize the group of each subtable to itself. Initially
+    ** there are no groups. Groups are created according to the tree
+    ** structure in postorder fashion.
+    */
+    for (i = 0; i < nvars; i++)
+        table->subtables[i].next = i;
+
+
+    /* Reorder. */
+    result = ddTreeSiftingAux(table, table->tree, method);
+
+#ifdef DD_STATS		/* print stats */
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+	(table->groupcheck == CUDD_GROUP_CHECK7 ||
+	 table->groupcheck == CUDD_GROUP_CHECK5)) {
+	(void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
+	(void) fprintf(table->out,"extsymm = %d",extsymm);
+    }
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+	table->groupcheck == CUDD_GROUP_CHECK7) {
+	(void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
+	(void) fprintf(table->out,"secdiff = %d\n",secdiff);
+	(void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
+    }
+#endif
+
+    if (tempTree)
+	Cudd_FreeTree(table);
+    return(result);
+
+} /* end of cuddTreeSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Visits the group tree and reorders each group.]
+
+  Description [Recursively visits the group tree and reorders each
+  group in postorder fashion.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddTreeSiftingAux(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    MtrNode  *auxnode;
+    int res;
+    Cudd_AggregationType saveCheck;
+
+#ifdef DD_DEBUG
+    Mtr_PrintGroups(treenode,1);
+#endif
+
+    auxnode = treenode;
+    while (auxnode != NULL) {
+	if (auxnode->child != NULL) {
+	    if (!ddTreeSiftingAux(table, auxnode->child, method))
+		return(0);
+	    saveCheck = table->groupcheck;
+	    table->groupcheck = CUDD_NO_CHECK;
+	    if (method != CUDD_REORDER_LAZY_SIFT)
+	      res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
+	    else
+	      res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT);
+	    table->groupcheck = saveCheck;
+
+	    if (res == 0)
+		return(0);
+	} else if (auxnode->size > 1) {
+	    if (!ddReorderChildren(table, auxnode, method))
+		return(0);
+	}
+	auxnode = auxnode->younger;
+    }
+
+    return(1);
+
+} /* end of ddTreeSiftingAux */
+
+
+#ifdef DD_STATS
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of internal nodes of the group tree.]
+
+  Description [Counts the number of internal nodes of the group tree.
+  Returns the count.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddCountInternalMtrNodes(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    MtrNode *auxnode;
+    int     count,nodeCount;
+
+
+    nodeCount = 0;
+    auxnode = treenode;
+    while (auxnode != NULL) {
+	if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
+	    nodeCount++;
+	    count = ddCountInternalMtrNodes(table,auxnode->child);
+	    nodeCount += count;
+	}
+	auxnode = auxnode->younger;
+    }
+
+    return(nodeCount);
+
+} /* end of ddCountInternalMtrNodes */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders the children of a group tree node according to
+  the options.]
+
+  Description [Reorders the children of a group tree node according to
+  the options. After reordering puts all the variables in the group
+  and/or its descendents in a single group. This allows hierarchical
+  reordering.  If the variables in the group do not exist yet, simply
+  does nothing. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddReorderChildren(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    int lower;
+    int upper;
+    int result;
+    unsigned int initialSize;
+
+    ddFindNodeHiLo(table,treenode,&lower,&upper);
+    /* If upper == -1 these variables do not exist yet. */
+    if (upper == -1)
+	return(1);
+
+    if (treenode->flags == MTR_FIXED) {
+	result = 1;
+    } else {
+#ifdef DD_STATS
+	(void) fprintf(table->out," ");
+#endif
+	switch (method) {
+	case CUDD_REORDER_RANDOM:
+	case CUDD_REORDER_RANDOM_PIVOT:
+	    result = cuddSwapping(table,lower,upper,method);
+	    break;
+	case CUDD_REORDER_SIFT:
+	    result = cuddSifting(table,lower,upper);
+	    break;
+	case CUDD_REORDER_SIFT_CONVERGE:
+	    do {
+		initialSize = table->keys - table->isolated;
+		result = cuddSifting(table,lower,upper);
+		if (initialSize <= table->keys - table->isolated)
+		    break;
+#ifdef DD_STATS
+		else
+		    (void) fprintf(table->out,"\n");
+#endif
+	    } while (result != 0);
+	    break;
+	case CUDD_REORDER_SYMM_SIFT:
+	    result = cuddSymmSifting(table,lower,upper);
+	    break;
+	case CUDD_REORDER_SYMM_SIFT_CONV:
+	    result = cuddSymmSiftingConv(table,lower,upper);
+	    break;
+	case CUDD_REORDER_GROUP_SIFT:
+	    if (table->groupcheck == CUDD_NO_CHECK) {
+		result = ddGroupSifting(table,lower,upper,ddNoCheck,
+					DD_NORMAL_SIFT);
+	    } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
+		result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+					DD_NORMAL_SIFT);
+	    } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
+		result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+					DD_NORMAL_SIFT);
+	    } else {
+		(void) fprintf(table->err,
+			       "Unknown group ckecking method\n");
+		result = 0;
+	    }
+	    break;
+	case CUDD_REORDER_GROUP_SIFT_CONV:
+	    do {
+		initialSize = table->keys - table->isolated;
+		if (table->groupcheck == CUDD_NO_CHECK) {
+		    result = ddGroupSifting(table,lower,upper,ddNoCheck,
+					    DD_NORMAL_SIFT);
+		} else if (table->groupcheck == CUDD_GROUP_CHECK5) {
+		    result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+					    DD_NORMAL_SIFT);
+		} else if (table->groupcheck == CUDD_GROUP_CHECK7) {
+		    result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
+					    DD_NORMAL_SIFT);
+		} else {
+		    (void) fprintf(table->err,
+				   "Unknown group ckecking method\n");
+		    result = 0;
+		}
+#ifdef DD_STATS
+		(void) fprintf(table->out,"\n");
+#endif
+		result = cuddWindowReorder(table,lower,upper,
+					   CUDD_REORDER_WINDOW4);
+		if (initialSize <= table->keys - table->isolated)
+		    break;
+#ifdef DD_STATS
+		else
+		    (void) fprintf(table->out,"\n");
+#endif
+	    } while (result != 0);
+	    break;
+	case CUDD_REORDER_WINDOW2:
+	case CUDD_REORDER_WINDOW3:
+	case CUDD_REORDER_WINDOW4:
+	case CUDD_REORDER_WINDOW2_CONV:
+	case CUDD_REORDER_WINDOW3_CONV:
+	case CUDD_REORDER_WINDOW4_CONV:
+	    result = cuddWindowReorder(table,lower,upper,method);
+	    break;
+	case CUDD_REORDER_ANNEALING:
+	    result = cuddAnnealing(table,lower,upper);
+	    break;
+	case CUDD_REORDER_GENETIC:
+	    result = cuddGa(table,lower,upper);
+	    break;
+	case CUDD_REORDER_LINEAR:
+	    result = cuddLinearAndSifting(table,lower,upper);
+	    break;
+	case CUDD_REORDER_LINEAR_CONVERGE:
+	    do {
+		initialSize = table->keys - table->isolated;
+		result = cuddLinearAndSifting(table,lower,upper);
+		if (initialSize <= table->keys - table->isolated)
+		    break;
+#ifdef DD_STATS
+		else
+		    (void) fprintf(table->out,"\n");
+#endif
+	    } while (result != 0);
+	    break;
+	case CUDD_REORDER_EXACT:
+	    result = cuddExact(table,lower,upper);
+	    break;
+	case CUDD_REORDER_LAZY_SIFT:
+	    result = ddGroupSifting(table,lower,upper,ddVarGroupCheck,
+				    DD_LAZY_SIFT);
+	    break;
+	default:
+	    return(0);
+	}
+    }
+
+    /* Create a single group for all the variables that were sifted,
+    ** so that they will be treated as a single block by successive
+    ** invocations of ddGroupSifting.
+    */
+    ddMergeGroups(table,treenode,lower,upper);
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:");
+#endif
+
+    return(result);
+
+} /* end of ddReorderChildren */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the lower and upper bounds of the group represented
+  by treenode.]
+
+  Description [Finds the lower and upper bounds of the group
+  represented by treenode.  From the index and size fields we need to
+  derive the current positions, and find maximum and minimum.]
+
+  SideEffects [The bounds are returned as side effects.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddFindNodeHiLo(
+  DdManager * table,
+  MtrNode * treenode,
+  int * lower,
+  int * upper)
+{
+    int low;
+    int high;
+
+    /* Check whether no variables in this group already exist.
+    ** If so, return immediately. The calling procedure will know from
+    ** the values of upper that no reordering is needed.
+    */
+    if ((int) treenode->low >= table->size) {
+	*lower = table->size;
+	*upper = -1;
+	return;
+    }
+
+    *lower = low = (unsigned int) table->perm[treenode->index];
+    high = (int) (low + treenode->size - 1);
+
+    if (high >= table->size) {
+	/* This is the case of a partially existing group. The aim is to
+	** reorder as many variables as safely possible.  If the tree
+	** node is terminal, we just reorder the subset of the group
+	** that is currently in existence.  If the group has
+	** subgroups, then we only reorder those subgroups that are
+	** fully instantiated.  This way we avoid breaking up a group.
+	*/
+	MtrNode *auxnode = treenode->child;
+	if (auxnode == NULL) {
+	    *upper = (unsigned int) table->size - 1;
+	} else {
+	    /* Search the subgroup that strands the table->size line.
+	    ** If the first group starts at 0 and goes past table->size
+	    ** upper will get -1, thus correctly signaling that no reordering
+	    ** should take place.
+	    */
+	    while (auxnode != NULL) {
+		int thisLower = table->perm[auxnode->low];
+		int thisUpper = thisLower + auxnode->size - 1;
+		if (thisUpper >= table->size && thisLower < table->size)
+		    *upper = (unsigned int) thisLower - 1;
+		auxnode = auxnode->younger;
+	    }
+	}
+    } else {
+	/* Normal case: All the variables of the group exist. */
+	*upper = (unsigned int) high;
+    }
+
+#ifdef DD_DEBUG
+    /* Make sure that all variables in group are contiguous. */
+    assert(treenode->size >= *upper - *lower + 1);
+#endif
+
+    return;
+
+} /* end of ddFindNodeHiLo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the variables
+  according to the number of keys in the subtables.  Returns the
+  difference in number of keys between the two variables being
+  compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddUniqueCompareGroup(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+	return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddUniqueCompareGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts from treenode->low to treenode->high.]
+
+  Description [Sifts from treenode->low to treenode->high. If
+  croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the
+  end of the initial sifting. If a group is created, it is then sifted
+  again. After sifting one variable, the group that contains it is
+  dissolved.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSifting(
+  DdManager * table,
+  int  lower,
+  int  upper,
+  DD_CHKFP checkFunction,
+  int lazyFlag)
+{
+    int		*var;
+    int		i,j,x,xInit;
+    int		nvars;
+    int		classes;
+    int		result;
+    int		*sifted;
+    int		merged;
+    int		dissolve;
+#ifdef DD_STATS
+    unsigned	previousSize;
+#endif
+    int		xindex;
+
+    nvars = table->size;
+
+    /* Order variables to sift. */
+    entry = NULL;
+    sifted = NULL;
+    var = ALLOC(int,nvars);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto ddGroupSiftingOutOfMem;
+    }
+    entry = ALLOC(int,nvars);
+    if (entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto ddGroupSiftingOutOfMem;
+    }
+    sifted = ALLOC(int,nvars);
+    if (sifted == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto ddGroupSiftingOutOfMem;
+    }
+
+    /* Here we consider only one representative for each group. */
+    for (i = 0, classes = 0; i < nvars; i++) {
+	sifted[i] = 0;
+	x = table->perm[i];
+	if ((unsigned) x >= table->subtables[x].next) {
+	    entry[i] = table->subtables[x].keys;
+	    var[classes] = i;
+	    classes++;
+	}
+    }
+
+    qsort((void *)var,classes,sizeof(int),
+	  (DD_QSFP) ddUniqueCompareGroup);
+
+    if (lazyFlag) {
+	for (i = 0; i < nvars; i ++) {
+	    ddResetVarHandled(table, i);
+	}
+    }
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
+	if (ddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	xindex = var[i];
+	if (sifted[xindex] == 1) /* variable already sifted as part of group */
+	    continue;
+        x = table->perm[xindex]; /* find current level of this variable */
+
+	if (x < lower || x > upper || table->subtables[x].bindVar == 1)
+	    continue;
+#ifdef DD_STATS
+	previousSize = table->keys - table->isolated;
+#endif
+#ifdef DD_DEBUG
+	/* x is bottom of group */
+        assert((unsigned) x >= table->subtables[x].next);
+#endif
+	if ((unsigned) x == table->subtables[x].next) {
+	    dissolve = 1;
+	    result = ddGroupSiftingAux(table,x,lower,upper,checkFunction,
+	    				lazyFlag);
+	} else {
+	    dissolve = 0;
+	    result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
+	}
+	if (!result) goto ddGroupSiftingOutOfMem;
+
+	/* check for aggregation */
+	merged = 0;
+	if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) {
+	    x = table->perm[xindex]; /* find current level */
+	    if ((unsigned) x == table->subtables[x].next) { /* not part of a group */
+		if (x != upper && sifted[table->invperm[x+1]] == 0 &&
+		(unsigned) x+1 == table->subtables[x+1].next) {
+		    if (ddSecDiffCheck(table,x,x+1)) {
+			merged =1;
+			ddCreateGroup(table,x,x+1);
+		    }
+		}
+		if (x != lower && sifted[table->invperm[x-1]] == 0 &&
+		(unsigned) x-1 == table->subtables[x-1].next) {
+		    if (ddSecDiffCheck(table,x-1,x)) {
+			merged =1;
+			ddCreateGroup(table,x-1,x);
+		    }
+		}
+	    }
+	}
+
+	if (merged) { /* a group was created */
+	    /* move x to bottom of group */
+	    while ((unsigned) x < table->subtables[x].next)
+		x = table->subtables[x].next;
+	    /* sift */
+	    result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
+	    if (!result) goto ddGroupSiftingOutOfMem;
+#ifdef DD_STATS
+	    if (table->keys < previousSize + table->isolated) {
+		(void) fprintf(table->out,"_");
+	    } else if (table->keys > previousSize + table->isolated) {
+		(void) fprintf(table->out,"^");
+	    } else {
+		(void) fprintf(table->out,"*");
+	    }
+	    fflush(table->out);
+	} else {
+	    if (table->keys < previousSize + table->isolated) {
+		(void) fprintf(table->out,"-");
+	    } else if (table->keys > previousSize + table->isolated) {
+		(void) fprintf(table->out,"+");
+	    } else {
+		(void) fprintf(table->out,"=");
+	    }
+	    fflush(table->out);
+#endif
+	}
+
+	/* Mark variables in the group just sifted. */
+	x = table->perm[xindex];
+	if ((unsigned) x != table->subtables[x].next) {
+	    xInit = x;
+	    do {
+		j = table->invperm[x];
+		sifted[j] = 1;
+		x = table->subtables[x].next;
+	    } while (x != xInit);
+
+	    /* Dissolve the group if it was created. */
+	    if (lazyFlag == 0 && dissolve) {
+		do {
+		    j = table->subtables[x].next;
+		    table->subtables[x].next = x;
+		    x = j;
+		} while (x != xInit);
+	    }
+	}
+
+#ifdef DD_DEBUG
+	if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:");
+#endif
+
+      if (lazyFlag) ddSetVarHandled(table, xindex);
+    } /* for */
+
+    FREE(sifted);
+    FREE(var);
+    FREE(entry);
+
+    return(1);
+
+ddGroupSiftingOutOfMem:
+    if (entry != NULL)	FREE(entry);
+    if (var != NULL)	FREE(var);
+    if (sifted != NULL)	FREE(sifted);
+
+    return(0);
+
+} /* end of ddGroupSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a group encompassing variables from x to y in the
+  DD table.]
+
+  Description [Creates a group encompassing variables from x to y in the
+  DD table. In the current implementation it must be y == x+1.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddCreateGroup(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int  gybot;
+
+#ifdef DD_DEBUG
+    assert(y == x+1);
+#endif
+
+    /* Find bottom of second group. */
+    gybot = y;
+    while ((unsigned) gybot < table->subtables[gybot].next)
+	gybot = table->subtables[gybot].next;
+
+    /* Link groups. */
+    table->subtables[x].next = y;
+    table->subtables[gybot].next = x;
+
+    return;
+
+} /* ddCreateGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation.]
+
+  Description [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation. There may be at most two sweeps,
+  even if the group grows.  Assumes that x is either an isolated
+  variable, or it is the bottom of a group. All groups may not have
+  been found. The variable being moved is returned to the best position
+  seen during sifting.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh,
+  DD_CHKFP checkFunction,
+  int lazyFlag)
+{
+    Move *move;
+    Move *moves;	/* list of moves */
+    int  initialSize;
+    int  result;
+    int  y;
+    int  topbot;
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,
+			       "ddGroupSiftingAux from %d to %d\n",xLow,xHigh);
+    assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */
+#endif
+
+    initialSize = table->keys - table->isolated;
+    moves = NULL;
+
+    originalSize = initialSize;		/* for lazy sifting */
+
+    /* If we have a singleton, we check for aggregation in both
+    ** directions before we sift.
+    */
+    if ((unsigned) x == table->subtables[x].next) {
+	/* Will go down first, unless x == xHigh:
+	** Look for aggregation above x.
+	*/
+	for (y = x; y > xLow; y--) {
+	    if (!checkFunction(table,y-1,y))
+		break;
+	    topbot = table->subtables[y-1].next; /* find top of y-1's group */
+	    table->subtables[y-1].next = y;
+	    table->subtables[x].next = topbot; /* x is bottom of group so its */
+					       /* next is top of y-1's group */
+	    y = topbot + 1; /* add 1 for y--; new y is top of group */
+	}
+	/* Will go up first unless x == xlow:
+	** Look for aggregation below x.
+	*/
+	for (y = x; y < xHigh; y++) {
+	    if (!checkFunction(table,y,y+1))
+		break;
+	    /* find bottom of y+1's group */
+	    topbot = y + 1;
+	    while ((unsigned) topbot < table->subtables[topbot].next) {
+		topbot = table->subtables[topbot].next;
+	    }
+	    table->subtables[topbot].next = table->subtables[y].next;
+	    table->subtables[y].next = y + 1;
+	    y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */
+	}
+    }
+
+    /* Now x may be in the middle of a group.
+    ** Find bottom of x's group.
+    */
+    while ((unsigned) x < table->subtables[x].next)
+	x = table->subtables[x].next;
+
+    if (x == xLow) { /* Sift down */
+#ifdef DD_DEBUG
+	/* x must be a singleton */
+	assert((unsigned) x == table->subtables[x].next);
+#endif
+	if (x == xHigh) return(1);	/* just one variable */
+
+        if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+	/* at this point x == xHigh, unless early term */
+
+	/* move backward and stop at best position */
+	result = ddGroupSiftingBackward(table,moves,initialSize,
+					DD_SIFT_DOWN,lazyFlag);
+#ifdef DD_DEBUG
+	assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+
+    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
+#ifdef DD_DEBUG
+	/* x is bottom of group */
+        assert((unsigned) x >= table->subtables[x].next);
+#endif
+        /* Find top of x's group */
+        x = table->subtables[x].next;
+
+        if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+	/* at this point x == xLow, unless early term */
+
+	/* move backward and stop at best position */
+	result = ddGroupSiftingBackward(table,moves,initialSize,
+					DD_SIFT_UP,lazyFlag);
+#ifdef DD_DEBUG
+	assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+
+    } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
+        if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+	/* at this point x == xHigh, unless early term */
+
+        /* Find top of group */
+	if (moves) {
+	    x = moves->y;
+	}
+	while ((unsigned) x < table->subtables[x].next)
+	    x = table->subtables[x].next;
+	x = table->subtables[x].next;
+#ifdef DD_DEBUG
+        /* x should be the top of a group */
+        assert((unsigned) x <= table->subtables[x].next);
+#endif
+
+        if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+
+	/* move backward and stop at best position */
+	result = ddGroupSiftingBackward(table,moves,initialSize,
+					DD_SIFT_UP,lazyFlag);
+#ifdef DD_DEBUG
+	assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+        /* Find top of x's group */
+        x = table->subtables[x].next;
+
+        if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+	/* at this point x == xHigh, unless early term */
+
+        if (moves) {
+	    x = moves->x;
+	}
+	while ((unsigned) x < table->subtables[x].next)
+	    x = table->subtables[x].next;
+#ifdef DD_DEBUG
+        /* x is bottom of a group */
+        assert((unsigned) x >= table->subtables[x].next);
+#endif
+
+        if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
+            goto ddGroupSiftingAuxOutOfMem;
+
+	/* move backward and stop at best position */
+	result = ddGroupSiftingBackward(table,moves,initialSize,
+					DD_SIFT_DOWN,lazyFlag);
+#ifdef DD_DEBUG
+	assert(table->keys - table->isolated <= (unsigned) initialSize);
+#endif
+        if (!result) goto ddGroupSiftingAuxOutOfMem;
+    }
+
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(1);
+
+ddGroupSiftingAuxOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(0);
+
+} /* end of ddGroupSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts up a variable until either it reaches position xLow
+  or the size of the DD heap increases too much.]
+
+  Description [Sifts up a variable until either it reaches position
+  xLow or the size of the DD heap increases too much. Assumes that y is
+  the top of a group (or a singleton).  Checks y for aggregation to the
+  adjacent variables. Records all the moves that are appended to the
+  list of moves received as input and returned as a side effect.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  DD_CHKFP checkFunction,
+  Move ** moves)
+{
+    Move *move;
+    int  x;
+    int  size;
+    int  i;
+    int  gxtop,gybot;
+    int  limitSize;
+    int  xindex, yindex;
+    int  zindex;
+    int  z;
+    int  isolated;
+    int  L;	/* lower bound on DD size */
+#ifdef DD_DEBUG
+    int  checkL;
+#endif
+
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below the bottom of y's group will not change.
+    ** The part of the DD above y that does not interact with any
+    ** variable of y's group will not change.
+    ** The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    ** What we use here is not really a lower bound, because we ignore
+    ** the interactions with all variables except y.
+    */
+    limitSize = L = table->keys - table->isolated;
+    gybot = y;
+    while ((unsigned) gybot < table->subtables[gybot].next)
+	gybot = table->subtables[gybot].next;
+    for (z = xLow + 1; z <= gybot; z++) {
+	zindex = table->invperm[z];
+	if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+	    isolated = table->vars[zindex]->ref == 1;
+	    L -= table->subtables[z].keys - isolated;
+	}
+    }
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+#ifdef DD_DEBUG
+	gybot = y;
+	while ((unsigned) gybot < table->subtables[gybot].next)
+	    gybot = table->subtables[gybot].next;
+	checkL = table->keys - table->isolated;
+	for (z = xLow + 1; z <= gybot; z++) {
+	    zindex = table->invperm[z];
+	    if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkL -= table->subtables[z].keys - isolated;
+	    }
+	}
+	if (pr > 0 && L != checkL) {
+	    (void) fprintf(table->out,
+			   "Inaccurate lower bound: L = %d checkL = %d\n",
+			   L, checkL);
+	}
+#endif
+        gxtop = table->subtables[x].next;
+        if (checkFunction(table,x,y)) {
+	    /* Group found, attach groups */
+	    table->subtables[x].next = y;
+	    i = table->subtables[y].next;
+	    while (table->subtables[i].next != (unsigned) y)
+		i = table->subtables[i].next;
+	    table->subtables[i].next = gxtop;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddGroupSiftingUpOutOfMem;
+	    move->x = x;
+	    move->y = y;
+	    move->flags = MTR_NEWNODE;
+	    move->size = table->keys - table->isolated;
+	    move->next = *moves;
+	    *moves = move;
+        } else if (table->subtables[x].next == (unsigned) x &&
+		   table->subtables[y].next == (unsigned) y) {
+            /* x and y are self groups */
+	    xindex = table->invperm[x];
+            size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtables[x].next == (unsigned) x);
+            assert(table->subtables[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto ddGroupSiftingUpOutOfMem;
+	    /* Update the lower bound. */
+	    if (cuddTestInteract(table,xindex,yindex)) {
+		isolated = table->vars[xindex]->ref == 1;
+		L += table->subtables[y].keys - isolated;
+	    }
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddGroupSiftingUpOutOfMem;
+            move->x = x;
+            move->y = y;
+	    move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+	    if (pr > 0) (void) fprintf(table->out,
+				       "ddGroupSiftingUp (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+		return(1);
+            if (size < limitSize) limitSize = size;
+        } else { /* Group move */
+            size = ddGroupMove(table,x,y,moves);
+	    if (size == 0) goto ddGroupSiftingUpOutOfMem;
+	    /* Update the lower bound. */
+	    z = (*moves)->y;
+	    do {
+		zindex = table->invperm[z];
+		if (cuddTestInteract(table,zindex,yindex)) {
+		    isolated = table->vars[zindex]->ref == 1;
+		    L += table->subtables[z].keys - isolated;
+		}
+		z = table->subtables[z].next;
+	    } while (z != (int) (*moves)->y);
+            if ((double) size > (double) limitSize * table->maxGrowth)
+		return(1);
+            if (size < limitSize) limitSize = size;
+        }
+        y = gxtop;
+        x = cuddNextLow(table,y);
+    }
+
+    return(1);
+
+ddGroupSiftingUpOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of ddGroupSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts down a variable until it reaches position xHigh.]
+
+  Description [Sifts down a variable until it reaches position xHigh.
+  Assumes that x is the bottom of a group (or a singleton).  Records
+  all the moves.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  DD_CHKFP checkFunction,
+  Move ** moves)
+{
+    Move *move;
+    int  y;
+    int  size;
+    int  limitSize;
+    int  gxtop,gybot;
+    int  R;	/* upper bound on node decrease */
+    int  xindex, yindex;
+    int  isolated, allVars;
+    int  z;
+    int  zindex;
+#ifdef DD_DEBUG
+    int  checkR;
+#endif
+
+    /* If the group consists of simple variables, there is no point in
+    ** sifting it down. This check is redundant if the projection functions
+    ** do not have external references, because the computation of the
+    ** lower bound takes care of the problem.  It is necessary otherwise to
+    ** prevent the sifting down of simple variables. */
+    y = x;
+    allVars = 1;
+    do {
+	if (table->subtables[y].keys != 1) {
+	    allVars = 0;
+	    break;
+	}
+	y = table->subtables[y].next;
+    } while (table->subtables[y].next != (unsigned) x);
+    if (allVars)
+	return(1);
+    
+    /* Initialize R. */
+    xindex = table->invperm[x];
+    gxtop = table->subtables[x].next;
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (z = xHigh; z > gxtop; z--) {
+	zindex = table->invperm[z];
+	if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+	    isolated = table->vars[zindex]->ref == 1;
+	    R += table->subtables[z].keys - isolated;
+	}
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+	gxtop = table->subtables[x].next;
+	checkR = 0;
+	for (z = xHigh; z > gxtop; z--) {
+	    zindex = table->invperm[z];
+	    if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkR += table->subtables[z].keys - isolated;
+	    }
+	}
+	assert(R >= checkR);
+#endif
+	/* Find bottom of y group. */
+        gybot = table->subtables[y].next;
+        while (table->subtables[gybot].next != (unsigned) y)
+            gybot = table->subtables[gybot].next;
+
+        if (checkFunction(table,x,y)) {
+	    /* Group found: attach groups and record move. */
+	    gxtop = table->subtables[x].next;
+	    table->subtables[x].next = y;
+	    table->subtables[gybot].next = gxtop;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddGroupSiftingDownOutOfMem;
+	    move->x = x;
+	    move->y = y;
+	    move->flags = MTR_NEWNODE;
+	    move->size = table->keys - table->isolated;
+	    move->next = *moves;
+	    *moves = move;
+        } else if (table->subtables[x].next == (unsigned) x &&
+		   table->subtables[y].next == (unsigned) y) {
+            /* x and y are self groups */
+	    /* Update upper bound on node decrease. */
+	    yindex = table->invperm[y];
+	    if (cuddTestInteract(table,xindex,yindex)) {
+		isolated = table->vars[yindex]->ref == 1;
+		R -= table->subtables[y].keys - isolated;
+	    }
+            size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtables[x].next == (unsigned) x);
+            assert(table->subtables[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto ddGroupSiftingDownOutOfMem;
+
+	    /* Record move. */
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto ddGroupSiftingDownOutOfMem;
+            move->x = x;
+            move->y = y;
+	    move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,
+				       "ddGroupSiftingDown (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+
+            x = y;
+            y = cuddNextHigh(table,x);
+        } else { /* Group move */
+	    /* Update upper bound on node decrease: first phase. */
+	    gxtop = table->subtables[x].next;
+	    z = gxtop + 1;
+	    do {
+		zindex = table->invperm[z];
+		if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+		    isolated = table->vars[zindex]->ref == 1;
+		    R -= table->subtables[z].keys - isolated;
+		}
+		z++;
+	    } while (z <= gybot);
+            size = ddGroupMove(table,x,y,moves);
+            if (size == 0) goto ddGroupSiftingDownOutOfMem;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+		return(1);
+            if (size < limitSize) limitSize = size;
+
+	    /* Update upper bound on node decrease: second phase. */
+	    gxtop = table->subtables[gybot].next;
+	    for (z = gxtop + 1; z <= gybot; z++) {
+		zindex = table->invperm[z];
+		if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+		    isolated = table->vars[zindex]->ref == 1;
+		    R += table->subtables[z].keys - isolated;
+		}
+	    }
+        }
+        x = gybot;
+        y = cuddNextHigh(table,x);
+    }
+
+    return(1);
+
+ddGroupSiftingDownOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+
+    return(0);
+
+} /* end of ddGroupSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two groups and records the move.]
+
+  Description [Swaps two groups and records the move. Returns the
+  number of keys in the DD table in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupMove(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move *move;
+    int  size;
+    int  i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+    int  swapx,swapy;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    int  initialSize,bestSize;
+#endif
+
+#if DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+        ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    initialSize = bestSize = table->keys - table->isolated;
+#endif
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddSwapInPlace(table,x,y);
+            if (size == 0) goto ddGroupMoveOutOfMem;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+	    if (size < bestSize)
+		bestSize = size;
+#endif
+            swapx = x; swapy = y;
+            y = x;
+            x = cuddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddNextLow(table,y);
+    }
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if ((bestSize < initialSize) && (bestSize < size))
+	(void) fprintf(table->out,"Missed local minimum: initialSize:%d  bestSize:%d  finalSize:%d\n",initialSize,bestSize,size);
+#endif
+
+    /* fix groups */
+    y = xtop; /* ytop is now where xtop used to be */
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtables[y].next = cuddNextHigh(table,y);
+        y = cuddNextHigh(table,y);
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+                                    /* it to top of its group */
+    x = cuddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtables[x].next = cuddNextHigh(table,x);
+        x = cuddNextHigh(table,x);
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* it to top of its group */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n");
+#endif
+
+    /* Store group move */
+    move = (Move *) cuddDynamicAllocNode(table);
+    if (move == NULL) goto ddGroupMoveOutOfMem;
+    move->x = swapx;
+    move->y = swapy;
+    move->flags = MTR_DEFAULT;
+    move->size = table->keys - table->isolated;
+    move->next = *moves;
+    *moves = move;
+
+    return(table->keys - table->isolated);
+
+ddGroupMoveOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of ddGroupMove */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Undoes the swap two groups.]
+
+  Description [Undoes the swap two groups.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupMoveBackward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int size;
+    int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+
+
+#if DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+        ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddSwapInPlace(table,x,y);
+            if (size == 0)
+                return(0);
+            y = x;
+            x = cuddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddNextLow(table,y);
+    }
+
+    /* fix groups */
+    y = xtop;
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtables[y].next = cuddNextHigh(table,y);
+        y = cuddNextHigh(table,y);
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+                                    /* to its top */
+    x = cuddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtables[x].next = cuddNextHigh(table,x);
+        x = cuddNextHigh(table,x);
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* to its top */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n");
+#endif
+
+    return(1);
+
+} /* end of ddGroupMoveBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines the best position for a variables and returns
+  it there.]
+
+  Description [Determines the best position for a variables and returns
+  it there.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddGroupSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size,
+  int  upFlag, 
+  int  lazyFlag)
+{
+    Move *move;
+    int  res;
+    Move *end_move;
+    int diff, tmp_diff;
+    int index, pairlev;
+
+    if (lazyFlag) {
+	end_move = NULL;
+
+	/* Find the minimum size, and the earliest position at which it
+        ** was achieved. */
+	for (move = moves; move != NULL; move = move->next) {
+	    if (move->size < size) {
+		size = move->size;
+		end_move = move;
+	    } else if (move->size == size) {
+		if (end_move == NULL) end_move = move;
+	    } 
+	}
+
+	/* Find among the moves that give minimum size the one that
+        ** minimizes the distance from the corresponding variable. */
+	if (moves != NULL) {
+	    diff = Cudd_ReadSize(table) + 1;
+	    index = (upFlag == 1) ? 
+		    table->invperm[moves->x] : table->invperm[moves->y];
+	    pairlev = table->perm[Cudd_bddReadPairIndex(table, index)];
+
+	    for (move = moves; move != NULL; move = move->next) {
+		if (move->size == size) {
+		    if (upFlag == 1) {
+			tmp_diff = (move->x > pairlev) ? 
+				    move->x - pairlev : pairlev - move->x;
+		    } else {
+			tmp_diff = (move->y > pairlev) ?
+				    move->y - pairlev : pairlev - move->y;
+		    }
+		    if (tmp_diff < diff) {
+			diff = tmp_diff;
+			end_move = move;
+		    } 
+		}
+	    }
+	}
+    } else {
+	/* Find the minimum size. */
+	for (move = moves; move != NULL; move = move->next) {
+	    if (move->size < size) {
+		size = move->size;
+	    } 
+	}
+    }
+
+    /* In case of lazy sifting, end_move identifies the position at
+    ** which we want to stop.  Otherwise, we stop as soon as we meet
+    ** the minimum size. */
+    for (move = moves; move != NULL; move = move->next) {
+	if (lazyFlag) {
+	    if (move == end_move) return(1);
+	} else {
+	    if (move->size == size) return(1);
+	}
+        if ((table->subtables[move->x].next == move->x) &&
+	(table->subtables[move->y].next == move->y)) {
+            res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n");
+            assert(table->subtables[move->x].next == move->x);
+            assert(table->subtables[move->y].next == move->y);
+#endif
+        } else { /* Group move necessary */
+	    if (move->flags == MTR_NEWNODE) {
+		ddDissolveGroup(table,(int)move->x,(int)move->y);
+	    } else {
+		res = ddGroupMoveBackward(table,(int)move->x,(int)move->y);
+		if (!res) return(0);
+	    }
+        }
+
+    }
+
+    return(1);
+
+} /* end of ddGroupSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges groups in the DD table.]
+
+  Description [Creates a single group from low to high and adjusts the
+  index field of the tree node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddMergeGroups(
+  DdManager * table,
+  MtrNode * treenode,
+  int  low,
+  int  high)
+{
+    int i;
+    MtrNode *auxnode;
+    int saveindex;
+    int newindex;
+
+    /* Merge all variables from low to high in one group, unless
+    ** this is the topmost group. In such a case we do not merge lest
+    ** we lose the symmetry information. */
+    if (treenode != table->tree) {
+	for (i = low; i < high; i++)
+	    table->subtables[i].next = i+1;
+	table->subtables[high].next = low;
+    }
+
+    /* Adjust the index fields of the tree nodes. If a node is the
+    ** first child of its parent, then the parent may also need adjustment. */
+    saveindex = treenode->index;
+    newindex = table->invperm[low];
+    auxnode = treenode;
+    do {
+	auxnode->index = newindex;
+	if (auxnode->parent == NULL ||
+		(int) auxnode->parent->index != saveindex)
+	    break;
+	auxnode = auxnode->parent;
+    } while (1);
+    return;
+
+} /* end of ddMergeGroups */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dissolves a group in the DD table.]
+
+  Description [x and y are variables in a group to be cut in two. The cut
+  is to pass between x and y.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddDissolveGroup(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int topx;
+    int boty;
+
+    /* find top and bottom of the two groups */
+    boty = y;
+    while ((unsigned) boty < table->subtables[boty].next)
+	boty = table->subtables[boty].next;
+    
+    topx = table->subtables[boty].next;
+
+    table->subtables[boty].next = y;
+    table->subtables[x].next = topx;
+
+    return;
+
+} /* end of ddDissolveGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Pretends to check two variables for aggregation.]
+
+  Description [Pretends to check two variables for aggregation. Always
+  returns 0.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddNoCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    return(0);
+
+} /* end of ddNoCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks two variables for aggregation.]
+
+  Description [Checks two variables for aggregation. The check is based
+  on the second difference of the number of nodes as a function of the
+  layer. If the second difference is lower than a given threshold
+  (typically negative) then the two variables should be aggregated.
+  Returns 1 if the two variables pass the test; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSecDiffCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    double Nx,Nx_1;
+    double Sx;
+    double threshold;
+    int    xindex,yindex;
+
+    if (x==0) return(0);
+
+#ifdef DD_STATS
+    secdiffcalls++;
+#endif
+    Nx = (double) table->subtables[x].keys;
+    Nx_1 = (double) table->subtables[x-1].keys;
+    Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1);
+
+    threshold = table->recomb / 100.0;
+    if (Sx < threshold) {
+	xindex = table->invperm[x];
+	yindex = table->invperm[y];
+	if (cuddTestInteract(table,xindex,yindex)) {
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+	    (void) fprintf(table->out,
+			   "Second difference for %d = %g Pos(%d)\n",
+			   table->invperm[x],Sx,x);
+#endif
+#ifdef DD_STATS
+	    secdiff++;
+#endif
+	    return(1);
+	} else {
+#ifdef DD_STATS
+	    secdiffmisfire++;
+#endif
+	    return(0);
+	}
+
+    }
+    return(0);
+
+} /* end of ddSecDiffCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for extended symmetry of x and y.]
+
+  Description [Checks for extended symmetry of x and y. Returns 1 in
+  case of extended symmetry; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddExtSymmCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
+    DdNode *one;
+    int comple;		/* f0 is complemented */
+    int notproj;	/* f is not a projection function */
+    int arccount;	/* number of arcs from layer x to layer y */
+    int TotalRefCount;	/* total reference count of layer y minus 1 */
+    int counter;	/* number of nodes of layer x that are allowed */
+    			/* to violate extended symmetry conditions */
+    int arccounter;	/* number of arcs into layer y that are allowed */
+			/* to come from layers other than x */
+    int i;
+    int xindex;
+    int yindex;
+    int res;
+    int slots;
+    DdNodePtr *list;
+    DdNode *sentinel = &(table->sentinel);
+
+    xindex = table->invperm[x];
+    yindex = table->invperm[y];
+
+    /* If the two variables do not interact, we do not want to merge them. */
+    if (!cuddTestInteract(table,xindex,yindex))
+	return(0);
+
+#ifdef DD_DEBUG
+    /* Checks that x and y do not contain just the projection functions.
+    ** With the test on interaction, these test become redundant,
+    ** because an isolated projection function does not interact with
+    ** any other variable.
+    */
+    if (table->subtables[x].keys == 1) {
+	assert(table->vars[xindex]->ref != 1);
+    }
+    if (table->subtables[y].keys == 1) {
+	assert(table->vars[yindex]->ref != 1);
+    }
+#endif
+
+#ifdef DD_STATS
+    extsymmcalls++;
+#endif
+
+    arccount = 0;
+    counter = (int) (table->subtables[x].keys *
+	      (table->symmviolation/100.0) + 0.5);
+    one = DD_ONE(table);
+
+    slots = table->subtables[x].slots;
+    list = table->subtables[x].nodelist;
+    for (i = 0; i < slots; i++) {
+	f = list[i];
+	while (f != sentinel) {
+	    /* Find f1, f0, f11, f10, f01, f00. */
+	    f1 = cuddT(f);
+	    f0 = Cudd_Regular(cuddE(f));
+	    comple = Cudd_IsComplement(cuddE(f));
+	    notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1;
+	    if (f1->index == yindex) {
+		arccount++;
+		f11 = cuddT(f1); f10 = cuddE(f1);
+	    } else {
+		if ((int) f0->index != yindex) {
+		    /* If f is an isolated projection function it is
+		    ** allowed to bypass layer y.
+		    */
+		    if (notproj) {
+			if (counter == 0)
+			    return(0);
+			counter--; /* f bypasses layer y */
+		    }
+		}
+		f11 = f10 = f1;
+	    }
+	    if ((int) f0->index == yindex) {
+		arccount++;
+		f01 = cuddT(f0); f00 = cuddE(f0);
+	    } else {
+		f01 = f00 = f0;
+	    }
+	    if (comple) {
+		f01 = Cudd_Not(f01);
+		f00 = Cudd_Not(f00);
+	    }
+
+	    /* Unless we are looking at a projection function
+	    ** without external references except the one from the
+	    ** table, we insist that f01 == f10 or f11 == f00
+	    */
+	    if (notproj) {
+		if (f01 != f10 && f11 != f00) {
+		    if (counter == 0)
+			return(0);
+		    counter--;
+		}
+	    }
+
+	    f = f->next;
+	} /* while */
+    } /* for */
+
+    /* Calculate the total reference counts of y */
+    TotalRefCount = -1;	/* -1 for projection function */
+    slots = table->subtables[y].slots;
+    list = table->subtables[y].nodelist;
+    for (i = 0; i < slots; i++) {
+	f = list[i];
+	while (f != sentinel) {
+	    TotalRefCount += f->ref;
+	    f = f->next;
+	}
+    }
+
+    arccounter = (int) (table->subtables[y].keys *
+		 (table->arcviolation/100.0) + 0.5);
+    res = arccount >= TotalRefCount - arccounter;
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if (res) {
+	(void) fprintf(table->out,
+		       "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n",
+		       xindex,yindex,x,y);
+    }
+#endif
+
+#ifdef DD_STATS
+    if (res)
+	extsymm++;
+#endif
+    return(res);
+
+} /* end ddExtSymmCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for grouping of x and y.]
+
+  Description [Checks for grouping of x and y. Returns 1 in
+  case of grouping; 0 otherwise. This function is used for lazy sifting.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddVarGroupCheck(
+  DdManager * table,
+  int x,
+  int y)
+{
+    int xindex = table->invperm[x];
+    int yindex = table->invperm[y];
+
+    if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0);
+
+    if (Cudd_bddReadPairIndex(table, xindex) == yindex) {
+	if (ddIsVarHandled(table, xindex) ||
+	    ddIsVarHandled(table, yindex)) {
+	    if (Cudd_bddIsVarToBeGrouped(table, xindex) ||
+		Cudd_bddIsVarToBeGrouped(table, yindex) ) {
+		if (table->keys - table->isolated <= originalSize) {
+		    return(1);
+		}
+	    }
+	}
+    }
+
+    return(0);
+
+} /* end of ddVarGroupCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to already handled.]
+
+  Description [Sets a variable to already handled. This function is used
+  for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddSetVarHandled(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varHandled = 1;
+    return(1);
+
+} /* end of ddSetVarHandled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resets a variable to be processed.]
+
+  Description [Resets a variable to be processed. This function is used
+  for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddResetVarHandled(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(0);
+    dd->subtables[dd->perm[index]].varHandled = 0;
+    return(1);
+
+} /* end of ddResetVarHandled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variables is already handled.]
+
+  Description [Checks whether a variables is already handled. This
+  function is used for lazy sifting.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddIsVarHandled(
+  DdManager *dd,
+  int index)
+{
+    if (index >= dd->size || index < 0) return(-1);
+    return dd->subtables[dd->perm[index]].varHandled;
+
+} /* end of ddIsVarHandled */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddHarwell.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddHarwell.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddHarwell.c	(revision 8)
@@ -0,0 +1,568 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddHarwell.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Function to read a matrix in Harwell format.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addHarwell()
+		</ul>
+	]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.9 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in a matrix in the format of the Harwell-Boeing
+  benchmark suite.]
+
+  Description [Reads in a matrix in the format of the Harwell-Boeing
+  benchmark suite. The variables are ordered as follows:
+  <blockquote>
+  x\[0\] y\[0\] x\[1\] y\[1\] ...
+  </blockquote>
+  0 is the most significant bit.  On input, nx and ny hold the numbers
+  of row and column variables already in existence. On output, they
+  hold the numbers of row and column variables actually used by the
+  matrix.  m and n are set to the numbers of rows and columns of the
+  matrix.  Their values on input are immaterial.  Returns 1 on
+  success; 0 otherwise. The ADD for the sparse matrix is returned in
+  E, and its reference count is > 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addRead Cudd_bddRead]
+
+******************************************************************************/
+int
+Cudd_addHarwell(
+  FILE * fp /* pointer to the input file */,
+  DdManager * dd /* DD manager */,
+  DdNode ** E /* characteristic function of the graph */,
+  DdNode *** x /* array of row variables */,
+  DdNode *** y /* array of column variables */,
+  DdNode *** xn /* array of complemented row variables */,
+  DdNode *** yn_ /* array of complemented column variables */,
+  int * nx /* number or row variables */,
+  int * ny /* number or column variables */,
+  int * m /* number of rows */,
+  int * n /* number of columns */,
+  int  bx /* first index of row variables */,
+  int  sx /* step of row variables */,
+  int  by /* first index of column variables */,
+  int  sy /* step of column variables */,
+  int  pr /* verbosity level */)
+{
+    DdNode *one, *zero;
+    DdNode *w;
+    DdNode *cubex, *cubey, *minterm1;
+    int u, v, err, i, j, nv;
+    double val;
+    DdNode **lx, **ly, **lxn, **lyn;	/* local copies of x, y, xn, yn_ */
+    int lnx, lny;			/* local copies of nx and ny */
+    char title[73], key[9], mxtype[4], rhstyp[4];
+    int totcrd, ptrcrd, indcrd, valcrd, rhscrd,
+        nrow, ncol, nnzero, neltvl,
+	nrhs, nrhsix;
+    int *colptr, *rowind;
+#if 0
+    int nguess, nexact;
+    int	*rhsptr, *rhsind;
+#endif
+
+    if (*nx < 0 || *ny < 0) return(0);
+
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Read the header */
+    err = fscanf(fp, "%72c %8c", title, key);
+    if (err == EOF) {
+	return(0);
+    } else if (err != 2) {
+        return(0);
+    }
+    title[72] = (char) 0;
+    key[8] = (char) 0;
+
+    err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd,
+    &valcrd, &rhscrd);
+    if (err == EOF) {
+	return(0);
+    } else if (err != 5) {
+        return(0);
+    }
+
+    err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol,
+    &nnzero, &neltvl);
+    if (err == EOF) {
+	return(0);
+    } else if (err != 5) {
+        return(0);
+    }
+
+    /* Skip FORTRAN formats */
+    if (rhscrd == 0) {
+	err = fscanf(fp, "%*s %*s %*s \n");
+    } else {
+	err = fscanf(fp, "%*s %*s %*s %*s \n");
+    }
+    if (err == EOF) {
+	return(0);
+    } else if (err != 0) {
+        return(0);
+    }
+
+    /* Print out some stuff if requested to be verbose */
+    if (pr>0) {
+	(void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key,
+	mxtype, nrow, ncol, nnzero);
+	if (pr>1) (void) fprintf(dd->out,"%s\n", title);
+    }
+
+    /* Check matrix type */
+    if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') {
+	(void) fprintf(dd->err,"%s: Illegal matrix type: %s\n",
+		       key, mxtype);
+	return(0);
+    }
+    if (neltvl != 0) return(0);
+
+    /* Read optional 5-th line */
+    if (rhscrd != 0) {
+	err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix);
+	if (err == EOF) {
+	    return(0);
+	} else if (err != 3) {
+	    return(0);
+	}
+	rhstyp[3] = (char) 0;
+	if (rhstyp[0] != 'F') {
+	    (void) fprintf(dd->err,
+	    "%s: Sparse right-hand side not yet supported\n", key);
+	    return(0);
+	}
+	if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs);
+    } else {
+	nrhs = 0;
+    }
+
+    /* Compute the number of variables */
+
+    /* row and column numbers start from 0 */
+    u = nrow - 1;
+    for (i=0; u > 0; i++) {
+	u >>= 1;
+    }
+    lnx = i;
+    if (nrhs == 0) {
+	v = ncol - 1;
+    } else {
+	v = 2* (ddMax(ncol, nrhs) - 1);
+    }
+    for (i=0; v > 0; i++) {
+	v >>= 1;
+    }
+    lny = i;
+
+    /* Allocate or reallocate arrays for variables as needed */
+    if (*nx == 0) {
+	if (lnx > 0) {
+	    *x = lx = ALLOC(DdNode *,lnx);
+	    if (lx == NULL) {
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    *xn = lxn =  ALLOC(DdNode *,lnx);
+	    if (lxn == NULL) {
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	} else {
+	    *x = *xn = NULL;
+	}
+    } else if (lnx > *nx) {
+	*x = lx = REALLOC(DdNode *, *x, lnx);
+	if (lx == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	*xn = lxn =  REALLOC(DdNode *, *xn, lnx);
+	if (lxn == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+    } else {
+	lx = *x;
+	lxn = *xn;
+    }
+    if (*ny == 0) {
+	if (lny >0) {
+	    *y = ly = ALLOC(DdNode *,lny);
+	    if (ly == NULL) {
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    *yn_ = lyn = ALLOC(DdNode *,lny);
+	    if (lyn == NULL) {
+		dd->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	} else {
+	    *y = *yn_ = NULL;
+	}
+    } else if (lny > *ny) {
+	*y = ly = REALLOC(DdNode *, *y, lny);
+	if (ly == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	*yn_ = lyn = REALLOC(DdNode *, *yn_, lny);
+	if (lyn == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+    } else {
+	ly = *y;
+	lyn = *yn_;
+    }
+
+    /* Create new variables as needed */
+    for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) {
+	do {
+	    dd->reordered = 0;
+	    lx[i] = cuddUniqueInter(dd, nv, one, zero);
+	} while (dd->reordered == 1);
+	if (lx[i] == NULL) return(0);
+        cuddRef(lx[i]);
+	do {
+	    dd->reordered = 0;
+	    lxn[i] = cuddUniqueInter(dd, nv, zero, one);
+	} while (dd->reordered == 1);
+	if (lxn[i] == NULL) return(0);
+        cuddRef(lxn[i]);
+    }
+    for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) {
+	do {
+	    dd->reordered = 0;
+	    ly[i] = cuddUniqueInter(dd, nv, one, zero);
+	} while (dd->reordered == 1);
+	if (ly[i] == NULL) return(0);
+	cuddRef(ly[i]);
+	do {
+	    dd->reordered = 0;
+	    lyn[i] = cuddUniqueInter(dd, nv, zero, one);
+	} while (dd->reordered == 1);
+	if (lyn[i] == NULL) return(0);
+	cuddRef(lyn[i]);
+    }
+
+    /* Update matrix parameters */
+    *nx = lnx;
+    *ny = lny;
+    *m = nrow;
+    if (nrhs == 0) {
+	*n = ncol;
+    } else {
+	*n = (1 << (lny - 1)) + nrhs;
+    }
+    
+    /* Read structure data */
+    colptr = ALLOC(int, ncol+1);
+    if (colptr == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    rowind = ALLOC(int, nnzero);
+    if (rowind == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+
+    for (i=0; i<ncol+1; i++) {
+	err = fscanf(fp, " %d ", &u);
+	if (err == EOF){ 
+	    FREE(colptr);
+	    FREE(rowind);
+	    return(0);
+	} else if (err != 1) {
+	    FREE(colptr);
+	    FREE(rowind);
+	    return(0);
+	}
+	colptr[i] = u - 1;
+    }
+    if (colptr[0] != 0) {
+	(void) fprintf(dd->err,"%s: Unexpected colptr[0] (%d)\n",
+		       key,colptr[0]);
+	FREE(colptr);
+	FREE(rowind);
+	return(0);
+    }
+    for (i=0; i<nnzero; i++) {
+	err = fscanf(fp, " %d ", &u);
+	if (err == EOF){ 
+	    FREE(colptr);
+	    FREE(rowind);
+	    return(0);
+	} else if (err != 1) {
+	    FREE(colptr);
+	    FREE(rowind);
+	    return(0);
+	}
+	rowind[i] = u - 1;
+    }
+
+    *E = zero; cuddRef(*E);
+
+    for (j=0; j<ncol; j++) {
+	v = j;
+	cubey = one; cuddRef(cubey);
+	for (nv = lny - 1; nv>=0; nv--) {
+	    if (v & 1) {
+		w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
+	    } else {
+		w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
+	    }
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		FREE(colptr);
+		FREE(rowind);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd, cubey);
+	    cubey = w;
+	    v >>= 1;
+	}
+	for (i=colptr[j]; i<colptr[j+1]; i++) {
+	    u = rowind[i];
+	    err = fscanf(fp, " %lf ", &val);
+	    if (err == EOF || err != 1){ 
+		Cudd_RecursiveDeref(dd, cubey);
+		FREE(colptr);
+		FREE(rowind);
+		return(0);
+	    }
+	    /* Create new Constant node if necessary */
+	    cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
+	    if (cubex == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		FREE(colptr);
+		FREE(rowind);
+		return(0);
+	    }
+	    cuddRef(cubex);
+
+	    for (nv = lnx - 1; nv>=0; nv--) {
+		if (u & 1) {
+		    w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
+		} else { 
+		    w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
+		}
+		if (w == NULL) {
+		    Cudd_RecursiveDeref(dd, cubey);
+		    Cudd_RecursiveDeref(dd, cubex);
+		    FREE(colptr);
+		    FREE(rowind);
+		    return(0);
+		}
+		cuddRef(w);
+		Cudd_RecursiveDeref(dd, cubex);
+		cubex = w;
+		u >>= 1;
+	    }
+	    minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
+	    if (minterm1 == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		Cudd_RecursiveDeref(dd, cubex);
+		FREE(colptr);
+		FREE(rowind);
+		return(0);
+	    }
+	    cuddRef(minterm1);
+	    Cudd_RecursiveDeref(dd, cubex);
+	    w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		FREE(colptr);
+		FREE(rowind);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    Cudd_RecursiveDeref(dd, *E);
+	    *E = w;
+	}
+	Cudd_RecursiveDeref(dd, cubey);
+    }
+    FREE(colptr);
+    FREE(rowind);
+
+    /* Read right-hand sides */
+    for (j=0; j<nrhs; j++) {
+	v = j + (1<< (lny-1));
+	cubey = one; cuddRef(cubey);
+	for (nv = lny - 1; nv>=0; nv--) {
+	    if (v & 1) {
+		w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
+	    } else {
+		w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
+	    }
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd, cubey);
+	    cubey = w;
+	    v >>= 1;
+	}
+	for (i=0; i<nrow; i++) {
+	    u = i;
+	    err = fscanf(fp, " %lf ", &val);
+	    if (err == EOF || err != 1){ 
+		Cudd_RecursiveDeref(dd, cubey);
+		return(0);
+	    }
+	    /* Create new Constant node if necessary */
+	    if (val == (double) 0.0) continue;
+	    cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
+	    if (cubex == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		return(0);
+	    }
+	    cuddRef(cubex);
+
+	    for (nv = lnx - 1; nv>=0; nv--) {
+		if (u & 1) {
+		   w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
+		} else { 
+		    w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
+		}
+		if (w == NULL) {
+		    Cudd_RecursiveDeref(dd, cubey);
+		    Cudd_RecursiveDeref(dd, cubex);
+		    return(0);
+		}
+		cuddRef(w);
+		Cudd_RecursiveDeref(dd, cubex);
+		cubex = w;
+		u >>= 1;
+	    }
+	    minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
+	    if (minterm1 == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		Cudd_RecursiveDeref(dd, cubex);
+		return(0);
+	    }
+	    cuddRef(minterm1);
+	    Cudd_RecursiveDeref(dd, cubex);
+	    w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, cubey);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    Cudd_RecursiveDeref(dd, *E);
+	    *E = w;
+	}
+	Cudd_RecursiveDeref(dd, cubey);
+    }
+
+    return(1);
+
+} /* end of Cudd_addHarwell */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddInit.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddInit.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddInit.c	(revision 8)
@@ -0,0 +1,308 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddInit.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to initialize and shut down the DD manager.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_Init()
+		<li> Cudd_Quit()
+		</ul>
+	       Internal procedures included in this module:
+		<ul>
+		<li> cuddZddInitUniv()
+		<li> cuddZddFreeUniv()
+		</ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.32 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new DD manager.]
+
+  Description [Creates a new DD manager, initializes the table, the
+  basic constants and the projection functions. If maxMemory is 0,
+  Cudd_Init decides suitable values for the maximum size of the cache
+  and for the limit for fast unique table growth based on the available
+  memory. Returns a pointer to the manager if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Quit]
+
+******************************************************************************/
+DdManager *
+Cudd_Init(
+  unsigned int numVars /* initial number of BDD variables (i.e., subtables) */,
+  unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */,
+  unsigned int numSlots /* initial size of the unique tables */,
+  unsigned int cacheSize /* initial size of the cache */,
+  unsigned long maxMemory /* target maximum memory occupation */)
+{
+    DdManager *unique;
+    int i,result;
+    DdNode *one, *zero;
+    unsigned int maxCacheSize;
+    unsigned int looseUpTo;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (maxMemory == 0) {
+	maxMemory = getSoftDataLimit();
+    }
+    looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) /
+				DD_MAX_LOOSE_FRACTION);
+    unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo);
+    unique->maxmem = (unsigned long) maxMemory / 10 * 9;
+    if (unique == NULL) return(NULL);
+    maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) /
+				   DD_MAX_CACHE_FRACTION);
+    result = cuddInitCache(unique,cacheSize,maxCacheSize);
+    if (result == 0) return(NULL);
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4);
+    MMoutOfMemory = saveHandler;
+    if (unique->stash == NULL) {
+	(void) fprintf(unique->err,"Unable to set aside memory\n");
+    }
+
+    /* Initialize constants. */
+    unique->one = cuddUniqueConst(unique,1.0);
+    if (unique->one == NULL) return(0);
+    cuddRef(unique->one);
+    unique->zero = cuddUniqueConst(unique,0.0);
+    if (unique->zero == NULL) return(0);
+    cuddRef(unique->zero);
+#ifdef HAVE_IEEE_754
+    if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 ||
+	DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) {
+	(void) fprintf(unique->err,"Warning: Crippled infinite values\n");
+	(void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n");
+    }
+#endif
+    unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL);
+    if (unique->plusinfinity == NULL) return(0);
+    cuddRef(unique->plusinfinity);
+    unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL);
+    if (unique->minusinfinity == NULL) return(0);
+    cuddRef(unique->minusinfinity);
+    unique->background = unique->zero;
+
+    /* The logical zero is different from the CUDD_VALUE_TYPE zero! */
+    one = unique->one;
+    zero = Cudd_Not(one);
+    /* Create the projection functions. */
+    unique->vars = ALLOC(DdNodePtr,unique->maxSize);
+    if (unique->vars == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < unique->size; i++) {
+	unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
+	if (unique->vars[i] == NULL) return(0);
+	cuddRef(unique->vars[i]);
+    }
+
+    if (unique->sizeZ)
+	cuddZddInitUniv(unique);
+
+    unique->memused += sizeof(DdNode *) * unique->maxSize;
+
+    return(unique);
+
+} /* end of Cudd_Init */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes resources associated with a DD manager.]
+
+  Description [Deletes resources associated with a DD manager and
+  resets the global statistical counters. (Otherwise, another manaqger
+  subsequently created would inherit the stats of this one.)]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Init]
+
+******************************************************************************/
+void
+Cudd_Quit(
+  DdManager * unique)
+{
+    if (unique->stash != NULL) FREE(unique->stash);
+    cuddFreeTable(unique);
+
+} /* end of Cudd_Quit */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the ZDD universe.]
+
+  Description [Initializes the ZDD universe. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddFreeUniv]
+
+******************************************************************************/
+int
+cuddZddInitUniv(
+  DdManager * zdd)
+{
+    DdNode	*p, *res;
+    int		i;
+
+    zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ);
+    if (zdd->univ == NULL) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+
+    res = DD_ONE(zdd);
+    cuddRef(res);
+    for (i = zdd->sizeZ - 1; i >= 0; i--) {
+	unsigned int index = zdd->invpermZ[i];
+	p = res;
+	res = cuddUniqueInterZdd(zdd, index, p, p);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(zdd,p);
+	    FREE(zdd->univ);
+	    return(0);
+	}
+	cuddRef(res);
+	cuddDeref(p);
+	zdd->univ[i] = res;
+    }
+
+#ifdef DD_VERBOSE
+    cuddZddP(zdd, zdd->univ[0]);
+#endif
+
+    return(1);
+
+} /* end of cuddZddInitUniv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the ZDD universe.]
+
+  Description [Frees the ZDD universe.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddInitUniv]
+
+******************************************************************************/
+void
+cuddZddFreeUniv(
+  DdManager * zdd)
+{
+    if (zdd->univ) {
+	Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]);
+	FREE(zdd->univ);
+    }
+
+} /* end of cuddZddFreeUniv */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddInt.h
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddInt.h	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddInt.h	(revision 8)
@@ -0,0 +1,1203 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cuddInt.h]
+
+  PackageName [cudd]
+
+  Synopsis    [Internal data structures of the CUDD package.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: cuddInt.h,v 1.138 2004/08/13 18:04:49 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CUDDINT
+#define _CUDDINT
+
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#ifdef DD_MIS
+#include "array.h"
+#include "list.h"
+#include "st.h"
+#include "espresso.h"
+#include "node.h"
+#ifdef SIS
+#include "graph.h"
+#include "astg.h"
+#endif
+#include "network.h"
+#endif
+
+#include <math.h>
+#include "cudd.h"
+#include "st.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__GNUC__)
+# define DD_INLINE __inline__
+# if (__GNUC__ >2 || __GNUC_MINOR__ >=7)
+#   define DD_UNUSED __attribute__ ((__unused__))
+# else
+#   define DD_UNUSED
+# endif
+#else
+# if defined(__cplusplus)
+#   define DD_INLINE inline
+# else
+#   define DD_INLINE
+# endif
+# define DD_UNUSED
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAXREF		((DdHalfWord) ~0)
+
+#define DD_DEFAULT_RESIZE	10	/* how many extra variables */
+					/* should be added when resizing */
+#define DD_MEM_CHUNK		1022
+
+/* These definitions work for CUDD_VALUE_TYPE == double */
+#define DD_ONE_VAL		(1.0)
+#define DD_ZERO_VAL		(0.0)
+#define DD_EPSILON		(1.0e-12)
+
+/* The definitions of +/- infinity in terms of HUGE_VAL work on
+** the DECstations and on many other combinations of OS/compiler.
+*/
+#ifdef HAVE_IEEE_754
+#  define DD_PLUS_INF_VAL	(HUGE_VAL)
+#else
+#  define DD_PLUS_INF_VAL	(10e301)
+#  define DD_CRI_HI_MARK	(10e150)
+#  define DD_CRI_LO_MARK	(-(DD_CRI_HI_MARK))
+#endif
+#define DD_MINUS_INF_VAL	(-(DD_PLUS_INF_VAL))
+
+#define DD_NON_CONSTANT		((DdNode *) 1)	/* for Cudd_bddIteConstant */
+
+/* Unique table and cache management constants. */
+#define DD_MAX_SUBTABLE_DENSITY 4	/* tells when to resize a subtable */
+/* gc when this percent are dead (measured w.r.t. slots, not keys)
+** The first limit (LO) applies normally. The second limit applies when
+** the package believes more space for the unique table (i.e., more dead
+** nodes) would improve performance, and the unique table is not already
+** too large. The third limit applies when memory is low.
+*/
+#define DD_GC_FRAC_LO		DD_MAX_SUBTABLE_DENSITY * 0.25
+#define DD_GC_FRAC_HI		DD_MAX_SUBTABLE_DENSITY * 1.0
+#define DD_GC_FRAC_MIN		0.2
+#define DD_MIN_HIT		30	/* resize cache when hit ratio
+					   above this percentage (default) */
+#define DD_MAX_LOOSE_FRACTION	5 /* 1 / (max fraction of memory used for
+				     unique table in fast growth mode) */
+#define DD_MAX_CACHE_FRACTION	3 /* 1 / (max fraction of memory used for
+				     computed table if resizing enabled) */
+#define DD_STASH_FRACTION	64 /* 1 / (fraction of memory set
+				      aside for emergencies) */
+#define DD_MAX_CACHE_TO_SLOTS_RATIO 4 /* used to limit the cache size */
+
+/* Variable ordering default parameter values. */
+#define DD_SIFT_MAX_VAR		1000
+#define DD_SIFT_MAX_SWAPS	2000000
+#define DD_DEFAULT_RECOMB	0
+#define DD_MAX_REORDER_GROWTH	1.2
+#define DD_FIRST_REORDER	4004	/* 4 for the constants */
+#define DD_DYN_RATIO		2	/* when to dynamically reorder */
+
+/* Primes for cache hash functions. */
+#define DD_P1			12582917
+#define DD_P2			4256249
+#define DD_P3			741457
+#define DD_P4			1618033999
+
+/* Cache tags for 3-operand operators.  These tags are stored in the
+** least significant bits of the cache operand pointers according to
+** the following scheme.  The tag consists of two hex digits.  Both digits
+** must be even, so that they do not interfere with complementation bits.
+** The least significant one is stored in Bits 3:1 of the f operand in the
+** cache entry.  Bit 1 is always 1, so that we can differentiate
+** three-operand operations from one- and two-operand operations.
+** Therefore, the least significant digit is one of {2,6,a,e}.  The most
+** significant digit occupies Bits 3:1 of the g operand in the cache
+** entry.  It can by any even digit between 0 and e.  This gives a total
+** of 5 bits for the tag proper, which means a maximum of 32 three-operand
+** operations. */
+#define DD_ADD_ITE_TAG				0x02
+#define DD_BDD_AND_ABSTRACT_TAG			0x06
+#define DD_BDD_XOR_EXIST_ABSTRACT_TAG		0x0a
+#define DD_BDD_ITE_TAG				0x0e
+#define DD_ADD_BDD_DO_INTERVAL_TAG		0x22
+#define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG	0x26
+#define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG	0x2a
+#define DD_BDD_COMPOSE_RECUR_TAG		0x2e
+#define DD_ADD_COMPOSE_RECUR_TAG		0x42
+#define DD_ADD_NON_SIM_COMPOSE_TAG		0x46
+#define DD_EQUIV_DC_TAG				0x4a
+#define DD_ZDD_ITE_TAG				0x4e
+#define DD_ADD_ITE_CONSTANT_TAG			0x62
+#define DD_ADD_EVAL_CONST_TAG			0x66
+#define DD_BDD_ITE_CONSTANT_TAG			0x6a
+#define DD_ADD_OUT_SUM_TAG			0x6e
+#define DD_BDD_LEQ_UNLESS_TAG			0x82
+#define DD_ADD_TRIANGLE_TAG			0x86
+
+/* Generator constants. */
+#define CUDD_GEN_CUBES 0
+#define CUDD_GEN_PRIMES 1
+#define CUDD_GEN_NODES 2
+#define CUDD_GEN_ZDD_PATHS 3
+#define CUDD_GEN_EMPTY 0
+#define CUDD_GEN_NONEMPTY 1
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+struct DdGen {
+    DdManager	*manager;
+    int		type;
+    int		status;
+    union {
+	struct {
+	    int			*cube;
+	    CUDD_VALUE_TYPE	value;
+	} cubes;
+	struct {
+	    int			*cube;
+	    DdNode		*ub;
+	} primes;
+	struct {
+	    int                 size;
+	} nodes;
+    } gen;
+    struct {
+	int	sp;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+	DdNode	**stack;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    } stack;
+    DdNode	*node;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/* Hooks in CUDD are functions that the application registers with the
+** manager so that they are called at appropriate times. The functions
+** are passed the manager as argument; they should return 1 if
+** successful and 0 otherwise.
+*/
+typedef struct DdHook {		/* hook list element */
+    DD_HFP f; /* function to be called */
+    struct DdHook *next;	/* next element in the list */
+} DdHook;
+
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+typedef long ptrint;
+typedef unsigned long ptruint;
+#else
+typedef int ptrint;
+typedef unsigned int ptruint;
+#endif
+
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+
+typedef DdNode *DdNodePtr;
+
+/* Generic local cache item. */
+typedef struct DdLocalCacheItem {
+    DdNode *value;
+#ifdef DD_CACHE_PROFILE
+    ptrint count;
+#endif
+    DdNode *key[1];
+} DdLocalCacheItem;
+
+/* Local cache. */
+typedef struct DdLocalCache {
+    DdLocalCacheItem *item;
+    unsigned int itemsize;
+    unsigned int keysize;
+    unsigned int slots;
+    int shift;
+    double lookUps;
+    double minHit;
+    double hits;
+    unsigned int maxslots;
+    DdManager *manager;
+    struct DdLocalCache *next;
+} DdLocalCache;
+
+/* Generic hash item. */
+typedef struct DdHashItem {
+    struct DdHashItem *next;
+    ptrint count;
+    DdNode *value;
+    DdNode *key[1];
+} DdHashItem;
+
+/* Local hash table */
+typedef struct DdHashTable {
+    unsigned int keysize;
+    unsigned int itemsize;
+    DdHashItem **bucket;
+    DdHashItem *nextFree;
+    DdHashItem **memoryList;
+    unsigned int numBuckets;
+    int shift;
+    unsigned int size;
+    unsigned int maxsize;
+    DdManager *manager;
+} DdHashTable;
+
+typedef struct DdCache {
+    DdNode *f,*g;		/* DDs */
+    ptruint h;			/* either operator or DD */
+    DdNode *data;		/* already constructed DD */
+#ifdef DD_CACHE_PROFILE
+    ptrint count;
+#endif
+} DdCache;
+
+typedef struct DdSubtable {	/* subtable for one index */
+    DdNode **nodelist;		/* hash table */
+    int shift;			/* shift for hash function */
+    unsigned int slots;		/* size of the hash table */
+    unsigned int keys;		/* number of nodes stored in this table */
+    unsigned int maxKeys;	/* slots * DD_MAX_SUBTABLE_DENSITY */
+    unsigned int dead;		/* number of dead nodes in this table */
+    unsigned int next;		/* index of next variable in group */
+    int bindVar;		/* flag to bind this variable to its level */
+    /* Fields for lazy sifting. */
+    Cudd_VariableType varType;  /* variable type (ps, ns, pi) */
+    int pairIndex;              /* corresponding variable index (ps <-> ns) */
+    int varHandled;		/* flag: 1 means variable is already handled */
+    Cudd_LazyGroupType varToBeGrouped; /* tells what grouping to apply */
+} DdSubtable;
+
+struct DdManager {	/* specialized DD symbol table */
+    /* Constants */
+    DdNode sentinel;		/* for collision lists */
+    DdNode *one;		/* constant 1 */
+    DdNode *zero;		/* constant 0 */
+    DdNode *plusinfinity;	/* plus infinity */
+    DdNode *minusinfinity;	/* minus infinity */
+    DdNode *background;		/* background value */
+    /* Computed Table */
+    DdCache *acache;		/* address of allocated memory for cache */
+    DdCache *cache;		/* the cache-based computed table */
+    unsigned int cacheSlots;	/* total number of cache entries */
+    int cacheShift;		/* shift value for cache hash function */
+    double cacheMisses;		/* number of cache misses (since resizing) */
+    double cacheHits;		/* number of cache hits (since resizing) */
+    double minHit;		/* hit percentage above which to resize */
+    int cacheSlack;		/* slots still available for resizing */
+    unsigned int maxCacheHard;	/* hard limit for cache size */
+    /* Unique Table */
+    int size;			/* number of unique subtables */
+    int sizeZ;			/* for ZDD */
+    int maxSize;		/* max number of subtables before resizing */
+    int maxSizeZ;		/* for ZDD */
+    DdSubtable *subtables;	/* array of unique subtables */
+    DdSubtable *subtableZ;	/* for ZDD */
+    DdSubtable constants;	/* unique subtable for the constants */
+    unsigned int slots;		/* total number of hash buckets */
+    unsigned int keys;		/* total number of BDD and ADD nodes */
+    unsigned int keysZ;		/* total number of ZDD nodes */
+    unsigned int dead;		/* total number of dead BDD and ADD nodes */
+    unsigned int deadZ;		/* total number of dead ZDD nodes */
+    unsigned int maxLive;	/* maximum number of live nodes */
+    unsigned int minDead;	/* do not GC if fewer than these dead */
+    double gcFrac;		/* gc when this fraction is dead */
+    int gcEnabled;		/* gc is enabled */
+    unsigned int looseUpTo;	/* slow growth beyond this limit */
+				/* (measured w.r.t. slots, not keys) */
+    unsigned int initSlots;	/* initial size of a subtable */
+    DdNode **stack;		/* stack for iterative procedures */
+    double allocated;		/* number of nodes allocated */
+				/* (not during reordering) */
+    double reclaimed;		/* number of nodes brought back from the dead */
+    int isolated;		/* isolated projection functions */
+    int *perm;			/* current variable perm. (index to level) */
+    int *permZ;			/* for ZDD */
+    int *invperm;		/* current inv. var. perm. (level to index) */
+    int *invpermZ;		/* for ZDD */
+    DdNode **vars;		/* projection functions */
+    int *map;			/* variable map for fast swap */
+    DdNode **univ;		/* ZDD 1 for each variable */
+    int linearSize;		/* number of rows and columns of linear */
+    long *interact;		/* interacting variable matrix */
+    long *linear;		/* linear transform matrix */
+    /* Memory Management */
+    DdNode **memoryList;	/* memory manager for symbol table */
+    DdNode *nextFree;		/* list of free nodes */
+    char *stash;		/* memory reserve */
+#ifndef DD_NO_DEATH_ROW
+    DdNode **deathRow;		/* queue for dereferencing */
+    int deathRowDepth;		/* number of slots in the queue */
+    int nextDead;		/* index in the queue */
+    unsigned deadMask;		/* mask for circular index update */
+#endif
+    /* General Parameters */
+    CUDD_VALUE_TYPE epsilon;	/* tolerance on comparisons */
+    /* Dynamic Reordering Parameters */
+    int reordered;		/* flag set at the end of reordering */
+    int reorderings;		/* number of calls to Cudd_ReduceHeap */
+    int siftMaxVar;		/* maximum number of vars sifted */
+    int siftMaxSwap;		/* maximum number of swaps per sifting */
+    double maxGrowth;		/* maximum growth during reordering */
+    double maxGrowthAlt;	/* alternate maximum growth for reordering */
+    int reordCycle;		/* how often to apply alternate threshold */
+    int autoDyn;		/* automatic dynamic reordering flag (BDD) */
+    int autoDynZ;		/* automatic dynamic reordering flag (ZDD) */
+    Cudd_ReorderingType autoMethod;  /* default reordering method */
+    Cudd_ReorderingType autoMethodZ; /* default reordering method (ZDD) */
+    int realign;		/* realign ZDD order after BDD reordering */
+    int realignZ;		/* realign BDD order after ZDD reordering */
+    unsigned int nextDyn;	/* reorder if this size is reached */
+    unsigned int countDead;	/* if 0, count deads to trigger reordering */
+    MtrNode *tree;		/* Variable group tree (BDD) */
+    MtrNode *treeZ;		/* Variable group tree (ZDD) */
+    Cudd_AggregationType groupcheck; /* Used during group sifting */
+    int recomb;			/* Used during group sifting */
+    int symmviolation;		/* Used during group sifting */
+    int arcviolation;		/* Used during group sifting */
+    int populationSize;		/* population size for GA */
+    int	numberXovers;		/* number of crossovers for GA */
+    DdLocalCache *localCaches;	/* local caches currently in existence */
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    char *hooks;		/* application-specific field (used by vis) */
+    DdHook *preGCHook;		/* hooks to be called before GC */
+    DdHook *postGCHook;		/* hooks to be called after GC */
+    DdHook *preReorderingHook;	/* hooks to be called before reordering */
+    DdHook *postReorderingHook;	/* hooks to be called after reordering */
+    FILE *out;			/* stdout for this manager */
+    FILE *err;			/* stderr for this manager */
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    Cudd_ErrorType errorCode;	/* info on last error */
+    /* Statistical counters. */
+    unsigned long memused;	/* total memory allocated for the manager */
+    unsigned long maxmem;	/* target maximum memory */
+    unsigned long maxmemhard;	/* hard limit for maximum memory */
+    int garbageCollections;	/* number of garbage collections */
+    long GCTime;		/* total time spent in garbage collection */
+    long reordTime;		/* total time spent in reordering */
+    double totCachehits;	/* total number of cache hits */
+    double totCacheMisses;	/* total number of cache misses */
+    double cachecollisions;	/* number of cache collisions */
+    double cacheinserts;	/* number of cache insertions */
+    double cacheLastInserts;	/* insertions at the last cache resizing */
+    double cachedeletions;	/* number of deletions during garbage coll. */
+#ifdef DD_STATS
+    double nodesFreed;		/* number of nodes returned to the free list */
+    double nodesDropped;	/* number of nodes killed by dereferencing */
+#endif
+    unsigned int peakLiveNodes;	/* maximum number of live nodes */
+#ifdef DD_UNIQUE_PROFILE
+    double uniqueLookUps;	/* number of unique table lookups */
+    double uniqueLinks;		/* total distance traveled in coll. chains */
+#endif
+#ifdef DD_COUNT
+    double recursiveCalls;	/* number of recursive calls */
+#ifdef DD_STATS
+    double nextSample;		/* when to write next line of stats */
+#endif
+    double swapSteps;		/* number of elementary reordering steps */
+#endif
+#ifdef DD_MIS
+    /* mis/verif compatibility fields */
+    array_t *iton;		/* maps ids in ddNode to node_t */
+    array_t *order;		/* copy of order_list */
+    lsHandle handle;		/* where it is in network BDD list */
+    network_t *network;
+    st_table *local_order;	/* for local BDDs */
+    int nvars;			/* variables used so far */
+    int threshold;		/* for pseudo var threshold value*/
+#endif
+};
+
+typedef struct Move {
+    DdHalfWord x;
+    DdHalfWord y;
+    unsigned int flags;
+    int size;
+    struct Move *next;
+} Move;
+
+/* Generic level queue item. */
+typedef struct DdQueueItem {
+    struct DdQueueItem *next;
+    struct DdQueueItem *cnext;
+    void *key;
+} DdQueueItem;
+
+/* Level queue. */
+typedef struct DdLevelQueue {
+    void *first;
+    DdQueueItem **last;
+    DdQueueItem *freelist;
+    DdQueueItem **buckets;
+    int levels;
+    int itemsize;
+    int size;
+    int maxsize;
+    int numBuckets;
+    int shift;
+} DdLevelQueue;
+
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Adds node to the head of the free list.]
+
+  Description [Adds node to the head of the free list.  Does not
+  deallocate memory chunks that become free.  This function is also
+  used by the dynamic reordering functions.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAllocNode cuddDynamicAllocNode cuddDeallocMove]
+
+******************************************************************************/
+#define cuddDeallocNode(unique,node) \
+    (node)->next = (unique)->nextFree; \
+    (unique)->nextFree = node;
+
+/**Macro***********************************************************************
+
+  Synopsis    [Adds node to the head of the free list.]
+
+  Description [Adds node to the head of the free list.  Does not
+  deallocate memory chunks that become free.  This function is also
+  used by the dynamic reordering functions.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddDeallocNode cuddDynamicAllocNode]
+
+******************************************************************************/
+#define cuddDeallocMove(unique,node) \
+    ((DdNode *)(node))->ref = 0; \
+    ((DdNode *)(node))->next = (unique)->nextFree; \
+    (unique)->nextFree = (DdNode *)(node);
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Increases the reference count of a node, if it is not
+  saturated.]
+
+  Description  [Increases the reference count of a node, if it is not
+  saturated. This being a macro, it is faster than Cudd_Ref, but it
+  cannot be used in constructs like cuddRef(a = b()).]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Ref]
+
+******************************************************************************/
+#define cuddRef(n) cuddSatInc(Cudd_Regular(n)->ref)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Decreases the reference count of a node, if it is not
+  saturated.]
+
+  Description  [Decreases the reference count of node. It is primarily
+  used in recursive procedures to decrease the ref count of a result
+  node before returning it. This accomplishes the goal of removing the
+  protection applied by a previous cuddRef. This being a macro, it is
+  faster than Cudd_Deref, but it cannot be used in constructs like
+  cuddDeref(a = b()).]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_Deref]
+
+******************************************************************************/
+#define cuddDeref(n) cuddSatDec(Cudd_Regular(n)->ref)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns 1 if the node is a constant node.]
+
+  Description  [Returns 1 if the node is a constant node (rather than an
+  internal node). All constant nodes have the same index
+  (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_IsConstant]
+
+******************************************************************************/
+#define cuddIsConstant(node) ((node)->index == CUDD_CONST_INDEX)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the then child of an internal node.]
+
+  Description  [Returns the then child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.
+  The pointer passed to cuddT must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_T]
+
+******************************************************************************/
+#define cuddT(node) ((node)->type.kids.T)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the else child of an internal node.]
+
+  Description  [Returns the else child of an internal node. If
+  <code>node</code> is a constant node, the result is unpredictable.
+  The pointer passed to cuddE must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_E]
+
+******************************************************************************/
+#define cuddE(node) ((node)->type.kids.E)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the value of a constant node.]
+
+  Description  [Returns the value of a constant node. If
+  <code>node</code> is an internal node, the result is unpredictable.
+  The pointer passed to cuddV must be regular.]
+
+  SideEffects  [none]
+
+  SeeAlso      [Cudd_V]
+
+******************************************************************************/
+#define cuddV(node) ((node)->type.value)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Finds the current position of variable index in the
+  order.]
+
+  Description [Finds the current position of variable index in the
+  order.  This macro duplicates the functionality of Cudd_ReadPerm,
+  but it does not check for out-of-bounds indices and it is more
+  efficient.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadPerm]
+
+******************************************************************************/
+#define	cuddI(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)])
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Finds the current position of ZDD variable index in the
+  order.]
+
+  Description [Finds the current position of ZDD variable index in the
+  order.  This macro duplicates the functionality of Cudd_ReadPermZdd,
+  but it does not check for out-of-bounds indices and it is more
+  efficient.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_ReadPermZdd]
+
+******************************************************************************/
+#define	cuddIZ(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)])
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the unique table.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddCHash ddCHash2]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddHash(f,g,s) \
+((((unsigned)(unsigned long)(f) * DD_P1 + \
+   (unsigned)(unsigned long)(g)) * DD_P2) >> (s))
+#else
+#define ddHash(f,g,s) \
+((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the cache.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddHash ddCHash2]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddCHash(o,f,g,h,s) \
+((((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \
+    (unsigned)(unsigned long)(g)) * DD_P2 + \
+   (unsigned)(unsigned long)(h)) * DD_P3) >> (s))
+#else
+#define ddCHash(o,f,g,h,s) \
+((((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2 + \
+   (unsigned)(h)) * DD_P3) >> (s))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the cache for functions with two
+  operands.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddHash ddCHash]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddCHash2(o,f,g,s) \
+(((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \
+   (unsigned)(unsigned long)(g)) * DD_P2) >> (s))
+#else
+#define ddCHash2(o,f,g,s) \
+(((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Clears the 4 least significant bits of a pointer.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define cuddClean(p) ((DdNode *)((ptruint)(p) & ~0xf))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes the minimum of two numbers.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddMax]
+
+******************************************************************************/
+#define ddMin(x,y) (((y) < (x)) ? (y) : (x))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes the maximum of two numbers.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [ddMin]
+
+******************************************************************************/
+#define ddMax(x,y) (((y) > (x)) ? (y) : (x))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes the absolute value of a number.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define ddAbs(x) (((x)<0) ? -(x) : (x))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns 1 if the absolute value of the difference of the two
+  arguments x and y is less than e.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define ddEqualVal(x,y,e) (ddAbs((x)-(y))<(e))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Saturating increment operator.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [cuddSatDec]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define cuddSatInc(x) ((x)++)
+#else
+#define cuddSatInc(x) ((x) += (x) != (DdHalfWord)DD_MAXREF)
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Saturating decrement operator.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [cuddSatInc]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define cuddSatDec(x) ((x)--)
+#else
+#define cuddSatDec(x) ((x) -= (x) != (DdHalfWord)DD_MAXREF)
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the constant 1 node.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ZERO DD_PLUS_INFINITY DD_MINUS_INFINITY]
+
+******************************************************************************/
+#define DD_ONE(dd)		((dd)->one)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the arithmetic 0 constant node.]
+
+  Description [Returns the arithmetic 0 constant node. This is different
+  from the logical zero. The latter is obtained by
+  Cudd_Not(DD_ONE(dd)).]
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY]
+
+******************************************************************************/
+#define DD_ZERO(dd) ((dd)->zero)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the plus infinity constant node.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ONE DD_ZERO DD_MINUS_INFINITY]
+
+******************************************************************************/
+#define DD_PLUS_INFINITY(dd) ((dd)->plusinfinity)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the minus infinity constant node.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [DD_ONE DD_ZERO DD_PLUS_INFINITY]
+
+******************************************************************************/
+#define DD_MINUS_INFINITY(dd) ((dd)->minusinfinity)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.]
+
+  Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.
+  Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to
+  DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to
+  DD_PLUS_INF_VAL.  Normally this macro is a NOOP. However, if
+  HAVE_IEEE_754 is not defined, it makes sure that a value does not
+  get larger than infinity in absolute value, and once it gets to
+  infinity, stays there.  If the value overflows before this macro is
+  applied, no recovery is possible.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef HAVE_IEEE_754
+#define cuddAdjust(x)
+#else
+#define cuddAdjust(x)		((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x)))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Extract the least significant digit of a double digit.]
+
+  Description [Extract the least significant digit of a double digit. Used
+  in the manipulation of arbitrary precision integers.]
+
+  SideEffects [None]
+
+  SeeAlso     [DD_MSDIGIT]
+
+******************************************************************************/
+#define DD_LSDIGIT(x)	((x) & DD_APA_MASK)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Extract the most significant digit of a double digit.]
+
+  Description [Extract the most significant digit of a double digit. Used
+  in the manipulation of arbitrary precision integers.]
+
+  SideEffects [None]
+
+  SeeAlso     [DD_LSDIGIT]
+
+******************************************************************************/
+#define DD_MSDIGIT(x)	((x) >> DD_APA_BITS)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Outputs a line of stats.]
+
+  Description [Outputs a line of stats if DD_COUNT and DD_STATS are
+  defined. Increments the number of recursive calls if DD_COUNT is
+  defined.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef DD_COUNT
+#ifdef DD_STATS
+#define statLine(dd) dd->recursiveCalls++; \
+if (dd->recursiveCalls == dd->nextSample) {(void) fprintf(dd->err, \
+"@%.0f: %u nodes %u live %.0f dropped %.0f reclaimed\n", dd->recursiveCalls, \
+dd->keys, dd->keys - dd->dead, dd->nodesDropped, dd->reclaimed); \
+dd->nextSample += 250000;}
+#else
+#define statLine(dd) dd->recursiveCalls++;
+#endif
+#else
+#define statLine(dd)
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern DdNode * cuddAddExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * cuddAddUnivAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * cuddAddOrAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * cuddAddApplyRecur (DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g);
+extern DdNode * cuddAddMonadicApplyRecur (DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f);
+extern DdNode * cuddAddScalarInverseRecur (DdManager *dd, DdNode *f, DdNode *epsilon);
+extern DdNode * cuddAddIteRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * cuddAddCmplRecur (DdManager *dd, DdNode *f);
+extern DdNode * cuddAddNegateRecur (DdManager *dd, DdNode *f);
+extern DdNode * cuddAddRoundOffRecur (DdManager *dd, DdNode *f, double trunc);
+extern DdNode * cuddUnderApprox (DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality);
+extern DdNode * cuddRemapUnderApprox (DdManager *dd, DdNode *f, int numVars, int threshold, double quality);
+extern DdNode * cuddBiasedUnderApprox (DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0);
+extern DdNode * cuddBddAndAbstractRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube);
+extern int cuddAnnealing (DdManager *table, int lower, int upper);
+extern DdNode * cuddBddExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *cube);
+extern DdNode * cuddBddXorExistAbstractRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube);
+extern DdNode * cuddBddBooleanDiffRecur (DdManager *manager, DdNode *f, DdNode *var);
+extern DdNode * cuddBddIteRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * cuddBddIntersectRecur (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * cuddBddAndRecur (DdManager *manager, DdNode *f, DdNode *g);
+extern DdNode * cuddBddXorRecur (DdManager *manager, DdNode *f, DdNode *g);
+extern DdNode * cuddBddTransfer (DdManager *ddS, DdManager *ddD, DdNode *f);
+extern DdNode * cuddAddBddDoPattern (DdManager *dd, DdNode *f);
+extern int cuddInitCache (DdManager *unique, unsigned int cacheSize, unsigned int maxCacheSize);
+extern void cuddCacheInsert (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data);
+extern void cuddCacheInsert2 (DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g, DdNode *data);
+extern void cuddCacheInsert1 (DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f, DdNode *data);
+extern DdNode * cuddCacheLookup (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * cuddCacheLookupZdd (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * cuddCacheLookup2 (DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g);
+extern DdNode * cuddCacheLookup1 (DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f);
+extern DdNode * cuddCacheLookup2Zdd (DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g);
+extern DdNode * cuddCacheLookup1Zdd (DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f);
+extern DdNode * cuddConstantLookup (DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h);
+extern int cuddCacheProfile (DdManager *table, FILE *fp);
+extern void cuddCacheResize (DdManager *table);
+extern void cuddCacheFlush (DdManager *table);
+extern int cuddComputeFloorLog2 (unsigned int value);
+extern int cuddHeapProfile (DdManager *dd);
+extern void cuddPrintNode (DdNode *f, FILE *fp);
+extern void cuddPrintVarGroups (DdManager * dd, MtrNode * root, int zdd, int silent);
+extern DdNode * cuddBddClippingAnd (DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction);
+extern DdNode * cuddBddClippingAndAbstract (DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction);
+extern void cuddGetBranches (DdNode *g, DdNode **g1, DdNode **g0);
+extern int cuddCheckCube (DdManager *dd, DdNode *g);
+extern DdNode * cuddCofactorRecur (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * cuddBddComposeRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *proj);
+extern DdNode * cuddAddComposeRecur (DdManager *dd, DdNode *f, DdNode *g, DdNode *proj);
+extern int cuddExact (DdManager *table, int lower, int upper);
+extern DdNode * cuddBddConstrainRecur (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * cuddBddRestrictRecur (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * cuddBddNPAndRecur (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * cuddAddConstrainRecur (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * cuddAddRestrictRecur (DdManager *dd, DdNode *f, DdNode *c);
+extern DdNode * cuddBddLICompaction (DdManager *dd, DdNode *f, DdNode *c);
+extern int cuddGa (DdManager *table, int lower, int upper);
+extern int cuddTreeSifting (DdManager *table, Cudd_ReorderingType method);
+extern int cuddZddInitUniv (DdManager *zdd);
+extern void cuddZddFreeUniv (DdManager *zdd);
+extern void cuddSetInteract (DdManager *table, int x, int y);
+extern int cuddTestInteract (DdManager *table, int x, int y);
+extern int cuddInitInteract (DdManager *table);
+extern DdLocalCache * cuddLocalCacheInit (DdManager *manager, unsigned int keySize, unsigned int cacheSize, unsigned int maxCacheSize);
+extern void cuddLocalCacheQuit (DdLocalCache *cache);
+extern void cuddLocalCacheInsert (DdLocalCache *cache, DdNodePtr *key, DdNode *value);
+extern DdNode * cuddLocalCacheLookup (DdLocalCache *cache, DdNodePtr *key);
+extern void cuddLocalCacheClearDead (DdManager *manager);
+extern int cuddIsInDeathRow (DdManager *dd, DdNode *f);
+extern int cuddTimesInDeathRow (DdManager *dd, DdNode *f);
+extern void cuddLocalCacheClearAll (DdManager *manager);
+#ifdef DD_CACHE_PROFILE
+extern int cuddLocalCacheProfile (DdLocalCache *cache);
+#endif
+extern DdHashTable * cuddHashTableInit (DdManager *manager, unsigned int keySize, unsigned int initSize);
+extern void cuddHashTableQuit (DdHashTable *hash);
+extern int cuddHashTableInsert (DdHashTable *hash, DdNodePtr *key, DdNode *value, ptrint count);
+extern DdNode * cuddHashTableLookup (DdHashTable *hash, DdNodePtr *key);
+extern int cuddHashTableInsert1 (DdHashTable *hash, DdNode *f, DdNode *value, ptrint count);
+extern DdNode * cuddHashTableLookup1 (DdHashTable *hash, DdNode *f);
+extern int cuddHashTableInsert2 (DdHashTable *hash, DdNode *f, DdNode *g, DdNode *value, ptrint count);
+extern DdNode * cuddHashTableLookup2 (DdHashTable *hash, DdNode *f, DdNode *g);
+extern int cuddHashTableInsert3 (DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h, DdNode *value, ptrint count);
+extern DdNode * cuddHashTableLookup3 (DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h);
+extern DdLevelQueue * cuddLevelQueueInit (int levels, int itemSize, int numBuckets);
+extern void cuddLevelQueueQuit (DdLevelQueue *queue);
+extern void * cuddLevelQueueEnqueue (DdLevelQueue *queue, void *key, int level);
+extern void cuddLevelQueueDequeue (DdLevelQueue *queue, int level);
+extern int cuddLinearAndSifting (DdManager *table, int lower, int upper);
+extern int cuddLinearInPlace (DdManager * table, int  x, int  y);
+extern void cuddUpdateInteractionMatrix (DdManager * table, int  xindex, int  yindex);
+extern int cuddInitLinear (DdManager *table);
+extern int cuddResizeLinear (DdManager *table);
+extern DdNode * cuddBddLiteralSetIntersectionRecur (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode * cuddCProjectionRecur (DdManager *dd, DdNode *R, DdNode *Y, DdNode *Ysupp);
+extern DdNode * cuddBddClosestCube (DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE bound);
+extern void cuddReclaim (DdManager *table, DdNode *n);
+extern void cuddReclaimZdd (DdManager *table, DdNode *n);
+extern void cuddClearDeathRow (DdManager *table);
+extern void cuddShrinkDeathRow (DdManager *table);
+extern DdNode * cuddDynamicAllocNode (DdManager *table);
+extern int cuddSifting (DdManager *table, int lower, int upper);
+extern int cuddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic);
+extern int cuddNextHigh (DdManager *table, int x);
+extern int cuddNextLow (DdManager *table, int x);
+extern int cuddSwapInPlace (DdManager *table, int x, int y);
+extern int cuddBddAlignToZdd (DdManager *table);
+extern DdNode * cuddBddMakePrime (DdManager *dd, DdNode *cube, DdNode *f);
+extern DdNode * cuddSolveEqnRecur (DdManager *bdd, DdNode *F, DdNode *Y, DdNode **G, int n, int *yIndex, int i);
+extern DdNode * cuddVerifySol (DdManager *bdd, DdNode *F, DdNode **G, int *yIndex, int n);
+#ifdef ST_INCLUDED
+extern DdNode* cuddSplitSetRecur (DdManager *manager, st_table *mtable, int *varSeen, DdNode *p, double n, double max, int index);
+#endif
+extern DdNode * cuddSubsetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold);
+extern DdNode * cuddSubsetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit);
+extern int cuddSymmCheck (DdManager *table, int x, int y);
+extern int cuddSymmSifting (DdManager *table, int lower, int upper);
+extern int cuddSymmSiftingConv (DdManager *table, int lower, int upper);
+extern DdNode * cuddAllocNode (DdManager *unique);
+extern DdManager * cuddInitTable (unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo);
+extern void cuddFreeTable (DdManager *unique);
+extern int cuddGarbageCollect (DdManager *unique, int clearCache);
+extern DdNode * cuddZddGetNode (DdManager *zdd, int id, DdNode *T, DdNode *E);
+extern DdNode * cuddZddGetNodeIVO (DdManager *dd, int index, DdNode *g, DdNode *h);
+extern DdNode * cuddUniqueInter (DdManager *unique, int index, DdNode *T, DdNode *E);
+extern DdNode * cuddUniqueInterIVO (DdManager *unique, int index, DdNode *T, DdNode *E);
+extern DdNode * cuddUniqueInterZdd (DdManager *unique, int index, DdNode *T, DdNode *E);
+extern DdNode * cuddUniqueConst (DdManager *unique, CUDD_VALUE_TYPE value);
+extern void cuddRehash (DdManager *unique, int i);
+extern void cuddShrinkSubtable (DdManager *unique, int i);
+extern int cuddInsertSubtables (DdManager *unique, int n, int level);
+extern int cuddDestroySubtables (DdManager *unique, int n);
+extern int cuddResizeTableZdd (DdManager *unique, int index);
+extern void cuddSlowTableGrowth (DdManager *unique);
+extern int cuddP (DdManager *dd, DdNode *f);
+#ifdef ST_INCLUDED
+extern enum st_retval cuddStCountfree (char *key, char *value, char *arg);
+extern int cuddCollectNodes (DdNode *f, st_table *visited);
+#endif
+extern DdNodePtr * cuddNodeArray (DdNode *f, int *n);
+extern int cuddWindowReorder (DdManager *table, int low, int high, Cudd_ReorderingType submethod);
+extern DdNode	* cuddZddProduct (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* cuddZddUnateProduct (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* cuddZddWeakDiv (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* cuddZddWeakDivF (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* cuddZddDivide (DdManager *dd, DdNode *f, DdNode *g);
+extern DdNode	* cuddZddDivideF (DdManager *dd, DdNode *f, DdNode *g);
+extern int cuddZddGetCofactors3 (DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0, DdNode **fd);
+extern int cuddZddGetCofactors2 (DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0);
+extern DdNode	* cuddZddComplement (DdManager *dd, DdNode *node);
+extern int cuddZddGetPosVarIndex(DdManager * dd, int index);
+extern int cuddZddGetNegVarIndex(DdManager * dd, int index);
+extern int cuddZddGetPosVarLevel(DdManager * dd, int index);
+extern int cuddZddGetNegVarLevel(DdManager * dd, int index);
+extern int cuddZddTreeSifting (DdManager *table, Cudd_ReorderingType method);
+extern DdNode	* cuddZddIsop (DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I);
+extern DdNode	* cuddBddIsop (DdManager *dd, DdNode *L, DdNode *U);
+extern DdNode	* cuddMakeBddFromZddCover (DdManager *dd, DdNode *node);
+extern int cuddZddLinearSifting (DdManager *table, int lower, int upper);
+extern int cuddZddAlignToBdd (DdManager *table);
+extern int cuddZddNextHigh (DdManager *table, int x);
+extern int cuddZddNextLow (DdManager *table, int x);
+extern int cuddZddUniqueCompare (int *ptr_x, int *ptr_y);
+extern int cuddZddSwapInPlace (DdManager *table, int x, int y);
+extern int cuddZddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic);
+extern int cuddZddSifting (DdManager *table, int lower, int upper);
+extern DdNode * cuddZddIte (DdManager *dd, DdNode *f, DdNode *g, DdNode *h);
+extern DdNode * cuddZddUnion (DdManager *zdd, DdNode *P, DdNode *Q);
+extern DdNode * cuddZddIntersect (DdManager *zdd, DdNode *P, DdNode *Q);
+extern DdNode * cuddZddDiff (DdManager *zdd, DdNode *P, DdNode *Q);
+extern DdNode * cuddZddChangeAux (DdManager *zdd, DdNode *P, DdNode *zvar);
+extern DdNode * cuddZddSubset1 (DdManager *dd, DdNode *P, int var);
+extern DdNode * cuddZddSubset0 (DdManager *dd, DdNode *P, int var);
+extern DdNode * cuddZddChange (DdManager *dd, DdNode *P, int var);
+extern int cuddZddSymmCheck (DdManager *table, int x, int y);
+extern int cuddZddSymmSifting (DdManager *table, int lower, int upper);
+extern int cuddZddSymmSiftingConv (DdManager *table, int lower, int upper);
+extern int cuddZddP (DdManager *zdd, DdNode *f);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _CUDDINT */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddInteract.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddInteract.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddInteract.c	(revision 8)
@@ -0,0 +1,429 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddInteract.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to manipulate the variable interaction matrix.]
+
+  Description [Internal procedures included in this file:
+	<ul>
+	<li> cuddSetInteract()
+	<li> cuddTestInteract()
+	<li> cuddInitInteract()
+	</ul>
+  Static procedures included in this file:
+	<ul>
+	<li> ddSuppInteract()
+	<li> ddClearLocal()
+	<li> ddUpdateInteract()
+	<li> ddClearGlobal()
+	</ul>
+  The interaction matrix tells whether two variables are
+  both in the support of some function of the DD. The main use of the
+  interaction matrix is in the in-place swapping. Indeed, if two
+  variables do not interact, there is no arc connecting the two layers;
+  therefore, the swap can be performed in constant time, without
+  scanning the subtables. Another use of the interaction matrix is in
+  the computation of the lower bounds for sifting. Finally, the
+  interaction matrix can be used to speed up aggregation checks in
+  symmetric and group sifting.<p>
+  The computation of the interaction matrix is done with a series of
+  depth-first searches. The searches start from those nodes that have
+  only external references. The matrix is stored as a packed array of bits;
+  since it is symmetric, only the upper triangle is kept in memory.
+  As a final remark, we note that there may be variables that do
+  intercat, but that for a given variable order have no arc connecting
+  their layers when they are adjacent.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#if SIZEOF_LONG == 8
+#define BPL 64
+#define LOGBPL 6
+#else
+#define BPL 32
+#define LOGBPL 5
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.12 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ddSuppInteract (DdNode *f, int *support);
+static void ddClearLocal (DdNode *f);
+static void ddUpdateInteract (DdManager *table, int *support);
+static void ddClearGlobal (DdManager *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set interaction matrix entries.]
+
+  Description [Given a pair of variables 0 <= x < y < table->size,
+  sets the corresponding bit of the interaction matrix to 1.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddSetInteract(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int posn, word, bit;
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(y < table->size);
+    assert(x >= 0);
+#endif
+
+    posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
+    word = posn >> LOGBPL;
+    bit = posn & (BPL-1);
+    table->interact[word] |= 1L << bit;
+
+} /* end of cuddSetInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Test interaction matrix entries.]
+
+  Description [Given a pair of variables 0 <= x < y < table->size,
+  tests whether the corresponding bit of the interaction matrix is 1.
+  Returns the value of the bit.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddTestInteract(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int posn, word, bit, result;
+
+    if (x > y) {
+	int tmp = x;
+	x = y;
+	y = tmp;
+    }
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(y < table->size);
+    assert(x >= 0);
+#endif
+
+    posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
+    word = posn >> LOGBPL;
+    bit = posn & (BPL-1);
+    result = (table->interact[word] >> bit) & 1L;
+    return(result);
+
+} /* end of cuddTestInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the interaction matrix.]
+
+  Description [Initializes the interaction matrix. The interaction
+  matrix is implemented as a bit vector storing the upper triangle of
+  the symmetric interaction matrix. The bit vector is kept in an array
+  of long integers. The computation is based on a series of depth-first
+  searches, one for each root of the DAG. Two flags are needed: The
+  local visited flag uses the LSB of the then pointer. The global
+  visited flag uses the LSB of the next pointer.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddInitInteract(
+  DdManager * table)
+{
+    int i,j,k;
+    int words;
+    long *interact;
+    int *support;
+    DdNode *f;
+    DdNode *sentinel = &(table->sentinel);
+    DdNodePtr *nodelist;
+    int slots;
+    int n = table->size;
+
+    words = ((n * (n-1)) >> (1 + LOGBPL)) + 1;
+    table->interact = interact = ALLOC(long,words);
+    if (interact == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < words; i++) {
+	interact[i] = 0;
+    }
+
+    support = ALLOC(int,n);
+    if (support == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	FREE(interact);
+	return(0);
+    }
+
+    for (i = 0; i < n; i++) {
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+	for (j = 0; j < slots; j++) {
+	    f = nodelist[j];
+	    while (f != sentinel) {
+		/* A node is a root of the DAG if it cannot be
+		** reached by nodes above it. If a node was never
+		** reached during the previous depth-first searches,
+		** then it is a root, and we start a new depth-first
+		** search from it.
+		*/
+		if (!Cudd_IsComplement(f->next)) {
+		    for (k = 0; k < n; k++) {
+			support[k] = 0;
+		    }
+		    ddSuppInteract(f,support);
+		    ddClearLocal(f);
+		    ddUpdateInteract(table,support);
+		}
+		f = Cudd_Regular(f->next);
+	    }
+	}
+    }
+    ddClearGlobal(table);
+
+    FREE(support);
+    return(1);
+
+} /* end of cuddInitInteract */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find the support of f.]
+
+  Description [Performs a DFS from f. Uses the LSB of the then pointer
+  as visited flag.]
+
+  SideEffects [Accumulates in support the variables on which f depends.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddSuppInteract(
+  DdNode * f,
+  int * support)
+{
+    if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) {
+	return;
+    }
+
+    support[f->index] = 1;
+    ddSuppInteract(cuddT(f),support);
+    ddSuppInteract(Cudd_Regular(cuddE(f)),support);
+    /* mark as visited */
+    cuddT(f) = Cudd_Complement(cuddT(f));
+    f->next = Cudd_Complement(f->next);
+    return;
+
+} /* end of ddSuppInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a DFS from f, clearing the LSB of the then pointers.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddClearLocal(
+  DdNode * f)
+{
+    if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) {
+	return;
+    }
+    /* clear visited flag */
+    cuddT(f) = Cudd_Regular(cuddT(f));
+    ddClearLocal(cuddT(f));
+    ddClearLocal(Cudd_Regular(cuddE(f)));
+    return;
+
+} /* end of ddClearLocal */
+
+
+/**Function********************************************************************
+
+  Synopsis [Marks as interacting all pairs of variables that appear in
+  support.]
+
+  Description [If support[i] == support[j] == 1, sets the (i,j) entry
+  of the interaction matrix to 1.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddUpdateInteract(
+  DdManager * table,
+  int * support)
+{
+    int i,j;
+    int n = table->size;
+
+    for (i = 0; i < n-1; i++) {
+	if (support[i] == 1) {
+	    for (j = i+1; j < n; j++) {
+		if (support[j] == 1) {
+		    cuddSetInteract(table,i,j);
+		}
+	    }
+	}
+    }
+
+} /* end of ddUpdateInteract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Scans the DD and clears the LSB of the next pointers.]
+
+  Description [The LSB of the next pointers are used as markers to tell
+  whether a node was reached by at least one DFS. Once the interaction
+  matrix is built, these flags are reset.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddClearGlobal(
+  DdManager * table)
+{
+    int i,j;
+    DdNode *f;
+    DdNode *sentinel = &(table->sentinel);
+    DdNodePtr *nodelist;
+    int slots;
+
+    for (i = 0; i < table->size; i++) {
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+	for (j = 0; j < slots; j++) {
+	    f = nodelist[j];
+	    while (f != sentinel) {
+		f->next = Cudd_Regular(f->next);
+		f = f->next;
+	    }
+	}
+    }
+
+} /* end of ddClearGlobal */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddLCache.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddLCache.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddLCache.c	(revision 8)
@@ -0,0 +1,1455 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLCache.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for local caches.]
+
+  Description [Internal procedures included in this module:
+		<ul>
+		<li> cuddLocalCacheInit()
+		<li> cuddLocalCacheQuit()
+		<li> cuddLocalCacheInsert()
+		<li> cuddLocalCacheLookup()
+		<li> cuddLocalCacheClearDead()
+		<li> cuddLocalCacheClearAll()
+		<li> cuddLocalCacheProfile()
+		<li> cuddHashTableInit()
+		<li> cuddHashTableQuit()
+		<li> cuddHashTableInsert()
+		<li> cuddHashTableLookup()
+		<li> cuddHashTableInsert2()
+		<li> cuddHashTableLookup2()
+		<li> cuddHashTableInsert3()
+		<li> cuddHashTableLookup3()
+		</ul>
+	    Static procedures included in this module:
+		<ul>
+		<li> cuddLocalCacheResize()
+		<li> ddLCHash()
+		<li> cuddLocalCacheAddToList()
+		<li> cuddLocalCacheRemoveFromList()
+		<li> cuddHashTableResize()
+		<li> cuddHashTableAlloc()
+		</ul> ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAX_HASHTABLE_DENSITY 2	/* tells when to resize a table */
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.21 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes hash function for keys of two operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [ddLCHash3 ddLCHash]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define ddLCHash2(f,g,shift) \
+((((unsigned)(unsigned long)(f) * DD_P1 + \
+   (unsigned)(unsigned long)(g)) * DD_P2) >> (shift))
+#else
+#define ddLCHash2(f,g,shift) \
+((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift))
+#endif
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Computes hash function for keys of three operands.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [ddLCHash2 ddLCHash]
+
+******************************************************************************/
+#define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift)
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void cuddLocalCacheResize (DdLocalCache *cache);
+DD_INLINE static unsigned int ddLCHash (DdNodePtr *key, unsigned int keysize, int shift);
+static void cuddLocalCacheAddToList (DdLocalCache *cache);
+static void cuddLocalCacheRemoveFromList (DdLocalCache *cache);
+static int cuddHashTableResize (DdHashTable *hash);
+DD_INLINE static DdHashItem * cuddHashTableAlloc (DdHashTable *hash);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a local computed table.]
+
+  Description [Initializes a computed table.  Returns a pointer the
+  the new local cache in case of success; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddInitCache]
+
+******************************************************************************/
+DdLocalCache *
+cuddLocalCacheInit(
+  DdManager * manager /* manager */,
+  unsigned int  keySize /* size of the key (number of operands) */,
+  unsigned int  cacheSize /* Initial size of the cache */,
+  unsigned int  maxCacheSize /* Size of the cache beyond which no resizing occurs */)
+{
+    DdLocalCache *cache;
+    int logSize;
+
+    cache = ALLOC(DdLocalCache,1);
+    if (cache == NULL) {
+	manager->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    cache->manager = manager;
+    cache->keysize = keySize;
+    cache->itemsize = (keySize + 1) * sizeof(DdNode *);
+#ifdef DD_CACHE_PROFILE
+    cache->itemsize += sizeof(ptrint);
+#endif
+    logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2));
+    cacheSize = 1 << logSize;
+    cache->item = (DdLocalCacheItem *)
+	ALLOC(char, cacheSize * cache->itemsize);
+    if (cache->item == NULL) {
+	manager->errorCode = CUDD_MEMORY_OUT;
+	FREE(cache);
+	return(NULL);
+    }
+    cache->slots = cacheSize;
+    cache->shift = sizeof(int) * 8 - logSize;
+    cache->maxslots = ddMin(maxCacheSize,manager->slots);
+    cache->minHit = manager->minHit;
+    /* Initialize to avoid division by 0 and immediate resizing. */
+    cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1);
+    cache->hits = 0;
+    manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache);
+
+    /* Initialize the cache. */
+    memset(cache->item, 0, cacheSize * cache->itemsize);
+
+    /* Add to manager's list of local caches for GC. */
+    cuddLocalCacheAddToList(cache);
+
+    return(cache);
+
+} /* end of cuddLocalCacheInit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shuts down a local computed table.]
+
+  Description [Initializes the computed table. It is called by
+  Cudd_Init. Returns a pointer the the new local cache in case of
+  success; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLocalCacheInit]
+
+******************************************************************************/
+void
+cuddLocalCacheQuit(
+  DdLocalCache * cache /* cache to be shut down */)
+{
+    cache->manager->memused -=
+	cache->slots * cache->itemsize + sizeof(DdLocalCache);
+    cuddLocalCacheRemoveFromList(cache);
+    FREE(cache->item);
+    FREE(cache);
+
+    return;
+
+} /* end of cuddLocalCacheQuit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a result in a local cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddLocalCacheInsert(
+  DdLocalCache * cache,
+  DdNodePtr * key,
+  DdNode * value)
+{
+    unsigned int posn;
+    DdLocalCacheItem *entry;
+
+    posn = ddLCHash(key,cache->keysize,cache->shift);
+    entry = (DdLocalCacheItem *) ((char *) cache->item +
+				  posn * cache->itemsize);
+    memcpy(entry->key,key,cache->keysize * sizeof(DdNode *));
+    entry->value = value;
+#ifdef DD_CACHE_PROFILE
+    entry->count++;
+#endif
+
+} /* end of cuddLocalCacheInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up in a local cache.]
+
+  Description [Looks up in a local cache. Returns the result if found;
+  it returns NULL if no result is found.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddLocalCacheLookup(
+  DdLocalCache * cache,
+  DdNodePtr * key)
+{
+    unsigned int posn;
+    DdLocalCacheItem *entry;
+    DdNode *value;
+
+    cache->lookUps++;
+    posn = ddLCHash(key,cache->keysize,cache->shift);
+    entry = (DdLocalCacheItem *) ((char *) cache->item +
+				  posn * cache->itemsize);
+    if (entry->value != NULL &&
+	memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) {
+	cache->hits++;
+	value = Cudd_Regular(entry->value);
+	if (value->ref == 0) {
+	    cuddReclaim(cache->manager,value);
+	}
+	return(entry->value);
+    }
+
+    /* Cache miss: decide whether to resize */
+
+    if (cache->slots < cache->maxslots &&
+	cache->hits > cache->lookUps * cache->minHit) {
+	cuddLocalCacheResize(cache);
+    }
+
+    return(NULL);
+
+} /* end of cuddLocalCacheLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis [Clears the dead entries of the local caches of a manager.]
+
+  Description [Clears the dead entries of the local caches of a manager.
+  Used during garbage collection.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddLocalCacheClearDead(
+  DdManager * manager)
+{
+    DdLocalCache *cache = manager->localCaches;
+    unsigned int keysize;
+    unsigned int itemsize;
+    unsigned int slots;
+    DdLocalCacheItem *item;
+    DdNodePtr *key;
+    unsigned int i, j;
+
+    while (cache != NULL) {
+	keysize = cache->keysize;
+	itemsize = cache->itemsize;
+	slots = cache->slots;
+	item = cache->item;
+	for (i = 0; i < slots; i++) {
+	    if (item->value != NULL && Cudd_Regular(item->value)->ref == 0) {
+		item->value = NULL;
+	    } else {
+		key = item->key;
+		for (j = 0; j < keysize; j++) {
+		    if (Cudd_Regular(key[j])->ref == 0) {
+			item->value = NULL;
+			break;
+		    }
+		}
+	    }
+	    item = (DdLocalCacheItem *) ((char *) item + itemsize);
+	}
+	cache = cache->next;
+    }
+    return;
+
+} /* end of cuddLocalCacheClearDead */
+
+
+/**Function********************************************************************
+
+  Synopsis [Clears the local caches of a manager.]
+
+  Description [Clears the local caches of a manager.
+  Used before reordering.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddLocalCacheClearAll(
+  DdManager * manager)
+{
+    DdLocalCache *cache = manager->localCaches;
+
+    while (cache != NULL) {
+	memset(cache->item, 0, cache->slots * cache->itemsize);
+	cache = cache->next;
+    }
+    return;
+
+} /* end of cuddLocalCacheClearAll */
+
+
+#ifdef DD_CACHE_PROFILE
+
+#define DD_HYSTO_BINS 8
+
+/**Function********************************************************************
+
+  Synopsis    [Computes and prints a profile of a local cache usage.]
+
+  Description [Computes and prints a profile of a local cache usage.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddLocalCacheProfile(
+  DdLocalCache * cache)
+{
+    double count, mean, meansq, stddev, expected;
+    long max, min;
+    int imax, imin;
+    int i, retval, slots;
+    long *hystogram;
+    int nbins = DD_HYSTO_BINS;
+    int bin;
+    long thiscount;
+    double totalcount;
+    int nzeroes;
+    DdLocalCacheItem *entry;
+    FILE *fp = cache->manager->out;
+
+    slots = cache->slots;
+
+    meansq = mean = expected = 0.0;
+    max = min = (long) cache->item[0].count;
+    imax = imin = nzeroes = 0;
+    totalcount = 0.0;
+
+    hystogram = ALLOC(long, nbins);
+    if (hystogram == NULL) {
+	return(0);
+    }
+    for (i = 0; i < nbins; i++) {
+	hystogram[i] = 0;
+    }
+
+    for (i = 0; i < slots; i++) {
+	entry = (DdLocalCacheItem *) ((char *) cache->item +
+				      i * cache->itemsize);
+	thiscount = (long) entry->count;
+	if (thiscount > max) {
+	    max = thiscount;
+	    imax = i;
+	}
+	if (thiscount < min) {
+	    min = thiscount;
+	    imin = i;
+	}
+	if (thiscount == 0) {
+	    nzeroes++;
+	}
+	count = (double) thiscount;
+	mean += count;
+	meansq += count * count;
+	totalcount += count;
+	expected += count * (double) i;
+	bin = (i * nbins) / slots;
+	hystogram[bin] += thiscount;
+    }
+    mean /= (double) slots;
+    meansq /= (double) slots;
+    stddev = sqrt(meansq - mean*mean);
+
+    retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"standard deviation = %g\n", stddev);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes);
+    if (retval == EOF) return(0);
+
+    if (totalcount) {
+	expected /= totalcount;
+	retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
+	if (retval == EOF) return(0);
+	retval = fprintf(fp," (expected bin value = %g)\n# ", expected);
+	if (retval == EOF) return(0);
+	for (i = nbins - 1; i>=0; i--) {
+	    retval = fprintf(fp,"%ld ", hystogram[i]);
+	    if (retval == EOF) return(0);
+	}
+	retval = fprintf(fp,"\n");
+	if (retval == EOF) return(0);
+    }
+
+    FREE(hystogram);
+    return(1);
+
+} /* end of cuddLocalCacheProfile */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a hash table.]
+
+  Description [Initializes a hash table. Returns a pointer to the new
+  table if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableQuit]
+
+******************************************************************************/
+DdHashTable *
+cuddHashTableInit(
+  DdManager * manager,
+  unsigned int  keySize,
+  unsigned int  initSize)
+{
+    DdHashTable *hash;
+    int logSize;
+
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    hash = ALLOC(DdHashTable, 1);
+    if (hash == NULL) {
+	manager->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    hash->keysize = keySize;
+    hash->manager = manager;
+    hash->memoryList = NULL;
+    hash->nextFree = NULL;
+    hash->itemsize = (keySize + 1) * sizeof(DdNode *) +
+	sizeof(ptrint) + sizeof(DdHashItem *);
+    /* We have to guarantee that the shift be < 32. */
+    if (initSize < 2) initSize = 2;
+    logSize = cuddComputeFloorLog2(initSize);
+    hash->numBuckets = 1 << logSize;
+    hash->shift = sizeof(int) * 8 - logSize;
+    hash->bucket = ALLOC(DdHashItem *, hash->numBuckets);
+    if (hash->bucket == NULL) {
+	manager->errorCode = CUDD_MEMORY_OUT;
+	FREE(hash);
+	return(NULL);
+    }
+    memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *));
+    hash->size = 0;
+    hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    return(hash);
+
+} /* end of cuddHashTableInit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shuts down a hash table.]
+
+  Description [Shuts down a hash table, dereferencing all the values.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInit]
+
+******************************************************************************/
+void
+cuddHashTableQuit(
+  DdHashTable * hash)
+{
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    unsigned int i;
+    DdManager *dd = hash->manager;
+    DdHashItem *bucket;
+    DdHashItem **memlist, **nextmem;
+    unsigned int numBuckets = hash->numBuckets;
+
+    for (i = 0; i < numBuckets; i++) {
+	bucket = hash->bucket[i];
+	while (bucket != NULL) {
+	    Cudd_RecursiveDeref(dd, bucket->value);
+	    bucket = bucket->next;
+	}
+    }
+
+    memlist = hash->memoryList;
+    while (memlist != NULL) {
+	nextmem = (DdHashItem **) memlist[0];
+	FREE(memlist);
+	memlist = nextmem;
+    }
+
+    FREE(hash->bucket);
+    FREE(hash);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+    return;
+
+} /* end of cuddHashTableQuit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key has more than
+  three pointers.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3
+  cuddHashTableLookup]
+
+******************************************************************************/
+int
+cuddHashTableInsert(
+  DdHashTable * hash,
+  DdNodePtr * key,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+    unsigned int i;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize > 3);
+#endif
+
+    if (hash->size > hash->maxsize) {
+	result = cuddHashTableResize(hash);
+	if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    for (i = 0; i < hash->keysize; i++) {
+	item->key[i] = key[i];
+    }
+    posn = ddLCHash(key,hash->keysize,hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key in a hash table.]
+
+  Description [Looks up a key consisting of more than three pointers
+  in a hash table.  Returns the value associated to the key if there
+  is an entry for the given key in the table; NULL otherwise. If the
+  entry is present, its reference counter is decremented if not
+  saturated. If the counter reaches 0, the value of the entry is
+  dereferenced, and the entry is returned to the free list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3
+  cuddHashTableInsert]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup(
+  DdHashTable * hash,
+  DdNodePtr * key)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+    unsigned int i, keysize;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize > 3);
+#endif
+
+    posn = ddLCHash(key,hash->keysize,hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    keysize = hash->keysize;
+    while (item != NULL) {
+	DdNodePtr *key2 = item->key;
+	int equal = 1;
+	for (i = 0; i < keysize; i++) {
+	    if (key[i] != key2[i]) {
+		equal = 0;
+		break;
+	    }
+	}
+	if (equal) {
+	    DdNode *value = item->value;
+	    cuddSatDec(item->count);
+	    if (item->count == 0) {
+		cuddDeref(value);
+		if (prev == NULL) {
+		    hash->bucket[posn] = item->next;
+		} else {
+		    prev->next = item->next;
+		}
+		item->next = hash->nextFree;
+		hash->nextFree = item;
+		hash->size--;
+	    }
+	    return(value);
+	}
+	prev = item;
+	item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key is one pointer.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3
+  cuddHashTableLookup1]
+
+******************************************************************************/
+int
+cuddHashTableInsert1(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 1);
+#endif
+
+    if (hash->size > hash->maxsize) {
+	result = cuddHashTableResize(hash);
+	if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    item->key[0] = f;
+    posn = ddLCHash2(f,f,hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert1 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key consisting of one pointer in a hash table.]
+
+  Description [Looks up a key consisting of one pointer in a hash table.
+  Returns the value associated to the key if there is an entry for the given
+  key in the table; NULL otherwise. If the entry is present, its reference
+  counter is decremented if not saturated. If the counter reaches 0, the
+  value of the entry is dereferenced, and the entry is returned to the free
+  list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3
+  cuddHashTableInsert1]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup1(
+  DdHashTable * hash,
+  DdNode * f)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 1);
+#endif
+
+    posn = ddLCHash2(f,f,hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    while (item != NULL) {
+	DdNodePtr *key = item->key;
+	if (f == key[0]) {
+	    DdNode *value = item->value;
+	    cuddSatDec(item->count);
+	    if (item->count == 0) {
+		cuddDeref(value);
+		if (prev == NULL) {
+		    hash->bucket[posn] = item->next;
+		} else {
+		    prev->next = item->next;
+		}
+		item->next = hash->nextFree;
+		hash->nextFree = item;
+		hash->size--;
+	    }
+	    return(value);
+	}
+	prev = item;
+	item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup1 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key is
+  composed of two pointers. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3
+  cuddHashTableLookup2]
+
+******************************************************************************/
+int
+cuddHashTableInsert2(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 2);
+#endif
+
+    if (hash->size > hash->maxsize) {
+	result = cuddHashTableResize(hash);
+	if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    item->key[0] = f;
+    item->key[1] = g;
+    posn = ddLCHash2(f,g,hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key consisting of two pointers in a hash table.]
+
+  Description [Looks up a key consisting of two pointer in a hash table.
+  Returns the value associated to the key if there is an entry for the given
+  key in the table; NULL otherwise. If the entry is present, its reference
+  counter is decremented if not saturated. If the counter reaches 0, the
+  value of the entry is dereferenced, and the entry is returned to the free
+  list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3
+  cuddHashTableInsert2]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup2(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 2);
+#endif
+
+    posn = ddLCHash2(f,g,hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    while (item != NULL) {
+	DdNodePtr *key = item->key;
+	if ((f == key[0]) && (g == key[1])) {
+	    DdNode *value = item->value;
+	    cuddSatDec(item->count);
+	    if (item->count == 0) {
+		cuddDeref(value);
+		if (prev == NULL) {
+		    hash->bucket[posn] = item->next;
+		} else {
+		    prev->next = item->next;
+		}
+		item->next = hash->nextFree;
+		hash->nextFree = item;
+		hash->size--;
+	    }
+	    return(value);
+	}
+	prev = item;
+	item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a hash table.]
+
+  Description [Inserts an item in a hash table when the key is
+  composed of three pointers. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2
+  cuddHashTableLookup3]
+
+******************************************************************************/
+int
+cuddHashTableInsert3(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h,
+  DdNode * value,
+  ptrint count)
+{
+    int result;
+    unsigned int posn;
+    DdHashItem *item;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 3);
+#endif
+
+    if (hash->size > hash->maxsize) {
+	result = cuddHashTableResize(hash);
+	if (result == 0) return(0);
+    }
+    item = cuddHashTableAlloc(hash);
+    if (item == NULL) return(0);
+    hash->size++;
+    item->value = value;
+    cuddRef(value);
+    item->count = count;
+    item->key[0] = f;
+    item->key[1] = g;
+    item->key[2] = h;
+    posn = ddLCHash3(f,g,h,hash->shift);
+    item->next = hash->bucket[posn];
+    hash->bucket[posn] = item;
+
+    return(1);
+
+} /* end of cuddHashTableInsert3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key consisting of three pointers in a hash table.]
+
+  Description [Looks up a key consisting of three pointers in a hash table.
+  Returns the value associated to the key if there is an entry for the given
+  key in the table; NULL otherwise. If the entry is present, its reference
+  counter is decremented if not saturated. If the counter reaches 0, the
+  value of the entry is dereferenced, and the entry is returned to the free
+  list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2
+  cuddHashTableInsert3]
+
+******************************************************************************/
+DdNode *
+cuddHashTableLookup3(
+  DdHashTable * hash,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    unsigned int posn;
+    DdHashItem *item, *prev;
+
+#ifdef DD_DEBUG
+    assert(hash->keysize == 3);
+#endif
+
+    posn = ddLCHash3(f,g,h,hash->shift);
+    item = hash->bucket[posn];
+    prev = NULL;
+
+    while (item != NULL) {
+	DdNodePtr *key = item->key;
+	if ((f == key[0]) && (g == key[1]) && (h == key[2])) {
+	    DdNode *value = item->value;
+	    cuddSatDec(item->count);
+	    if (item->count == 0) {
+		cuddDeref(value);
+		if (prev == NULL) {
+		    hash->bucket[posn] = item->next;
+		} else {
+		    prev->next = item->next;
+		}
+		item->next = hash->nextFree;
+		hash->nextFree = item;
+		hash->size--;
+	    }
+	    return(value);
+	}
+	prev = item;
+	item = item->next;
+    }
+    return(NULL);
+
+} /* end of cuddHashTableLookup3 */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes a local cache.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddLocalCacheResize(
+  DdLocalCache * cache)
+{
+    DdLocalCacheItem *item, *olditem, *entry, *old;
+    int i, shift;
+    unsigned int posn;
+    unsigned int slots, oldslots;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    olditem = cache->item;
+    oldslots = cache->slots;
+    slots = cache->slots = oldslots << 1;
+
+#ifdef DD_VERBOSE
+    (void) fprintf(cache->manager->err,
+		   "Resizing local cache from %d to %d entries\n",
+		   oldslots, slots);
+    (void) fprintf(cache->manager->err,
+		   "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n",
+		   cache->hits, cache->lookUps, cache->hits / cache->lookUps);
+#endif
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    cache->item = item =
+	(DdLocalCacheItem *) ALLOC(char, slots * cache->itemsize);
+    MMoutOfMemory = saveHandler;
+    /* If we fail to allocate the new table we just give up. */
+    if (item == NULL) {
+#ifdef DD_VERBOSE
+	(void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n");
+#endif
+	cache->slots = oldslots;
+	cache->item = olditem;
+	/* Do not try to resize again. */
+	cache->maxslots = oldslots - 1;
+	return;
+    }
+    shift = --(cache->shift);
+    cache->manager->memused += (slots - oldslots) * cache->itemsize;
+
+    /* Clear new cache. */
+    memset(item, 0, slots * cache->itemsize);
+
+    /* Copy from old cache to new one. */
+    for (i = 0; (unsigned) i < oldslots; i++) {
+	old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize);
+	if (old->value != NULL) {
+	    posn = ddLCHash(old->key,cache->keysize,shift);
+	    entry = (DdLocalCacheItem *) ((char *) item +
+					  posn * cache->itemsize);
+	    memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *));
+	    entry->value = old->value;	
+	}
+    }
+
+    FREE(olditem);
+
+    /* Reinitialize measurements so as to avoid division by 0 and
+    ** immediate resizing.
+    */
+    cache->lookUps = (double) (int) (slots * cache->minHit + 1);
+    cache->hits = 0;
+
+} /* end of cuddLocalCacheResize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the hash value for a local cache.]
+
+  Description [Computes the hash value for a local cache. Returns the
+  bucket index.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static unsigned int
+ddLCHash(
+  DdNodePtr * key,
+  unsigned int keysize,
+  int shift)
+{
+    unsigned int val = (unsigned int) (ptrint) key[0] * DD_P2;
+    unsigned int i;
+
+    for (i = 1; i < keysize; i++) {
+	val = val * DD_P1 + (int) (ptrint) key[i];
+    }
+
+    return(val >> shift);
+
+} /* end of ddLCHash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a local cache in the manager list.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddLocalCacheAddToList(
+  DdLocalCache * cache)
+{
+    DdManager *manager = cache->manager;
+
+    cache->next = manager->localCaches;
+    manager->localCaches = cache;
+    return;
+
+} /* end of cuddLocalCacheAddToList */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes a local cache from the manager list.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddLocalCacheRemoveFromList(
+  DdLocalCache * cache)
+{
+    DdManager *manager = cache->manager;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdLocalCache **prevCache, *nextCache;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+
+    prevCache = &(manager->localCaches);
+    nextCache = manager->localCaches;
+
+    while (nextCache != NULL) {
+	if (nextCache == cache) {
+	    *prevCache = nextCache->next;
+	    return;
+	}
+	prevCache = &(nextCache->next);
+	nextCache = nextCache->next;
+    }
+    return;			/* should never get here */
+
+} /* end of cuddLocalCacheRemoveFromList */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes a hash table.]
+
+  Description [Resizes a hash table. Returns 1 if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddHashTableInsert]
+
+******************************************************************************/
+static int
+cuddHashTableResize(
+  DdHashTable * hash)
+{
+    int j;
+    unsigned int posn;
+    DdHashItem *item;
+    DdHashItem *next;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdNode **key;
+    int numBuckets;
+    DdHashItem **buckets;
+    DdHashItem **oldBuckets = hash->bucket;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    int shift;
+    int oldNumBuckets = hash->numBuckets;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    /* Compute the new size of the table. */
+    numBuckets = oldNumBuckets << 1;
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    buckets = ALLOC(DdHashItem *, numBuckets);
+    MMoutOfMemory = saveHandler;
+    if (buckets == NULL) {
+	hash->maxsize <<= 1;
+	return(1);
+    }
+
+    hash->bucket = buckets;
+    hash->numBuckets = numBuckets;
+    shift = --(hash->shift);
+    hash->maxsize <<= 1;
+    memset(buckets, 0, numBuckets * sizeof(DdHashItem *));
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    if (hash->keysize == 1) {
+	for (j = 0; j < oldNumBuckets; j++) {
+	    item = oldBuckets[j];
+	    while (item != NULL) {
+		next = item->next;
+		key = item->key;
+		posn = ddLCHash2(key[0], key[0], shift);
+		item->next = buckets[posn];
+		buckets[posn] = item;
+		item = next;
+	    }
+	}
+    } else if (hash->keysize == 2) {
+	for (j = 0; j < oldNumBuckets; j++) {
+	    item = oldBuckets[j];
+	    while (item != NULL) {
+		next = item->next;
+		key = item->key;
+		posn = ddLCHash2(key[0], key[1], shift);
+		item->next = buckets[posn];
+		buckets[posn] = item;
+		item = next;
+	    }
+	}
+    } else if (hash->keysize == 3) {
+	for (j = 0; j < oldNumBuckets; j++) {
+	    item = oldBuckets[j];
+	    while (item != NULL) {
+		next = item->next;
+		key = item->key;
+		posn = ddLCHash3(key[0], key[1], key[2], shift);
+		item->next = buckets[posn];
+		buckets[posn] = item;
+		item = next;
+	    }
+	}
+    } else {
+	for (j = 0; j < oldNumBuckets; j++) {
+	    item = oldBuckets[j];
+	    while (item != NULL) {
+		next = item->next;
+		posn = ddLCHash(item->key, hash->keysize, shift);
+		item->next = buckets[posn];
+		buckets[posn] = item;
+		item = next;
+	    }
+	}
+    }
+    FREE(oldBuckets);
+    return(1);
+
+} /* end of cuddHashTableResize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fast storage allocation for items in a hash table.]
+
+  Description [Fast storage allocation for items in a hash table. The
+  first 4 bytes of a chunk contain a pointer to the next block; the
+  rest contains DD_MEM_CHUNK spaces for hash items.  Returns a pointer to
+  a new item if successful; NULL is memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAllocNode cuddDynamicAllocNode]
+
+******************************************************************************/
+DD_INLINE
+static DdHashItem *
+cuddHashTableAlloc(
+  DdHashTable * hash)
+{
+    int i;
+    unsigned int itemsize = hash->itemsize;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdHashItem **mem, *thisOne, *next, *item;
+
+    if (hash->nextFree == NULL) {
+	saveHandler = MMoutOfMemory;
+	MMoutOfMemory = Cudd_OutOfMem;
+	mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
+	MMoutOfMemory = saveHandler;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+	if (mem == NULL) {
+	    if (hash->manager->stash != NULL) {
+		FREE(hash->manager->stash);
+		hash->manager->stash = NULL;
+		/* Inhibit resizing of tables. */
+		hash->manager->maxCacheHard = hash->manager->cacheSlots - 1;
+		hash->manager->cacheSlack = -(hash->manager->cacheSlots + 1);
+		for (i = 0; i < hash->manager->size; i++) {
+		    hash->manager->subtables[i].maxKeys <<= 2;
+		}
+		hash->manager->gcFrac = 0.2;
+		hash->manager->minDead =
+		    (unsigned) (0.2 * (double) hash->manager->slots);
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+		mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+	    }
+	    if (mem == NULL) {
+		(*MMoutOfMemory)((long)((DD_MEM_CHUNK + 1) * itemsize));
+		hash->manager->errorCode = CUDD_MEMORY_OUT;
+		return(NULL);
+	    }
+	}
+
+	mem[0] = (DdHashItem *) hash->memoryList;
+	hash->memoryList = mem;
+
+	thisOne = (DdHashItem *) ((char *) mem + itemsize);
+	hash->nextFree = thisOne;
+	for (i = 1; i < DD_MEM_CHUNK; i++) {
+	    next = (DdHashItem *) ((char *) thisOne + itemsize);
+	    thisOne->next = next;
+	    thisOne = next;
+	}
+
+	thisOne->next = NULL;
+
+    }
+    item = hash->nextFree;
+    hash->nextFree = item->next;
+    return(item);
+
+} /* end of cuddHashTableAlloc */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddLevelQ.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddLevelQ.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddLevelQ.c	(revision 8)
@@ -0,0 +1,561 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLevelQ.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedure to manage level queues.]
+
+  Description [The functions in this file allow an application to
+  easily manipulate a queue where nodes are prioritized by level. The
+  emphasis is on efficiency. Therefore, the queue items can have
+  variable size.  If the application does not need to attach
+  information to the nodes, it can declare the queue items to be of
+  type DdQueueItem. Otherwise, it can declare them to be of a
+  structure type such that the first three fields are data
+  pointers. The third pointer points to the node.  The first two
+  pointers are used by the level queue functions. The remaining fields
+  are initialized to 0 when a new item is created, and are then left
+  to the exclusive use of the application. On the DEC Alphas the three
+  pointers must be 32-bit pointers when CUDD is compiled with 32-bit
+  pointers.  The level queue functions make sure that each node
+  appears at most once in the queue. They do so by keeping a hash
+  table where the node is used as key.  Queue items are recycled via a
+  free list for efficiency.
+  
+  Internal procedures provided by this module:
+                <ul>
+		<li> cuddLevelQueueInit()
+		<li> cuddLevelQueueQuit()
+		<li> cuddLevelQueueEnqueue()
+		<li> cuddLevelQueueDequeue()
+		</ul>
+  Static procedures included in this module:
+		<ul>
+		<li> hashLookup()
+		<li> hashInsert()
+		<li> hashDelete()
+		<li> hashResize()
+		</ul>
+		]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.12 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the table of a level queue.]
+
+  Description [Hash function for the table of a level queue.]
+
+  SideEffects [None]
+
+  SeeAlso     [hashInsert hashLookup hashDelete]
+
+******************************************************************************/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define lqHash(key,shift) \
+(((unsigned)(unsigned long)(key) * DD_P1) >> (shift))
+#else
+#define lqHash(key,shift) \
+(((unsigned)(key) * DD_P1) >> (shift))
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdQueueItem * hashLookup (DdLevelQueue *queue, void *key);
+static int hashInsert (DdLevelQueue *queue, DdQueueItem *item);
+static void hashDelete (DdLevelQueue *queue, DdQueueItem *item);
+static int hashResize (DdLevelQueue *queue);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a level queue.]
+
+  Description [Initializes a level queue. A level queue is a queue
+  where inserts are based on the levels of the nodes. Within each
+  level the policy is FIFO. Level queues are useful in traversing a
+  BDD top-down. Queue items are kept in a free list when dequeued for
+  efficiency. Returns a pointer to the new queue if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue]
+
+******************************************************************************/
+DdLevelQueue *
+cuddLevelQueueInit(
+  int  levels /* number of levels */,
+  int  itemSize /* size of the item */,
+  int  numBuckets /* initial number of hash buckets */)
+{
+    DdLevelQueue *queue;
+    int logSize;
+
+    queue = ALLOC(DdLevelQueue,1);
+    if (queue == NULL)
+	return(NULL);
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    /* Keep pointers to the insertion points for all levels. */
+    queue->last = ALLOC(DdQueueItem *, levels);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    if (queue->last == NULL) {
+	FREE(queue);
+	return(NULL);
+    }
+    /* Use a hash table to test for uniqueness. */
+    if (numBuckets < 2) numBuckets = 2;
+    logSize = cuddComputeFloorLog2(numBuckets);
+    queue->numBuckets = 1 << logSize;
+    queue->shift = sizeof(int) * 8 - logSize;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    if (queue->buckets == NULL) {
+	FREE(queue->last);
+	FREE(queue);
+	return(NULL);
+    }
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    memset(queue->last, 0, levels * sizeof(DdQueueItem *));
+    memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *));
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    queue->first = NULL;
+    queue->freelist = NULL;
+    queue->levels = levels;
+    queue->itemsize = itemSize;
+    queue->size = 0;
+    queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY;
+    return(queue);
+
+} /* end of cuddLevelQueueInit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shuts down a level queue.]
+
+  Description [Shuts down a level queue and releases all the
+  associated memory.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueInit]
+
+******************************************************************************/
+void
+cuddLevelQueueQuit(
+  DdLevelQueue * queue)
+{
+    DdQueueItem *item;
+
+    while (queue->freelist != NULL) {
+	item = queue->freelist;
+	queue->freelist = item->next;
+	FREE(item);
+    }
+    while (queue->first != NULL) {
+	item = (DdQueueItem *) queue->first;
+	queue->first = item->next;
+	FREE(item);
+    }
+    FREE(queue->buckets);
+    FREE(queue->last);
+    FREE(queue);
+    return;
+
+} /* end of cuddLevelQueueQuit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a new key in a level queue.]
+
+  Description [Inserts a new key in a level queue. A new entry is
+  created in the queue only if the node is not already
+  enqueued. Returns a pointer to the queue item if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueInit cuddLevelQueueDequeue]
+
+******************************************************************************/
+void *
+cuddLevelQueueEnqueue(
+  DdLevelQueue * queue /* level queue */,
+  void * key /* key to be enqueued */,
+  int  level /* level at which to insert */)
+{
+    int plevel;
+    DdQueueItem *item;
+
+#ifdef DD_DEBUG
+    assert(level < queue->levels);
+#endif
+    /* Check whether entry for this node exists. */
+    item = hashLookup(queue,key);
+    if (item != NULL) return(item);
+
+    /* Get a free item from either the free list or the memory manager. */
+    if (queue->freelist == NULL) {
+	item = (DdQueueItem *) ALLOC(char, queue->itemsize);
+	if (item == NULL)
+	    return(NULL);
+    } else {
+	item = queue->freelist;
+	queue->freelist = item->next;
+    }
+    /* Initialize. */
+    memset(item, 0, queue->itemsize);
+    item->key = key;
+    /* Update stats. */
+    queue->size++;
+
+    if (queue->last[level]) {
+	/* There are already items for this level in the queue. */
+	item->next = queue->last[level]->next;
+	queue->last[level]->next = item;
+    } else {
+	/* There are no items at the current level.  Look for the first
+	** non-empty level preceeding this one. */
+	plevel = level;
+	while (plevel != 0 && queue->last[plevel] == NULL)
+	    plevel--;
+	if (queue->last[plevel] == NULL) {
+	    /* No element precedes this one in the queue. */
+	    item->next = (DdQueueItem *) queue->first;
+	    queue->first = item;
+	} else {
+	    item->next = queue->last[plevel]->next;
+	    queue->last[plevel]->next = item;
+	}
+    }
+    queue->last[level] = item;
+
+    /* Insert entry for the key in the hash table. */
+    if (hashInsert(queue,item) == 0) {
+	return(NULL);
+    }
+    return(item);
+
+} /* end of cuddLevelQueueEnqueue */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Remove an item from the front of a level queue.]
+
+  Description [Remove an item from the front of a level queue.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueEnqueue]
+
+******************************************************************************/
+void
+cuddLevelQueueDequeue(
+  DdLevelQueue * queue,
+  int  level)
+{
+    DdQueueItem *item = (DdQueueItem *) queue->first;
+
+    /* Delete from the hash table. */
+    hashDelete(queue,item);
+
+    /* Since we delete from the front, if this is the last item for
+    ** its level, there are no other items for the same level. */
+    if (queue->last[level] == item)
+	queue->last[level] = NULL;
+
+    queue->first = item->next;
+    /* Put item on the free list. */
+    item->next = queue->freelist;
+    queue->freelist = item;
+    /* Update stats. */
+    queue->size--;
+    return;
+
+} /* end of cuddLevelQueueDequeue */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up a key in the hash table of a level queue.]
+
+  Description [Looks up a key in the hash table of a level queue. Returns
+  a pointer to the item with the given key if the key is found; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueEnqueue hashInsert]
+
+******************************************************************************/
+static DdQueueItem *
+hashLookup(
+  DdLevelQueue * queue,
+  void * key)
+{
+    int posn;
+    DdQueueItem *item;
+
+    posn = lqHash(key,queue->shift);
+    item = queue->buckets[posn];
+
+    while (item != NULL) {
+	if (item->key == key) {
+	    return(item);
+	}
+	item = item->cnext;
+    }
+    return(NULL);
+
+} /* end of hashLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in the hash table of a level queue.]
+
+  Description [Inserts an item in the hash table of a level queue. Returns
+  1 if successful; 0 otherwise. No check is performed to see if an item with
+  the same key is already in the hash table.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueEnqueue]
+
+******************************************************************************/
+static int
+hashInsert(
+  DdLevelQueue * queue,
+  DdQueueItem * item)
+{
+    int result;
+    int posn;
+
+    if (queue->size > queue->maxsize) {
+	result = hashResize(queue);
+	if (result == 0) return(0);
+    }
+
+    posn = lqHash(item->key,queue->shift);
+    item->cnext = queue->buckets[posn];
+    queue->buckets[posn] = item;
+
+    return(1);
+    
+} /* end of hashInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes an item from the hash table of a level queue.]
+
+  Description [Removes an item from the hash table of a level queue.
+  Nothing is done if the item is not in the table.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddLevelQueueDequeue hashInsert]
+
+******************************************************************************/
+static void
+hashDelete(
+  DdLevelQueue * queue,
+  DdQueueItem * item)
+{
+    int posn;
+    DdQueueItem *prevItem;
+
+    posn = lqHash(item->key,queue->shift);
+    prevItem = queue->buckets[posn];
+
+    if (prevItem == NULL) return;
+    if (prevItem == item) {
+	queue->buckets[posn] = prevItem->cnext;
+	return;
+    }
+
+    while (prevItem->cnext != NULL) {
+	if (prevItem->cnext == item) {
+	    prevItem->cnext = item->cnext;
+	    return;
+	}
+	prevItem = prevItem->cnext;
+    }
+    return;
+
+} /* end of hashDelete */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes the hash table of a level queue.]
+
+  Description [Resizes the hash table of a level queue. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [hashInsert]
+
+******************************************************************************/
+static int
+hashResize(
+  DdLevelQueue * queue)
+{
+    int j;
+    int posn;
+    DdQueueItem *item;
+    DdQueueItem *next;
+    int numBuckets;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    DdQueueItem **buckets;
+    DdQueueItem **oldBuckets = queue->buckets;
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    int shift;
+    int oldNumBuckets = queue->numBuckets;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    /* Compute the new size of the subtable. */
+    numBuckets = oldNumBuckets << 1;
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+    buckets = queue->buckets = ALLOC(DdQueueItem *, numBuckets);
+    MMoutOfMemory = saveHandler;
+    if (buckets == NULL) {
+	queue->maxsize <<= 1;
+	return(1);
+    }
+
+    queue->numBuckets = numBuckets;
+    shift = --(queue->shift);
+    queue->maxsize <<= 1;
+    memset(buckets, 0, numBuckets * sizeof(DdQueueItem *));
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+    for (j = 0; j < oldNumBuckets; j++) {
+	item = oldBuckets[j];
+	while (item != NULL) {
+	    next = item->cnext;
+	    posn = lqHash(item->key, shift);
+	    item->cnext = buckets[posn];
+	    buckets[posn] = item;
+	    item = next;
+	}
+    }
+    FREE(oldBuckets);
+    return(1);
+
+} /* end of hashResize */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddLinear.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddLinear.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddLinear.c	(revision 8)
@@ -0,0 +1,1358 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLinear.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for DD reduction by linear transformations.]
+
+  Description [ Internal procedures included in this module:
+		<ul>
+		<li> cuddLinearAndSifting()
+		<li> cuddLinearInPlace()
+		<li> cuddUpdateInteractionMatrix()
+		<li> cuddInitLinear()
+		<li> cuddResizeLinear()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddLinearUniqueCompare()
+		<li> ddLinearAndSiftingAux()
+		<li> ddLinearAndSiftingUp()
+		<li> ddLinearAndSiftingDown()
+		<li> ddLinearAndSiftingBackward()
+		<li> ddUndoMoves()
+		<li> cuddXorLinear()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CUDD_SWAP_MOVE 0
+#define CUDD_LINEAR_TRANSFORM_MOVE 1
+#define CUDD_INVERSE_TRANSFORM_MOVE 2
+#if SIZEOF_LONG == 8
+#define BPL 64
+#define LOGBPL 6
+#else
+#define BPL 32
+#define LOGBPL 5
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.26 2004/08/13 18:04:49 fabio Exp $";
+#endif
+
+static	int	*entry;
+
+#ifdef DD_STATS
+extern	int	ddTotalNumberSwapping;
+extern	int	ddTotalNISwaps;
+static	int	ddTotalNumberLinearTr;
+#endif
+
+#ifdef DD_DEBUG
+static	int	zero = 0;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddLinearUniqueCompare (int *ptrX, int *ptrY);
+static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves);
+static Move * ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves);
+static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves);
+static Move* ddUndoMoves (DdManager *table, Move *moves);
+static void cuddXorLinear (DdManager *table, int x, int y);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [Prints the linear transform matrix.]
+
+  Description [Prints the linear transform matrix. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_PrintLinear(
+  DdManager * table)
+{
+    int i,j,k;
+    int retval;
+    int nvars = table->linearSize;
+    int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    long word;
+
+    for (i = 0; i < nvars; i++) {
+	for (j = 0; j < wordsPerRow; j++) {
+	    word = table->linear[i*wordsPerRow + j];
+	    for (k = 0; k < BPL; k++) {
+		retval = fprintf(table->out,"%ld",word & 1);
+		if (retval == 0) return(0);
+		word >>= 1;
+	    }
+	}
+	retval = fprintf(table->out,"\n");
+	if (retval == 0) return(0);
+    }
+    return(1);
+
+} /* end of Cudd_PrintLinear */
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [Reads an entry of the linear transform matrix.]
+
+  Description [Reads an entry of the linear transform matrix.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_ReadLinear(
+  DdManager * table /* CUDD manager */,
+  int  x /* row index */,
+  int  y /* column index */)
+{
+    int nvars = table->size;
+    int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    long word;
+    int bit;
+    int result;
+
+    assert(table->size == table->linearSize);
+
+    word = wordsPerRow * x + (y >> LOGBPL);
+    bit  = y & (BPL-1);
+    result = (int) ((table->linear[word] >> bit) & 1);
+    return(result);
+
+} /* end of Cudd_ReadLinear */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [BDD reduction based on combination of sifting and linear
+  transformations.]
+
+  Description [BDD reduction based on combination of sifting and linear
+  transformations.  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down, remembering each time the
+    total size of the DD heap. At each position, linear transformation
+    of the two adjacent variables is tried and is accepted if it reduces
+    the size of the DD.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddLinearAndSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int		i;
+    int		*var;
+    int		size;
+    int		x;
+    int		result;
+#ifdef DD_STATS
+    int		previousSize;
+#endif
+
+#ifdef DD_STATS
+    ddTotalNumberLinearTr = 0;
+#endif
+
+    size = table->size;
+
+    var = NULL;
+    entry = NULL;
+    if (table->linear == NULL) {
+	result = cuddInitLinear(table);
+	if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
+#if 0
+	(void) fprintf(table->out,"\n");
+	result = Cudd_PrintLinear(table);
+	if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
+#endif
+    } else if (table->size != table->linearSize) {
+	result = cuddResizeLinear(table);
+	if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
+#if 0
+	(void) fprintf(table->out,"\n");
+	result = Cudd_PrintLinear(table);
+	if (result == 0) goto cuddLinearAndSiftingOutOfMem; 
+#endif
+    }
+
+    /* Find order in which to sift variables. */
+    entry = ALLOC(int,size);
+    if (entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddLinearAndSiftingOutOfMem;
+    }
+    var = ALLOC(int,size);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddLinearAndSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+	x = table->perm[i];
+	entry[i] = table->subtables[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
+	x = table->perm[var[i]];
+	if (x < lower || x > upper) continue;
+#ifdef DD_STATS
+	previousSize = table->keys - table->isolated;
+#endif
+	result = ddLinearAndSiftingAux(table,x,lower,upper);
+	if (!result) goto cuddLinearAndSiftingOutOfMem; 
+#ifdef DD_STATS
+	if (table->keys < (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keys > (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	    (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+#ifdef DD_DEBUG
+	(void) Cudd_DebugCheck(table);
+#endif
+    }
+
+    FREE(var);
+    FREE(entry);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
+		   ddTotalNumberLinearTr);
+#endif
+
+    return(1);
+
+cuddLinearAndSiftingOutOfMem:
+
+    if (entry != NULL) FREE(entry);
+    if (var != NULL) FREE(var);
+
+    return(0); 
+
+} /* end of cuddLinearAndSifting */
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [Linearly combines two adjacent variables.]
+
+  Description [Linearly combines two adjacent variables. Specifically,
+  replaces the top variable with the exclusive nor of the two variables.
+  It assumes that no dead nodes are present on entry to this
+  procedure.  The procedure then guarantees that no dead nodes will be
+  present when it terminates.  cuddLinearInPlace assumes that x &lt;
+  y.  Returns the number of keys in the table if successful; 0
+  otherwise.]
+
+  SideEffects [The two subtables corrresponding to variables x and y are
+  modified. The global counters of the unique table are also affected.]
+
+  SeeAlso     [cuddSwapInPlace]
+
+******************************************************************************/
+int
+cuddLinearInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr *xlist, *ylist;
+    int    xindex, yindex;
+    int    xslots, yslots;
+    int    xshift, yshift;
+    int    oldxkeys, oldykeys;
+    int    newxkeys, newykeys;
+    int    comple, newcomplement;
+    int    i;
+    int    posn;
+    int    isolated;
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
+    DdNode *g,*next,*last;
+    DdNodePtr *previousP;
+    DdNode *tmp;
+    DdNode *sentinel = &(table->sentinel);
+#if DD_DEBUG
+    int    count, idcheck;
+#endif
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddNextHigh(table,x) == y);
+    assert(table->subtables[x].keys != 0);
+    assert(table->subtables[y].keys != 0);
+    assert(table->subtables[x].dead == 0);
+    assert(table->subtables[y].dead == 0);
+#endif
+
+    xindex = table->invperm[x];
+    yindex = table->invperm[y];
+
+    if (cuddTestInteract(table,xindex,yindex)) {
+#ifdef DD_STATS
+	ddTotalNumberLinearTr++;
+#endif
+	/* Get parameters of x subtable. */
+	xlist = table->subtables[x].nodelist; 
+	oldxkeys = table->subtables[x].keys;
+	xslots = table->subtables[x].slots;
+	xshift = table->subtables[x].shift;
+
+	/* Get parameters of y subtable. */
+	ylist = table->subtables[y].nodelist;
+	oldykeys = table->subtables[y].keys;
+	yslots = table->subtables[y].slots;
+	yshift = table->subtables[y].shift;
+
+	newxkeys = 0;
+	newykeys = oldykeys;
+
+	/* Check whether the two projection functions involved in this
+	** swap are isolated. At the end, we'll be able to tell how many
+	** isolated projection functions are there by checking only these
+	** two functions again. This is done to eliminate the isolated
+	** projection functions from the node count.
+	*/
+	isolated = - ((table->vars[xindex]->ref == 1) +
+		     (table->vars[yindex]->ref == 1));
+
+	/* The nodes in the x layer are put in a chain.
+	** The chain is handled as a FIFO; g points to the beginning and
+	** last points to the end.
+	*/
+	g = NULL;
+	for (i = 0; i < xslots; i++) {
+	    f = xlist[i];
+	    if (f == sentinel) continue;
+	    xlist[i] = sentinel;
+	    if (g == NULL) {
+		g = f;
+	    } else {
+		last->next = f;
+	    }
+	    while ((next = f->next) != sentinel) {
+		f = next;
+	    } /* while there are elements in the collision chain */
+	    last = f;
+	} /* for each slot of the x subtable */
+	last->next = NULL;
+
+#ifdef DD_COUNT
+	table->swapSteps += oldxkeys;
+#endif
+	/* Take care of the x nodes that must be re-expressed.
+	** They form a linked list pointed by g.
+	*/
+	f = g;
+	while (f != NULL) {
+	    next = f->next;
+	    /* Find f1, f0, f11, f10, f01, f00. */
+	    f1 = cuddT(f);
+#ifdef DD_DEBUG
+	    assert(!(Cudd_IsComplement(f1)));
+#endif
+	    if ((int) f1->index == yindex) {
+		f11 = cuddT(f1); f10 = cuddE(f1);
+	    } else {
+		f11 = f10 = f1;
+	    }
+#ifdef DD_DEBUG
+	    assert(!(Cudd_IsComplement(f11)));
+#endif
+	    f0 = cuddE(f);
+	    comple = Cudd_IsComplement(f0);
+	    f0 = Cudd_Regular(f0);
+	    if ((int) f0->index == yindex) {
+		f01 = cuddT(f0); f00 = cuddE(f0);
+	    } else {
+		f01 = f00 = f0;
+	    }
+	    if (comple) {
+		f01 = Cudd_Not(f01);
+		f00 = Cudd_Not(f00);
+	    }
+	    /* Decrease ref count of f1. */
+	    cuddSatDec(f1->ref);
+	    /* Create the new T child. */
+	    if (f11 == f00) {
+		newf1 = f11;
+		cuddSatInc(newf1->ref);
+	    } else {
+		/* Check ylist for triple (yindex,f11,f00). */
+		posn = ddHash(f11, f00, yshift);
+		/* For each element newf1 in collision list ylist[posn]. */
+		previousP = &(ylist[posn]);
+		newf1 = *previousP;
+		while (f11 < cuddT(newf1)) {
+		    previousP = &(newf1->next);
+		    newf1 = *previousP;
+		}
+		while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
+		    previousP = &(newf1->next);
+		    newf1 = *previousP;
+		}
+		if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
+		    cuddSatInc(newf1->ref);
+		} else { /* no match */
+		    newf1 = cuddDynamicAllocNode(table);
+		    if (newf1 == NULL)
+			goto cuddLinearOutOfMem;
+		    newf1->index = yindex; newf1->ref = 1;
+		    cuddT(newf1) = f11;
+		    cuddE(newf1) = f00;
+		    /* Insert newf1 in the collision list ylist[posn];
+		    ** increase the ref counts of f11 and f00.
+		    */
+		    newykeys++;
+		    newf1->next = *previousP;
+		    *previousP = newf1;
+		    cuddSatInc(f11->ref);
+		    tmp = Cudd_Regular(f00);
+		    cuddSatInc(tmp->ref);
+		}
+	    }
+	    cuddT(f) = newf1;
+#ifdef DD_DEBUG
+	    assert(!(Cudd_IsComplement(newf1)));
+#endif
+
+	    /* Do the same for f0, keeping complement dots into account. */
+	    /* decrease ref count of f0 */
+	    tmp = Cudd_Regular(f0);
+	    cuddSatDec(tmp->ref);
+	    /* create the new E child */
+	    if (f01 == f10) {
+		newf0 = f01;
+		tmp = Cudd_Regular(newf0);
+		cuddSatInc(tmp->ref); 
+	    } else {
+		/* make sure f01 is regular */
+		newcomplement = Cudd_IsComplement(f01);
+		if (newcomplement) {
+		    f01 = Cudd_Not(f01);
+		    f10 = Cudd_Not(f10);
+		}
+		/* Check ylist for triple (yindex,f01,f10). */
+		posn = ddHash(f01, f10, yshift);
+		/* For each element newf0 in collision list ylist[posn]. */
+		previousP = &(ylist[posn]);
+		newf0 = *previousP;
+		while (f01 < cuddT(newf0)) {
+		    previousP = &(newf0->next);
+		    newf0 = *previousP;
+		}
+		while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
+		    previousP = &(newf0->next);
+		    newf0 = *previousP;
+		}
+		if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
+		    cuddSatInc(newf0->ref); 
+		} else { /* no match */
+		    newf0 = cuddDynamicAllocNode(table);
+		    if (newf0 == NULL)
+			goto cuddLinearOutOfMem;
+		    newf0->index = yindex; newf0->ref = 1;
+		    cuddT(newf0) = f01;
+		    cuddE(newf0) = f10;
+		    /* Insert newf0 in the collision list ylist[posn];
+		    ** increase the ref counts of f01 and f10.
+		    */
+		    newykeys++;
+		    newf0->next = *previousP;
+		    *previousP = newf0;
+		    cuddSatInc(f01->ref);
+		    tmp = Cudd_Regular(f10);
+		    cuddSatInc(tmp->ref);
+		}
+		if (newcomplement) {
+		    newf0 = Cudd_Not(newf0);
+		}
+	    }
+	    cuddE(f) = newf0;
+
+	    /* Re-insert the modified f in xlist.
+	    ** The modified f does not already exists in xlist.
+	    ** (Because of the uniqueness of the cofactors.)
+	    */
+	    posn = ddHash(newf1, newf0, xshift);
+	    newxkeys++;
+	    previousP = &(xlist[posn]);
+	    tmp = *previousP;
+	    while (newf1 < cuddT(tmp)) {
+		previousP = &(tmp->next);
+		tmp = *previousP;
+	    }
+	    while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
+		previousP = &(tmp->next);
+		tmp = *previousP;
+	    }
+	    f->next = *previousP;
+	    *previousP = f;
+	    f = next;
+	} /* while f != NULL */
+
+	/* GC the y layer. */
+
+	/* For each node f in ylist. */
+	for (i = 0; i < yslots; i++) {
+	    previousP = &(ylist[i]);
+	    f = *previousP;
+	    while (f != sentinel) {
+		next = f->next;
+		if (f->ref == 0) {
+		    tmp = cuddT(f);
+		    cuddSatDec(tmp->ref);
+		    tmp = Cudd_Regular(cuddE(f));
+		    cuddSatDec(tmp->ref);
+		    cuddDeallocNode(table,f);
+		    newykeys--;
+		} else {
+		    *previousP = f;
+		    previousP = &(f->next);
+		}
+		f = next;
+	    } /* while f */
+	    *previousP = sentinel;
+	} /* for every collision list */
+
+#if DD_DEBUG
+#if 0
+	(void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
+#endif
+	count = 0;
+	idcheck = 0;
+	for (i = 0; i < yslots; i++) {
+	    f = ylist[i];
+	    while (f != sentinel) {
+		count++;
+		if (f->index != (DdHalfWord) yindex)
+		    idcheck++;
+		f = f->next;
+	    }
+	}
+	if (count != newykeys) {
+	    fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
+	}
+	if (idcheck != 0)
+	    fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
+	count = 0;
+	idcheck = 0;
+	for (i = 0; i < xslots; i++) {
+	    f = xlist[i];
+	    while (f != sentinel) {
+		count++;
+		if (f->index != (DdHalfWord) xindex)
+		    idcheck++;
+		f = f->next;
+	    }
+	}
+	if (count != newxkeys || newxkeys != oldxkeys) {
+	    fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
+	}
+	if (idcheck != 0)
+	    fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
+#endif
+
+	isolated += (table->vars[xindex]->ref == 1) +
+		    (table->vars[yindex]->ref == 1);
+	table->isolated += isolated;
+
+	/* Set the appropriate fields in table. */
+	table->subtables[y].keys = newykeys;
+
+	/* Here we should update the linear combination table
+	** to record that x <- x EXNOR y. This is done by complementing
+	** the (x,y) entry of the table.
+	*/
+
+	table->keys += newykeys - oldykeys;
+
+	cuddXorLinear(table,xindex,yindex);
+    }
+
+#ifdef DD_DEBUG
+    if (zero) {
+	(void) Cudd_DebugCheck(table);
+    }
+#endif
+
+    return(table->keys - table->isolated);
+
+cuddLinearOutOfMem:
+    (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddLinearInPlace */
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [Updates the interaction matrix.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddUpdateInteractionMatrix(
+  DdManager * table,
+  int  xindex,
+  int  yindex)
+{
+    int i;
+    for (i = 0; i < yindex; i++) {
+	if (i != xindex && cuddTestInteract(table,i,yindex)) {
+	    if (i < xindex) {
+		cuddSetInteract(table,i,xindex);
+	    } else {
+		cuddSetInteract(table,xindex,i);
+	    }
+	}
+    }
+    for (i = yindex+1; i < table->size; i++) {
+	if (i != xindex && cuddTestInteract(table,yindex,i)) {
+	    if (i < xindex) {
+		cuddSetInteract(table,i,xindex);
+	    } else {
+		cuddSetInteract(table,xindex,i);
+	    }
+	}
+    }
+
+} /* end of cuddUpdateInteractionMatrix */
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [Initializes the linear transform matrix.]
+
+  Description [Initializes the linear transform matrix.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddInitLinear(
+  DdManager * table)
+{
+    int words;
+    int wordsPerRow;
+    int nvars;
+    int word;
+    int bit;
+    int i;
+    long *linear;
+
+    nvars = table->size;
+    wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    words = wordsPerRow * nvars;
+    table->linear = linear = ALLOC(long,words);
+    if (linear == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    table->memused += words * sizeof(long);
+    table->linearSize = nvars;
+    for (i = 0; i < words; i++) linear[i] = 0;
+    for (i = 0; i < nvars; i++) {
+	word = wordsPerRow * i + (i >> LOGBPL);
+	bit  = i & (BPL-1);
+	linear[word] = 1 << bit;
+    }
+    return(1);
+
+} /* end of cuddInitLinear */
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [Resizes the linear transform matrix.]
+
+  Description [Resizes the linear transform matrix.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddResizeLinear(
+  DdManager * table)
+{
+    int words,oldWords;
+    int wordsPerRow,oldWordsPerRow;
+    int nvars,oldNvars;
+    int word,oldWord;
+    int bit;
+    int i,j;
+    long *linear,*oldLinear;
+
+    oldNvars = table->linearSize;
+    oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
+    oldWords = oldWordsPerRow * oldNvars;
+    oldLinear = table->linear;
+
+    nvars = table->size;
+    wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    words = wordsPerRow * nvars;
+    table->linear = linear = ALLOC(long,words);
+    if (linear == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    table->memused += (words - oldWords) * sizeof(long);
+    for (i = 0; i < words; i++) linear[i] = 0;
+
+    /* Copy old matrix. */
+    for (i = 0; i < oldNvars; i++) {
+	for (j = 0; j < oldWordsPerRow; j++) {
+	    oldWord = oldWordsPerRow * i + j;
+	    word = wordsPerRow * i + j;
+	    linear[word] = oldLinear[oldWord];
+	}
+    }
+    FREE(oldLinear);
+
+    /* Add elements to the diagonal. */
+    for (i = oldNvars; i < nvars; i++) {
+	word = wordsPerRow * i + (i >> LOGBPL);
+	bit  = i & (BPL-1);
+	linear[word] = 1 << bit;
+    }
+    table->linearSize = nvars;
+
+    return(1);
+
+} /* end of cuddResizeLinear */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddLinearUniqueCompare(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+	return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddLinearUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. At each step a linear transformation is tried, and, if it
+  decreases the size of the DD, it is accepted. Finds the best position
+  and does the required changes.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddLinearAndSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+
+    Move	*move;
+    Move	*moveUp;		/* list of up moves */
+    Move	*moveDown;		/* list of down moves */
+    int		initialSize;
+    int		result;
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) {
+	moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
+	/* At this point x --> xHigh unless bounding occurred. */
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+	/* Move backward and stop at best position. */	
+	result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
+	if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+
+    } else if (x == xHigh) {
+	moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
+	/* At this point x --> xLow unless bounding occurred. */
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+	/* Move backward and stop at best position. */
+	result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
+	if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+	moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
+	/* At this point x --> xHigh unless bounding occurred. */
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+	moveUp = ddUndoMoves(table,moveDown);
+#ifdef DD_DEBUG
+	assert(moveUp == NULL || moveUp->x == x);
+#endif
+	moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+	/* Move backward and stop at best position. */	
+	result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
+	if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+
+    } else { /* must go up first: shorter */
+	moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
+	/* At this point x --> xLow unless bounding occurred. */
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+	moveDown = ddUndoMoves(table,moveUp);
+#ifdef DD_DEBUG
+	assert(moveDown == NULL || moveDown->y == x);
+#endif
+	moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
+	/* Move backward and stop at best position. */	
+	result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
+	if (!result) goto ddLinearAndSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(1);
+
+ddLinearAndSiftingAuxOutOfMem:
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(0);
+
+} /* end of ddLinearAndSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up and applies linear transformations.]
+
+  Description [Sifts a variable up and applies linear transformations.
+  Moves y up until either it reaches the bound (xLow) or the size of
+  the DD heap increases too much.  Returns the set of moves in case of
+  success; NULL if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddLinearAndSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  Move * prevMoves)
+{
+    Move	*moves;
+    Move	*move;
+    int		x;
+    int		size, newsize;
+    int		limitSize;
+    int		xindex, yindex;
+    int		isolated;
+    int		L;	/* lower bound on DD size */
+#ifdef DD_DEBUG
+    int checkL;
+    int z;
+    int zindex;
+#endif
+
+    moves = prevMoves;
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below y will not change.
+    ** The part of the DD above y that does not interact with y will not
+    ** change. The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    */
+    limitSize = L = table->keys - table->isolated;
+    for (x = xLow + 1; x < y; x++) {
+	xindex = table->invperm[x];
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[xindex]->ref == 1;
+	    L -= table->subtables[x].keys - isolated;
+	}
+    }
+    isolated = table->vars[yindex]->ref == 1;
+    L -= table->subtables[y].keys - isolated;
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+	xindex = table->invperm[x];
+#ifdef DD_DEBUG
+	checkL = table->keys - table->isolated;
+	for (z = xLow + 1; z < y; z++) {
+	    zindex = table->invperm[z];
+	    if (cuddTestInteract(table,zindex,yindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkL -= table->subtables[z].keys - isolated;
+	    }
+	}
+	isolated = table->vars[yindex]->ref == 1;
+	checkL -= table->subtables[y].keys - isolated;
+	if (L != checkL) {
+	    (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
+	}
+#endif
+	size = cuddSwapInPlace(table,x,y);
+	if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
+	newsize = cuddLinearInPlace(table,x,y);
+	if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
+	move = (Move *) cuddDynamicAllocNode(table);
+	if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->next = moves;
+	moves = move;
+	move->flags = CUDD_SWAP_MOVE;
+	if (newsize >= size) {
+	    /* Undo transformation. The transformation we apply is
+	    ** its own inverse. Hence, we just apply the transformation
+	    ** again.
+	    */
+	    newsize = cuddLinearInPlace(table,x,y);
+	    if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
+#ifdef DD_DEBUG
+	    if (newsize != size) {
+		(void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+	    }
+#endif
+	} else if (cuddTestInteract(table,xindex,yindex)) {
+	    size = newsize;
+	    move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+	    cuddUpdateInteractionMatrix(table,xindex,yindex);
+	}
+	move->size = size;
+	/* Update the lower bound. */
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[xindex]->ref == 1;
+	    L += table->subtables[y].keys - isolated;
+	}
+	if ((double) size > (double) limitSize * table->maxGrowth) break;
+	if (size < limitSize) limitSize = size;
+	y = x;
+	x = cuddNextLow(table,y);
+    }
+    return(moves);
+
+ddLinearAndSiftingUpOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddLinearAndSiftingUp */
+    
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down and applies linear transformations.]
+
+  Description [Sifts a variable down and applies linear
+  transformations. Moves x down until either it reaches the bound
+  (xHigh) or the size of the DD heap increases too much. Returns the
+  set of moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddLinearAndSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  Move * prevMoves)
+{
+    Move	*moves;
+    Move	*move;
+    int		y;
+    int		size, newsize;
+    int		R;	/* upper bound on node decrease */
+    int		limitSize;
+    int		xindex, yindex;
+    int		isolated;
+#ifdef DD_DEBUG
+    int		checkR;
+    int		z;
+    int		zindex;
+#endif
+
+    moves = prevMoves;
+    /* Initialize R */
+    xindex = table->invperm[x];
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (y = xHigh; y > x; y--) {
+	yindex = table->invperm[y];
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[yindex]->ref == 1;
+	    R += table->subtables[y].keys - isolated;
+	}
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+	checkR = 0;
+	for (z = xHigh; z > x; z--) {
+	    zindex = table->invperm[z];
+	    if (cuddTestInteract(table,xindex,zindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkR += table->subtables[z].keys - isolated;
+	    }
+	}
+	if (R != checkR) {
+	    (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
+	}
+#endif
+	/* Update upper bound on node decrease. */
+	yindex = table->invperm[y];
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[yindex]->ref == 1;
+	    R -= table->subtables[y].keys - isolated;
+	}
+	size = cuddSwapInPlace(table,x,y);
+	if (size == 0) goto ddLinearAndSiftingDownOutOfMem; 
+	newsize = cuddLinearInPlace(table,x,y);
+	if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
+	move = (Move *) cuddDynamicAllocNode(table);
+	if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->next = moves;
+	moves = move;
+	move->flags = CUDD_SWAP_MOVE;
+	if (newsize >= size) {
+	    /* Undo transformation. The transformation we apply is
+	    ** its own inverse. Hence, we just apply the transformation
+	    ** again.
+	    */
+	    newsize = cuddLinearInPlace(table,x,y);
+	    if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
+	    if (newsize != size) {
+		(void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+	    }
+	} else if (cuddTestInteract(table,xindex,yindex)) {
+	    size = newsize;
+	    move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+	    cuddUpdateInteractionMatrix(table,xindex,yindex);
+	}
+	move->size = size;
+	if ((double) size > (double) limitSize * table->maxGrowth) break;
+	if (size < limitSize) limitSize = size;
+	x = y;
+	y = cuddNextHigh(table,x);
+    }
+    return(moves);
+
+ddLinearAndSiftingDownOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddLinearAndSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the order
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddLinearAndSiftingBackward(
+  DdManager * table,
+  int  size,
+  Move * moves)
+{
+    Move *move;
+    int	res;
+
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size < size) {
+	    size = move->size;
+	}
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size == size) return(1);
+	if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+	    res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!res) return(0);
+	}
+	res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+	if (!res) return(0);
+	if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
+	    res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!res) return(0);
+	}
+    }
+
+    return(1);
+
+} /* end of ddLinearAndSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the order
+  in effect before the moves.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  order in effect before the moves.  Returns 1 in case of success;
+  0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move*
+ddUndoMoves(
+  DdManager * table,
+  Move * moves)
+{
+    Move *invmoves = NULL;
+    Move *move;
+    Move *invmove;
+    int	size;
+
+    for (move = moves; move != NULL; move = move->next) {
+	invmove = (Move *) cuddDynamicAllocNode(table);
+	if (invmove == NULL) goto ddUndoMovesOutOfMem;
+	invmove->x = move->x;
+	invmove->y = move->y;
+	invmove->next = invmoves;
+	invmoves = invmove;
+	if (move->flags == CUDD_SWAP_MOVE) {
+	    invmove->flags = CUDD_SWAP_MOVE;
+	    size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto ddUndoMovesOutOfMem;
+	} else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+	    invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
+	    size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto ddUndoMovesOutOfMem;
+	    size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto ddUndoMovesOutOfMem;
+	} else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
+#ifdef DD_DEBUG
+	    (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
+#endif
+	    invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+	    size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto ddUndoMovesOutOfMem;
+	    size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto ddUndoMovesOutOfMem;
+	}
+	invmove->size = size;
+    }
+
+    return(invmoves);
+
+ddUndoMovesOutOfMem:
+    while (invmoves != NULL) {
+	move = invmoves->next;
+	cuddDeallocMove(table, invmoves);
+	invmoves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddUndoMoves */
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [XORs two rows of the linear transform matrix.]
+
+  Description [XORs two rows of the linear transform matrix and replaces
+  the first row with the result.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddXorLinear(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int i;
+    int nvars = table->size;
+    int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
+    int xstart = wordsPerRow * x;
+    int ystart = wordsPerRow * y;
+    long *linear = table->linear;
+
+    for (i = 0; i < wordsPerRow; i++) {
+	linear[xstart+i] ^= linear[ystart+i];
+    }
+
+} /* end of cuddXorLinear */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddLiteral.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddLiteral.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddLiteral.c	(revision 8)
@@ -0,0 +1,264 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddLiteral.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for manipulation of literal sets represented by
+  BDDs.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_bddLiteralSetIntersection()
+		</ul>
+	    Internal procedures included in this file:
+		<ul>
+		<li> cuddBddLiteralSetIntersectionRecur()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddLiteral.c,v 1.8 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the intesection of two sets of literals
+  represented as BDDs.]
+
+  Description [Computes the intesection of two sets of literals
+  represented as BDDs. Each set is represented as a cube of the
+  literals in the set. The empty set is represented by the constant 1.
+  No variable can be simultaneously present in both phases in a set.
+  Returns a pointer to the BDD representing the intersected sets, if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+Cudd_bddLiteralSetIntersection(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddLiteralSetIntersectionRecur(dd,f,g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddLiteralSetIntersection */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of
+  Cudd_bddLiteralSetIntersection.]
+
+  Description [Performs the recursive step of
+  Cudd_bddLiteralSetIntersection. Scans the cubes for common variables,
+  and checks whether they agree in phase.  Returns a pointer to the
+  resulting cube if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddBddLiteralSetIntersectionRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode *res, *tmp;
+    DdNode *F, *G;
+    DdNode *fc, *gc;
+    DdNode *one;
+    DdNode *zero;
+    unsigned int topf, topg, comple;
+    int phasef, phaseg;
+
+    statLine(dd);
+    if (f == g) return(f);
+
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    one = DD_ONE(dd);
+
+    /* Here f != g. If F == G, then f and g are complementary.
+    ** Since they are two cubes, this case only occurs when f == v,
+    ** g == v', and v is a variable or its complement.
+    */
+    if (F == G) return(one);
+
+    zero = Cudd_Not(one);
+    topf = cuddI(dd,F->index);
+    topg = cuddI(dd,G->index);
+    /* Look for a variable common to both cubes. If there are none, this
+    ** loop will stop when the constant node is reached in both cubes.
+    */
+    while (topf != topg) {
+	if (topf < topg) {	/* move down on f */
+	    comple = f != F;
+	    f = cuddT(F);
+	    if (comple) f = Cudd_Not(f);
+	    if (f == zero) {
+		f = cuddE(F);
+		if (comple) f = Cudd_Not(f);
+	    }
+	    F = Cudd_Regular(f);
+	    topf = cuddI(dd,F->index);
+	} else if (topg < topf) {
+	    comple = g != G;
+	    g = cuddT(G);
+	    if (comple) g = Cudd_Not(g);
+	    if (g == zero) {
+		g = cuddE(G);
+		if (comple) g = Cudd_Not(g);
+	    }
+	    G = Cudd_Regular(g);
+	    topg = cuddI(dd,G->index);
+	}
+    }
+
+    /* At this point, f == one <=> g == 1. It suffices to test one of them. */
+    if (f == one) return(one);
+
+    res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g);
+    if (res != NULL) {
+	return(res);
+    }
+
+    /* Here f and g are both non constant and have the same top variable. */
+    comple = f != F;
+    fc = cuddT(F);
+    phasef = 1;
+    if (comple) fc = Cudd_Not(fc);
+    if (fc == zero) {
+	fc = cuddE(F);
+	phasef = 0;
+	if (comple) fc = Cudd_Not(fc);
+    }
+    comple = g != G;
+    gc = cuddT(G);
+    phaseg = 1;
+    if (comple) gc = Cudd_Not(gc);
+    if (gc == zero) {
+	gc = cuddE(G);
+	phaseg = 0;
+	if (comple) gc = Cudd_Not(gc);
+    }
+
+    tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc);
+    if (tmp == NULL) {
+	return(NULL);
+    }
+
+    if (phasef != phaseg) {
+	res = tmp;
+    } else {
+	cuddRef(tmp);
+	if (phasef == 0) {
+	    res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp);
+	} else {
+	    res = cuddBddAndRecur(dd,dd->vars[F->index],tmp);
+	}
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd,tmp);
+	    return(NULL);
+	}
+	cuddDeref(tmp); /* Just cuddDeref, because it is included in result */
+    }
+
+    cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res);
+
+    return(res);
+
+} /* end of cuddBddLiteralSetIntersectionRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddMatMult.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddMatMult.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddMatMult.c	(revision 8)
@@ -0,0 +1,707 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddMatMult.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Matrix multiplication functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addMatrixMultiply()
+		<li> Cudd_addTimesPlus()
+		<li> Cudd_addTriangle()
+		<li> Cudd_addOuterSum()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> addMMRecur()
+		<li> addTriangleRecur()
+		<li> cuddAddOuterSumRecur()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddMatMult.c,v 1.17 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * addMMRecur (DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars);
+static DdNode * addTriangleRecur (DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube);
+static DdNode * cuddAddOuterSumRecur (DdManager *dd, DdNode *M, DdNode *r, DdNode *c);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Calculates the product of two matrices represented as
+  ADDs.]
+
+  Description [Calculates the product of two matrices, A and B,
+  represented as ADDs. This procedure implements the quasiring multiplication
+  algorithm.  A is assumed to depend on variables x (rows) and z
+  (columns).  B is assumed to depend on variables z (rows) and y
+  (columns).  The product of A and B then depends on x (rows) and y
+  (columns).  Only the z variables have to be explicitly identified;
+  they are the "summation" variables.  Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addMatrixMultiply(
+  DdManager * dd,
+  DdNode * A,
+  DdNode * B,
+  DdNode ** z,
+  int  nz)
+{
+    int i, nvars, *vars;
+    DdNode *res; 
+
+    /* Array vars says what variables are "summation" variables. */
+    nvars = dd->size;
+    vars = ALLOC(int,nvars);
+    if (vars == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < nvars; i++) {
+        vars[i] = 0;
+    }
+    for (i = 0; i < nz; i++) {
+        vars[z[i]->index] = 1;
+    }
+
+    do {
+	dd->reordered = 0;
+	res = addMMRecur(dd,A,B,-1,vars);
+    } while (dd->reordered == 1);
+    FREE(vars);
+    return(res);
+
+} /* end of Cudd_addMatrixMultiply */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Calculates the product of two matrices represented as
+  ADDs.]
+
+  Description [Calculates the product of two matrices, A and B,
+  represented as ADDs, using the CMU matrix by matrix multiplication
+  procedure by Clarke et al..  Matrix A has x's as row variables and z's
+  as column variables, while matrix B has z's as row variables and y's
+  as column variables. Returns the pointer to the result if successful;
+  NULL otherwise. The resulting matrix has x's as row variables and y's
+  as column variables.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMatrixMultiply]
+
+******************************************************************************/
+DdNode *
+Cudd_addTimesPlus(
+  DdManager * dd,
+  DdNode * A,
+  DdNode * B,
+  DdNode ** z,
+  int  nz)
+{
+    DdNode *w, *cube, *tmp, *res; 
+    int i;
+    tmp = Cudd_addApply(dd,Cudd_addTimes,A,B);
+    if (tmp == NULL) return(NULL);
+    Cudd_Ref(tmp);
+    Cudd_Ref(cube = DD_ONE(dd));
+    for (i = nz-1; i >= 0; i--) {
+	 w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd));
+	 if (w == NULL) {
+	    Cudd_RecursiveDeref(dd,tmp);
+	    return(NULL);
+	 }
+	 Cudd_Ref(w);
+	 Cudd_RecursiveDeref(dd,cube);
+	 cube = w;
+    }
+    res = Cudd_addExistAbstract(dd,tmp,cube);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd,tmp);
+	Cudd_RecursiveDeref(dd,cube);
+	return(NULL);
+    }
+    Cudd_Ref(res);
+    Cudd_RecursiveDeref(dd,cube);
+    Cudd_RecursiveDeref(dd,tmp);
+    Cudd_Deref(res);
+    return(res);
+
+} /* end of Cudd_addTimesPlus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the triangulation step for the shortest path
+  computation.]
+
+  Description [Implements the semiring multiplication algorithm used in
+  the triangulation step for the shortest path computation.  f
+  is assumed to depend on variables x (rows) and z (columns).  g is
+  assumed to depend on variables z (rows) and y (columns).  The product
+  of f and g then depends on x (rows) and y (columns).  Only the z
+  variables have to be explicitly identified; they are the
+  "abstraction" variables.  Returns a pointer to the result if
+  successful; NULL otherwise. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addMatrixMultiply Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_addTriangle(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode ** z,
+  int  nz)
+{
+    int    i, nvars, *vars;
+    DdNode *res, *cube;
+
+    nvars = dd->size;
+    vars = ALLOC(int, nvars);
+    if (vars == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < nvars; i++) vars[i] = -1;
+    for (i = 0; i < nz; i++) vars[z[i]->index] = i;
+    cube = Cudd_addComputeCube(dd, z, NULL, nz);
+    if (cube == NULL) {
+	FREE(vars);
+	return(NULL);
+    }
+    cuddRef(cube);
+
+    do {
+	dd->reordered = 0;
+	res = addTriangleRecur(dd, f, g, vars, cube);
+    } while (dd->reordered == 1);
+    if (res != NULL) cuddRef(res);
+    Cudd_RecursiveDeref(dd,cube);
+    if (res != NULL) cuddDeref(res);
+    FREE(vars);
+    return(res);
+
+} /* end of Cudd_addTriangle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Takes the minimum of a matrix and the outer sum of two vectors.]
+
+  Description [Takes the pointwise minimum of a matrix and the outer
+  sum of two vectors.  This procedure is used in the Floyd-Warshall
+  all-pair shortest path algorithm.  Returns a pointer to the result if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addOuterSum(
+  DdManager *dd,
+  DdNode *M,
+  DdNode *r,
+  DdNode *c)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddAddOuterSumRecur(dd, M, r, c);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_addOuterSum */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addMatrixMultiply.]
+
+  Description [Performs the recursive step of Cudd_addMatrixMultiply.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+addMMRecur(
+  DdManager * dd,
+  DdNode * A,
+  DdNode * B,
+  int  topP,
+  int * vars)
+{
+    DdNode *zero,
+           *At,		/* positive cofactor of first operand */
+	   *Ae,		/* negative cofactor of first operand */
+	   *Bt,		/* positive cofactor of second operand */
+	   *Be,		/* negative cofactor of second operand */
+	   *t,		/* positive cofactor of result */
+	   *e,		/* negative cofactor of result */
+	   *scaled,	/* scaled result */
+	   *add_scale,	/* ADD representing the scaling factor */
+	   *res;
+    int	i;		/* loop index */
+    double scale;	/* scaling factor */
+    int index;		/* index of the top variable */
+    CUDD_VALUE_TYPE value;
+    unsigned int topA, topB, topV;
+    DD_CTFP cacheOp;
+
+    statLine(dd);
+    zero = DD_ZERO(dd);
+
+    if (A == zero || B == zero) {
+        return(zero);
+    }
+
+    if (cuddIsConstant(A) && cuddIsConstant(B)) {
+	/* Compute the scaling factor. It is 2^k, where k is the
+	** number of summation variables below the current variable.
+	** Indeed, these constants represent blocks of 2^k identical
+	** constant values in both A and B.
+	*/
+	value = cuddV(A) * cuddV(B);
+	for (i = 0; i < dd->size; i++) {
+	    if (vars[i]) {
+		if (dd->perm[i] > topP) {
+		    value *= (CUDD_VALUE_TYPE) 2;
+		}
+	    }
+	}
+	res = cuddUniqueConst(dd, value);
+	return(res);
+    }
+
+    /* Standardize to increase cache efficiency. Clearly, A*B != B*A
+    ** in matrix multiplication. However, which matrix is which is
+    ** determined by the variables appearing in the ADDs and not by
+    ** which one is passed as first argument.
+    */
+    if (A > B) {
+	DdNode *tmp = A;
+	A = B;
+	B = tmp;
+    }
+
+    topA = cuddI(dd,A->index); topB = cuddI(dd,B->index);
+    topV = ddMin(topA,topB);
+
+    cacheOp = (DD_CTFP) addMMRecur;
+    res = cuddCacheLookup2(dd,cacheOp,A,B);
+    if (res != NULL) {
+	/* If the result is 0, there is no need to normalize.
+	** Otherwise we count the number of z variables between
+	** the current depth and the top of the ADDs. These are
+	** the missing variables that determine the size of the
+	** constant blocks.
+	*/
+	if (res == zero) return(res);
+	scale = 1.0;
+	for (i = 0; i < dd->size; i++) {
+	    if (vars[i]) {
+		if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
+		    scale *= 2;
+		}
+	    }
+	}
+	if (scale > 1.0) {
+	    cuddRef(res);
+	    add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
+	    if (add_scale == NULL) {
+		Cudd_RecursiveDeref(dd, res);
+		return(NULL);
+	    }
+	    cuddRef(add_scale);
+	    scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
+	    if (scaled == NULL) {
+		Cudd_RecursiveDeref(dd, add_scale);
+		Cudd_RecursiveDeref(dd, res);
+		return(NULL);
+	    }
+	    cuddRef(scaled);
+	    Cudd_RecursiveDeref(dd, add_scale);
+	    Cudd_RecursiveDeref(dd, res);
+	    res = scaled;
+	    cuddDeref(res);
+	}
+        return(res);
+    }
+
+    /* compute the cofactors */
+    if (topV == topA) {
+	At = cuddT(A);
+	Ae = cuddE(A);
+    } else {
+	At = Ae = A;
+    }
+    if (topV == topB) {
+	Bt = cuddT(B);
+	Be = cuddE(B);
+    } else {
+	Bt = Be = B;
+    }
+
+    t = addMMRecur(dd, At, Bt, (int)topV, vars);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = addMMRecur(dd, Ae, Be, (int)topV, vars);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(dd, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    index = dd->invperm[topV];
+    if (vars[index] == 0) {
+	/* We have split on either the rows of A or the columns
+	** of B. We just need to connect the two subresults,
+	** which correspond to two submatrices of the result.
+	*/
+	res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    Cudd_RecursiveDeref(dd, e);
+	    return(NULL);
+	}
+	cuddRef(res);
+	cuddDeref(t);
+	cuddDeref(e);
+    } else {
+	/* we have simultaneously split on the columns of A and
+	** the rows of B. The two subresults must be added.
+	*/
+	res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    Cudd_RecursiveDeref(dd, e);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDeref(dd, t);
+	Cudd_RecursiveDeref(dd, e);
+    }
+
+    cuddCacheInsert2(dd,cacheOp,A,B,res);
+
+    /* We have computed (and stored in the computed table) a minimal
+    ** result; that is, a result that assumes no summation variables
+    ** between the current depth of the recursion and its top
+    ** variable. We now take into account the z variables by properly
+    ** scaling the result.
+    */
+    if (res != zero) {
+	scale = 1.0;
+	for (i = 0; i < dd->size; i++) {
+	    if (vars[i]) {
+		if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
+		    scale *= 2;
+		}
+	    }
+	}
+	if (scale > 1.0) {
+	    add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
+	    if (add_scale == NULL) {
+		Cudd_RecursiveDeref(dd, res);
+		return(NULL);
+	    }
+	    cuddRef(add_scale);
+	    scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
+	    if (scaled == NULL) {
+		Cudd_RecursiveDeref(dd, res);
+		Cudd_RecursiveDeref(dd, add_scale);
+		return(NULL);
+	    }
+	    cuddRef(scaled);
+	    Cudd_RecursiveDeref(dd, add_scale);
+	    Cudd_RecursiveDeref(dd, res);
+	    res = scaled;
+	}
+    }
+    cuddDeref(res);
+    return(res);
+
+} /* end of addMMRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addTriangle.]
+
+  Description [Performs the recursive step of Cudd_addTriangle. Returns
+  a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+addTriangleRecur(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  int * vars,
+  DdNode *cube)
+{
+    DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res;
+    CUDD_VALUE_TYPE value;
+    int top, topf, topg, index;
+
+    statLine(dd);
+    if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) {
+	return(DD_PLUS_INFINITY(dd));
+    }
+
+    if (cuddIsConstant(f) && cuddIsConstant(g)) {
+	value = cuddV(f) + cuddV(g);
+	res = cuddUniqueConst(dd, value);
+	return(res);
+    }
+    if (f < g) {
+	DdNode *tmp = f;
+	f = g;
+	g = tmp;
+    }
+
+    if (f->ref != 1 || g->ref != 1) {
+	res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube);
+	if (res != NULL) {
+	    return(res);
+	}
+    }
+
+    topf = cuddI(dd,f->index); topg = cuddI(dd,g->index);
+    top = ddMin(topf,topg);
+
+    if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
+    if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
+
+    t = addTriangleRecur(dd, fv, gv, vars, cube);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = addTriangleRecur(dd, fvn, gvn, vars, cube);
+    if (e == NULL) {
+	Cudd_RecursiveDeref(dd, t);
+	return(NULL);
+    }
+    cuddRef(e);
+
+    index = dd->invperm[top];
+    if (vars[index] < 0) {
+	res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    Cudd_RecursiveDeref(dd, e);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    } else {
+	res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd, t);
+	    Cudd_RecursiveDeref(dd, e);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDeref(dd, t);
+	Cudd_RecursiveDeref(dd, e);
+	cuddDeref(res);
+    }
+
+    if (f->ref != 1 || g->ref != 1) {
+	cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res);
+    }
+
+    return(res);
+
+} /* end of addTriangleRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_addOuterSum.]
+
+  Description [Performs the recursive step of Cudd_addOuterSum.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+cuddAddOuterSumRecur(
+  DdManager *dd,
+  DdNode *M,
+  DdNode *r,
+  DdNode *c)
+{
+    DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re;
+    int topM, topc, topr;
+    int v, index;
+
+    statLine(dd);
+    /* Check special cases. */
+    if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); 
+
+    if (cuddIsConstant(c) && cuddIsConstant(r)) {
+	R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r));
+	cuddRef(R);
+	if (cuddIsConstant(M)) {
+	    if (cuddV(R) <= cuddV(M)) {
+		cuddDeref(R);
+	        return(R);
+	    } else {
+	        Cudd_RecursiveDeref(dd,R);       
+		return(M);
+	    }
+	} else {
+	    P = Cudd_addApply(dd,Cudd_addMinimum,R,M);
+	    cuddRef(P);
+	    Cudd_RecursiveDeref(dd,R);
+	    cuddDeref(P);
+	    return(P);
+	}
+    }
+
+    /* Check the cache. */
+    R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c);
+    if (R != NULL) return(R);
+
+    topM = cuddI(dd,M->index); topr = cuddI(dd,r->index);
+    topc = cuddI(dd,c->index);
+    v = ddMin(topM,ddMin(topr,topc));
+
+    /* Compute cofactors. */
+    if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; }
+    if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; }
+    if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; }
+
+    /* Recursively solve. */
+    Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct);
+    if (Rt == NULL) return(NULL);
+    cuddRef(Rt);
+    Re = cuddAddOuterSumRecur(dd,Me,re,ce);
+    if (Re == NULL) {
+	Cudd_RecursiveDeref(dd, Rt);
+	return(NULL);
+    }
+    cuddRef(Re);
+    index = dd->invperm[v];
+    R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re);
+    if (R == NULL) {
+	Cudd_RecursiveDeref(dd, Rt);
+	Cudd_RecursiveDeref(dd, Re);
+	return(NULL);
+    }
+    cuddDeref(Rt);
+    cuddDeref(Re);
+
+    /* Store the result in the cache. */
+    cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R);
+
+    return(R);
+
+} /* end of cuddAddOuterSumRecur */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddPriority.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddPriority.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddPriority.c	(revision 8)
@@ -0,0 +1,1566 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddPriority.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Priority functions.]
+
+  Description [External procedures included in this file:
+	    <ul>
+	    <li> Cudd_PrioritySelect()
+	    <li> Cudd_Xgty()
+	    <li> Cudd_Xeqy()
+	    <li> Cudd_addXeqy()
+	    <li> Cudd_Dxygtdxz()
+	    <li> Cudd_Dxygtdyz()
+	    <li> Cudd_CProjection()
+	    <li> Cudd_addHamming()
+	    <li> Cudd_MinHammingDist()
+	    <li> Cudd_bddClosestCube()
+	    </ul>
+	Internal procedures included in this module:
+	    <ul>
+	    <li> cuddCProjectionRecur()
+	    <li> cuddBddClosestCube()
+	    </ul>
+	Static procedures included in this module:
+	    <ul>
+	    <li> cuddMinHammingDistRecur()
+	    <li> separateCube()
+	    <li> createResult()
+	    </ul>
+	    ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_DEBUG 1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddPriority.c,v 1.26 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static int cuddMinHammingDistRecur (DdNode * f, int *minterm, DdHashTable * table, int upperBound);
+static DdNode * separateCube (DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance);
+static DdNode * createResult (DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Selects pairs from R using a priority function.]
+
+  Description [Selects pairs from a relation R(x,y) (given as a BDD)
+  in such a way that a given x appears in one pair only. Uses a
+  priority function to determine which y should be paired to a given x.
+  Cudd_PrioritySelect returns a pointer to
+  the selected function if successful; NULL otherwise.
+  Three of the arguments--x, y, and z--are vectors of BDD variables.
+  The first two are the variables on which R depends. The third vectore
+  is a vector of auxiliary variables, used during the computation. This
+  vector is optional. If a NULL value is passed instead,
+  Cudd_PrioritySelect will create the working variables on the fly.
+  The sizes of x and y (and z if it is not NULL) should equal n.
+  The priority function Pi can be passed as a BDD, or can be built by
+  Cudd_PrioritySelect. If NULL is passed instead of a DdNode *,
+  parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the
+  priority function. (Pifunc is a pointer to a C function.) If Pi is not
+  NULL, then Pifunc is ignored. Pifunc should have the same interface as
+  the standard priority functions (e.g., Cudd_Dxygtdxz).
+  Cudd_PrioritySelect and Cudd_CProjection can sometimes be used
+  interchangeably. Specifically, calling Cudd_PrioritySelect with
+  Cudd_Xgty as Pifunc produces the same result as calling
+  Cudd_CProjection with the all-zero minterm as reference minterm.
+  However, depending on the application, one or the other may be
+  preferable:
+  <ul>
+  <li> When extracting representatives from an equivalence relation,
+  Cudd_CProjection has the advantage of nor requiring the auxiliary
+  variables.
+  <li> When computing matchings in general bipartite graphs,
+  Cudd_PrioritySelect normally obtains better results because it can use
+  more powerful matching schemes (e.g., Cudd_Dxygtdxz).
+  </ul>
+  ]
+
+  SideEffects [If called with z == NULL, will create new variables in
+  the manager.]
+
+  SeeAlso     [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty
+  Cudd_bddAdjPermuteX Cudd_CProjection]
+
+******************************************************************************/
+DdNode *
+Cudd_PrioritySelect(
+  DdManager * dd /* manager */,
+  DdNode * R /* BDD of the relation */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */,
+  DdNode ** z /* array of z variables (optional: may be NULL) */,
+  DdNode * Pi /* BDD of the priority function (optional: may be NULL) */,
+  int  n /* size of x, y, and z */,
+  DD_PRFP Pifunc /* function used to build Pi if it is NULL */)
+{
+    DdNode *res = NULL;
+    DdNode *zcube = NULL;
+    DdNode *Rxz, *Q;
+    int createdZ = 0;
+    int createdPi = 0;
+    int i;
+
+    /* Create z variables if needed. */
+    if (z == NULL) {
+	if (Pi != NULL) return(NULL);
+	z = ALLOC(DdNode *,n);
+	if (z == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(NULL);
+	}
+	createdZ = 1;
+	for (i = 0; i < n; i++) {
+	    if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame;
+	    z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one));
+	    if (z[i] == NULL) goto endgame;
+	}
+    }
+
+    /* Create priority function BDD if needed. */
+    if (Pi == NULL) {
+	Pi = Pifunc(dd,n,x,y,z);
+	if (Pi == NULL) goto endgame;
+	createdPi = 1;
+	cuddRef(Pi);
+    }
+
+    /* Initialize abstraction cube. */
+    zcube = DD_ONE(dd);
+    cuddRef(zcube);
+    for (i = n - 1; i >= 0; i--) {
+	DdNode *tmpp;
+	tmpp = Cudd_bddAnd(dd,z[i],zcube);
+	if (tmpp == NULL) goto endgame;
+	cuddRef(tmpp);
+	Cudd_RecursiveDeref(dd,zcube);
+	zcube = tmpp;
+    }
+
+    /* Compute subset of (x,y) pairs. */
+    Rxz = Cudd_bddSwapVariables(dd,R,y,z,n);
+    if (Rxz == NULL) goto endgame;
+    cuddRef(Rxz);
+    Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube);
+    if (Q == NULL) {
+	Cudd_RecursiveDeref(dd,Rxz);
+	goto endgame;
+    }
+    cuddRef(Q);
+    Cudd_RecursiveDeref(dd,Rxz);
+    res = Cudd_bddAnd(dd,R,Cudd_Not(Q));
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd,Q);
+	goto endgame;
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,Q);
+
+endgame:
+    if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube);
+    if (createdZ) {
+	FREE(z);
+    }
+    if (createdPi) {
+	Cudd_RecursiveDeref(dd,Pi);
+    }
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* Cudd_PrioritySelect */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function x &gt; y.]
+
+  Description [This function generates a BDD for the function x &gt; y.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The BDD is built bottom-up.
+  It has 3*N-1 internal nodes, if the variables are ordered as follows: 
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].
+  Argument z is not used by Cudd_Xgty: it is included to make it
+  call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Dxygtdyz]
+
+******************************************************************************/
+DdNode *
+Cudd_Xgty(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  DdNode ** z /* array of z variables: unused */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    DdNode *u, *v, *w;
+    int     i;
+
+    /* Build bottom part of BDD outside loop. */
+    u = Cudd_bddAnd(dd, x[N-1], Cudd_Not(y[N-1]));
+    if (u == NULL) return(NULL);
+    cuddRef(u);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+	v = Cudd_bddAnd(dd, y[i], Cudd_Not(u));
+	if (v == NULL) {
+	    Cudd_RecursiveDeref(dd, u);
+	    return(NULL);
+	}
+	cuddRef(v);
+	w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u);
+	if (w == NULL) {
+	    Cudd_RecursiveDeref(dd, u);
+	    Cudd_RecursiveDeref(dd, v);
+	    return(NULL);
+	}
+	cuddRef(w);
+	Cudd_RecursiveDeref(dd, u);
+	u = Cudd_bddIte(dd, x[i], Cudd_Not(v), w);
+	if (u == NULL) {
+	    Cudd_RecursiveDeref(dd, v);
+	    Cudd_RecursiveDeref(dd, w);
+	    return(NULL);
+	}
+	cuddRef(u);
+	Cudd_RecursiveDeref(dd, v);
+	Cudd_RecursiveDeref(dd, w);
+
+    }
+    cuddDeref(u);
+    return(u);
+
+} /* end of Cudd_Xgty */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function x==y.]
+
+  Description [This function generates a BDD for the function x==y.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The BDD is built bottom-up.
+  It has 3*N-1 internal nodes, if the variables are ordered as follows: 
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addXeqy]
+
+******************************************************************************/
+DdNode *
+Cudd_Xeqy(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    DdNode *u, *v, *w;
+    int     i;
+
+    /* Build bottom part of BDD outside loop. */
+    u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1]));
+    if (u == NULL) return(NULL);
+    cuddRef(u);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+	v = Cudd_bddAnd(dd, y[i], u);
+	if (v == NULL) {
+	    Cudd_RecursiveDeref(dd, u);
+	    return(NULL);
+	}
+	cuddRef(v);
+	w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u);
+	if (w == NULL) {
+	    Cudd_RecursiveDeref(dd, u);
+	    Cudd_RecursiveDeref(dd, v);
+	    return(NULL);
+	}
+	cuddRef(w);
+	Cudd_RecursiveDeref(dd, u);
+	u = Cudd_bddIte(dd, x[i], v, w);
+	if (u == NULL) {
+	    Cudd_RecursiveDeref(dd, v);
+	    Cudd_RecursiveDeref(dd, w);
+	    return(NULL);
+	}
+	cuddRef(u);
+	Cudd_RecursiveDeref(dd, v);
+	Cudd_RecursiveDeref(dd, w);
+    }
+    cuddDeref(u);
+    return(u);
+
+} /* end of Cudd_Xeqy */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates an ADD for the function x==y.]
+
+  Description [This function generates an ADD for the function x==y.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The ADD is built bottom-up.
+  It has 3*N-1 internal nodes, if the variables are ordered as follows: 
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Xeqy]
+
+******************************************************************************/
+DdNode *
+Cudd_addXeqy(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x and y variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */)
+{
+    DdNode *one, *zero;
+    DdNode *u, *v, *w;
+    int     i;
+
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    /* Build bottom part of ADD outside loop. */
+    v = Cudd_addIte(dd, y[N-1], one, zero);
+    if (v == NULL) return(NULL);
+    cuddRef(v);
+    w = Cudd_addIte(dd, y[N-1], zero, one);
+    if (w == NULL) {
+	Cudd_RecursiveDeref(dd, v);
+	return(NULL);
+    }
+    cuddRef(w);
+    u = Cudd_addIte(dd, x[N-1], v, w);
+    if (w == NULL) {
+	Cudd_RecursiveDeref(dd, v);
+	Cudd_RecursiveDeref(dd, w);
+	return(NULL);
+    }
+    cuddRef(u);
+    Cudd_RecursiveDeref(dd, v);
+    Cudd_RecursiveDeref(dd, w);
+
+    /* Loop to build the rest of the ADD. */
+    for (i = N-2; i >= 0; i--) {
+	v = Cudd_addIte(dd, y[i], u, zero);
+	if (v == NULL) {
+	    Cudd_RecursiveDeref(dd, u);
+	    return(NULL);
+	}
+	cuddRef(v);
+	w = Cudd_addIte(dd, y[i], zero, u);
+	if (w == NULL) {
+	    Cudd_RecursiveDeref(dd, u);
+	    Cudd_RecursiveDeref(dd, v);
+	    return(NULL);
+	}
+	cuddRef(w);
+	Cudd_RecursiveDeref(dd, u);
+	u = Cudd_addIte(dd, x[i], v, w);
+	if (w == NULL) {
+	    Cudd_RecursiveDeref(dd, v);
+	    Cudd_RecursiveDeref(dd, w);
+	    return(NULL);
+	}
+	cuddRef(u);
+	Cudd_RecursiveDeref(dd, v);
+	Cudd_RecursiveDeref(dd, w);
+    }
+    cuddDeref(u);
+    return(u);
+
+} /* end of Cudd_addXeqy */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function d(x,y) &gt; d(x,z).]
+
+  Description [This function generates a BDD for the function d(x,y)
+  &gt; d(x,z);
+  x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\],
+  y\[0\] y\[1\] ...  y\[N-1\], and z\[0\] z\[1\] ...  z\[N-1\],
+  with 0 the most significant bit.
+  The distance d(x,y) is defined as:
+	\sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).
+  The BDD is built bottom-up.
+  It has 7*N-3 internal nodes, if the variables are ordered as follows: 
+  x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX]
+
+******************************************************************************/
+DdNode *
+Cudd_Dxygtdxz(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x, y, and z variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */,
+  DdNode ** z /* array of z variables */)
+{
+    DdNode *one, *zero;
+    DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1;
+    int     i;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Build bottom part of BDD outside loop. */
+    y1_ = Cudd_bddIte(dd, y[N-1], one, Cudd_Not(z[N-1]));
+    if (y1_ == NULL) return(NULL);
+    cuddRef(y1_);
+    y2 = Cudd_bddIte(dd, y[N-1], z[N-1], one);
+    if (y2 == NULL) {
+	Cudd_RecursiveDeref(dd, y1_);
+	return(NULL);
+    }
+    cuddRef(y2);
+    x1 = Cudd_bddIte(dd, x[N-1], y1_, y2);
+    if (x1 == NULL) {
+	Cudd_RecursiveDeref(dd, y1_);
+	Cudd_RecursiveDeref(dd, y2);
+	return(NULL);
+    }
+    cuddRef(x1);
+    Cudd_RecursiveDeref(dd, y1_);
+    Cudd_RecursiveDeref(dd, y2);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+	z1 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1));
+	if (z1 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    return(NULL);
+	}
+	cuddRef(z1);
+	z2 = Cudd_bddIte(dd, z[i], x1, one);
+	if (z2 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    Cudd_RecursiveDeref(dd, z1);
+	    return(NULL);
+	}
+	cuddRef(z2);
+	z3 = Cudd_bddIte(dd, z[i], one, x1);
+	if (z3 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    return(NULL);
+	}
+	cuddRef(z3);
+	z4 = Cudd_bddIte(dd, z[i], x1, zero);
+	if (z4 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    Cudd_RecursiveDeref(dd, z3);
+	    return(NULL);
+	}
+	cuddRef(z4);
+	Cudd_RecursiveDeref(dd, x1);
+	y1_ = Cudd_bddIte(dd, y[i], z2, Cudd_Not(z1));
+	if (y1_ == NULL) {
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    Cudd_RecursiveDeref(dd, z3);
+	    Cudd_RecursiveDeref(dd, z4);
+	    return(NULL);
+	}
+	cuddRef(y1_);
+	y2 = Cudd_bddIte(dd, y[i], z4, z3);
+	if (y2 == NULL) {
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    Cudd_RecursiveDeref(dd, z3);
+	    Cudd_RecursiveDeref(dd, z4);
+	    Cudd_RecursiveDeref(dd, y1_);
+	    return(NULL);
+	}
+	cuddRef(y2);
+	Cudd_RecursiveDeref(dd, z1);
+	Cudd_RecursiveDeref(dd, z2);
+	Cudd_RecursiveDeref(dd, z3);
+	Cudd_RecursiveDeref(dd, z4);
+	x1 = Cudd_bddIte(dd, x[i], y1_, y2);
+	if (x1 == NULL) {
+	    Cudd_RecursiveDeref(dd, y1_);
+	    Cudd_RecursiveDeref(dd, y2);
+	    return(NULL);
+	}
+	cuddRef(x1);
+	Cudd_RecursiveDeref(dd, y1_);
+	Cudd_RecursiveDeref(dd, y2);
+    }
+    cuddDeref(x1);
+    return(Cudd_Not(x1));
+
+} /* end of Cudd_Dxygtdxz */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function d(x,y) &gt; d(y,z).]
+
+  Description [This function generates a BDD for the function d(x,y)
+  &gt; d(y,z);
+  x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\],
+  y\[0\] y\[1\] ...  y\[N-1\], and z\[0\] z\[1\] ...  z\[N-1\],
+  with 0 the most significant bit.
+  The distance d(x,y) is defined as:
+	\sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).
+  The BDD is built bottom-up.
+  It has 7*N-3 internal nodes, if the variables are ordered as follows: 
+  x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX]
+
+******************************************************************************/
+DdNode *
+Cudd_Dxygtdyz(
+  DdManager * dd /* DD manager */,
+  int  N /* number of x, y, and z variables */,
+  DdNode ** x /* array of x variables */,
+  DdNode ** y /* array of y variables */,
+  DdNode ** z /* array of z variables */)
+{
+    DdNode *one, *zero;
+    DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1;
+    int     i;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    /* Build bottom part of BDD outside loop. */
+    y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]);
+    if (y1_ == NULL) return(NULL);
+    cuddRef(y1_);
+    y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero);
+    if (y2 == NULL) {
+	Cudd_RecursiveDeref(dd, y1_);
+	return(NULL);
+    }
+    cuddRef(y2);
+    x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2));
+    if (x1 == NULL) {
+	Cudd_RecursiveDeref(dd, y1_);
+	Cudd_RecursiveDeref(dd, y2);
+	return(NULL);
+    }
+    cuddRef(x1);
+    Cudd_RecursiveDeref(dd, y1_);
+    Cudd_RecursiveDeref(dd, y2);
+
+    /* Loop to build the rest of the BDD. */
+    for (i = N-2; i >= 0; i--) {
+	z1 = Cudd_bddIte(dd, z[i], x1, zero);
+	if (z1 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    return(NULL);
+	}
+	cuddRef(z1);
+	z2 = Cudd_bddIte(dd, z[i], x1, one);
+	if (z2 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    Cudd_RecursiveDeref(dd, z1);
+	    return(NULL);
+	}
+	cuddRef(z2);
+	z3 = Cudd_bddIte(dd, z[i], one, x1);
+	if (z3 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    return(NULL);
+	}
+	cuddRef(z3);
+	z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1));
+	if (z4 == NULL) {
+	    Cudd_RecursiveDeref(dd, x1);
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    Cudd_RecursiveDeref(dd, z3);
+	    return(NULL);
+	}
+	cuddRef(z4);
+	Cudd_RecursiveDeref(dd, x1);
+	y1_ = Cudd_bddIte(dd, y[i], z2, z1);
+	if (y1_ == NULL) {
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    Cudd_RecursiveDeref(dd, z3);
+	    Cudd_RecursiveDeref(dd, z4);
+	    return(NULL);
+	}
+	cuddRef(y1_);
+	y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3));
+	if (y2 == NULL) {
+	    Cudd_RecursiveDeref(dd, z1);
+	    Cudd_RecursiveDeref(dd, z2);
+	    Cudd_RecursiveDeref(dd, z3);
+	    Cudd_RecursiveDeref(dd, z4);
+	    Cudd_RecursiveDeref(dd, y1_);
+	    return(NULL);
+	}
+	cuddRef(y2);
+	Cudd_RecursiveDeref(dd, z1);
+	Cudd_RecursiveDeref(dd, z2);
+	Cudd_RecursiveDeref(dd, z3);
+	Cudd_RecursiveDeref(dd, z4);
+	x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2));
+	if (x1 == NULL) {
+	    Cudd_RecursiveDeref(dd, y1_);
+	    Cudd_RecursiveDeref(dd, y2);
+	    return(NULL);
+	}
+	cuddRef(x1);
+	Cudd_RecursiveDeref(dd, y1_);
+	Cudd_RecursiveDeref(dd, y2);
+    }
+    cuddDeref(x1);
+    return(Cudd_Not(x1));
+
+} /* end of Cudd_Dxygtdyz */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the compatible projection of R w.r.t. cube Y.]
+
+  Description [Computes the compatible projection of relation R with
+  respect to cube Y. Returns a pointer to the c-projection if
+  successful; NULL otherwise. For a comparison between Cudd_CProjection
+  and Cudd_PrioritySelect, see the documentation of the latter.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrioritySelect]
+
+******************************************************************************/
+DdNode *
+Cudd_CProjection(
+  DdManager * dd,
+  DdNode * R,
+  DdNode * Y)
+{
+    DdNode *res;
+    DdNode *support;
+
+    if (cuddCheckCube(dd,Y) == 0) {
+	(void) fprintf(dd->err,
+	"Error: The third argument of Cudd_CProjection should be a cube\n");
+	dd->errorCode = CUDD_INVALID_ARG;
+	return(NULL);
+    }
+
+    /* Compute the support of Y, which is used by the abstraction step
+    ** in cuddCProjectionRecur.
+    */
+    support = Cudd_Support(dd,Y);
+    if (support == NULL) return(NULL);
+    cuddRef(support);
+
+    do {
+	dd->reordered = 0;
+	res = cuddCProjectionRecur(dd,R,Y,support);
+    } while (dd->reordered == 1);
+
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd,support);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,support);
+    cuddDeref(res);
+
+    return(res);
+
+} /* end of Cudd_CProjection */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the Hamming distance ADD.]
+
+  Description [Computes the Hamming distance ADD. Returns an ADD that
+  gives the Hamming distance between its two arguments if successful;
+  NULL otherwise. The two vectors xVars and yVars identify the variables
+  that form the two arguments.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_addHamming(
+  DdManager * dd,
+  DdNode ** xVars,
+  DdNode ** yVars,
+  int  nVars)
+{
+    DdNode  *result,*tempBdd;
+    DdNode  *tempAdd,*temp;
+    int     i;
+
+    result = DD_ZERO(dd);
+    cuddRef(result);
+
+    for (i = 0; i < nVars; i++) {
+	tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]);
+	if (tempBdd == NULL) {
+	    Cudd_RecursiveDeref(dd,result);
+	    return(NULL);
+	}
+	cuddRef(tempBdd);
+	tempAdd = Cudd_BddToAdd(dd,tempBdd);
+	if (tempAdd == NULL) {
+	    Cudd_RecursiveDeref(dd,tempBdd);
+	    Cudd_RecursiveDeref(dd,result);
+	    return(NULL);
+	}
+	cuddRef(tempAdd);
+	Cudd_RecursiveDeref(dd,tempBdd);
+	temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result);
+	if (temp == NULL) {
+	    Cudd_RecursiveDeref(dd,tempAdd);
+	    Cudd_RecursiveDeref(dd,result);
+	    return(NULL);
+	}
+	cuddRef(temp);
+	Cudd_RecursiveDeref(dd,tempAdd);
+	Cudd_RecursiveDeref(dd,result);
+	result = temp;
+    }
+
+    cuddDeref(result);
+    return(result);
+
+} /* end of Cudd_addHamming */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the minimum Hamming distance between f and minterm.]
+
+  Description [Returns the minimum Hamming distance between the
+  minterms of a function f and a reference minterm. The function is
+  given as a BDD; the minterm is given as an array of integers, one
+  for each variable in the manager.  Returns the minimum distance if
+  it is less than the upper bound; the upper bound if the minimum
+  distance is at least as large; CUDD_OUT_OF_MEM in case of failure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addHamming Cudd_bddClosestCube]
+
+******************************************************************************/
+int
+Cudd_MinHammingDist(
+  DdManager *dd /* DD manager */,
+  DdNode *f /* function to examine */,
+  int *minterm /* reference minterm */,
+  int upperBound /* distance above which an approximate answer is OK */)
+{
+    DdHashTable *table;
+    CUDD_VALUE_TYPE epsilon;
+    int res;
+
+    table = cuddHashTableInit(dd,1,2);
+    if (table == NULL) {
+	return(CUDD_OUT_OF_MEM);
+    }
+    epsilon = Cudd_ReadEpsilon(dd);
+    Cudd_SetEpsilon(dd,(CUDD_VALUE_TYPE)0.0);
+    res = cuddMinHammingDistRecur(f,minterm,table,upperBound);
+    cuddHashTableQuit(table);
+    Cudd_SetEpsilon(dd,epsilon);
+
+    return(res);
+    
+} /* end of Cudd_MinHammingDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a cube of f at minimum Hamming distance from g.]
+
+  Description [Finds a cube of f at minimum Hamming distance from the
+  minterms of g.  All the minterms of the cube are at the minimum
+  distance.  If the distance is 0, the cube belongs to the
+  intersection of f and g.  Returns the cube if successful; NULL
+  otherwise.]
+
+  SideEffects [The distance is returned as a side effect.]
+
+  SeeAlso     [Cudd_MinHammingDist]
+
+******************************************************************************/
+DdNode *
+Cudd_bddClosestCube(
+  DdManager *dd,
+  DdNode * f,
+  DdNode *g,
+  int *distance)
+{
+    DdNode *res, *acube;
+    CUDD_VALUE_TYPE rdist;
+
+    /* Compute the cube and distance as a single ADD. */
+    do {
+	dd->reordered = 0;
+	res = cuddBddClosestCube(dd,f,g,CUDD_CONST_INDEX + 1.0);
+    } while (dd->reordered == 1);
+    if (res == NULL) return(NULL);
+    cuddRef(res);
+
+    /* Unpack distance and cube. */
+    do {
+	dd->reordered = 0;
+	acube = separateCube(dd, res, &rdist);
+    } while (dd->reordered == 1);
+    if (acube == NULL) {
+	Cudd_RecursiveDeref(dd, res);
+	return(NULL);
+    }
+    cuddRef(acube);
+    Cudd_RecursiveDeref(dd, res);
+
+    /* Convert cube from ADD to BDD. */
+    do {
+	dd->reordered = 0;
+	res = cuddAddBddDoPattern(dd, acube);
+    } while (dd->reordered == 1);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, acube);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, acube);
+
+    *distance = (int) rdist;
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_bddClosestCube */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CProjection.]
+
+  Description [Performs the recursive step of Cudd_CProjection. Returns
+  the projection if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CProjection]
+
+******************************************************************************/
+DdNode *
+cuddCProjectionRecur(
+  DdManager * dd,
+  DdNode * R,
+  DdNode * Y,
+  DdNode * Ysupp)
+{
+    DdNode *res, *res1, *res2, *resA;
+    DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha;
+    unsigned int topR, topY, top, index;
+    DdNode *one = DD_ONE(dd);
+
+    statLine(dd);
+    if (Y == one) return(R);
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsConstant(Y));
+#endif
+
+    if (R == Cudd_Not(one)) return(R);
+
+    res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y);
+    if (res != NULL) return(res);
+
+    r = Cudd_Regular(R);
+    topR = cuddI(dd,r->index);
+    y = Cudd_Regular(Y);
+    topY = cuddI(dd,y->index);
+
+    top = ddMin(topR, topY);
+
+    /* Compute the cofactors of R */
+    if (topR == top) {
+	index = r->index;
+	RT = cuddT(r);
+	RE = cuddE(r);
+	if (r != R) {
+	    RT = Cudd_Not(RT); RE = Cudd_Not(RE);
+	}
+    } else {
+	RT = RE = R;
+    }
+
+    if (topY > top) {
+	/* Y does not depend on the current top variable.
+	** We just need to compute the results on the two cofactors of R
+	** and make them the children of a node labeled r->index.
+	*/
+	res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp);
+	if (res1 == NULL) return(NULL);
+	cuddRef(res1);
+	res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp);
+	if (res2 == NULL) {
+	    Cudd_RecursiveDeref(dd,res1);
+	    return(NULL);
+	}
+	cuddRef(res2);
+	res = cuddBddIteRecur(dd, dd->vars[index], res1, res2);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd,res1);
+	    Cudd_RecursiveDeref(dd,res2);
+	    return(NULL);
+	}
+	/* If we have reached this point, res1 and res2 are now
+	** incorporated in res. cuddDeref is therefore sufficient.
+	*/
+	cuddDeref(res1);
+	cuddDeref(res2);
+    } else {
+	/* Compute the cofactors of Y */
+	index = y->index;
+	YT = cuddT(y);
+	YE = cuddE(y);
+	if (y != Y) {
+	    YT = Cudd_Not(YT); YE = Cudd_Not(YE);
+	}
+	if (YT == Cudd_Not(one)) {
+	    Alpha  = Cudd_Not(dd->vars[index]);
+	    Yrest = YE;
+	    Ra = RE;
+	    Ran = RT;
+	} else {
+	    Alpha = dd->vars[index];
+	    Yrest = YT;
+	    Ra = RT;
+	    Ran = RE;
+	}
+	Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp));
+	if (Gamma == NULL) return(NULL);
+	if (Gamma == one) {
+	    res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
+	    if (res1 == NULL) return(NULL);
+	    cuddRef(res1);
+	    res = cuddBddAndRecur(dd, Alpha, res1);
+	    if (res == NULL) {
+		Cudd_RecursiveDeref(dd,res1);
+		return(NULL);
+	    }
+	    cuddDeref(res1);
+	} else if (Gamma == Cudd_Not(one)) {
+	    res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
+	    if (res1 == NULL) return(NULL);
+	    cuddRef(res1);
+	    res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1);
+	    if (res == NULL) {
+		Cudd_RecursiveDeref(dd,res1);
+		return(NULL);
+	    }
+	    cuddDeref(res1);
+	} else {
+	    cuddRef(Gamma);
+	    resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
+	    if (resA == NULL) {
+		Cudd_RecursiveDeref(dd,Gamma);
+		return(NULL);
+	    }
+	    cuddRef(resA);
+	    res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA);
+	    if (res2 == NULL) {
+		Cudd_RecursiveDeref(dd,Gamma);
+		Cudd_RecursiveDeref(dd,resA);
+		return(NULL);
+	    }
+	    cuddRef(res2);
+	    Cudd_RecursiveDeref(dd,Gamma);
+	    Cudd_RecursiveDeref(dd,resA);
+	    res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
+	    if (res1 == NULL) {
+		Cudd_RecursiveDeref(dd,res2);
+		return(NULL);
+	    }
+	    cuddRef(res1);
+	    res = cuddBddIteRecur(dd, Alpha, res1, res2);
+	    if (res == NULL) {
+		Cudd_RecursiveDeref(dd,res1);
+		Cudd_RecursiveDeref(dd,res2);
+		return(NULL);
+	    }
+	    cuddDeref(res1);
+	    cuddDeref(res2);
+	}
+    }
+
+    cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res);
+
+    return(res);
+
+} /* end of cuddCProjectionRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddClosestCube.]
+
+  Description [Performs the recursive step of Cudd_bddClosestCube.
+  Returns the cube if succesful; NULL otherwise.  The procedure uses a
+  four-way recursion to examine all four combinations of cofactors of
+  <code>f</code> and <code>g</code> according to the following formula.
+  <pre>
+    H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
+  </pre>
+  Bounding is based on the following observations.
+  <ul>
+  <li> If we already found two points at distance 0, there is no point in
+       continuing.  Furthermore,
+  <li> If F == not(G) then the best we can hope for is a minimum distance
+       of 1.  If we have already found two points at distance 1, there is
+       no point in continuing.  (Indeed, H(F,G) == 1 in this case.  We
+       have to continue, though, to find the cube.)
+  </ul>
+  The variable <code>bound</code> is set at the largest value of the distance
+  that we are still interested in.  Therefore, we desist when
+  <pre>
+    (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
+  </pre>
+  If we were maximally aggressive in using the bound, we would always
+  set the bound to the minimum distance seen thus far minus one.  That
+  is, we would maintain the invariant
+  <pre>
+    bound < minD,
+  </pre>
+  except at the very beginning, when we have no value for
+  <code>minD</code>.<p>
+
+  However, we do not use <code>bound < minD</code> when examining the
+  two negative cofactors, because we try to find a large cube at
+  minimum distance.  To do so, we try to find a cube in the negative
+  cofactors at the same or smaller distance from the cube found in the
+  positive cofactors.<p>
+
+  When we compute <code>H(ft,ge)</code> and <code>H(fe,gt)</code> we
+  know that we are going to add 1 to the result of the recursive call
+  to account for the difference in the splitting variable.  Therefore,
+  we decrease the bound correspondingly.<p>
+
+  Another important observation concerns the need of examining all
+  four pairs of cofators only when both <code>f</code> and
+  <code>g</code> depend on the top variable.<p>
+
+  Suppose <code>gt == ge == g</code>.  (That is, <code>g</code> does
+  not depend on the top variable.)  Then
+  <pre>
+    H(f,g) = min(H(ft,g), H(fe,g), H(ft,g)+1, H(fe,g)+1)
+           = min(H(ft,g), H(fe,g)) .
+  </pre>
+  Therefore, under these circumstances, we skip the two "cross" cases.<p>
+
+  An interesting feature of this function is the scheme used for
+  caching the results in the global computed table.  Since we have a
+  cube and a distance, we combine them to form an ADD.  The
+  combination replaces the zero child of the top node of the cube with
+  the negative of the distance.  (The use of the negative is to avoid
+  ambiguity with 1.)  The degenerate cases (zero and one) are treated
+  specially because the distance is known (0 for one, and infinity for
+  zero).]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddClosestCube]
+
+******************************************************************************/
+DdNode *
+cuddBddClosestCube(
+  DdManager *dd,
+  DdNode *f,
+  DdNode *g,
+  CUDD_VALUE_TYPE bound)
+{
+    DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee;
+    DdNode *ctt, *cee, *cte, *cet;
+    CUDD_VALUE_TYPE minD, dtt, dee, dte, det;
+    DdNode *one = DD_ONE(dd);
+    DdNode *lzero = Cudd_Not(one);
+    DdNode *azero = DD_ZERO(dd);
+    unsigned int topf, topg, index;
+
+    statLine(dd);
+    if (bound < (f == Cudd_Not(g))) return(azero);
+    /* Terminal cases. */
+    if (g == lzero || f == lzero) return(azero);
+    if (f == one && g == one) return(one);
+
+    /* Check cache. */
+    F = Cudd_Regular(f);
+    G = Cudd_Regular(g);
+    if (F->ref != 1 || G->ref != 1) {
+	res = cuddCacheLookup2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g);
+	if (res != NULL) return(res);
+    }
+
+    topf = cuddI(dd,F->index);
+    topg = cuddI(dd,G->index);
+
+    /* Compute cofactors. */
+    if (topf <= topg) {
+	index = F->index;
+	ft = cuddT(F);
+	fe = cuddE(F);
+	if (Cudd_IsComplement(f)) {
+	    ft = Cudd_Not(ft);
+	    fe = Cudd_Not(fe);
+	}
+    } else {
+	index = G->index;
+	ft = fe = f;
+    }
+
+    if (topg <= topf) {
+	gt = cuddT(G);
+	ge = cuddE(G);
+	if (Cudd_IsComplement(g)) {
+	    gt = Cudd_Not(gt);
+	    ge = Cudd_Not(ge);
+	}
+    } else {
+	gt = ge = g;
+    }
+
+    tt = cuddBddClosestCube(dd,ft,gt,bound);
+    if (tt == NULL) return(NULL);
+    cuddRef(tt);
+    ctt = separateCube(dd,tt,&dtt);
+    if (ctt == NULL) {
+	Cudd_RecursiveDeref(dd, tt);
+	return(NULL);
+    }
+    cuddRef(ctt);
+    Cudd_RecursiveDeref(dd, tt);
+    minD = dtt;
+    bound = ddMin(bound,minD);
+
+    ee = cuddBddClosestCube(dd,fe,ge,bound);
+    if (ee == NULL) {
+	Cudd_RecursiveDeref(dd, ctt);
+	return(NULL);
+    }
+    cuddRef(ee);
+    cee = separateCube(dd,ee,&dee);
+    if (cee == NULL) {
+	Cudd_RecursiveDeref(dd, ctt);
+	Cudd_RecursiveDeref(dd, ee);
+	return(NULL);
+    }
+    cuddRef(cee);
+    Cudd_RecursiveDeref(dd, ee);
+    minD = ddMin(dtt, dee);
+    if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
+
+    if (minD > 0 && topf == topg) {
+	DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1);
+	if (te == NULL) {
+	    Cudd_RecursiveDeref(dd, ctt);
+	    Cudd_RecursiveDeref(dd, cee);
+	    return(NULL);
+	}
+	cuddRef(te);
+	cte = separateCube(dd,te,&dte);
+	if (cte == NULL) {
+	    Cudd_RecursiveDeref(dd, ctt);
+	    Cudd_RecursiveDeref(dd, cee);
+	    Cudd_RecursiveDeref(dd, te);
+	    return(NULL);
+	}
+	cuddRef(cte);
+	Cudd_RecursiveDeref(dd, te);
+	dte += 1.0;
+	minD = ddMin(minD, dte);
+    } else {
+	cte = azero;
+	cuddRef(cte);
+	dte = CUDD_CONST_INDEX + 1.0;
+    }
+    if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
+
+    if (minD > 0 && topf == topg) {
+	DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1);
+	if (et == NULL) {
+	    Cudd_RecursiveDeref(dd, ctt);
+	    Cudd_RecursiveDeref(dd, cee);
+	    Cudd_RecursiveDeref(dd, cte);
+	    return(NULL);
+	}
+	cuddRef(et);
+	cet = separateCube(dd,et,&det);
+	if (cet == NULL) {
+	    Cudd_RecursiveDeref(dd, ctt);
+	    Cudd_RecursiveDeref(dd, cee);
+	    Cudd_RecursiveDeref(dd, cte);
+	    Cudd_RecursiveDeref(dd, et);
+	    return(NULL);
+	}
+	cuddRef(cet);
+	Cudd_RecursiveDeref(dd, et);
+	det += 1.0;
+	minD = ddMin(minD, det);
+    } else {
+	cet = azero;
+	cuddRef(cet);
+	det = CUDD_CONST_INDEX + 1.0;
+    }
+
+    if (minD == dtt) {
+	if (dtt == dee && ctt == cee) {
+	    res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt);
+	} else {
+	    res = createResult(dd,index,1,ctt,dtt);
+	}
+    } else if (minD == dee) {
+	res = createResult(dd,index,0,cee,dee);
+    } else if (minD == dte) {
+#ifdef DD_DEBUG
+	assert(topf == topg);
+#endif
+	res = createResult(dd,index,1,cte,dte);
+    } else {
+#ifdef DD_DEBUG
+	assert(topf == topg);
+#endif
+	res = createResult(dd,index,0,cet,det);
+    }
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, ctt);
+	Cudd_RecursiveDeref(dd, cee);
+	Cudd_RecursiveDeref(dd, cte);
+	Cudd_RecursiveDeref(dd, cet);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd, ctt);
+    Cudd_RecursiveDeref(dd, cee);
+    Cudd_RecursiveDeref(dd, cte);
+    Cudd_RecursiveDeref(dd, cet);
+
+    /* Only cache results that are different from azero to avoid
+    ** storing results that depend on the value of the bound. */
+    if ((F->ref != 1 || G->ref != 1) && res != azero)
+	cuddCacheInsert2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g, res);
+
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddBddClosestCube */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_MinHammingDist.]
+
+  Description [Performs the recursive step of Cudd_MinHammingDist.
+  It is based on the following identity. Let H(f) be the
+  minimum Hamming distance of the minterms of f from the reference
+  minterm. Then:
+  <xmp>
+    H(f) = min(H(f0)+h0,H(f1)+h1)
+  </xmp>
+  where f0 and f1 are the two cofactors of f with respect to its top
+  variable; h0 is 1 if the minterm assigns 1 to the top variable of f;
+  h1 is 1 if the minterm assigns 0 to the top variable of f.
+  The upper bound on the distance is used to bound the depth of the
+  recursion.
+  Returns the minimum distance unless it exceeds the upper bound or
+  computation fails.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_MinHammingDist]
+
+******************************************************************************/
+static int
+cuddMinHammingDistRecur(
+  DdNode * f,
+  int *minterm,
+  DdHashTable * table,
+  int upperBound)
+{
+    DdNode	*F, *Ft, *Fe;
+    double	h, hT, hE;
+    DdNode	*zero, *res;
+    DdManager	*dd = table->manager;
+
+    statLine(dd);
+    if (upperBound == 0) return(0);
+
+    F = Cudd_Regular(f);
+
+    if (cuddIsConstant(F)) {
+	zero = Cudd_Not(DD_ONE(dd));
+	if (f == dd->background || f == zero) {
+	    return(upperBound);
+	} else {
+	    return(0);
+	}
+    }
+    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
+	h = cuddV(res);
+	if (res->ref == 0) {
+	    dd->dead++;
+	    dd->constants.dead++;
+	}
+	return((int) h);
+    }
+
+    Ft = cuddT(F); Fe = cuddE(F);
+    if (Cudd_IsComplement(f)) {
+	Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe);
+    }
+    if (minterm[F->index] == 0) {
+	DdNode *temp = Ft;
+	Ft = Fe; Fe = temp;
+    }
+
+    hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound);
+    if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    if (hT == 0) {
+	hE = upperBound;
+    } else {
+	hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1);
+	if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    }
+    h = ddMin(hT, hE + 1);
+
+    if (F->ref != 1) {
+	ptrint fanout = (ptrint) F->ref;
+	cuddSatDec(fanout);
+	res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h);
+	if (!cuddHashTableInsert1(table,f,res,fanout)) {
+	    cuddRef(res); Cudd_RecursiveDeref(dd, res);
+	    return(CUDD_OUT_OF_MEM);
+	}
+    }
+
+    return((int) h);
+
+} /* end of cuddMinHammingDistRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Separates cube from distance.]
+
+  Description [Separates cube from distance.  Returns the cube if
+  successful; NULL otherwise.]
+
+  SideEffects [The distance is returned as a side effect.]
+
+  SeeAlso     [cuddBddClosestCube createResult]
+
+******************************************************************************/
+static DdNode *
+separateCube(
+  DdManager *dd,
+  DdNode *f,
+  CUDD_VALUE_TYPE *distance)
+{
+    DdNode *cube, *t;
+
+    /* One and zero are special cases because the distance is implied. */
+    if (Cudd_IsConstant(f)) {
+	*distance = (f == DD_ONE(dd)) ? 0.0 :
+	    (1.0 + (CUDD_VALUE_TYPE) CUDD_CONST_INDEX);
+	return(f);
+    }
+
+    /* Find out which branch points to the distance and replace the top
+    ** node with one pointing to zero instead. */
+    t = cuddT(f);
+    if (Cudd_IsConstant(t) && cuddV(t) <= 0) {
+#ifdef DD_DEBUG
+	assert(!Cudd_IsConstant(cuddE(f)) || cuddE(f) == DD_ONE(dd));
+#endif
+	*distance = -cuddV(t);
+	cube = cuddUniqueInter(dd, f->index, DD_ZERO(dd), cuddE(f));
+    } else {
+#ifdef DD_DEBUG
+	assert(!Cudd_IsConstant(t) || t == DD_ONE(dd));
+#endif
+	*distance = -cuddV(cuddE(f));
+	cube = cuddUniqueInter(dd, f->index, t, DD_ZERO(dd));
+    }
+
+    return(cube);
+
+} /* end of separateCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a result for cache storage.]
+
+  Description [Builds a result for cache storage.  Returns a pointer
+  to the resulting ADD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddBddClosestCube separateCube]
+
+******************************************************************************/
+static DdNode *
+createResult(
+  DdManager *dd,
+  unsigned int index,
+  unsigned int phase,
+  DdNode *cube,
+  CUDD_VALUE_TYPE distance)
+{
+    DdNode *res, *constant;
+
+    /* Special case.  The cube is either one or zero, and we do not
+    ** add any variables.  Hence, the result is also one or zero,
+    ** and the distance remains implied by the value of the constant. */
+    if (index == CUDD_CONST_INDEX && Cudd_IsConstant(cube)) return(cube);
+
+    constant = cuddUniqueConst(dd,-distance);
+    if (constant == NULL) return(NULL);
+    cuddRef(constant);
+
+    if (index == CUDD_CONST_INDEX) {
+	/* Replace the top node. */
+	if (cuddT(cube) == DD_ZERO(dd)) {
+	    res = cuddUniqueInter(dd,cube->index,constant,cuddE(cube));
+	} else {
+	    res = cuddUniqueInter(dd,cube->index,cuddT(cube),constant);
+	}
+    } else {
+	/* Add a new top node. */
+#ifdef DD_DEBUG
+	assert(cuddI(dd,index) < cuddI(dd,cube->index));
+#endif
+	if (phase) {
+	    res = cuddUniqueInter(dd,index,cube,constant);
+	} else {
+	    res = cuddUniqueInter(dd,index,constant,cube);
+	}
+    }
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd, constant);
+	return(NULL);
+    }
+    cuddDeref(constant); /* safe because constant is part of res */
+
+    return(res);
+
+} /* end of createResult */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddRead.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddRead.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddRead.c	(revision 8)
@@ -0,0 +1,517 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddRead.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to read in a matrix]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_addRead()
+		<li> Cudd_bddRead()
+		</ul>]
+
+  SeeAlso     [cudd_addHarwell.c]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.6 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in a sparse matrix.]
+
+  Description [Reads in a sparse matrix specified in a simple format.
+  The first line of the input contains the numbers of rows and columns.
+  The remaining lines contain the elements of the matrix, one per line.
+  Given a background value
+  (specified by the background field of the manager), only the values
+  different from it are explicitly listed.  Each foreground element is
+  described by two integers, i.e., the row and column number, and a
+  real number, i.e., the value.<p>
+  Cudd_addRead produces an ADD that depends on two sets of variables: x
+  and y.  The x variables (x\[0\] ... x\[nx-1\]) encode the row index and
+  the y variables (y\[0\] ... y\[ny-1\]) encode the column index.
+  x\[0\] and y\[0\] are the most significant bits in the indices.
+  The variables may already exist or may be created by the function.
+  The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
+  On input, nx and ny hold the numbers
+  of row and column variables already in existence. On output, they
+  hold the numbers of row and column variables actually used by the
+  matrix. When Cudd_addRead creates the variable arrays,
+  the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.
+  When some variables already exist Cudd_addRead expects the indices
+  of the existing x variables to be bx+i*sx, and the indices of the
+  existing y variables to be by+i*sy.<p>
+  m and n are set to the numbers of rows and columns of the
+  matrix.  Their values on input are immaterial.
+  The ADD for the
+  sparse matrix is returned in E, and its reference count is > 0.
+  Cudd_addRead returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [nx and ny are set to the numbers of row and column
+  variables. m and n are set to the numbers of rows and columns. x and y
+  are possibly extended to represent the array of row and column
+  variables. Similarly for xn and yn_, which hold on return from
+  Cudd_addRead the complements of the row and column variables.]
+
+  SeeAlso     [Cudd_addHarwell Cudd_bddRead]
+
+******************************************************************************/
+int
+Cudd_addRead(
+  FILE * fp /* input file pointer */,
+  DdManager * dd /* DD manager */,
+  DdNode ** E /* characteristic function of the graph */,
+  DdNode *** x /* array of row variables */,
+  DdNode *** y /* array of column variables */,
+  DdNode *** xn /* array of complemented row variables */,
+  DdNode *** yn_ /* array of complemented column variables */,
+  int * nx /* number or row variables */,
+  int * ny /* number or column variables */,
+  int * m /* number of rows */,
+  int * n /* number of columns */,
+  int  bx /* first index of row variables */,
+  int  sx /* step of row variables */,
+  int  by /* first index of column variables */,
+  int  sy /* step of column variables */)
+{
+    DdNode *one, *zero;
+    DdNode *w, *neW;
+    DdNode *minterm1;
+    int u, v, err, i, nv;
+    int lnx, lny;
+    CUDD_VALUE_TYPE val;
+    DdNode **lx, **ly, **lxn, **lyn;
+
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+
+    err = fscanf(fp, "%d %d", &u, &v);
+    if (err == EOF) {
+	return(0);
+    } else if (err != 2) {
+	return(0);
+    }
+
+    *m = u;
+    /* Compute the number of x variables. */
+    lx = *x; lxn = *xn;
+    u--; 	/* row and column numbers start from 0 */
+    for (lnx=0; u > 0; lnx++) {
+	u >>= 1;
+    }
+    /* Here we rely on the fact that REALLOC of a null pointer is
+    ** translates to an ALLOC.
+    */
+    if (lnx > *nx) {
+	*x = lx = REALLOC(DdNode *, *x, lnx);
+	if (lx == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	*xn = lxn =  REALLOC(DdNode *, *xn, lnx);
+	if (lxn == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+    }
+
+    *n = v;
+    /* Compute the number of y variables. */
+    ly = *y; lyn = *yn_;
+    v--; 	/* row and column numbers start from 0 */
+    for (lny=0; v > 0; lny++) {
+	v >>= 1;
+    }
+    /* Here we rely on the fact that REALLOC of a null pointer is
+    ** translates to an ALLOC.
+    */
+    if (lny > *ny) {
+	*y = ly = REALLOC(DdNode *, *y, lny);
+	if (ly == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	*yn_ = lyn =  REALLOC(DdNode *, *yn_, lny);
+	if (lyn == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+    }
+
+    /* Create all new variables. */
+    for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
+	do {
+	    dd->reordered = 0;
+	    lx[i] = cuddUniqueInter(dd, nv, one, zero);
+	} while (dd->reordered == 1);
+	if (lx[i] == NULL) return(0);
+        cuddRef(lx[i]);
+	do {
+	    dd->reordered = 0;
+	    lxn[i] = cuddUniqueInter(dd, nv, zero, one);
+	} while (dd->reordered == 1);
+	if (lxn[i] == NULL) return(0);
+        cuddRef(lxn[i]);
+    }
+    for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
+	do {
+	    dd->reordered = 0;
+	    ly[i] = cuddUniqueInter(dd, nv, one, zero);
+	} while (dd->reordered == 1);
+	if (ly[i] == NULL) return(0);
+	cuddRef(ly[i]);
+	do {
+	    dd->reordered = 0;
+	    lyn[i] = cuddUniqueInter(dd, nv, zero, one);
+	} while (dd->reordered == 1);
+	if (lyn[i] == NULL) return(0);
+	cuddRef(lyn[i]);
+    }
+    *nx = lnx;
+    *ny = lny;
+
+    *E = dd->background; /* this call will never cause reordering */
+    cuddRef(*E);
+
+    while (! feof(fp)) {
+	err = fscanf(fp, "%d %d %lf", &u, &v, &val);
+	if (err == EOF) {
+	    break;
+	} else if (err != 3) {
+	    return(0);
+	} else if (u >= *m || v >= *n || u < 0 || v < 0) {
+	    return(0);
+	}
+ 
+	minterm1 = one; cuddRef(minterm1);
+
+	/* Build minterm1 corresponding to this arc */
+	for (i = lnx - 1; i>=0; i--) {
+	    if (u & 1) {
+		w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]);
+	    } else {
+		w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]);
+	    }
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, minterm1);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    minterm1 = w;
+	    u >>= 1;
+	}
+	for (i = lny - 1; i>=0; i--) {
+	    if (v & 1) {
+		w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]);
+	    } else {
+		w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]);
+	    }
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, minterm1);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    minterm1 = w;
+	    v >>= 1;
+	}
+	/* Create new constant node if necessary.
+	** This call will never cause reordering.
+	*/
+	neW = cuddUniqueConst(dd, val);
+	if (neW == NULL) {
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    return(0);
+	}
+    	cuddRef(neW);
+
+	w = Cudd_addIte(dd, minterm1, neW, *E);
+	if (w == NULL) {
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    Cudd_RecursiveDeref(dd, neW);
+	    return(0);
+	}
+	cuddRef(w);
+	Cudd_RecursiveDeref(dd, minterm1);
+	Cudd_RecursiveDeref(dd, neW);
+	Cudd_RecursiveDeref(dd, *E);
+	*E = w;
+    }
+    return(1);
+
+} /* end of Cudd_addRead */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in a graph (without labels) given as a list of arcs.]
+
+  Description [Reads in a graph (without labels) given as an adjacency
+  matrix.  The first line of the input contains the numbers of rows and
+  columns of the adjacency matrix. The remaining lines contain the arcs
+  of the graph, one per line. Each arc is described by two integers,
+  i.e., the row and column number, or the indices of the two endpoints.
+  Cudd_bddRead produces a BDD that depends on two sets of variables: x
+  and y.  The x variables (x\[0\] ... x\[nx-1\]) encode
+  the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the
+  column index. x\[0\] and y\[0\] are the most significant bits in the
+  indices.
+  The variables may already exist or may be created by the function.
+  The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
+  On input, nx and ny hold the numbers of row and column variables already
+  in existence. On output, they hold the numbers of row and column
+  variables actually used by the matrix. When Cudd_bddRead creates the
+  variable arrays, the index of x\[i\] is bx+i*sx, and the index of
+  y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead
+  expects the indices of the existing x variables to be bx+i*sx, and the
+  indices of the existing y variables to be by+i*sy.<p>
+  m and n are set to the numbers of rows and columns of the
+  matrix.  Their values on input are immaterial.  The BDD for the graph
+  is returned in E, and its reference count is > 0. Cudd_bddRead returns
+  1 in case of success; 0 otherwise.]
+
+  SideEffects [nx and ny are set to the numbers of row and column
+  variables. m and n are set to the numbers of rows and columns. x and y
+  are possibly extended to represent the array of row and column
+  variables.]
+
+  SeeAlso     [Cudd_addHarwell Cudd_addRead]
+
+******************************************************************************/
+int
+Cudd_bddRead(
+  FILE * fp /* input file pointer */,
+  DdManager * dd /* DD manager */,
+  DdNode ** E /* characteristic function of the graph */,
+  DdNode *** x /* array of row variables */,
+  DdNode *** y /* array of column variables */,
+  int * nx /* number or row variables */,
+  int * ny /* number or column variables */,
+  int * m /* number of rows */,
+  int * n /* number of columns */,
+  int  bx /* first index of row variables */,
+  int  sx /* step of row variables */,
+  int  by /* first index of column variables */,
+  int  sy /* step of column variables */)
+{
+    DdNode *one, *zero;
+    DdNode *w;
+    DdNode *minterm1;
+    int u, v, err, i, nv;
+    int lnx, lny;
+    DdNode **lx, **ly;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    err = fscanf(fp, "%d %d", &u, &v);
+    if (err == EOF) {
+	return(0);
+    } else if (err != 2) {
+	return(0);
+    }
+
+    *m = u;
+    /* Compute the number of x variables. */
+    lx = *x;
+    u--; 	/* row and column numbers start from 0 */
+    for (lnx=0; u > 0; lnx++) {
+	u >>= 1;
+    }
+    if (lnx > *nx) {
+	*x = lx = REALLOC(DdNode *, *x, lnx);
+	if (lx == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+    }
+
+    *n = v;
+    /* Compute the number of y variables. */
+    ly = *y;
+    v--; 	/* row and column numbers start from 0 */
+    for (lny=0; v > 0; lny++) {
+	v >>= 1;
+    }
+    if (lny > *ny) {
+	*y = ly = REALLOC(DdNode *, *y, lny);
+	if (ly == NULL) {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+    }
+
+    /* Create all new variables. */
+    for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
+	do {
+	    dd->reordered = 0;
+	    lx[i] = cuddUniqueInter(dd, nv, one, zero);
+	} while (dd->reordered == 1);
+	if (lx[i] == NULL) return(0);
+        cuddRef(lx[i]);
+    }
+    for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
+	do {
+	    dd->reordered = 0;
+	    ly[i] = cuddUniqueInter(dd, nv, one, zero);
+	} while (dd->reordered == 1);
+	if (ly[i] == NULL) return(0);
+	cuddRef(ly[i]);
+    }
+    *nx = lnx;
+    *ny = lny;
+
+    *E = zero; /* this call will never cause reordering */
+    cuddRef(*E);
+
+    while (! feof(fp)) {
+	err = fscanf(fp, "%d %d", &u, &v);
+	if (err == EOF) {
+	    break;
+	} else if (err != 2) {
+	    return(0);
+	} else if (u >= *m || v >= *n || u < 0 || v < 0) {
+	    return(0);
+	}
+ 
+	minterm1 = one; cuddRef(minterm1);
+
+	/* Build minterm1 corresponding to this arc. */
+	for (i = lnx - 1; i>=0; i--) {
+	    if (u & 1) {
+		w = Cudd_bddAnd(dd, minterm1, lx[i]);
+	    } else {
+		w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i]));
+	    }
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, minterm1);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd,minterm1);
+	    minterm1 = w;
+	    u >>= 1;
+	}
+	for (i = lny - 1; i>=0; i--) {
+	    if (v & 1) {
+		w = Cudd_bddAnd(dd, minterm1, ly[i]);
+	    } else {
+		w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i]));
+	    }
+	    if (w == NULL) {
+		Cudd_RecursiveDeref(dd, minterm1);
+		return(0);
+	    }
+	    cuddRef(w);
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    minterm1 = w;
+	    v >>= 1;
+	}
+
+	w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E));
+	if (w == NULL) {
+	    Cudd_RecursiveDeref(dd, minterm1);
+	    return(0);
+	}
+	w = Cudd_Not(w);
+	cuddRef(w);
+	Cudd_RecursiveDeref(dd, minterm1);
+	Cudd_RecursiveDeref(dd, *E);
+	*E = w;
+    }
+    return(1);
+
+} /* end of Cudd_bddRead */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddRef.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddRef.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddRef.c	(revision 8)
@@ -0,0 +1,808 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddRef.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions that manipulate the reference counts.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_Ref()
+		    <li> Cudd_RecursiveDeref()
+		    <li> Cudd_IterDerefBdd()
+		    <li> Cudd_DelayedDerefBdd()
+		    <li> Cudd_RecursiveDerefZdd()
+		    <li> Cudd_Deref()
+		    <li> Cudd_CheckZeroRef()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    <li> cuddReclaim()
+		    <li> cuddReclaimZdd()
+		    <li> cuddClearDeathRow()
+		    <li> cuddShrinkDeathRow()
+		    <li> cuddIsInDeathRow()
+		    <li> cuddTimesInDeathRow()
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.28 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Increases the reference count of a node, if it is not
+  saturated.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_Deref]
+
+******************************************************************************/
+void
+Cudd_Ref(
+  DdNode * n)
+{
+
+    n = Cudd_Regular(n);
+
+    cuddSatInc(n->ref);
+
+} /* end of Cudd_Ref */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of node n.]
+
+  Description [Decreases the reference count of node n. If n dies,
+  recursively decreases the reference counts of its children.  It is
+  used to dispose of a DD that is no longer needed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd]
+
+******************************************************************************/
+void
+Cudd_RecursiveDeref(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    unsigned int live = table->keys - table->dead;
+    if (live > table->peakLiveNodes) {
+	table->peakLiveNodes = live;
+    }
+
+    N = Cudd_Regular(n);
+
+    do {
+#ifdef DD_DEBUG
+	assert(N->ref != 0);
+#endif
+
+	if (N->ref == 1) {
+	    N->ref = 0;
+	    table->dead++;
+#ifdef DD_STATS
+	    table->nodesDropped++;
+#endif
+	    if (cuddIsConstant(N)) {
+		table->constants.dead++;
+		N = stack[--SP];
+	    } else {
+		ord = table->perm[N->index];
+		stack[SP++] = Cudd_Regular(cuddE(N));
+		table->subtables[ord].dead++;
+		N = cuddT(N);
+	    }
+	} else {
+	    cuddSatDec(N->ref);
+	    N = stack[--SP];
+	}
+    } while (SP != 0);
+
+} /* end of Cudd_RecursiveDeref */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of BDD node n.]
+
+  Description [Decreases the reference count of node n. If n dies,
+  recursively decreases the reference counts of its children.  It is
+  used to dispose of a BDD that is no longer needed. It is more
+  efficient than Cudd_RecursiveDeref, but it cannot be used on
+  ADDs. The greater efficiency comes from being able to assume that no
+  constant node will ever die as a result of a call to this
+  procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_DelayedDerefBdd]
+
+******************************************************************************/
+void
+Cudd_IterDerefBdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    unsigned int live = table->keys - table->dead;
+    if (live > table->peakLiveNodes) {
+	table->peakLiveNodes = live;
+    }
+
+    N = Cudd_Regular(n);
+
+    do {
+#ifdef DD_DEBUG
+	assert(N->ref != 0);
+#endif
+
+	if (N->ref == 1) {
+	    N->ref = 0;
+	    table->dead++;
+#ifdef DD_STATS
+	    table->nodesDropped++;
+#endif
+	    ord = table->perm[N->index];
+	    stack[SP++] = Cudd_Regular(cuddE(N));
+	    table->subtables[ord].dead++;
+	    N = cuddT(N);
+	} else {
+	    cuddSatDec(N->ref);
+	    N = stack[--SP];
+	}
+    } while (SP != 0);
+
+} /* end of Cudd_IterDerefBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of BDD node n.]
+
+  Description [Enqueues node n for later dereferencing. If the queue
+  is full decreases the reference count of the oldest node N to make
+  room for n. If N dies, recursively decreases the reference counts of
+  its children.  It is used to dispose of a BDD that is currently not
+  needed, but may be useful again in the near future. The dereferencing
+  proper is done as in Cudd_IterDerefBdd.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_IterDerefBdd]
+
+******************************************************************************/
+void
+Cudd_DelayedDerefBdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack;
+    int SP;
+
+    unsigned int live = table->keys - table->dead;
+    if (live > table->peakLiveNodes) {
+	table->peakLiveNodes = live;
+    }
+
+    n = Cudd_Regular(n);
+#ifdef DD_DEBUG
+    assert(n->ref != 0);
+#endif
+
+#ifdef DD_NO_DEATH_ROW
+    N = n;
+#else
+    if (cuddIsConstant(n) || n->ref > 1) {
+#ifdef DD_DEBUG
+	assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table)));
+#endif
+	cuddSatDec(n->ref);
+	return;
+    }
+
+    N = table->deathRow[table->nextDead];
+
+    if (N != NULL) {
+#endif
+#ifdef DD_DEBUG
+	assert(!Cudd_IsComplement(N));
+#endif
+	stack = table->stack;
+	SP = 1;
+	do {
+#ifdef DD_DEBUG
+	    assert(N->ref != 0);
+#endif
+	    if (N->ref == 1) {
+		N->ref = 0;
+		table->dead++;
+#ifdef DD_STATS
+		table->nodesDropped++;
+#endif
+		ord = table->perm[N->index];
+		stack[SP++] = Cudd_Regular(cuddE(N));
+		table->subtables[ord].dead++;
+		N = cuddT(N);
+	    } else {
+		cuddSatDec(N->ref);
+		N = stack[--SP];
+	    }
+	} while (SP != 0);
+#ifndef DD_NO_DEATH_ROW
+    }
+    table->deathRow[table->nextDead] = n;
+
+    /* Udate insertion point. */
+    table->nextDead++;
+    table->nextDead &= table->deadMask;
+#if 0
+    if (table->nextDead == table->deathRowDepth) {
+	if (table->deathRowDepth < table->looseUpTo / 2) {
+	    extern void (*MMoutOfMemory)(long);
+	    void (*saveHandler)(long) = MMoutOfMemory;
+	    DdNodePtr *newRow;
+	    MMoutOfMemory = Cudd_OutOfMem;
+	    newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth);
+	    MMoutOfMemory = saveHandler;
+	    if (newRow == NULL) {
+		table->nextDead = 0;
+	    } else {
+		int i;
+		table->memused += table->deathRowDepth;
+		i = table->deathRowDepth;
+		table->deathRowDepth <<= 1;
+		for (; i < table->deathRowDepth; i++) {
+		    newRow[i] = NULL;
+		}
+		table->deadMask = table->deathRowDepth - 1;
+		table->deathRow = newRow;
+	    }
+	} else {
+	    table->nextDead = 0;
+	}
+    }
+#endif
+#endif
+
+} /* end of Cudd_DelayedDerefBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of ZDD node n.]
+
+  Description [Decreases the reference count of ZDD node n. If n dies,
+  recursively decreases the reference counts of its children.  It is
+  used to dispose of a ZDD that is no longer needed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref]
+
+******************************************************************************/
+void
+Cudd_RecursiveDerefZdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    N = n;
+
+    do {
+#ifdef DD_DEBUG
+	assert(N->ref != 0);
+#endif
+
+	cuddSatDec(N->ref);
+    
+	if (N->ref == 0) {
+	    table->deadZ++;
+#ifdef DD_STATS
+	    table->nodesDropped++;
+#endif
+#ifdef DD_DEBUG
+	    assert(!cuddIsConstant(N));
+#endif
+	    ord = table->permZ[N->index];
+	    stack[SP++] = cuddE(N);
+	    table->subtableZ[ord].dead++;
+	    N = cuddT(N);
+	} else {
+	    N = stack[--SP];
+	}
+    } while (SP != 0);
+
+} /* end of Cudd_RecursiveDerefZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decreases the reference count of node.]
+
+  Description [Decreases the reference count of node. It is primarily
+  used in recursive procedures to decrease the ref count of a result
+  node before returning it. This accomplishes the goal of removing the
+  protection applied by a previous Cudd_Ref.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref]
+
+******************************************************************************/
+void
+Cudd_Deref(
+  DdNode * node)
+{
+    node = Cudd_Regular(node);
+    cuddSatDec(node->ref);
+
+} /* end of Cudd_Deref */
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks the unique table for nodes with non-zero reference
+  counts.]
+
+  Description [Checks the unique table for nodes with non-zero
+  reference counts. It is normally called before Cudd_Quit to make sure
+  that there are no memory leaks due to missing Cudd_RecursiveDeref's.
+  Takes into account that reference counts may saturate and that the
+  basic constants and the projection functions are referenced by the
+  manager.  Returns the number of nodes with non-zero reference count.
+  (Except for the cases mentioned above.)]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_CheckZeroRef(
+  DdManager * manager)
+{
+    int size;
+    int i, j;
+    int remain;	/* the expected number of remaining references to one */
+    DdNodePtr *nodelist;
+    DdNode *node;
+    DdNode *sentinel = &(manager->sentinel);
+    DdSubtable *subtable;
+    int count = 0;
+    int index;
+
+#ifndef DD_NO_DEATH_ROW
+    cuddClearDeathRow(manager);
+#endif
+
+    /* First look at the BDD/ADD subtables. */
+    remain = 1; /* reference from the manager */
+    size = manager->size;
+    remain += 2 * size;	/* reference from the BDD projection functions */
+
+    for (i = 0; i < size; i++) {
+	subtable = &(manager->subtables[i]);
+	nodelist = subtable->nodelist;
+	for (j = 0; (unsigned) j < subtable->slots; j++) {
+	    node = nodelist[j];
+	    while (node != sentinel) {
+		if (node->ref != 0 && node->ref != DD_MAXREF) {
+		    index = (int) node->index;
+		    if (node != manager->vars[index]) {
+			count++;
+		    } else {
+			if (node->ref != 1) {
+			    count++;
+			}
+		    }
+		}
+		node = node->next;
+	    }
+	}
+    }
+
+    /* Then look at the ZDD subtables. */
+    size = manager->sizeZ;
+    if (size) /* references from ZDD universe */
+	remain += 2;
+
+    for (i = 0; i < size; i++) {
+	subtable = &(manager->subtableZ[i]);
+	nodelist = subtable->nodelist;
+	for (j = 0; (unsigned) j < subtable->slots; j++) {
+	    node = nodelist[j];
+	    while (node != NULL) {
+		if (node->ref != 0 && node->ref != DD_MAXREF) {
+		    index = (int) node->index;
+		    if (node == manager->univ[manager->permZ[index]]) {
+			if (node->ref > 2) {
+			    count++;
+			}
+		    } else {
+			count++;
+		    }
+		}
+		node = node->next;
+	    }
+	}
+    }
+
+    /* Now examine the constant table. Plusinfinity, minusinfinity, and
+    ** zero are referenced by the manager. One is referenced by the
+    ** manager, by the ZDD universe, and by all projection functions.
+    ** All other nodes should have no references.
+    */
+    nodelist = manager->constants.nodelist;
+    for (j = 0; (unsigned) j < manager->constants.slots; j++) {
+	node = nodelist[j];
+	while (node != NULL) {
+	    if (node->ref != 0 && node->ref != DD_MAXREF) {
+		if (node == manager->one) {
+		    if ((int) node->ref != remain) {
+			count++;
+		    }
+		} else if (node == manager->zero ||
+		node == manager->plusinfinity ||
+		node == manager->minusinfinity) {
+		    if (node->ref != 1) {
+			count++;
+		    }
+		} else {
+		    count++;
+		}
+	    }
+	    node = node->next;
+	}
+    }
+    return(count);
+
+} /* end of Cudd_CheckZeroRef */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Brings children of a dead node back.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddReclaimZdd]
+
+******************************************************************************/
+void
+cuddReclaim(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+    double initialDead = table->dead;
+
+    N = Cudd_Regular(n);
+
+#ifdef DD_DEBUG
+    assert(N->ref == 0);
+#endif
+
+    do {
+	if (N->ref == 0) {
+	    N->ref = 1;
+	    table->dead--;
+	    if (cuddIsConstant(N)) {
+		table->constants.dead--;
+		N = stack[--SP];
+	    } else {
+		ord = table->perm[N->index];
+		stack[SP++] = Cudd_Regular(cuddE(N));
+		table->subtables[ord].dead--;
+		N = cuddT(N);
+	    }
+	} else {
+	    cuddSatInc(N->ref);
+	    N = stack[--SP];
+	}
+    } while (SP != 0);
+
+    N = Cudd_Regular(n);
+    cuddSatDec(N->ref);
+    table->reclaimed += initialDead - table->dead;
+
+} /* end of cuddReclaim */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Brings children of a dead ZDD node back.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddReclaim]
+
+******************************************************************************/
+void
+cuddReclaimZdd(
+  DdManager * table,
+  DdNode * n)
+{
+    DdNode *N;
+    int ord;
+    DdNodePtr *stack = table->stack;
+    int SP = 1;
+
+    N = n;
+
+#ifdef DD_DEBUG
+    assert(N->ref == 0);
+#endif
+
+    do {
+	cuddSatInc(N->ref);
+
+	if (N->ref == 1) {
+	    table->deadZ--;
+	    table->reclaimed++;
+#ifdef DD_DEBUG
+	    assert(!cuddIsConstant(N));
+#endif
+	    ord = table->permZ[N->index];
+	    stack[SP++] = cuddE(N);
+	    table->subtableZ[ord].dead--;
+	    N = cuddT(N);
+	} else {
+	    N = stack[--SP];
+	}
+    } while (SP != 0);
+
+    cuddSatDec(n->ref);
+
+} /* end of cuddReclaimZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shrinks the death row.]
+
+  Description [Shrinks the death row by a factor of four.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddClearDeathRow]
+
+******************************************************************************/
+void
+cuddShrinkDeathRow(
+  DdManager *table)
+{
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    if (table->deathRowDepth > 3) {
+	for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) {
+	    if (table->deathRow[i] == NULL) break;
+	    Cudd_IterDerefBdd(table,table->deathRow[i]);
+	    table->deathRow[i] = NULL;
+	}
+	table->deathRowDepth /= 4;
+	table->deadMask = table->deathRowDepth - 1;
+	if ((unsigned) table->nextDead > table->deadMask) {
+	    table->nextDead = 0;
+	}
+	table->deathRow = REALLOC(DdNodePtr, table->deathRow,
+				   table->deathRowDepth);
+    }
+#endif
+
+} /* end of cuddShrinkDeathRow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clears the death row.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef
+  cuddGarbageCollect]
+
+******************************************************************************/
+void
+cuddClearDeathRow(
+  DdManager *table)
+{
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    for (i = 0; i < table->deathRowDepth; i++) {
+	if (table->deathRow[i] == NULL) break;
+	Cudd_IterDerefBdd(table,table->deathRow[i]);
+	table->deathRow[i] = NULL;
+    }
+#ifdef DD_DEBUG
+    for (; i < table->deathRowDepth; i++) {
+	assert(table->deathRow[i] == NULL);
+    }
+#endif
+    table->nextDead = 0;
+#endif
+
+} /* end of cuddClearDeathRow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a node is in the death row.]
+
+  Description [Checks whether a node is in the death row. Returns the
+  position of the first occurrence if the node is present; -1
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DelayedDerefBdd cuddClearDeathRow]
+
+******************************************************************************/
+int
+cuddIsInDeathRow(
+  DdManager *dd,
+  DdNode *f)
+{
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    for (i = 0; i < dd->deathRowDepth; i++) {
+	if (f == dd->deathRow[i]) {
+	    return(i);
+	}
+    }
+#endif
+
+    return(-1);
+
+} /* end of cuddIsInDeathRow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts how many times a node is in the death row.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow]
+
+******************************************************************************/
+int
+cuddTimesInDeathRow(
+  DdManager *dd,
+  DdNode *f)
+{
+    int count = 0;
+#ifndef DD_NO_DEATH_ROW
+    int i;
+
+    for (i = 0; i < dd->deathRowDepth; i++) {
+	count += f == dd->deathRow[i];
+    }
+#endif
+
+    return(count);
+
+} /* end of cuddTimesInDeathRow */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: /vis_dev/glu-2.1/src/cuBdd/cuddReorder.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddReorder.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddReorder.c	(revision 8)
@@ -0,0 +1,2129 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddReorder.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for dynamic variable reordering.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_ReduceHeap()
+		<li> Cudd_ShuffleHeap()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddDynamicAllocNode()
+		<li> cuddSifting()
+		<li> cuddSwapping()
+		<li> cuddNextHigh()
+		<li> cuddNextLow()
+		<li> cuddSwapInPlace()
+		<li> cuddBddAlignToZdd()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddUniqueCompare()
+		<li> ddSwapAny()
+		<li> ddSiftingAux()
+		<li> ddSiftingUp()
+		<li> ddSiftingDown()
+		<li> ddSiftingBackward()
+		<li> ddReorderPreprocess()
+		<li> ddReorderPostprocess()
+		<li> ddShuffle()
+		<li> ddSiftUp()
+		<li> bddFixTree()
+		</ul>]
+
+  Author      [Shipra Panda, Bernard Plessier, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAX_SUBTABLE_SPARSITY 8
+#define DD_SHRINK_FACTOR 2
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.67 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+static	int	*entry;
+
+int	ddTotalNumberSwapping;
+#ifdef DD_STATS
+int	ddTotalNISwaps;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddUniqueCompare (int *ptrX, int *ptrY);
+static Move * ddSwapAny (DdManager *table, int x, int y);
+static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * ddSiftingUp (DdManager *table, int y, int xLow);
+static Move * ddSiftingDown (DdManager *table, int x, int xHigh);
+static int ddSiftingBackward (DdManager *table, int size, Move *moves);
+static int ddReorderPreprocess (DdManager *table);
+static int ddReorderPostprocess (DdManager *table);
+static int ddShuffle (DdManager *table, int *permutation);
+static int ddSiftUp (DdManager *table, int x, int xLow);
+static void bddFixTree (DdManager *table, MtrNode *treenode);
+static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
+static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main dynamic reordering routine.]
+
+  Description [Main dynamic reordering routine.
+  Calls one of the possible reordering procedures:
+  <ul>
+  <li>Swapping
+  <li>Sifting
+  <li>Symmetric Sifting
+  <li>Group Sifting
+  <li>Window Permutation
+  <li>Simulated Annealing
+  <li>Genetic Algorithm
+  <li>Dynamic Programming (exact)
+  </ul>
+
+  For sifting, symmetric sifting, group sifting, and window
+  permutation it is possible to request reordering to convergence.<p>
+
+  The core of all methods is the reordering procedure
+  cuddSwapInPlace() which swaps two adjacent variables and is based
+  on Rudell's paper.
+  Returns 1 in case of success; 0 otherwise. In the case of symmetric
+  sifting (with and without convergence) returns 1 plus the number of
+  symmetric variables, in case of success.]
+
+  SideEffects [Changes the variable order for all diagrams and clears
+  the cache.]
+
+******************************************************************************/
+int
+Cudd_ReduceHeap(
+  DdManager * table /* DD manager */,
+  Cudd_ReorderingType heuristic /* method used for reordering */,
+  int  minsize /* bound below which no reordering occurs */)
+{
+    DdHook *hook;
+    int	result;
+    unsigned int nextDyn;
+#ifdef DD_STATS
+    unsigned int initialSize;
+    unsigned int finalSize;
+#endif
+    long localTime;
+
+    /* Don't reorder if there are too many dead nodes. */
+    if (table->keys - table->dead < (unsigned) minsize)
+	return(1);
+
+    if (heuristic == CUDD_REORDER_SAME) {
+	heuristic = table->autoMethod;
+    }
+    if (heuristic == CUDD_REORDER_NONE) {
+	return(1);
+    }
+
+    /* This call to Cudd_ReduceHeap does initiate reordering. Therefore
+    ** we count it.
+    */
+    table->reorderings++;
+
+    localTime = util_cpu_time();
+
+    /* Run the hook functions. */
+    hook = table->preReorderingHook;
+    while (hook != NULL) {
+	int res = (hook->f)(table, "BDD", (void *)heuristic);
+	if (res == 0) return(0);
+	hook = hook->next;
+    }
+
+    if (!ddReorderPreprocess(table)) return(0);
+    ddTotalNumberSwapping = 0;
+    
+    if (table->keys > table->peakLiveNodes) {
+	table->peakLiveNodes = table->keys;
+    }
+#ifdef DD_STATS
+    initialSize = table->keys - table->isolated;
+    ddTotalNISwaps = 0;
+
+    switch(heuristic) {
+    case CUDD_REORDER_RANDOM:
+    case CUDD_REORDER_RANDOM_PIVOT:
+	(void) fprintf(table->out,"#:I_RANDOM  ");
+	break;
+    case CUDD_REORDER_SIFT:
+    case CUDD_REORDER_SIFT_CONVERGE:
+    case CUDD_REORDER_SYMM_SIFT:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+    case CUDD_REORDER_GROUP_SIFT:
+    case CUDD_REORDER_GROUP_SIFT_CONV:
+	(void) fprintf(table->out,"#:I_SIFTING ");
+	break;
+    case CUDD_REORDER_WINDOW2:
+    case CUDD_REORDER_WINDOW3:
+    case CUDD_REORDER_WINDOW4:
+    case CUDD_REORDER_WINDOW2_CONV:
+    case CUDD_REORDER_WINDOW3_CONV:
+    case CUDD_REORDER_WINDOW4_CONV:
+	(void) fprintf(table->out,"#:I_WINDOW  ");
+	break;
+    case CUDD_REORDER_ANNEALING:
+	(void) fprintf(table->out,"#:I_ANNEAL  ");
+	break;
+    case CUDD_REORDER_GENETIC:
+	(void) fprintf(table->out,"#:I_GENETIC ");
+	break;
+    case CUDD_REORDER_LINEAR:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+	(void) fprintf(table->out,"#:I_LINSIFT ");
+	break;
+    case CUDD_REORDER_EXACT:
+	(void) fprintf(table->out,"#:I_EXACT   ");
+	break;
+    default:
+	return(0);
+    }
+    (void) fprintf(table->out,"%8d: initial size",initialSize); 
+#endif
+
+    /* See if we should use alternate threshold for maximum growth. */
+    if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
+	double saveGrowth = table->maxGrowth;
+	table->maxGrowth = table->maxGrowthAlt;
+	result = cuddTreeSifting(table,heuristic);
+	table->maxGrowth = saveGrowth;
+    } else {
+	result = cuddTreeSifting(table,heuristic);
+    }
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keys - table->isolated;
+    (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); 
+    (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
+		   ((double)(util_cpu_time() - localTime)/1000.0)); 
+    (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
+		   ddTotalNumberSwapping);
+    (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
+#endif
+
+    if (result == 0)
+	return(0);
+
+    if (!ddReorderPostprocess(table))
+	return(0);
+
+    if (table->realign) {
+	if (!cuddZddAlignToBdd(table))
+	    return(0);
+    }
+
+    nextDyn = (table->keys - table->constants.keys + 1) *
+	      DD_DYN_RATIO + table->constants.keys;
+    if (table->reorderings < 20 || nextDyn > table->nextDyn)
+	table->nextDyn = nextDyn;
+    else
+	table->nextDyn += 20;
+    table->reordered = 1;
+
+    /* Run hook functions. */
+    hook = table->postReorderingHook;
+    while (hook != NULL) {
+	int res = (hook->f)(table, "BDD", (void *)localTime);
+	if (res == 0) return(0);
+	hook = hook->next;
+    }
+    /* Update cumulative reordering time. */
+    table->reordTime += util_cpu_time() - localTime;
+
+    return(result);
+
+} /* end of Cudd_ReduceHeap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables according to given permutation.]
+
+  Description [Reorders variables according to given permutation.
+  The i-th entry of the permutation array contains the index of the variable
+  that should be brought to the i-th level.  The size of the array should be
+  equal or greater to the number of variables currently in use.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [Changes the variable order for all diagrams and clears
+  the cache.]
+
+  SeeAlso [Cudd_ReduceHeap]
+
+******************************************************************************/
+int
+Cudd_ShuffleHeap(
+  DdManager * table /* DD manager */,
+  int * permutation /* required variable permutation */)
+{
+
+    int	result;
+    int i;
+    int identity = 1;
+    int *perm;
+
+    /* Don't waste time in case of identity permutation. */
+    for (i = 0; i < table->size; i++) {
+	if (permutation[i] != table->invperm[i]) {
+	    identity = 0;
+	    break;
+	}
+    }
+    if (identity == 1) {
+	return(1);
+    }
+    if (!ddReorderPreprocess(table)) return(0);
+    if (table->keys > table->peakLiveNodes) {
+	table->peakLiveNodes = table->keys;
+    }
+
+    perm = ALLOC(int, table->size);
+    for (i = 0; i < table->size; i++)
+	perm[permutation[i]] = i;
+    if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
+	FREE(perm);
+	return(0);
+    }
+    if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
+	FREE(perm);
+	return(0);
+    }
+    FREE(perm);
+
+    result = ddShuffle(table,permutation);
+
+    if (!ddReorderPostprocess(table)) return(0);
+
+    return(result);
+
+} /* end of Cudd_ShuffleHeap */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dynamically allocates a Node.]
+
+  Description [Dynamically allocates a Node. This procedure is similar
+  to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage
+  collection, because during reordering there are no dead nodes.
+  Returns a pointer to a new node if successful; NULL is memory is
+  full.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAllocNode]
+
+******************************************************************************/
+DdNode *
+cuddDynamicAllocNode(
+  DdManager * table)
+{
+    int     i;
+    DdNodePtr *mem;
+    DdNode *list, *node;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (table->nextFree == NULL) {        /* free list is empty */
+	/* Try to allocate a new block. */
+	saveHandler = MMoutOfMemory;
+	MMoutOfMemory = Cudd_OutOfMem;
+	mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1);
+	MMoutOfMemory = saveHandler;
+	if (mem == NULL && table->stash != NULL) {
+	    FREE(table->stash);
+	    table->stash = NULL;
+	    /* Inhibit resizing of tables. */
+	    table->maxCacheHard = table->cacheSlots - 1;
+	    table->cacheSlack = -(table->cacheSlots + 1);
+	    for (i = 0; i < table->size; i++) {
+		table->subtables[i].maxKeys <<= 2;
+	    }
+	    mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
+	}
+	if (mem == NULL) {
+	    /* Out of luck. Call the default handler to do
+	    ** whatever it specifies for a failed malloc.  If this
+	    ** handler returns, then set error code, print
+	    ** warning, and return. */
+	    (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
+	    table->errorCode = CUDD_MEMORY_OUT;
+#ifdef DD_VERBOSE
+	    (void) fprintf(table->err,
+			   "cuddDynamicAllocNode: out of memory");
+	    (void) fprintf(table->err,"Memory in use = %lu\n",
+			   table->memused);
+#endif
+	    return(NULL);
+	} else {	/* successful allocation; slice memory */
+	    unsigned long offset;
+	    table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
+	    mem[0] = (DdNode *) table->memoryList;
+	    table->memoryList = mem;
+
+	    /* Here we rely on the fact that the size of a DdNode is a
+	    ** power of 2 and a multiple of the size of a pointer.
+	    ** If we align one node, all the others will be aligned
+	    ** as well. */
+	    offset = (unsigned long) mem & (sizeof(DdNode) - 1);
+	    mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
+#ifdef DD_DEBUG
+	    assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
+#endif
+	    list = (DdNode *) mem;
+
+	    i = 1;
+	    do {
+	        list[i - 1].ref = 0;
+		list[i - 1].next = &list[i];
+	    } while (++i < DD_MEM_CHUNK);
+
+	    list[DD_MEM_CHUNK-1].ref = 0;
+	    list[DD_MEM_CHUNK - 1].next = NULL;
+
+	    table->nextFree = &list[0];
+	}
+    } /* if free list empty */
+
+    node = table->nextFree;
+    table->nextFree = node->next;
+    return (node);
+
+} /* end of cuddDynamicAllocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implementation of Rudell's sifting algorithm.]
+
+  Description [Implementation of Rudell's sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down, remembering each time the
+    total size of the DD heap.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int	i;
+    int	*var;
+    int	size;
+    int	x;
+    int	result;
+#ifdef DD_STATS
+    int	previousSize;
+#endif
+
+    size = table->size;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    entry = ALLOC(int,size);
+    if (entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddSiftingOutOfMem;
+    }
+    var = ALLOC(int,size);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+	x = table->perm[i];
+	entry[i] = table->subtables[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
+	if (ddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	x = table->perm[var[i]];
+
+	if (x < lower || x > upper || table->subtables[x].bindVar == 1) 
+	    continue;
+#ifdef DD_STATS
+	previousSize = table->keys - table->isolated;
+#endif
+	result = ddSiftingAux(table, x, lower, upper);
+	if (!result) goto cuddSiftingOutOfMem;
+#ifdef DD_STATS
+	if (table->keys < (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keys > (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	    (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+    }
+
+    FREE(var);
+    FREE(entry);
+
+    return(1);
+
+cuddSiftingOutOfMem:
+
+    if (entry != NULL) FREE(entry);
+    if (var != NULL) FREE(var);
+
+    return(0); 
+
+} /* end of cuddSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables by a sequence of (non-adjacent) swaps.]
+
+  Description [Implementation of Plessier's algorithm that reorders
+  variables by a sequence of (non-adjacent) swaps.
+    <ol>
+    <li> Select two variables (RANDOM or HEURISTIC).
+    <li> Permute these variables.
+    <li> If the nodes have decreased accept the permutation.
+    <li> Otherwise reconstruct the original heap.
+    <li> Loop.
+    </ol>
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSwapping(
+  DdManager * table,
+  int lower,
+  int upper,
+  Cudd_ReorderingType heuristic)
+{
+    int	i, j;
+    int	max, keys;
+    int	nvars;
+    int	x, y;
+    int	iterate;
+    int previousSize;
+    Move *moves, *move;
+    int	pivot;
+    int	modulo;
+    int result;
+
+#ifdef DD_DEBUG
+    /* Sanity check */
+    assert(lower >= 0 && upper < table->size && lower <= upper);
+#endif
+
+    nvars = upper - lower + 1;
+    iterate = nvars;
+
+    for (i = 0; i < iterate; i++) {
+	if (ddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
+	    max = -1;
+	    for (j = lower; j <= upper; j++) {
+		if ((keys = table->subtables[j].keys) > max) {
+		    max = keys;
+		    pivot = j;
+		}
+	    }
+
+	    modulo = upper - pivot;
+	    if (modulo == 0) {
+		y = pivot;
+	    } else{
+		y = pivot + 1 + ((int) Cudd_Random() % modulo);
+	    }
+
+	    modulo = pivot - lower - 1;
+	    if (modulo < 1) {
+		x = lower;
+	    } else{
+		do {
+		    x = (int) Cudd_Random() % modulo;
+		} while (x == y);
+	    }
+	} else {
+	    x = ((int) Cudd_Random() % nvars) + lower;
+	    do {
+		y = ((int) Cudd_Random() % nvars) + lower;
+	    } while (x == y);
+	}
+	previousSize = table->keys - table->isolated;
+	moves = ddSwapAny(table,x,y);
+	if (moves == NULL) goto cuddSwappingOutOfMem;
+	result = ddSiftingBackward(table,previousSize,moves);
+	if (!result) goto cuddSwappingOutOfMem;
+	while (moves != NULL) {
+	    move = moves->next;
+	    cuddDeallocMove(table, moves);
+	    moves = move;
+	}
+#ifdef DD_STATS
+	if (table->keys < (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keys > (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+#if 0
+	(void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
+		       table->keys - table->isolated); 
+#endif
+    }
+
+    return(1);
+
+cuddSwappingOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+
+    return(0);
+
+} /* end of cuddSwapping */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a larger index.]
+
+  Description [Finds the next subtable with a larger index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddNextLow]
+
+******************************************************************************/
+int
+cuddNextHigh(
+  DdManager * table,
+  int  x)
+{
+    return(x+1);
+
+} /* end of cuddNextHigh */
+    
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a smaller index.]
+
+  Description [Finds the next subtable with a smaller index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddNextHigh]
+
+******************************************************************************/
+int
+cuddNextLow(
+  DdManager * table,
+  int  x)
+{
+    return(x-1);
+
+} /* end of cuddNextLow */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two adjacent variables.]
+
+  Description [Swaps two adjacent variables. It assumes that no dead
+  nodes are present on entry to this procedure.  The procedure then
+  guarantees that no dead nodes will be present when it terminates.
+  cuddSwapInPlace assumes that x &lt; y.  Returns the number of keys in
+  the table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSwapInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr *xlist, *ylist;
+    int    xindex, yindex;
+    int    xslots, yslots;
+    int    xshift, yshift;
+    int    oldxkeys, oldykeys;
+    int    newxkeys, newykeys;
+    int    comple, newcomplement;
+    int    i;
+    Cudd_VariableType varType;
+    Cudd_LazyGroupType groupType;
+    int    posn;
+    int    isolated;
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
+    DdNode *g,*next;
+    DdNodePtr *previousP;
+    DdNode *tmp;
+    DdNode *sentinel = &(table->sentinel);
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+#if DD_DEBUG
+    int    count,idcheck;
+#endif
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddNextHigh(table,x) == y);
+    assert(table->subtables[x].keys != 0);
+    assert(table->subtables[y].keys != 0);
+    assert(table->subtables[x].dead == 0);
+    assert(table->subtables[y].dead == 0);
+#endif
+
+    ddTotalNumberSwapping++;
+
+    /* Get parameters of x subtable. */
+    xindex = table->invperm[x];
+    xlist = table->subtables[x].nodelist; 
+    oldxkeys = table->subtables[x].keys;
+    xslots = table->subtables[x].slots;
+    xshift = table->subtables[x].shift;
+
+    /* Get parameters of y subtable. */
+    yindex = table->invperm[y];
+    ylist = table->subtables[y].nodelist;
+    oldykeys = table->subtables[y].keys;
+    yslots = table->subtables[y].slots;
+    yshift = table->subtables[y].shift;
+
+    if (!cuddTestInteract(table,xindex,yindex)) {
+#ifdef DD_STATS
+	ddTotalNISwaps++;
+#endif
+	newxkeys = oldxkeys;
+	newykeys = oldykeys;
+    } else {
+	newxkeys = 0;
+	newykeys = oldykeys;
+
+	/* Check whether the two projection functions involved in this
+	** swap are isolated. At the end, we'll be able to tell how many
+	** isolated projection functions are there by checking only these
+	** two functions again. This is done to eliminate the isolated
+	** projection functions from the node count.
+	*/
+	isolated = - ((table->vars[xindex]->ref == 1) +
+		     (table->vars[yindex]->ref == 1));
+
+	/* The nodes in the x layer that do not depend on
+	** y will stay there; the others are put in a chain.
+	** The chain is handled as a LIFO; g points to the beginning.
+	*/
+	g = NULL;
+	if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
+	    oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
+	    for (i = 0; i < xslots; i++) {
+		previousP = &(xlist[i]);
+		f = *previousP;
+		while (f != sentinel) {
+		    next = f->next;
+		    f1 = cuddT(f); f0 = cuddE(f);
+		    if (f1->index != (DdHalfWord) yindex &&
+			Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
+			/* stays */
+			newxkeys++;
+			*previousP = f;
+			previousP = &(f->next);
+		    } else {
+			f->index = yindex;
+			f->next = g;
+			g = f;
+		    }
+		    f = next;
+		} /* while there are elements in the collision chain */
+		*previousP = sentinel;
+	    } /* for each slot of the x subtable */
+	} else {		/* resize xlist */
+	    DdNode *h = NULL;
+	    DdNodePtr *newxlist;
+	    unsigned int newxslots;
+	    int newxshift;
+	    /* Empty current xlist. Nodes that stay go to list h;
+	    ** nodes that move go to list g. */
+	    for (i = 0; i < xslots; i++) {
+		f = xlist[i];
+		while (f != sentinel) {
+		    next = f->next;
+		    f1 = cuddT(f); f0 = cuddE(f);
+		    if (f1->index != (DdHalfWord) yindex &&
+			Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
+			/* stays */
+			f->next = h;
+			h = f;
+			newxkeys++;
+		    } else {
+			f->index = yindex;
+			f->next = g;
+			g = f;
+		    }
+		    f = next;
+		} /* while there are elements in the collision chain */
+	    } /* for each slot of the x subtable */
+	    /* Decide size of new subtable. */
+	    newxshift = xshift;
+	    newxslots = xslots;
+	    while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
+		newxshift--;
+		newxslots <<= 1;
+	    }
+	    while ((unsigned) oldxkeys < newxslots &&
+		   newxslots > table->initSlots) {
+		newxshift++;
+		newxslots >>= 1;
+	    }
+	    /* Try to allocate new table. Be ready to back off. */
+	    saveHandler = MMoutOfMemory;
+	    MMoutOfMemory = Cudd_OutOfMem;
+	    newxlist = ALLOC(DdNodePtr, newxslots);
+	    MMoutOfMemory = saveHandler;
+	    if (newxlist == NULL) {
+		(void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
+		newxlist = xlist;
+		newxslots = xslots;
+		newxshift = xshift;
+	    } else {
+		table->slots += ((int) newxslots - xslots);
+		table->minDead = (unsigned)
+		    (table->gcFrac * (double) table->slots);
+		table->cacheSlack = (int)
+		    ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO
+			  * table->slots) - 2 * (int) table->cacheSlots;
+		table->memused +=
+		    ((int) newxslots - xslots) * sizeof(DdNodePtr);
+		FREE(xlist);
+		xslots =  newxslots;
+		xshift = newxshift;
+		xlist = newxlist;
+	    }
+	    /* Initialize new subtable. */
+	    for (i = 0; i < xslots; i++) {
+		xlist[i] = sentinel;
+	    }
+	    /* Move nodes that were parked in list h to their new home. */
+	    f = h;
+	    while (f != NULL) {
+		next = f->next;
+		f1 = cuddT(f);
+		f0 = cuddE(f);
+		/* Check xlist for pair (f11,f01). */
+		posn = ddHash(f1, f0, xshift);
+		/* For each element tmp in collision list xlist[posn]. */
+		previousP = &(xlist[posn]);
+		tmp = *previousP;
+		while (f1 < cuddT(tmp)) {
+		    previousP = &(tmp->next);
+		    tmp = *previousP;
+		}
+		while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
+		    previousP = &(tmp->next);
+		    tmp = *previousP;
+		}
+		f->next = *previousP;
+		*previousP = f;
+		f = next;
+	    }
+	}
+
+#ifdef DD_COUNT
+	table->swapSteps += oldxkeys - newxkeys;
+#endif
+	/* Take care of the x nodes that must be re-expressed.
+	** They form a linked list pointed by g. Their index has been
+	** already changed to yindex.
+	*/
+	f = g;
+	while (f != NULL) {
+	    next = f->next;
+	    /* Find f1, f0, f11, f10, f01, f00. */
+	    f1 = cuddT(f);
+#ifdef DD_DEBUG
+	    assert(!(Cudd_IsComplement(f1)));
+#endif
+	    if ((int) f1->index == yindex) {
+		f11 = cuddT(f1); f10 = cuddE(f1);
+	    } else {
+		f11 = f10 = f1;
+	    }
+#ifdef DD_DEBUG
+	    assert(!(Cudd_IsComplement(f11)));
+#endif
+	    f0 = cuddE(f);
+	    comple = Cudd_IsComplement(f0);
+	    f0 = Cudd_Regular(f0);
+	    if ((int) f0->index == yindex) {
+		f01 = cuddT(f0); f00 = cuddE(f0);
+	    } else {
+		f01 = f00 = f0;
+	    }
+	    if (comple) {
+		f01 = Cudd_Not(f01);
+		f00 = Cudd_Not(f00);
+	    }
+	    /* Decrease ref count of f1. */
+	    cuddSatDec(f1->ref);
+	    /* Create the new T child. */
+	    if (f11 == f01) {
+		newf1 = f11;
+		cuddSatInc(newf1->ref);
+	    } else {
+		/* Check xlist for triple (xindex,f11,f01). */
+		posn = ddHash(f11, f01, xshift);
+		/* For each element newf1 in collision list xlist[posn]. */
+		previousP = &(xlist[posn]);
+		newf1 = *previousP;
+		while (f11 < cuddT(newf1)) {
+		    previousP = &(newf1->next);
+		    newf1 = *previousP;
+		}
+		while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
+		    previousP = &(newf1->next);
+		    newf1 = *previousP;
+		}
+		if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
+		    cuddSatInc(newf1->ref);
+		} else { /* no match */
+		    newf1 = cuddDynamicAllocNode(table);
+		    if (newf1 == NULL)
+			goto cuddSwapOutOfMem;
+		    newf1->index = xindex; newf1->ref = 1;
+		    cuddT(newf1) = f11;
+		    cuddE(newf1) = f01;
+		    /* Insert newf1 in the collision list xlist[posn];
+		    ** increase the ref counts of f11 and f01.
+		    */
+		    newxkeys++;
+		    newf1->next = *previousP;
+		    *previousP = newf1;
+		    cuddSatInc(f11->ref);
+		    tmp = Cudd_Regular(f01);
+		    cuddSatInc(tmp->ref);
+		}
+	    }
+	    cuddT(f) = newf1;
+#ifdef DD_DEBUG
+	    assert(!(Cudd_IsComplement(newf1)));
+#endif
+
+	    /* Do the same for f0, keeping complement dots into account. */
+	    /* Decrease ref count of f0. */
+	    tmp = Cudd_Regular(f0);
+	    cuddSatDec(tmp->ref);
+	    /* Create the new E child. */
+	    if (f10 == f00) {
+		newf0 = f00;
+		tmp = Cudd_Regular(newf0);
+		cuddSatInc(tmp->ref); 
+	    } else {
+		/* make sure f10 is regular */
+		newcomplement = Cudd_IsComplement(f10);
+		if (newcomplement) {
+		    f10 = Cudd_Not(f10);
+		    f00 = Cudd_Not(f00);
+		}
+		/* Check xlist for triple (xindex,f10,f00). */
+		posn = ddHash(f10, f00, xshift);
+		/* For each element newf0 in collision list xlist[posn]. */
+		previousP = &(xlist[posn]);
+		newf0 = *previousP;
+		while (f10 < cuddT(newf0)) {
+		    previousP = &(newf0->next);
+		    newf0 = *previousP;
+		}
+		while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
+		    previousP = &(newf0->next);
+		    newf0 = *previousP;
+		}
+		if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
+		    cuddSatInc(newf0->ref); 
+		} else { /* no match */
+		    newf0 = cuddDynamicAllocNode(table);
+		    if (newf0 == NULL)
+			goto cuddSwapOutOfMem;
+		    newf0->index = xindex; newf0->ref = 1;
+		    cuddT(newf0) = f10;
+		    cuddE(newf0) = f00;
+		    /* Insert newf0 in the collision list xlist[posn];
+		    ** increase the ref counts of f10 and f00.
+		    */
+		    newxkeys++;
+		    newf0->next = *previousP;
+		    *previousP = newf0;
+		    cuddSatInc(f10->ref);
+		    tmp = Cudd_Regular(f00);
+		    cuddSatInc(tmp->ref);
+		}
+		if (newcomplement) {
+		    newf0 = Cudd_Not(newf0);
+		}
+	    }
+	    cuddE(f) = newf0;
+
+	    /* Insert the modified f in ylist.
+	    ** The modified f does not already exists in ylist.
+	    ** (Because of the uniqueness of the cofactors.)
+	    */
+	    posn = ddHash(newf1, newf0, yshift);
+	    newykeys++;
+	    previousP = &(ylist[posn]);
+	    tmp = *previousP;
+	    while (newf1 < cuddT(tmp)) {
+		previousP = &(tmp->next);
+		tmp = *previousP;
+	    }
+	    while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
+		previousP = &(tmp->next);
+		tmp = *previousP;
+	    }
+	    f->next = *previousP;
+	    *previousP = f;
+	    f = next;
+	} /* while f != NULL */
+
+	/* GC the y layer. */
+
+	/* For each node f in ylist. */
+	for (i = 0; i < yslots; i++) {
+	    previousP = &(ylist[i]);
+	    f = *previousP;
+	    while (f != sentinel) {
+		next = f->next;
+		if (f->ref == 0) {
+		    tmp = cuddT(f);
+		    cuddSatDec(tmp->ref);
+		    tmp = Cudd_Regular(cuddE(f));
+		    cuddSatDec(tmp->ref);
+		    cuddDeallocNode(table,f);
+		    newykeys--;
+		} else {
+		    *previousP = f;
+		    previousP = &(f->next);
+		}
+		f = next;
+	    } /* while f */
+	    *previousP = sentinel;
+	} /* for i */
+
+#if DD_DEBUG
+#if 0
+	(void) fprintf(table->out,"Swapping %d and %d\n",x,y);
+#endif
+	count = 0;
+	idcheck = 0;
+	for (i = 0; i < yslots; i++) {
+	    f = ylist[i];
+	    while (f != sentinel) {
+		count++;
+		if (f->index != (DdHalfWord) yindex)
+		    idcheck++;
+		f = f->next;
+	    }
+	}
+	if (count != newykeys) {
+	    (void) fprintf(table->out,
+			   "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
+			   oldykeys,newykeys,count);
+	}
+	if (idcheck != 0)
+	    (void) fprintf(table->out,
+			   "Error in id's of ylist\twrong id's = %d\n",
+			   idcheck);
+	count = 0;
+	idcheck = 0;
+	for (i = 0; i < xslots; i++) {
+	    f = xlist[i];
+	    while (f != sentinel) {
+		count++;
+		if (f->index != (DdHalfWord) xindex)
+		    idcheck++;
+		f = f->next;
+	    }
+	}
+	if (count != newxkeys) {
+	    (void) fprintf(table->out,
+			   "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
+			   oldxkeys,newxkeys,count);
+	}
+	if (idcheck != 0)
+	    (void) fprintf(table->out,
+			   "Error in id's of xlist\twrong id's = %d\n",
+			   idcheck);
+#endif
+
+	isolated += (table->vars[xindex]->ref == 1) +
+		    (table->vars[yindex]->ref == 1);
+	table->isolated += isolated;
+    }
+
+    /* Set the appropriate fields in table. */
+    table->subtables[x].nodelist = ylist;
+    table->subtables[x].slots = yslots;
+    table->subtables[x].shift = yshift;
+    table->subtables[x].keys = newykeys;
+    table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
+    i = table->subtables[x].bindVar;
+    table->subtables[x].bindVar = table->subtables[y].bindVar;
+    table->subtables[y].bindVar = i;
+    /* Adjust filds for lazy sifting. */
+    varType = table->subtables[x].varType;
+    table->subtables[x].varType = table->subtables[y].varType;
+    table->subtables[y].varType = varType;
+    i = table->subtables[x].pairIndex;
+    table->subtables[x].pairIndex = table->subtables[y].pairIndex;
+    table->subtables[y].pairIndex = i;
+    i = table->subtables[x].varHandled;
+    table->subtables[x].varHandled = table->subtables[y].varHandled;
+    table->subtables[y].varHandled = i;
+    groupType = table->subtables[x].varToBeGrouped;
+    table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
+    table->subtables[y].varToBeGrouped = groupType;
+
+    table->subtables[y].nodelist = xlist;
+    table->subtables[y].slots = xslots;
+    table->subtables[y].shift = xshift;
+    table->subtables[y].keys = newxkeys;
+    table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
+
+    table->perm[xindex] = y; table->perm[yindex] = x;
+    table->invperm[x] = yindex; table->invperm[y] = xindex;
+
+    table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
+
+    return(table->keys - table->isolated);
+
+cuddSwapOutOfMem:
+    (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddSwapInPlace */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders BDD variables according to the order of the ZDD
+  variables.]
+
+  Description [Reorders BDD variables according to the order of the
+  ZDD variables. This function can be called at the end of ZDD
+  reordering to insure that the order of the BDD variables is
+  consistent with the order of the ZDD variables. The number of ZDD
+  variables must be a multiple of the number of BDD variables. Let
+  <code>M</code> be the ratio of the two numbers. cuddBddAlignToZdd
+  then considers the ZDD variables from <code>M*i</code> to
+  <code>(M+1)*i-1</code> as corresponding to BDD variable
+  <code>i</code>.  This function should be normally called from
+  Cudd_zddReduceHeap, which clears the cache.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [Changes the BDD variable order for all diagrams and performs
+  garbage collection of the BDD unique table.]
+
+  SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap]
+
+******************************************************************************/
+int
+cuddBddAlignToZdd(
+  DdManager * table /* DD manager */)
+{
+    int *invperm;		/* permutation array */
+    int M;			/* ratio of ZDD variables to BDD variables */
+    int i;			/* loop index */
+    int result;			/* return value */
+
+    /* We assume that a ratio of 0 is OK. */
+    if (table->size == 0)
+	return(1);
+
+    M = table->sizeZ / table->size;
+    /* Check whether the number of ZDD variables is a multiple of the
+    ** number of BDD variables.
+    */
+    if (M * table->size != table->sizeZ)
+	return(0);
+    /* Create and initialize the inverse permutation array. */
+    invperm = ALLOC(int,table->size);
+    if (invperm == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < table->sizeZ; i += M) {
+	int indexZ = table->invpermZ[i];
+	int index  = indexZ / M;
+	invperm[i / M] = index;
+    }
+    /* Eliminate dead nodes. Do not scan the cache again, because we
+    ** assume that Cudd_zddReduceHeap has already cleared it.
+    */
+    cuddGarbageCollect(table,0);
+
+    /* Initialize number of isolated projection functions. */
+    table->isolated = 0;
+    for (i = 0; i < table->size; i++) {
+	if (table->vars[i]->ref == 1) table->isolated++;
+    }
+
+    /* Initialize the interaction matrix. */
+    result = cuddInitInteract(table);
+    if (result == 0) return(0);
+
+    result = ddShuffle(table, invperm);
+    FREE(invperm);
+    /* Free interaction matrix. */
+    FREE(table->interact);
+    /* Fix the BDD variable group tree. */
+    bddFixTree(table,table->tree);
+    return(result);
+
+} /* end of cuddBddAlignToZdd */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddUniqueCompare(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+	return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps any two variables.]
+
+  Description [Swaps any two variables. Returns the set of moves.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSwapAny(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    Move	*move, *moves;
+    int		xRef,yRef;
+    int		xNext,yNext;
+    int		size;
+    int		limitSize;
+    int		tmp;
+
+    if (x >y) {
+	tmp = x; x = y; y = tmp;
+    }
+
+    xRef = x; yRef = y;
+
+    xNext = cuddNextHigh(table,x);
+    yNext = cuddNextLow(table,y);
+    moves = NULL;
+    limitSize = table->keys - table->isolated;
+
+    for (;;) {
+	if ( xNext == yNext) {
+	    size = cuddSwapInPlace(table,x,xNext);
+	    if (size == 0) goto ddSwapAnyOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);			
+	    if (move == NULL) goto ddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = xNext;
+	    move->size = size; 
+	    move->next = moves;
+	    moves = move;
+
+	    size = cuddSwapInPlace(table,yNext,y);
+	    if (size == 0) goto ddSwapAnyOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddSwapAnyOutOfMem;
+	    move->x = yNext;
+	    move->y = y;
+	    move->size = size; 
+	    move->next = moves;
+	    moves = move;
+
+	    size = cuddSwapInPlace(table,x,xNext);
+	    if (size == 0) goto ddSwapAnyOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = xNext;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    tmp = x; x = y; y = tmp;
+
+	} else if (x == yNext) {
+	    
+	    size = cuddSwapInPlace(table,x,xNext);
+	    if (size == 0) goto ddSwapAnyOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = xNext;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    tmp = x; x = y; y = tmp;
+
+	} else {
+	    size = cuddSwapInPlace(table,x,xNext);
+	    if (size == 0) goto ddSwapAnyOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = xNext;
+	    move->size = size; 
+	    move->next = moves;
+	    moves = move;
+
+	    size = cuddSwapInPlace(table,yNext,y);
+	    if (size == 0) goto ddSwapAnyOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddSwapAnyOutOfMem;
+	    move->x = yNext;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    x = xNext;
+	    y = yNext;
+	}
+
+	xNext = cuddNextHigh(table,x);
+	yNext = cuddNextLow(table,y);
+	if (xNext > yRef) break;
+
+	if ((double) size > table->maxGrowth * (double) limitSize) break;
+	if (size < limitSize) limitSize = size;
+    }
+    if (yNext>=xRef) {
+	size = cuddSwapInPlace(table,yNext,y);
+	if (size == 0) goto ddSwapAnyOutOfMem;
+	move = (Move *) cuddDynamicAllocNode(table);
+	if (move == NULL) goto ddSwapAnyOutOfMem;
+	move->x = yNext;
+	move->y = y;
+	move->size = size; 
+	move->next = moves;
+	moves = move;
+    }
+
+    return(moves);
+    
+ddSwapAnyOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(NULL);
+
+} /* end of ddSwapAny */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+
+    Move	*move;
+    Move	*moveUp;		/* list of up moves */
+    Move	*moveDown;		/* list of down moves */
+    int		initialSize;
+    int		result;
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) {
+	moveDown = ddSiftingDown(table,x,xHigh);
+	/* At this point x --> xHigh unless bounding occurred. */
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+	/* Move backward and stop at best position. */	
+	result = ddSiftingBackward(table,initialSize,moveDown);
+	if (!result) goto ddSiftingAuxOutOfMem;
+
+    } else if (x == xHigh) {
+	moveUp = ddSiftingUp(table,x,xLow);
+	/* At this point x --> xLow unless bounding occurred. */
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+	/* Move backward and stop at best position. */
+	result = ddSiftingBackward(table,initialSize,moveUp);
+	if (!result) goto ddSiftingAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+	moveDown = ddSiftingDown(table,x,xHigh);
+	/* At this point x --> xHigh unless bounding occurred. */
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+	if (moveDown != NULL) {
+	    x = moveDown->y;
+	}
+	moveUp = ddSiftingUp(table,x,xLow);
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+	/* Move backward and stop at best position */	
+	result = ddSiftingBackward(table,initialSize,moveUp);
+	if (!result) goto ddSiftingAuxOutOfMem;
+
+    } else { /* must go up first: shorter */
+	moveUp = ddSiftingUp(table,x,xLow);
+	/* At this point x --> xLow unless bounding occurred. */
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+	if (moveUp != NULL) {
+	    x = moveUp->x;
+	}
+	moveDown = ddSiftingDown(table,x,xHigh);
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
+	/* Move backward and stop at best position. */	
+	result = ddSiftingBackward(table,initialSize,moveDown);
+	if (!result) goto ddSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(1);
+
+ddSiftingAuxOutOfMem:
+    if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
+	while (moveDown != NULL) {
+	    move = moveDown->next;
+	    cuddDeallocMove(table, moveDown);
+	    moveDown = move;
+	}
+    }
+    if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
+	while (moveUp != NULL) {
+	    move = moveUp->next;
+	    cuddDeallocMove(table, moveUp);
+	    moveUp = move;
+	}
+    }
+
+    return(0);
+
+} /* end of ddSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up.]
+
+  Description [Sifts a variable up. Moves y up until either it reaches
+  the bound (xLow) or the size of the DD heap increases too much.
+  Returns the set of moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow)
+{
+    Move	*moves;
+    Move	*move;
+    int		x;
+    int		size;
+    int		limitSize;
+    int		xindex, yindex;
+    int		isolated;
+    int		L;	/* lower bound on DD size */
+#ifdef DD_DEBUG
+    int checkL;
+    int z;
+    int zindex;
+#endif
+
+    moves = NULL;
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below y will not change.
+    ** The part of the DD above y that does not interact with y will not
+    ** change. The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    */
+    limitSize = L = table->keys - table->isolated;
+    for (x = xLow + 1; x < y; x++) {
+	xindex = table->invperm[x];
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[xindex]->ref == 1;
+	    L -= table->subtables[x].keys - isolated;
+	}
+    }
+    isolated = table->vars[yindex]->ref == 1;
+    L -= table->subtables[y].keys - isolated;
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+	xindex = table->invperm[x];
+#ifdef DD_DEBUG
+	checkL = table->keys - table->isolated;
+	for (z = xLow + 1; z < y; z++) {
+	    zindex = table->invperm[z];
+	    if (cuddTestInteract(table,zindex,yindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkL -= table->subtables[z].keys - isolated;
+	    }
+	}
+	isolated = table->vars[yindex]->ref == 1;
+	checkL -= table->subtables[y].keys - isolated;
+	assert(L == checkL);
+#endif
+	size = cuddSwapInPlace(table,x,y);
+	if (size == 0) goto ddSiftingUpOutOfMem;
+	/* Update the lower bound. */
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[xindex]->ref == 1;
+	    L += table->subtables[y].keys - isolated;
+	}
+	move = (Move *) cuddDynamicAllocNode(table);
+	if (move == NULL) goto ddSiftingUpOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->size = size;
+	move->next = moves;
+	moves = move;
+	if ((double) size > (double) limitSize * table->maxGrowth) break;
+	if (size < limitSize) limitSize = size;
+	y = x;
+	x = cuddNextLow(table,y);
+    }
+    return(moves);
+
+ddSiftingUpOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddSiftingUp */
+    
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down.]
+
+  Description [Sifts a variable down. Moves x down until either it
+  reaches the bound (xHigh) or the size of the DD heap increases too
+  much. Returns the set of moves in case of success; NULL if memory is
+  full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh)
+{
+    Move	*moves;
+    Move	*move;
+    int		y;
+    int		size;
+    int		R;	/* upper bound on node decrease */
+    int		limitSize;
+    int		xindex, yindex;
+    int		isolated;
+#ifdef DD_DEBUG
+    int		checkR;
+    int		z;
+    int		zindex;
+#endif
+
+    moves = NULL;
+    /* Initialize R */
+    xindex = table->invperm[x];
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (y = xHigh; y > x; y--) {
+	yindex = table->invperm[y];
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[yindex]->ref == 1;
+	    R += table->subtables[y].keys - isolated;
+	}
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+	checkR = 0;
+	for (z = xHigh; z > x; z--) {
+	    zindex = table->invperm[z];
+	    if (cuddTestInteract(table,xindex,zindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkR += table->subtables[z].keys - isolated;
+	    }
+	}
+	assert(R == checkR);
+#endif
+	/* Update upper bound on node decrease. */
+	yindex = table->invperm[y];
+	if (cuddTestInteract(table,xindex,yindex)) {
+	    isolated = table->vars[yindex]->ref == 1;
+	    R -= table->subtables[y].keys - isolated;
+	}
+	size = cuddSwapInPlace(table,x,y);
+	if (size == 0) goto ddSiftingDownOutOfMem; 
+	move = (Move *) cuddDynamicAllocNode(table);
+	if (move == NULL) goto ddSiftingDownOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->size = size;
+	move->next = moves;
+	moves = move;
+	if ((double) size > (double) limitSize * table->maxGrowth) break;
+	if (size < limitSize) limitSize = size;
+	x = y;
+	y = cuddNextHigh(table,x);
+    }
+    return(moves);
+
+ddSiftingDownOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of ddSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSiftingBackward(
+  DdManager * table,
+  int  size,
+  Move * moves)
+{
+    Move *move;
+    int	res;
+
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size < size) {
+	    size = move->size;
+	}
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size == size) return(1);
+	res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+	if (!res) return(0);	
+    }
+
+    return(1);
+
+} /* end of ddSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prepares the DD heap for dynamic reordering.]
+
+  Description [Prepares the DD heap for dynamic reordering. Does
+  garbage collection, to guarantee that there are no dead nodes;
+  clears the cache, which is invalidated by dynamic reordering; initializes
+  the number of isolated projection functions; and initializes the
+  interaction matrix.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddReorderPreprocess(
+  DdManager * table)
+{
+    int i;
+    int res;
+
+    /* Clear the cache. */
+    cuddCacheFlush(table);
+    cuddLocalCacheClearAll(table);
+
+    /* Eliminate dead nodes. Do not scan the cache again. */
+    cuddGarbageCollect(table,0);
+
+    /* Initialize number of isolated projection functions. */
+    table->isolated = 0;
+    for (i = 0; i < table->size; i++) {
+	if (table->vars[i]->ref == 1) table->isolated++;
+    }
+
+    /* Initialize the interaction matrix. */
+    res = cuddInitInteract(table);
+    if (res == 0) return(0);
+
+    return(1);
+
+} /* end of ddReorderPreprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cleans up at the end of reordering.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddReorderPostprocess(
+  DdManager * table)
+{
+
+#ifdef DD_VERBOSE
+    (void) fflush(table->out);
+#endif
+
+    /* Free interaction matrix. */
+    FREE(table->interact);
+
+    return(1);
+
+} /* end of ddReorderPostprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables according to a given permutation.]
+
+  Description [Reorders variables according to a given permutation.
+  The i-th permutation array contains the index of the variable that
+  should be brought to the i-th level. ddShuffle assumes that no
+  dead nodes are present and that the interaction matrix is properly
+  initialized.  The reordering is achieved by a series of upward sifts.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+ddShuffle(
+  DdManager * table,
+  int * permutation)
+{
+    int		index;
+    int		level;
+    int		position;
+    int		numvars;
+    int		result;
+#ifdef DD_STATS
+    long	localTime;
+    int		initialSize;
+    int		finalSize;
+    int		previousSize;
+#endif
+
+    ddTotalNumberSwapping = 0;
+#ifdef DD_STATS
+    localTime = util_cpu_time();
+    initialSize = table->keys - table->isolated;
+    (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
+		   initialSize); 
+    ddTotalNISwaps = 0;
+#endif
+
+    numvars = table->size;
+
+    for (level = 0; level < numvars; level++) {
+	index = permutation[level];
+	position = table->perm[index];
+#ifdef DD_STATS
+	previousSize = table->keys - table->isolated;
+#endif
+	result = ddSiftUp(table,position,level);
+	if (!result) return(0);
+#ifdef DD_STATS
+	if (table->keys < (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keys > (unsigned) previousSize + table->isolated) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+    }
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keys - table->isolated;
+    (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); 
+    (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
+	((double)(util_cpu_time() - localTime)/1000.0)); 
+    (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
+		   ddTotalNumberSwapping);
+    (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
+#endif
+
+    return(1);
+
+} /* end of ddShuffle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one variable up.]
+
+  Description [Takes a variable from position x and sifts it up to
+  position xLow;  xLow should be less than or equal to x.
+  Returns 1 if successful; 0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddSiftUp(
+  DdManager * table,
+  int  x,
+  int  xLow)
+{
+    int        y;
+    int        size;
+
+    y = cuddNextLow(table,x);
+    while (y >= xLow) {
+	size = cuddSwapInPlace(table,y,x);
+	if (size == 0) {
+	    return(0);
+	}
+	x = y;
+	y = cuddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of ddSiftUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes the BDD variable group tree after a shuffle.]
+
+  Description [Fixes the BDD variable group tree after a
+  shuffle. Assumes that the order of the variables in a terminal node
+  has not been changed.]
+
+  SideEffects [Changes the BDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+bddFixTree(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    if (treenode == NULL) return;
+    treenode->low = ((int) treenode->index < table->size) ?
+	table->perm[treenode->index] : treenode->index;
+    if (treenode->child != NULL) {
+	bddFixTree(table, treenode->child);
+    }
+    if (treenode->younger != NULL)
+	bddFixTree(table, treenode->younger);
+    if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
+	treenode->parent->low = treenode->low;
+	treenode->parent->index = treenode->index;
+    }
+    return;
+
+} /* end of bddFixTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the BDD variable group tree before a shuffle.]
+
+  Description [Updates the BDD variable group tree before a shuffle.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Changes the BDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddUpdateMtrTree(
+  DdManager * table,
+  MtrNode * treenode,
+  int * perm,
+  int * invperm)
+{
+    int	i, size, index, level;
+    int	minLevel, maxLevel, minIndex;
+
+    if (treenode == NULL) return(1);
+
+    minLevel = CUDD_MAXINDEX;
+    maxLevel = 0;
+    minIndex = -1;
+    /* i : level */
+    for (i = treenode->low; i < treenode->low + treenode->size; i++) {
+	index = table->invperm[i];
+	level = perm[index];
+	if (level < minLevel) {
+	    minLevel = level;
+	    minIndex = index;
+	}
+	if (level > maxLevel)
+	    maxLevel = level;
+    }
+    size = maxLevel - minLevel + 1;
+    if (minIndex == -1) return(0);
+    if (size == treenode->size) {
+	treenode->low = minLevel;
+	treenode->index = minIndex;
+    } else {
+	return(0);
+    }
+
+    if (treenode->child != NULL) {
+	if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
+	    return(0);
+    }
+    if (treenode->younger != NULL) {
+	if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
+	    return(0);
+    }
+    return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the BDD variable group tree before a shuffle.]
+
+  Description [Checks the BDD variable group tree before a shuffle.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [Changes the BDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ddCheckPermuation(
+  DdManager * table,
+  MtrNode * treenode,
+  int * perm,
+  int * invperm)
+{
+    int	i, size, index, level;
+    int	minLevel, maxLevel;
+
+    if (treenode == NULL) return(1);
+
+    minLevel = table->size;
+    maxLevel = 0;
+    /* i : level */
+    for (i = treenode->low; i < treenode->low + treenode->size; i++) {
+	index = table->invperm[i];
+	level = perm[index];
+	if (level < minLevel)
+	    minLevel = level;
+	if (level > maxLevel)
+	    maxLevel = level;
+    }
+    size = maxLevel - minLevel + 1;
+    if (size != treenode->size)
+	return(0);
+
+    if (treenode->child != NULL) {
+	if (!ddCheckPermuation(table, treenode->child, perm, invperm))
+	    return(0);
+    }
+    if (treenode->younger != NULL) {
+	if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
+	    return(0);
+    }
+    return(1);
+}
Index: /vis_dev/glu-2.1/src/cuBdd/cuddSat.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddSat.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddSat.c	(revision 8)
@@ -0,0 +1,1345 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSat.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for the solution of satisfiability related
+  problems.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_Eval()
+		<li> Cudd_ShortestPath()
+		<li> Cudd_LargestCube()
+		<li> Cudd_ShortestLength()
+		<li> Cudd_Decreasing()
+		<li> Cudd_Increasing()
+		<li> Cudd_EquivDC()
+		<li> Cudd_bddLeqUnless()
+		<li> Cudd_EqualSupNorm()
+		<li> Cudd_bddMakePrime()
+		</ul>
+	Internal procedures included in this module:
+	        <ul>
+		<li> cuddBddMakePrime()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> freePathPair()
+		<li> getShortest()
+		<li> getPath()
+		<li> getLargest()
+		<li> getCube()
+		</ul>]
+
+  Author      [Seh-Woong Jeong, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define	DD_BIGGY	1000000
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct cuddPathPair {
+    int	pos;
+    int	neg;
+} cuddPathPair;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.34 2004/08/13 18:04:50 fabio Exp $";
+#endif
+
+static	DdNode	*one, *zero;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define WEIGHT(weight, col)	((weight) == NULL ? 1 : weight[col])
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static enum st_retval freePathPair (char *key, char *value, char *arg);
+static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st_table *visited);
+static DdNode * getPath (DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost);
+static cuddPathPair getLargest (DdNode *root, st_table *visited);
+static DdNode * getCube (DdManager *manager, st_table *visited, DdNode *f, int cost);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the value of a DD for a given variable assignment.]
+
+  Description [Finds the value of a DD for a given variable
+  assignment. The variable assignment is passed in an array of int's,
+  that should specify a zero or a one for each variable in the support
+  of the function. Returns a pointer to a constant node. No new nodes
+  are produced.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLeq Cudd_addEvalConst]
+
+******************************************************************************/
+DdNode *
+Cudd_Eval(
+  DdManager * dd,
+  DdNode * f,
+  int * inputs)
+{
+    int comple;
+    DdNode *ptr;
+
+    comple = Cudd_IsComplement(f);
+    ptr = Cudd_Regular(f);
+
+    while (!cuddIsConstant(ptr)) {
+	if (inputs[ptr->index] == 1) {
+	    ptr = cuddT(ptr);
+	} else {
+	    comple ^= Cudd_IsComplement(cuddE(ptr));
+	    ptr = Cudd_Regular(cuddE(ptr));
+	}
+    }
+    return(Cudd_NotCond(ptr,comple));
+
+} /* end of Cudd_Eval */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a shortest path in a DD.]
+
+  Description [Finds a shortest path in a DD. f is the DD we want to
+  get the shortest path for; weight\[i\] is the weight of the THEN arc
+  coming from the node whose index is i. If weight is NULL, then unit
+  weights are assumed for all THEN arcs. All ELSE arcs have 0 weight.
+  If non-NULL, both weight and support should point to arrays with at
+  least as many entries as there are variables in the manager.
+  Returns the shortest path as the BDD of a cube.]
+
+  SideEffects [support contains on return the true support of f.
+  If support is NULL on entry, then Cudd_ShortestPath does not compute
+  the true support info. length contains the length of the path.]
+
+  SeeAlso     [Cudd_ShortestLength Cudd_LargestCube]
+
+******************************************************************************/
+DdNode *
+Cudd_ShortestPath(
+  DdManager * manager,
+  DdNode * f,
+  int * weight,
+  int * support,
+  int * length)
+{
+    DdNode	*F;
+    st_table	*visited;
+    DdNode	*sol;
+    cuddPathPair *rootPair;
+    int		complement, cost;
+    int		i;
+
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    /* Initialize support. Support does not depend on variable order.
+    ** Hence, it does not need to be reinitialized if reordering occurs.
+    */
+    if (support) {
+      for (i = 0; i < manager->size; i++) {
+	support[i] = 0;
+      }
+    }
+
+    if (f == Cudd_Not(one) || f == zero) {
+      *length = DD_BIGGY;
+      return(Cudd_Not(one));
+    }
+    /* From this point on, a path exists. */
+
+    do {
+	manager->reordered = 0;
+
+	/* Initialize visited table. */
+	visited = st_init_table(st_ptrcmp, st_ptrhash);
+
+	/* Now get the length of the shortest path(s) from f to 1. */
+	(void) getShortest(f, weight, support, visited);
+
+	complement = Cudd_IsComplement(f);
+
+	F = Cudd_Regular(f);
+
+	st_lookup(visited, F, &rootPair);
+
+	if (complement) {
+	  cost = rootPair->neg;
+	} else {
+	  cost = rootPair->pos;
+	}
+
+	/* Recover an actual shortest path. */
+	sol = getPath(manager,visited,f,weight,cost);
+
+	st_foreach(visited, freePathPair, NULL);
+	st_free_table(visited);
+
+    } while (manager->reordered == 1);
+
+    *length = cost;
+    return(sol);
+
+} /* end of Cudd_ShortestPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a largest cube in a DD.]
+
+  Description [Finds a largest cube in a DD. f is the DD we want to
+  get the largest cube for. The problem is translated into the one of
+  finding a shortest path in f, when both THEN and ELSE arcs are assumed to
+  have unit length. This yields a largest cube in the disjoint cover
+  corresponding to the DD. Therefore, it is not necessarily the largest
+  implicant of f.  Returns the largest cube as a BDD.]
+
+  SideEffects [The number of literals of the cube is returned in length.]
+
+  SeeAlso     [Cudd_ShortestPath]
+
+******************************************************************************/
+DdNode *
+Cudd_LargestCube(
+  DdManager * manager,
+  DdNode * f,
+  int * length)
+{
+    register 	DdNode	*F;
+    st_table	*visited;
+    DdNode	*sol;
+    cuddPathPair *rootPair;
+    int		complement, cost;
+
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    if (f == Cudd_Not(one) || f == zero) {
+	*length = DD_BIGGY;
+	return(Cudd_Not(one));
+    }
+    /* From this point on, a path exists. */
+
+    do {
+	manager->reordered = 0;
+
+	/* Initialize visited table. */
+	visited = st_init_table(st_ptrcmp, st_ptrhash);
+
+	/* Now get the length of the shortest path(s) from f to 1. */
+	(void) getLargest(f, visited);
+
+	complement = Cudd_IsComplement(f);
+
+	F = Cudd_Regular(f);
+
+	st_lookup(visited, F, &rootPair);
+
+	if (complement) {
+	  cost = rootPair->neg;
+	} else {
+	  cost = rootPair->pos;
+	}
+
+	/* Recover an actual shortest path. */
+	sol = getCube(manager,visited,f,cost);
+
+	st_foreach(visited, freePathPair, NULL);
+	st_free_table(visited);
+
+    } while (manager->reordered == 1);
+
+    *length = cost;
+    return(sol);
+
+} /* end of Cudd_LargestCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find the length of the shortest path(s) in a DD.]
+
+  Description [Find the length of the shortest path(s) in a DD. f is
+  the DD we want to get the shortest path for; weight\[i\] is the
+  weight of the THEN edge coming from the node whose index is i. All
+  ELSE edges have 0 weight. Returns the length of the shortest
+  path(s) if successful; CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ShortestPath]
+
+******************************************************************************/
+int
+Cudd_ShortestLength(
+  DdManager * manager,
+  DdNode * f,
+  int * weight)
+{
+    register 	DdNode	*F;
+    st_table	*visited;
+    cuddPathPair *my_pair;
+    int		complement, cost;
+
+    one = DD_ONE(manager);
+    zero = DD_ZERO(manager);
+
+    if (f == Cudd_Not(one) || f == zero) {
+	return(DD_BIGGY);
+    }
+
+    /* From this point on, a path exists. */
+    /* Initialize visited table and support. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+
+    /* Now get the length of the shortest path(s) from f to 1. */
+    (void) getShortest(f, weight, NULL, visited);
+
+    complement = Cudd_IsComplement(f);
+
+    F = Cudd_Regular(f);
+
+    st_lookup(visited, F, &my_pair);
+    
+    if (complement) {
+	cost = my_pair->neg;
+    } else {
+	cost = my_pair->pos;
+    }
+
+    st_foreach(visited, freePathPair, NULL);
+    st_free_table(visited);
+
+    return(cost);
+
+} /* end of Cudd_ShortestLength */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether a BDD is negative unate in a
+  variable.]
+
+  Description [Determines whether the function represented by BDD f is
+  negative unate (monotonic decreasing) in variable i. Returns the
+  constant one is f is unate and the (logical) constant zero if it is not.
+  This function does not generate any new nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Increasing]
+
+******************************************************************************/
+DdNode *
+Cudd_Decreasing(
+  DdManager * dd,
+  DdNode * f,
+  int  i)
+{
+    unsigned int topf, level;
+    DdNode *F, *fv, *fvn, *res;
+    DD_CTFP cacheOp;
+
+    statLine(dd);
+#ifdef DD_DEBUG
+    assert(0 <= i && i < dd->size);
+#endif
+
+    F = Cudd_Regular(f);
+    topf = cuddI(dd,F->index);
+
+    /* Check terminal case. If topf > i, f does not depend on var.
+    ** Therefore, f is unate in i.
+    */
+    level = (unsigned) dd->perm[i];
+    if (topf > level) {
+	return(DD_ONE(dd));
+    }
+
+    /* From now on, f is not constant. */
+
+    /* Check cache. */
+    cacheOp = (DD_CTFP) Cudd_Decreasing;
+    res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
+    if (res != NULL) {
+	return(res);
+    }
+
+    /* Compute cofactors. */
+    fv = cuddT(F); fvn = cuddE(F);
+    if (F != f) {
+	fv = Cudd_Not(fv);
+	fvn = Cudd_Not(fvn);
+    }
+
+    if (topf == (unsigned) level) {
+	/* Special case: if fv is regular, fv(1,...,1) = 1;
+	** If in addition fvn is complemented, fvn(1,...,1) = 0.
+	** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not
+	** monotonic decreasing in i.
+	*/
+	if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
+	    return(Cudd_Not(DD_ONE(dd)));
+	}
+	res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
+    } else {
+	res = Cudd_Decreasing(dd,fv,i);
+	if (res == DD_ONE(dd)) {
+	    res = Cudd_Decreasing(dd,fvn,i);
+	}
+    }
+
+    cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
+    return(res);
+
+} /* end of Cudd_Decreasing */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines whether a BDD is positive unate in a
+  variable.]
+
+  Description [Determines whether the function represented by BDD f is
+  positive unate (monotonic increasing) in variable i. It is based on
+  Cudd_Decreasing and the fact that f is monotonic increasing in i if
+  and only if its complement is monotonic decreasing in i.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Decreasing]
+
+******************************************************************************/
+DdNode *
+Cudd_Increasing(
+  DdManager * dd,
+  DdNode * f,
+  int  i)
+{
+    return(Cudd_Decreasing(dd,Cudd_Not(f),i));
+
+} /* end of Cudd_Increasing */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether F and G are identical wherever D is 0.]
+
+  Description [Tells whether F and G are identical wherever D is 0.  F
+  and G are either two ADDs or two BDDs.  D is either a 0-1 ADD or a
+  BDD.  The function returns 1 if F and G are equivalent, and 0
+  otherwise.  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddLeqUnless]
+
+******************************************************************************/
+int
+Cudd_EquivDC(
+  DdManager * dd,
+  DdNode * F,
+  DdNode * G,
+  DdNode * D)
+{
+    DdNode *tmp, *One, *Gr, *Dr;
+    DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
+    int res;
+    unsigned int flevel, glevel, dlevel, top;
+
+    One = DD_ONE(dd);
+
+    statLine(dd);
+    /* Check terminal cases. */
+    if (D == One || F == G) return(1);
+    if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);
+
+    /* From now on, D is non-constant. */
+
+    /* Normalize call to increase cache efficiency. */
+    if (F > G) {
+	tmp = F;
+	F = G;
+	G = tmp;
+    }
+    if (Cudd_IsComplement(F)) {
+	F = Cudd_Not(F);
+	G = Cudd_Not(G);
+    }
+
+    /* From now on, F is regular. */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
+    if (tmp != NULL) return(tmp == One);
+
+    /* Find splitting variable. */
+    flevel = cuddI(dd,F->index);
+    Gr = Cudd_Regular(G);
+    glevel = cuddI(dd,Gr->index);
+    top = ddMin(flevel,glevel);
+    Dr = Cudd_Regular(D);
+    dlevel = dd->perm[Dr->index];
+    top = ddMin(top,dlevel);
+
+    /* Compute cofactors. */
+    if (top == flevel) {
+	Fv = cuddT(F);
+	Fvn = cuddE(F);
+    } else {
+	Fv = Fvn = F;
+    }
+    if (top == glevel) {
+	Gv = cuddT(Gr);
+	Gvn = cuddE(Gr);
+	if (G != Gr) {
+	    Gv = Cudd_Not(Gv);
+	    Gvn = Cudd_Not(Gvn);
+	}
+    } else {
+	Gv = Gvn = G;
+    }
+    if (top == dlevel) {
+	Dv = cuddT(Dr);
+	Dvn = cuddE(Dr);
+	if (D != Dr) {
+	    Dv = Cudd_Not(Dv);
+	    Dvn = Cudd_Not(Dvn);
+	}
+    } else {
+	Dv = Dvn = D;
+    }
+
+    /* Solve recursively. */
+    res = Cudd_EquivDC(dd,Fv,Gv,Dv);
+    if (res != 0) {
+	res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
+    }
+    cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));
+
+    return(res);
+
+} /* end of Cudd_EquivDC */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tells whether f is less than of equal to G unless D is 1.]
+
+  Description [Tells whether f is less than of equal to G unless D is
+  1.  f, g, and D are BDDs.  The function returns 1 if f is less than
+  of equal to G, and 0 otherwise.  No new nodes are created.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant]
+
+******************************************************************************/
+int
+Cudd_bddLeqUnless(
+  DdManager *dd,
+  DdNode *f,
+  DdNode *g,
+  DdNode *D)
+{
+    DdNode *tmp, *One, *F, *G;
+    DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
+    int res;
+    unsigned int flevel, glevel, dlevel, top;
+
+    statLine(dd);
+
+    One = DD_ONE(dd);
+
+    /* Check terminal cases. */
+    if (f == g || g == One || f == Cudd_Not(One) || D == One ||
+	D == f || D == Cudd_Not(g)) return(1);
+    /* Check for two-operand cases. */
+    if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
+	return(Cudd_bddLeq(dd,f,g));
+    if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
+    if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));
+
+    /* From now on, f, g, and D are non-constant, distinct, and
+    ** non-complementary. */
+
+    /* Normalize call to increase cache efficiency.  We rely on the
+    ** fact that f <= g unless D is equivalent to not(g) <= not(f)
+    ** unless D and to f <= D unless g.  We make sure that D is
+    ** regular, and that at most one of f and g is complemented.  We also
+    ** ensure that when two operands can be swapped, the one with the
+    ** lowest address comes first. */
+
+    if (Cudd_IsComplement(D)) {
+	if (Cudd_IsComplement(g)) {
+	    /* Special case: if f is regular and g is complemented,
+	    ** f(1,...,1) = 1 > 0 = g(1,...,1).  If D(1,...,1) = 0, return 0.
+	    */
+	    if (!Cudd_IsComplement(f)) return(0);
+	    /* !g <= D unless !f  or  !D <= g unless !f */
+	    tmp = D;
+	    D = Cudd_Not(f);
+	    if (g < tmp) {
+		f = Cudd_Not(g);
+		g = tmp;
+	    } else {
+		f = Cudd_Not(tmp);
+	    }
+	} else {
+	    if (Cudd_IsComplement(f)) {
+		/* !D <= !f unless g  or  !D <= g unless !f */
+		tmp = f;
+		f = Cudd_Not(D);
+		if (tmp < g) {
+		    D = g;
+		    g = Cudd_Not(tmp);
+		} else {
+		    D = Cudd_Not(tmp);
+		}
+	    } else {
+		/* f <= D unless g  or  !D <= !f unless g */
+		tmp = D;
+		D = g;
+		if (tmp < f) {
+		    g = Cudd_Not(f);
+		    f = Cudd_Not(tmp);
+		} else {
+		    g = tmp;
+		}
+	    }
+	}
+    } else {
+	if (Cudd_IsComplement(g)) {
+	    if (Cudd_IsComplement(f)) {
+		/* !g <= !f unless D  or  !g <= D unless !f */
+		tmp = f;
+		f = Cudd_Not(g);
+		if (D < tmp) {
+		    g = D;
+		    D = Cudd_Not(tmp);
+		} else {
+		    g = Cudd_Not(tmp);
+		}
+	    } else {
+		/* f <= g unless D  or  !g <= !f unless D */
+		if (g < f) {
+		    tmp = g;
+		    g = Cudd_Not(f);
+		    f = Cudd_Not(tmp);
+		}
+	    }
+	} else {
+	    /* f <= g unless D  or  f <= D unless g */
+	    if (D < g) {
+		tmp = D;
+		D = g;
+		g = tmp;
+	    }
+	}
+    }
+
+    /* From now on, D is regular. */
+
+    /* Check cache. */
+    tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
+    if (tmp != NULL) return(tmp == One);
+
+    /* Find splitting variable. */
+    F = Cudd_Regular(f);
+    flevel = dd->perm[F->index];
+    G = Cudd_Regular(g);
+    glevel = dd->perm[G->index];
+    top = ddMin(flevel,glevel);
+    dlevel = dd->perm[D->index];
+    top = ddMin(top,dlevel);
+
+    /* Compute cofactors. */
+    if (top == flevel) {
+	Ft = cuddT(F);
+	Fe = cuddE(F);
+	if (F != f) {
+	    Ft = Cudd_Not(Ft);
+	    Fe = Cudd_Not(Fe);
+	}
+    } else {
+	Ft = Fe = f;
+    }
+    if (top == glevel) {
+	Gt = cuddT(G);
+	Ge = cuddE(G);
+	if (G != g) {
+	    Gt = Cudd_Not(Gt);
+	    Ge = Cudd_Not(Ge);
+	}
+    } else {
+	Gt = Ge = g;
+    }
+    if (top == dlevel) {
+	Dt = cuddT(D);
+	De = cuddE(D);
+    } else {
+	Dt = De = D;
+    }
+
+    /* Solve recursively. */
+    res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
+    if (res != 0) {
+	res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
+    }
+    cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res));
+
+    return(res);
+
+} /* end of Cudd_bddLeqUnless */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two ADDs for equality within tolerance.]
+
+  Description [Compares two ADDs for equality within tolerance. Two
+  ADDs are reported to be equal if the maximum difference between them
+  (the sup norm of their difference) is less than or equal to the
+  tolerance parameter. Returns 1 if the two ADDs are equal (within
+  tolerance); 0 otherwise. If parameter <code>pr</code> is positive
+  the first failure is reported to the standard output.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_EqualSupNorm(
+  DdManager * dd /* manager */,
+  DdNode * f /* first ADD */,
+  DdNode * g /* second ADD */,
+  CUDD_VALUE_TYPE  tolerance /* maximum allowed difference */,
+  int  pr /* verbosity level */)
+{
+    DdNode *fv, *fvn, *gv, *gvn, *r;
+    unsigned int topf, topg;
+
+    statLine(dd);
+    /* Check terminal cases. */
+    if (f == g) return(1);
+    if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
+	if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
+	    return(1);
+	} else {
+	    if (pr>0) {
+		(void) fprintf(dd->out,"Offending nodes:\n");
+#if SIZEOF_VOID_P == 8
+		(void) fprintf(dd->out,
+			       "f: address = %lx\t value = %40.30f\n",
+			       (unsigned long) f, cuddV(f));
+		(void) fprintf(dd->out,
+			       "g: address = %lx\t value = %40.30f\n",
+			       (unsigned long) g, cuddV(g));
+#else
+		(void) fprintf(dd->out,
+			       "f: address = %x\t value = %40.30f\n",
+			       (unsigned) f, cuddV(f));
+		(void) fprintf(dd->out,
+			       "g: address = %x\t value = %40.30f\n",
+			       (unsigned) g, cuddV(g));
+#endif
+	    }
+	    return(0);
+	}
+    }
+
+    /* We only insert the result in the cache if the comparison is
+    ** successful. Therefore, if we hit we return 1. */
+    r = cuddCacheLookup2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g);
+    if (r != NULL) {
+	return(1);
+    }
+
+    /* Compute the cofactors and solve the recursive subproblems. */
+    topf = cuddI(dd,f->index);
+    topg = cuddI(dd,g->index);
+
+    if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
+    if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
+
+    if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
+    if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);
+
+    cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd));
+
+    return(1);
+
+} /* end of Cudd_EqualSupNorm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Expands cube to a prime implicant of f.]
+
+  Description [Expands cube to a prime implicant of f. Returns the prime
+  if successful; NULL otherwise.  In particular, NULL is returned if cube
+  is not a real cube or is not an implicant of f.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_bddMakePrime(
+  DdManager *dd /* manager */,
+  DdNode *cube /* cube to be expanded */,
+  DdNode *f /* function of which the cube is to be made a prime */)
+{
+    DdNode *res;
+
+    if (!Cudd_bddLeq(dd,cube,f)) return(NULL);
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddMakePrime(dd,cube,f);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddMakePrime */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddMakePrime.]
+
+  Description [Performs the recursive step of Cudd_bddMakePrime.
+  Returns the prime if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddBddMakePrime(
+  DdManager *dd /* manager */,
+  DdNode *cube /* cube to be expanded */,
+  DdNode *f /* function of which the cube is to be made a prime */)
+{
+    DdNode *scan;
+    DdNode *t, *e;
+    DdNode *res = cube;
+    DdNode *zero = Cudd_Not(DD_ONE(dd));
+
+    Cudd_Ref(res);
+    scan = cube;
+    while (!Cudd_IsConstant(scan)) {
+	DdNode *reg = Cudd_Regular(scan);
+	DdNode *var = dd->vars[reg->index];
+	DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
+	if (expanded == NULL) {
+	    return(NULL);
+	}
+	Cudd_Ref(expanded);
+	if (Cudd_bddLeq(dd,expanded,f)) {
+	    Cudd_RecursiveDeref(dd,res);
+	    res = expanded;
+	} else {
+	    Cudd_RecursiveDeref(dd,expanded);
+	}
+	cuddGetBranches(scan,&t,&e);
+	if (t == zero) {
+	    scan = e;
+	} else if (e == zero) {
+	    scan = t;
+	} else {
+	    Cudd_RecursiveDeref(dd,res);
+	    return(NULL);	/* cube is not a cube */
+	}
+    }
+
+    if (scan == DD_ONE(dd)) {
+	Cudd_Deref(res);
+	return(res);
+    } else {
+	Cudd_RecursiveDeref(dd,res);
+	return(NULL);
+    }
+
+} /* end of cuddBddMakePrime */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the entries of the visited symbol table.]
+
+  Description [Frees the entries of the visited symbol table. Returns
+  ST_CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st_retval
+freePathPair(
+  char * key,
+  char * value,
+  char * arg)
+{
+    cuddPathPair *pair;
+
+    pair = (cuddPathPair *) value;
+	FREE(pair);
+    return(ST_CONTINUE);
+
+} /* end of freePathPair */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the length of the shortest path(s) in a DD.]
+
+  Description [Finds the length of the shortest path(s) in a DD.
+  Uses a local symbol table to store the lengths for each
+  node. Only the lengths for the regular nodes are entered in the table,
+  because those for the complement nodes are simply obtained by swapping
+  the two lenghts.
+  Returns a pair of lengths: the length of the shortest path to 1;
+  and the length of the shortest path to 0. This is done so as to take
+  complement arcs into account.]
+
+  SideEffects [Accumulates the support of the DD in support.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static cuddPathPair
+getShortest(
+  DdNode * root,
+  int * cost,
+  int * support,
+  st_table * visited)
+{
+    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
+    DdNode	*my_root, *T, *E;
+    int		weight;
+
+    my_root = Cudd_Regular(root);
+
+    if (st_lookup(visited, my_root, &my_pair)) {
+	if (Cudd_IsComplement(root)) {
+	    res_pair.pos = my_pair->neg;
+	    res_pair.neg = my_pair->pos;
+	} else {
+	    res_pair.pos = my_pair->pos;
+	    res_pair.neg = my_pair->neg;
+	}
+	return(res_pair);
+    }
+
+    /* In the case of a BDD the following test is equivalent to
+    ** testing whether the BDD is the constant 1. This formulation,
+    ** however, works for ADDs as well, by assuming the usual
+    ** dichotomy of 0 and != 0.
+    */
+    if (cuddIsConstant(my_root)) {
+	if (my_root != zero) {
+	    res_pair.pos = 0;
+	    res_pair.neg = DD_BIGGY;
+	} else {
+	    res_pair.pos = DD_BIGGY;
+	    res_pair.neg = 0;
+	}
+    } else {
+	T = cuddT(my_root);
+	E = cuddE(my_root);
+
+	pair_T = getShortest(T, cost, support, visited);
+	pair_E = getShortest(E, cost, support, visited);
+	weight = WEIGHT(cost, my_root->index);
+	res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
+	res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);
+
+	/* Update support. */
+	if (support != NULL) {
+	    support[my_root->index] = 1;
+	}
+    }
+
+    my_pair = ALLOC(cuddPathPair, 1);
+    if (my_pair == NULL) {
+	if (Cudd_IsComplement(root)) {
+	    int tmp = res_pair.pos;
+	    res_pair.pos = res_pair.neg;
+	    res_pair.neg = tmp;
+	}
+	return(res_pair);
+    }
+    my_pair->pos = res_pair.pos;
+    my_pair->neg = res_pair.neg;
+
+    st_insert(visited, (char *)my_root, (char *)my_pair);
+    if (Cudd_IsComplement(root)) {
+	res_pair.pos = my_pair->neg;
+	res_pair.neg = my_pair->pos;
+    } else {
+	res_pair.pos = my_pair->pos;
+	res_pair.neg = my_pair->neg;
+    }
+    return(res_pair);
+
+} /* end of getShortest */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Build a BDD for a shortest path of f.]
+
+  Description [Build a BDD for a shortest path of f.
+  Given the minimum length from the root, and the minimum
+  lengths for each node (in visited), apply triangulation at each node.
+  Of the two children of each node on a shortest path, at least one is
+  on a shortest path. In case of ties the procedure chooses the THEN
+  children.
+  Returns a pointer to the cube BDD representing the path if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+getPath(
+  DdManager * manager,
+  st_table * visited,
+  DdNode * f,
+  int * weight,
+  int  cost)
+{
+    DdNode	*sol, *tmp;
+    DdNode	*my_dd, *T, *E;
+    cuddPathPair *T_pair, *E_pair;
+    int		Tcost, Ecost;
+    int		complement;
+
+    my_dd = Cudd_Regular(f);
+    complement = Cudd_IsComplement(f);
+
+    sol = one;
+    cuddRef(sol);
+
+    while (!cuddIsConstant(my_dd)) {
+	Tcost = cost - WEIGHT(weight, my_dd->index);
+	Ecost = cost;
+
+	T = cuddT(my_dd);
+	E = cuddE(my_dd);
+
+	if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
+
+	st_lookup(visited, Cudd_Regular(T), &T_pair);
+	if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
+	(!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
+	    tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(manager,sol);
+		return(NULL);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(manager,sol);
+	    sol = tmp;
+
+	    complement =  Cudd_IsComplement(T);
+	    my_dd = Cudd_Regular(T);
+	    cost = Tcost;
+	    continue;
+	}
+	st_lookup(visited, Cudd_Regular(E), &E_pair);
+	if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
+	(!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
+	    tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(manager,sol);
+		return(NULL);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(manager,sol);
+	    sol = tmp;
+	    complement = Cudd_IsComplement(E);
+	    my_dd = Cudd_Regular(E);
+	    cost = Ecost;
+	    continue;
+	}
+	(void) fprintf(manager->err,"We shouldn't be here!!\n");
+	manager->errorCode = CUDD_INTERNAL_ERROR;
+	return(NULL);
+    }
+
+    cuddDeref(sol);
+    return(sol);
+
+} /* end of getPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the size of the largest cube(s) in a DD.]
+
+  Description [Finds the size of the largest cube(s) in a DD.
+  This problem is translated into finding the shortest paths from a node
+  when both THEN and ELSE arcs have unit lengths.
+  Uses a local symbol table to store the lengths for each
+  node. Only the lengths for the regular nodes are entered in the table,
+  because those for the complement nodes are simply obtained by swapping
+  the two lenghts.
+  Returns a pair of lengths: the length of the shortest path to 1;
+  and the length of the shortest path to 0. This is done so as to take
+  complement arcs into account.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static cuddPathPair
+getLargest(
+  DdNode * root,
+  st_table * visited)
+{
+    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
+    DdNode	*my_root, *T, *E;
+
+    my_root = Cudd_Regular(root);
+
+    if (st_lookup(visited, my_root, &my_pair)) {
+	if (Cudd_IsComplement(root)) {
+	    res_pair.pos = my_pair->neg;
+	    res_pair.neg = my_pair->pos;
+	} else {
+	    res_pair.pos = my_pair->pos;
+	    res_pair.neg = my_pair->neg;
+	}
+	return(res_pair);
+    }
+
+    /* In the case of a BDD the following test is equivalent to
+    ** testing whether the BDD is the constant 1. This formulation,
+    ** however, works for ADDs as well, by assuming the usual
+    ** dichotomy of 0 and != 0.
+    */
+    if (cuddIsConstant(my_root)) {
+	if (my_root != zero) {
+	    res_pair.pos = 0;
+	    res_pair.neg = DD_BIGGY;
+	} else {
+	    res_pair.pos = DD_BIGGY;
+	    res_pair.neg = 0;
+	}
+    } else {
+	T = cuddT(my_root);
+	E = cuddE(my_root);
+
+	pair_T = getLargest(T, visited);
+	pair_E = getLargest(E, visited);
+	res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
+	res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
+    }
+
+    my_pair = ALLOC(cuddPathPair, 1);
+    if (my_pair == NULL) {	/* simply do not cache this result */
+	if (Cudd_IsComplement(root)) {
+	    int tmp = res_pair.pos;
+	    res_pair.pos = res_pair.neg;
+	    res_pair.neg = tmp;
+	}
+	return(res_pair);
+    }
+    my_pair->pos = res_pair.pos;
+    my_pair->neg = res_pair.neg;
+
+    st_insert(visited, (char *)my_root, (char *)my_pair);
+    if (Cudd_IsComplement(root)) {
+	res_pair.pos = my_pair->neg;
+	res_pair.neg = my_pair->pos;
+    } else {
+	res_pair.pos = my_pair->pos;
+	res_pair.neg = my_pair->neg;
+    }
+    return(res_pair);
+
+} /* end of getLargest */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Build a BDD for a largest cube of f.]
+
+  Description [Build a BDD for a largest cube of f.
+  Given the minimum length from the root, and the minimum
+  lengths for each node (in visited), apply triangulation at each node.
+  Of the two children of each node on a shortest path, at least one is
+  on a shortest path. In case of ties the procedure chooses the THEN
+  children.
+  Returns a pointer to the cube BDD representing the path if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+getCube(
+  DdManager * manager,
+  st_table * visited,
+  DdNode * f,
+  int  cost)
+{
+    DdNode	*sol, *tmp;
+    DdNode	*my_dd, *T, *E;
+    cuddPathPair *T_pair, *E_pair;
+    int		Tcost, Ecost;
+    int		complement;
+
+    my_dd = Cudd_Regular(f);
+    complement = Cudd_IsComplement(f);
+
+    sol = one;
+    cuddRef(sol);
+
+    while (!cuddIsConstant(my_dd)) {
+	Tcost = cost - 1;
+	Ecost = cost - 1;
+
+	T = cuddT(my_dd);
+	E = cuddE(my_dd);
+
+	if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
+
+	st_lookup(visited, Cudd_Regular(T), &T_pair);
+	if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
+	(!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
+	    tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(manager,sol);
+		return(NULL);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(manager,sol);
+	    sol = tmp;
+
+	    complement =  Cudd_IsComplement(T);
+	    my_dd = Cudd_Regular(T);
+	    cost = Tcost;
+	    continue;
+	}
+	st_lookup(visited, Cudd_Regular(E), &E_pair);
+	if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
+	(!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
+	    tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(manager,sol);
+		return(NULL);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(manager,sol);
+	    sol = tmp;
+	    complement = Cudd_IsComplement(E);
+	    my_dd = Cudd_Regular(E);
+	    cost = Ecost;
+	    continue;
+	}
+	(void) fprintf(manager->err,"We shouldn't be here!\n");
+	manager->errorCode = CUDD_INTERNAL_ERROR;
+	return(NULL);
+    }
+
+    cuddDeref(sol);
+    return(sol);
+
+} /* end of getCube */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddSign.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddSign.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddSign.c	(revision 8)
@@ -0,0 +1,319 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSign.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Computation of signatures]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_CofMinterm();
+		    </ul>
+		Static procedures included in this module:
+		    <ul>
+		    <li> ddCofMintermAux()
+		    </ul>
+		    ]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSign.c,v 1.21 2005/05/14 17:27:11 fabio Exp $";
+#endif
+
+static int    size;
+
+#ifdef DD_STATS
+static int num_calls;	/* should equal 2n-1 (n is the # of nodes) */
+static int table_mem;
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static double * ddCofMintermAux (DdManager *dd, DdNode *node, st_table *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes the fraction of minterms in the on-set of all the
+  positive cofactors of a BDD or ADD.]
+
+  Description [Computes the fraction of minterms in the on-set of all
+  the positive cofactors of DD. Returns the pointer to an array of
+  doubles if successful; NULL otherwise. The array has as many
+  positions as there are BDD variables in the manager plus one. The
+  last position of the array contains the fraction of the minterms in
+  the ON-set of the function represented by the BDD or ADD. The other
+  positions of the array hold the variable signatures.]
+
+  SideEffects [None]
+
+******************************************************************************/
+double *
+Cudd_CofMinterm(
+  DdManager * dd,
+  DdNode * node)
+{
+    st_table	*table;
+    double	*values;
+    double	*result = NULL;
+    int		i, firstLevel;
+
+#ifdef DD_STATS
+    long startTime;
+    startTime = util_cpu_time();
+    num_calls = 0;
+    table_mem = sizeof(st_table);
+#endif
+
+    table = st_init_table(st_ptrcmp, st_ptrhash);
+    if (table == NULL) {
+	(void) fprintf(dd->err,
+		       "out-of-memory, couldn't measure DD cofactors.\n");
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    size = dd->size;
+    values = ddCofMintermAux(dd, node, table);
+    if (values != NULL) {
+	result = ALLOC(double,size + 1);
+	if (result != NULL) {
+#ifdef DD_STATS
+	    table_mem += (size + 1) * sizeof(double);
+#endif
+	    if (Cudd_IsConstant(node))
+		firstLevel = 1;
+	    else
+		firstLevel = cuddI(dd,Cudd_Regular(node)->index);
+	    for (i = 0; i < size; i++) {
+		if (i >= cuddI(dd,Cudd_Regular(node)->index)) {
+		    result[dd->invperm[i]] = values[i - firstLevel];
+		} else {
+		    result[dd->invperm[i]] = values[size - firstLevel];
+		}
+	    }
+	    result[size] = values[size - firstLevel];
+	} else {
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	}
+    }
+
+#ifdef DD_STATS
+    table_mem += table->num_bins * sizeof(st_table_entry *);
+#endif
+    if (Cudd_Regular(node)->ref == 1) FREE(values);
+    st_foreach(table, cuddStCountfree, NULL);
+    st_free_table(table);
+#ifdef DD_STATS
+    (void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n",
+   		  num_calls, table_mem);
+    (void) fprintf(dd->out,"Time to compute measures: %s\n",
+		  util_print_time(util_cpu_time() - startTime));
+#endif
+    if (result == NULL) {
+	(void) fprintf(dd->out,
+		       "out-of-memory, couldn't measure DD cofactors.\n");
+	dd->errorCode = CUDD_MEMORY_OUT;
+    }
+    return(result);
+
+} /* end of Cudd_CofMinterm */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive Step for Cudd_CofMinterm function.]
+
+  Description [Traverses the DD node and computes the fraction of
+  minterms in the on-set of all positive cofactors simultaneously.
+  It allocates an array with two more entries than there are
+  variables below the one labeling the node.  One extra entry (the
+  first in the array) is for the variable labeling the node. The other
+  entry (the last one in the array) holds the fraction of minterms of
+  the function rooted at node.  Each other entry holds the value for
+  one cofactor. The array is put in a symbol table, to avoid repeated
+  computation, and its address is returned by the procedure, for use
+  by the caller.  Returns a pointer to the array of cofactor measures.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double *
+ddCofMintermAux(
+  DdManager * dd,
+  DdNode * node,
+  st_table * table)
+{
+    DdNode	*N;		/* regular version of node */
+    DdNode	*Nv, *Nnv;
+    double	*values;
+    double	*valuesT, *valuesE;
+    int		i;
+    int		localSize, localSizeT, localSizeE;
+    double	vT, vE;
+
+    statLine(dd);
+#ifdef DD_STATS
+    num_calls++;
+#endif
+
+    if (st_lookup(table, node, &values)) {
+	return(values);
+    }
+
+    N = Cudd_Regular(node);
+    if (cuddIsConstant(N)) {
+	localSize = 1;
+    } else {
+	localSize = size - cuddI(dd,N->index) + 1;
+    }
+    values = ALLOC(double, localSize);
+    if (values == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    if (cuddIsConstant(N)) {
+	if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) {
+	    values[0] = 0.0;
+	} else {
+	    values[0] = 1.0;
+	}
+    } else {
+	Nv = Cudd_NotCond(cuddT(N),N!=node);
+	Nnv = Cudd_NotCond(cuddE(N),N!=node);
+
+	valuesT = ddCofMintermAux(dd, Nv, table);
+	if (valuesT == NULL) return(NULL);
+	valuesE = ddCofMintermAux(dd, Nnv, table);
+	if (valuesE == NULL) return(NULL);
+
+	if (Cudd_IsConstant(Nv)) {
+	    localSizeT = 1;
+	} else {
+	    localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1;
+	}
+	if (Cudd_IsConstant(Nnv)) {
+	    localSizeE = 1;
+	} else {
+	    localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1;
+	}
+	values[0] = valuesT[localSizeT - 1];
+	for (i = 1; i < localSize; i++) {
+	    if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) {
+		vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) +
+			    cuddI(dd,N->index)];
+	    } else {
+		vT = valuesT[localSizeT - 1];
+	    }
+	    if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) {
+		vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) +
+			    cuddI(dd,N->index)];
+	    } else {
+		vE = valuesE[localSizeE - 1];
+	    }
+	    values[i] = (vT + vE) / 2.0;
+	}
+	if (Cudd_Regular(Nv)->ref == 1) FREE(valuesT);
+	if (Cudd_Regular(Nnv)->ref == 1) FREE(valuesE);
+    }
+
+    if (N->ref > 1) {
+	if (st_add_direct(table, (char *) node, (char *) values) == ST_OUT_OF_MEM) {
+	    FREE(values);
+	    return(NULL);
+	}
+#ifdef DD_STATS
+	table_mem += localSize * sizeof(double) + sizeof(st_table_entry);
+#endif
+    }
+    return(values);
+
+} /* end of ddCofMintermAux */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddSolve.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddSolve.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddSolve.c	(revision 8)
@@ -0,0 +1,366 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSolve.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Boolean equation solver and related functions.]
+
+  Description [External functions included in this modoule:
+		<ul>
+		<li> Cudd_SolveEqn()
+		<li> Cudd_VerifySol()
+		</ul>
+	Internal functions included in this module:
+		<ul>
+		<li> cuddSolveEqnRecur()
+		<li> cuddVerifySol()
+		</ul> ]
+
+  SeeAlso     []
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.12 2004/08/13 18:04:51 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the solution of F(x,y) = 0.]
+
+  Description [Implements the solution for F(x,y) = 0. The return
+  value is the consistency condition. The y variables are the unknowns
+  and the remaining variables are the parameters.  Returns the
+  consistency condition if successful; NULL otherwise. Cudd_SolveEqn
+  allocates an array and fills it with the indices of the
+  unknowns. This array is used by Cudd_VerifySol.]
+
+  SideEffects [The solution is returned in G; the indices of the y
+  variables are returned in yIndex.]
+
+  SeeAlso     [Cudd_VerifySol]
+
+******************************************************************************/
+DdNode *
+Cudd_SolveEqn(
+  DdManager *  bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode * Y /* the cube of the y variables */,
+  DdNode ** G /* the array of solutions (return parameter) */,
+  int ** yIndex /* index of y variables */,
+  int  n /* numbers of unknowns */)
+{
+    DdNode *res;
+    int *temp;
+
+    *yIndex = temp = ALLOC(int, n);
+    if (temp == NULL) {
+	bdd->errorCode = CUDD_MEMORY_OUT;
+	(void) fprintf(bdd->out,
+		       "Cudd_SolveEqn: Out of memory for yIndex\n");
+	return(NULL);
+    }
+
+    do {
+	bdd->reordered = 0;
+	res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0);
+    } while (bdd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_SolveEqn */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the solution of F(x,y) = 0.]
+
+  Description [Checks the solution of F(x,y) = 0. This procedure 
+  substitutes the solution components for the unknowns of F and returns 
+  the resulting BDD for F.] 
+
+  SideEffects [Frees the memory pointed by yIndex.]
+
+  SeeAlso     [Cudd_SolveEqn]
+
+******************************************************************************/
+DdNode *
+Cudd_VerifySol(
+  DdManager *  bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode ** G /* the array of solutions */,
+  int * yIndex /* index of y variables */,
+  int  n /* numbers of unknowns */)
+{
+    DdNode *res;
+
+    do {
+	bdd->reordered = 0;
+	res = cuddVerifySol(bdd, F, G, yIndex, n);
+    } while (bdd->reordered == 1);
+
+    FREE(yIndex);
+
+    return(res);
+
+} /* end of Cudd_VerifySol */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_SolveEqn.]
+
+  Description [Implements the recursive step of Cudd_SolveEqn. 
+  Returns NULL if the intermediate solution blows up
+  or reordering occurs. The parametric solutions are
+  stored in the array G.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_SolveEqn, Cudd_VerifySol]
+
+******************************************************************************/
+DdNode *
+cuddSolveEqnRecur(
+  DdManager * bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode * Y /* the cube of remaining y variables */,
+  DdNode ** G /* the array of solutions */,
+  int  n /* number of unknowns */,
+  int * yIndex /* array holding the y variable indices */,
+  int  i /* level of recursion */)
+{
+    DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one;
+    DdNodePtr *variables;
+
+    int j;
+
+    statLine(bdd);
+    variables = bdd->vars;
+    one = DD_ONE(bdd);
+
+    /* Base condition. */
+    if (Y == one) {
+	return F;
+    }
+
+    /* Cofactor of Y. */
+    yIndex[i] = Y->index;
+    nextY = Cudd_T(Y);
+
+    /* Universal abstraction of F with respect to the top variable index. */
+    Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]);
+    if (Fm1) {
+	Fm1 = Cudd_Not(Fm1);
+	cuddRef(Fm1);
+    } else {
+	return(NULL);
+    }
+
+    Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1);
+    if (Fn) {
+	cuddRef(Fn);
+    } else {
+	Cudd_RecursiveDeref(bdd, Fm1);
+	return(NULL);
+    }
+
+    Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]);
+    if (Fv) {
+	cuddRef(Fv);
+    } else {
+	Cudd_RecursiveDeref(bdd, Fm1);
+	Cudd_RecursiveDeref(bdd, Fn);
+	return(NULL);
+    }
+
+    Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]]));
+    if (Fvbar) {
+	cuddRef(Fvbar);
+    } else {
+	Cudd_RecursiveDeref(bdd, Fm1);
+	Cudd_RecursiveDeref(bdd, Fn);
+	Cudd_RecursiveDeref(bdd, Fv);
+	return(NULL);
+    }
+
+    /* Build i-th component of the solution. */
+    w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar);
+    if (w) {
+	cuddRef(w);
+    } else {
+	Cudd_RecursiveDeref(bdd, Fm1);
+	Cudd_RecursiveDeref(bdd, Fn);
+	Cudd_RecursiveDeref(bdd, Fv);
+	Cudd_RecursiveDeref(bdd, Fvbar);
+	return(NULL);
+    }
+
+    T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1));
+    if(T) {
+	cuddRef(T);
+    } else {
+	Cudd_RecursiveDeref(bdd, Fm1);
+	Cudd_RecursiveDeref(bdd, Fn);
+	Cudd_RecursiveDeref(bdd, Fv);
+	Cudd_RecursiveDeref(bdd, Fvbar);
+	Cudd_RecursiveDeref(bdd, w);
+	return(NULL);
+    }
+
+    Cudd_RecursiveDeref(bdd,Fm1);
+    Cudd_RecursiveDeref(bdd,w);
+    Cudd_RecursiveDeref(bdd,Fv);
+    Cudd_RecursiveDeref(bdd,Fvbar);
+
+    /* Substitute components of solution already found into solution. */
+    for (j = n-1; j > i; j--) {
+	w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]);
+	if(w) {
+	    cuddRef(w);
+	} else {
+	    Cudd_RecursiveDeref(bdd, Fn);
+	    Cudd_RecursiveDeref(bdd, T);
+	    return(NULL);
+	}
+	Cudd_RecursiveDeref(bdd,T);
+	T = w;
+    }
+    G[i] = T;
+
+    Cudd_Deref(Fn);
+
+    return(Fn);
+
+} /* end of cuddSolveEqnRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_VerifySol. ]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_VerifySol]
+
+******************************************************************************/
+DdNode *
+cuddVerifySol(
+  DdManager * bdd,
+  DdNode * F /* the left-hand side of the equation */,
+  DdNode ** G /* the array of solutions */,
+  int * yIndex /* array holding the y variable indices */,
+  int  n /* number of unknowns */)
+{
+    DdNode *w, *R;
+
+    int j;
+
+    R = F;
+    cuddRef(R);
+    for(j = n - 1; j >= 0; j--) {
+	 w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]);
+	if (w) {
+	    cuddRef(w);
+	} else {
+	    return(NULL); 
+	}
+	Cudd_RecursiveDeref(bdd,R);
+	R = w;
+    }
+
+    cuddDeref(R);
+
+    return(R);
+
+} /* end of cuddVerifySol */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddSplit.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddSplit.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddSplit.c	(revision 8)
@@ -0,0 +1,684 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSplit.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Returns a subset of minterms from a boolean function.]
+
+  Description [External functions included in this modoule:
+		<ul>
+		<li> Cudd_SplitSet()
+		</ul>
+	Internal functions included in this module:
+		<ul>
+		<li> cuddSplitSetRecur()
+		</u>
+        Static functions included in this module:
+		<ul>
+		<li> selectMintermsFromUniverse()
+		<li> mintermsFromUniverse()
+		<li> bddAnnotateMintermCount()
+		</ul> ]
+
+  SeeAlso     []
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * selectMintermsFromUniverse (DdManager *manager, int *varSeen, double n);
+static DdNode * mintermsFromUniverse (DdManager *manager, DdNode **vars, int numVars, double n, int index);
+static double bddAnnotateMintermCount (DdManager *manager, DdNode *node, double max, st_table *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns m minterms from a BDD.]
+
+  Description [Returns <code>m</code> minterms from a BDD whose
+  support has <code>n</code> variables at most.  The procedure tries
+  to create as few extra nodes as possible. The function represented
+  by <code>S</code> depends on at most <code>n</code> of the variables
+  in <code>xVars</code>. Returns a BDD with <code>m</code> minterms
+  of the on-set of S if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_SplitSet(
+  DdManager * manager,
+  DdNode * S,
+  DdNode ** xVars,
+  int  n,
+  double  m)
+{
+    DdNode *result;
+    DdNode *zero, *one;
+    double  max, num;
+    st_table *mtable;
+    int *varSeen;
+    int i,index, size;
+
+    size = manager->size;
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Trivial cases. */
+    if (m == 0.0) {
+	return(zero);
+    }
+    if (S == zero) {
+	return(NULL);
+    }
+
+    max = pow(2.0,(double)n);
+    if (m > max)
+	return(NULL);
+
+    do {
+	manager->reordered = 0;
+	/* varSeen is used to mark the variables that are encountered
+	** while traversing the BDD S.
+	*/
+	varSeen = ALLOC(int, size);
+	if (varSeen == NULL) {
+	    manager->errorCode = CUDD_MEMORY_OUT;
+	    return(NULL);
+	}
+	for (i = 0; i < size; i++) {
+	    varSeen[i] = -1;
+	}
+	for (i = 0; i < n; i++) {
+	    index = (xVars[i])->index;
+	    varSeen[manager->invperm[index]] = 0;
+	}
+
+	if (S == one) {
+	    if (m == max) 
+		return(S);
+	    result = selectMintermsFromUniverse(manager,varSeen,m);
+	    if (result)
+		cuddRef(result);
+	    FREE(varSeen);
+	} else {
+	    mtable = st_init_table(st_ptrcmp,st_ptrhash);
+	    if (mtable == NULL) {
+		(void) fprintf(manager->out,
+			       "Cudd_SplitSet: out-of-memory.\n");
+		FREE(varSeen);
+		manager->errorCode = CUDD_MEMORY_OUT;
+		return(NULL);
+	    }
+	    /* The nodes of BDD S are annotated by the number of minterms
+	    ** in their onset. The node and the number of minterms in its
+	    ** onset are stored in mtable.
+	    */
+	    num = bddAnnotateMintermCount(manager,S,max,mtable);
+	    if (m == num) {
+		st_foreach(mtable,cuddStCountfree,NIL(char));
+		st_free_table(mtable);
+		FREE(varSeen);
+		return(S);
+	    }
+	    
+	    result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0);
+	    if (result)
+		cuddRef(result);
+	    st_foreach(mtable,cuddStCountfree,NULL);
+	    st_free_table(mtable);
+	    FREE(varSeen);
+	}
+    } while (manager->reordered == 1);
+
+    cuddDeref(result);
+    return(result);
+
+} /* end of Cudd_SplitSet */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Cudd_SplitSet.]
+
+  Description [Implements the recursive step of Cudd_SplitSet. The
+  procedure recursively traverses the BDD and checks to see if any
+  node satisfies the minterm requirements as specified by 'n'. At any
+  node X, n is compared to the number of minterms in the onset of X's
+  children. If either of the child nodes have exactly n minterms, then
+  that node is returned; else, if n is greater than the onset of one
+  of the child nodes, that node is retained and the difference in the
+  number of minterms is extracted from the other child. In case n
+  minterms can be extracted from constant 1, the algorithm returns the
+  result with at most log(n) nodes.]
+
+  SideEffects [The array 'varSeen' is updated at every recursive call
+  to set the variables traversed by the procedure.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode*
+cuddSplitSetRecur(
+  DdManager * manager,
+  st_table * mtable,
+  int * varSeen,
+  DdNode * p,
+  double  n,
+  double  max,
+  int  index)
+{
+    DdNode *one, *zero, *N, *Nv;
+    DdNode *Nnv, *q, *r, *v;
+    DdNode *result;
+    double *dummy, numT, numE;
+    int variable, positive;
+  
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* If p is constant, extract n minterms from constant 1.  The procedure by
+    ** construction guarantees that minterms will not be extracted from
+    ** constant 0.
+    */
+    if (Cudd_IsConstant(p)) {
+	q = selectMintermsFromUniverse(manager,varSeen,n);
+	return(q);
+    }
+
+    N = Cudd_Regular(p);
+
+    /* Set variable as seen. */
+    variable = N->index;
+    varSeen[manager->invperm[variable]] = -1;
+
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    if (Cudd_IsComplement(p)) {
+	Nv = Cudd_Not(Nv);
+	Nnv = Cudd_Not(Nnv);
+    }
+
+    /* If both the children of 'p' are constants, extract n minterms from a
+    ** constant node.
+    */
+    if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
+	q = selectMintermsFromUniverse(manager,varSeen,n);
+	if (q == NULL) {
+	    return(NULL);
+	}
+	cuddRef(q);
+	r = cuddBddAndRecur(manager,p,q);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(manager,q);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_RecursiveDeref(manager,q);
+	cuddDeref(r);
+	return(r);
+    }
+  
+    /* Lookup the # of minterms in the onset of the node from the table. */
+    if (!Cudd_IsConstant(Nv)) {
+	st_lookup(mtable, Nv, &dummy);
+	numT = *dummy/(2*(1<<index));
+    } else if (Nv == one) {
+	numT = max/(2*(1<<index));
+    } else {
+	numT = 0;
+    }
+  
+    if (!Cudd_IsConstant(Nnv)) {
+	st_lookup(mtable, Nnv, &dummy);
+	numE = *dummy/(2*(1<<index));
+    } else if (Nnv == one) {
+	numE = max/(2*(1<<index));
+    } else {
+	numE = 0;
+    }
+
+    v = cuddUniqueInter(manager,variable,one,zero);
+    cuddRef(v);
+
+    /* If perfect match. */
+    if (numT == n) {
+	q = cuddBddAndRecur(manager,v,Nv);
+	if (q == NULL) {
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(q);
+	Cudd_RecursiveDeref(manager,v);
+	cuddDeref(q);
+	return(q);
+    }
+    if (numE == n) {
+	q = cuddBddAndRecur(manager,Cudd_Not(v),Nnv);
+	if (q == NULL) {
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(q);
+	Cudd_RecursiveDeref(manager,v);
+	cuddDeref(q);
+	return(q);
+    }
+    /* If n is greater than numT, extract the difference from the ELSE child
+    ** and retain the function represented by the THEN branch.
+    */
+    if (numT < n) {
+	q = cuddSplitSetRecur(manager,mtable,varSeen,
+			      Nnv,(n-numT),max,index+1);
+	if (q == NULL) {
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(q);
+	r = cuddBddIteRecur(manager,v,Nv,q);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(manager,q);
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_RecursiveDeref(manager,q);
+	Cudd_RecursiveDeref(manager,v);
+	cuddDeref(r);
+	return(r);
+    }
+    /* If n is greater than numE, extract the difference from the THEN child
+    ** and retain the function represented by the ELSE branch.
+    */
+    if (numE < n) {
+	q = cuddSplitSetRecur(manager,mtable,varSeen,
+			      Nv, (n-numE),max,index+1);
+	if (q == NULL) {
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(q);
+	r = cuddBddIteRecur(manager,v,q,Nnv);
+	if (r == NULL) {
+	    Cudd_RecursiveDeref(manager,q);
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_RecursiveDeref(manager,q);
+	Cudd_RecursiveDeref(manager,v);
+	cuddDeref(r);    
+	return(r);
+    }
+
+    /* None of the above cases; (n < numT and n < numE) and either of
+    ** the Nv, Nnv or both are not constants. If possible extract the
+    ** required minterms the constant branch.
+    */
+    if (Cudd_IsConstant(Nv) && !Cudd_IsConstant(Nnv)) {
+	q = selectMintermsFromUniverse(manager,varSeen,n);
+	if (q == NULL) {
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(q);
+	result = cuddBddAndRecur(manager,v,q);
+	if (result == NULL) {
+	    Cudd_RecursiveDeref(manager,q);
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(result);
+	Cudd_RecursiveDeref(manager,q);
+	Cudd_RecursiveDeref(manager,v);
+	cuddDeref(result);
+	return(result);
+    } else if (!Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
+	q = selectMintermsFromUniverse(manager,varSeen,n);
+	if (q == NULL) {
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(q);
+	result = cuddBddAndRecur(manager,Cudd_Not(v),q);
+	if (result == NULL) {
+	    Cudd_RecursiveDeref(manager,q);
+	    Cudd_RecursiveDeref(manager,v);
+	    return(NULL);
+	}
+	cuddRef(result);
+	Cudd_RecursiveDeref(manager,q);
+	Cudd_RecursiveDeref(manager,v);
+	cuddDeref(result);
+	return(result);
+    }
+
+    /* Both Nv and Nnv are not constants. So choose the one which
+    ** has fewer minterms in its onset.
+    */
+    positive = 0;
+    if (numT < numE) {
+	q = cuddSplitSetRecur(manager,mtable,varSeen,
+			      Nv,n,max,index+1);
+	positive = 1;
+    } else {
+	q = cuddSplitSetRecur(manager,mtable,varSeen,
+			      Nnv,n,max,index+1);
+    }
+
+    if (q == NULL) {
+	Cudd_RecursiveDeref(manager,v);
+	return(NULL);
+    }
+    cuddRef(q);
+
+    if (positive) {
+	result = cuddBddAndRecur(manager,v,q);
+    } else {
+	result = cuddBddAndRecur(manager,Cudd_Not(v),q);
+    }
+    if (result == NULL) {
+	Cudd_RecursiveDeref(manager,q);
+	Cudd_RecursiveDeref(manager,v);
+	return(NULL);
+    }
+    cuddRef(result);
+    Cudd_RecursiveDeref(manager,q);
+    Cudd_RecursiveDeref(manager,v);
+    cuddDeref(result);
+
+    return(result);
+
+} /* end of cuddSplitSetRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This function prepares an array of variables which have not been
+  encountered so far when traversing the procedure cuddSplitSetRecur.]
+
+  Description [This function prepares an array of variables which have not been
+  encountered so far when traversing the procedure cuddSplitSetRecur. This
+  array is then used to extract the required number of minterms from a constant
+  1. The algorithm guarantees that the size of BDD will be utmost \log(n).]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+selectMintermsFromUniverse(
+  DdManager * manager,
+  int * varSeen,
+  double  n)
+{
+    int numVars;
+    int i, size, j;
+     DdNode *one, *zero, *result;
+    DdNode **vars;
+
+    numVars = 0;
+    size = manager->size;
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    /* Count the number of variables not encountered so far in procedure
+    ** cuddSplitSetRecur.
+    */
+    for (i = size-1; i >= 0; i--) {
+	if(varSeen[i] == 0)
+	    numVars++;
+    }
+    vars = ALLOC(DdNode *, numVars);
+    if (!vars) {
+	manager->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    j = 0;
+    for (i = size-1; i >= 0; i--) {
+	if(varSeen[i] == 0) {
+	    vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero);
+	    cuddRef(vars[j]);
+	    j++;
+	}
+    }
+
+    /* Compute a function which has n minterms and depends on at most
+    ** numVars variables.
+    */
+    result = mintermsFromUniverse(manager,vars,numVars,n, 0);
+    if (result) 
+	cuddRef(result);
+
+    for (i = 0; i < numVars; i++)
+	Cudd_RecursiveDeref(manager,vars[i]);
+    FREE(vars);
+
+    return(result);
+
+} /* end of selectMintermsFromUniverse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive procedure to extract n mintems from constant 1.]
+
+  Description [Recursive procedure to extract n mintems from constant 1.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static DdNode *
+mintermsFromUniverse(
+  DdManager * manager,
+  DdNode ** vars,
+  int  numVars,
+  double  n,
+  int  index)
+{
+    DdNode *one, *zero;
+    DdNode *q, *result;
+    double max, max2;
+    
+    statLine(manager);
+    one = DD_ONE(manager);
+    zero = Cudd_Not(one);
+
+    max = pow(2.0, (double)numVars);
+    max2 = max / 2.0;
+
+    if (n == max)
+	return(one);
+    if (n == 0.0)
+	return(zero);
+    /* if n == 2^(numVars-1), return a single variable */
+    if (n == max2)
+	return vars[index];
+    else if (n > max2) {
+	/* When n > 2^(numVars-1), a single variable vars[index]
+	** contains 2^(numVars-1) minterms. The rest are extracted
+	** from a constant with 1 less variable.
+	*/
+	q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1);
+	if (q == NULL)
+	    return(NULL);
+	cuddRef(q);
+	result = cuddBddIteRecur(manager,vars[index],one,q);
+    } else {
+	/* When n < 2^(numVars-1), a literal of variable vars[index]
+	** is selected. The required n minterms are extracted from a
+	** constant with 1 less variable.
+	*/
+	q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1);
+	if (q == NULL)
+	    return(NULL);
+	cuddRef(q);
+	result = cuddBddAndRecur(manager,vars[index],q);
+    }
+    
+    if (result == NULL) {
+	Cudd_RecursiveDeref(manager,q);
+	return(NULL);
+    }
+    cuddRef(result);
+    Cudd_RecursiveDeref(manager,q);
+    cuddDeref(result);
+    return(result);
+
+} /* end of mintermsFromUniverse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Annotates every node in the BDD node with its minterm count.]
+
+  Description [Annotates every node in the BDD node with its minterm count.
+  In this function, every node and the minterm count represented by it are
+  stored in a hash table.]
+
+  SideEffects [Fills up 'table' with the pair <node,minterm_count>.]
+
+******************************************************************************/
+static double
+bddAnnotateMintermCount(
+  DdManager * manager,
+  DdNode * node,
+  double  max,
+  st_table * table)
+{
+
+    DdNode *N,*Nv,*Nnv;
+    register double min_v,min_nv;
+    register double min_N;
+    double *pmin;
+    double *dummy;
+
+    statLine(manager);
+    N = Cudd_Regular(node);
+    if (cuddIsConstant(N)) {
+	if (node == DD_ONE(manager)) {
+	    return(max);
+	} else {
+	    return(0.0);
+	}
+    }
+
+    if (st_lookup(table, node, &dummy)) {
+	return(*dummy);
+    }	
+  
+    Nv = cuddT(N);
+    Nnv = cuddE(N);
+    if (N != node) {
+	Nv = Cudd_Not(Nv);
+	Nnv = Cudd_Not(Nnv);
+    }
+
+    /* Recur on the two branches. */
+    min_v  = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0;
+    if (min_v == (double)CUDD_OUT_OF_MEM)
+	return ((double)CUDD_OUT_OF_MEM);
+    min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0;
+    if (min_nv == (double)CUDD_OUT_OF_MEM)
+	return ((double)CUDD_OUT_OF_MEM);
+    min_N  = min_v + min_nv;
+
+    pmin = ALLOC(double,1);
+    if (pmin == NULL) {
+	manager->errorCode = CUDD_MEMORY_OUT;
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    *pmin = min_N;
+
+    if (st_insert(table,(char *)node, (char *)pmin) == ST_OUT_OF_MEM) {
+	FREE(pmin);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    
+    return(min_N);
+
+} /* end of bddAnnotateMintermCount */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddSubsetHB.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddSubsetHB.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddSubsetHB.c	(revision 8)
@@ -0,0 +1,1328 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSubsetHB.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedure to subset the given BDD by choosing the heavier
+		branches]
+
+
+  Description [External procedures provided by this module:
+                <ul>
+		<li> Cudd_SubsetHeavyBranch()
+		<li> Cudd_SupersetHeavyBranch()
+		</ul>
+	       Internal procedures included in this module:
+		<ul>
+		<li> cuddSubsetHeavyBranch()
+		</ul>
+	       Static procedures included in this module:
+		<ul>
+		<li> ResizeCountMintermPages();
+		<li> ResizeNodeDataPages()
+		<li> ResizeCountNodePages()
+		<li> SubsetCountMintermAux()
+		<li> SubsetCountMinterm()
+		<li> SubsetCountNodesAux()
+		<li> SubsetCountNodes()
+		<li> BuildSubsetBdd()
+		</ul>
+		]
+
+  SeeAlso     [cuddSubsetSP.c]
+
+  Author      [Kavita Ravi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#ifdef __STDC__
+#include <float.h>
+#else
+#define DBL_MAX_EXP 1024
+#endif
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define	DEFAULT_PAGE_SIZE 2048
+#define	DEFAULT_NODE_DATA_PAGE_SIZE 1024
+#define INITIAL_PAGES 128
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* data structure to store the information on each node. It keeps
+ * the number of minterms represented by the DAG rooted at this node
+ * in terms of the number of variables specified by the user, number
+ * of nodes in this DAG and the number of nodes of its child with
+ * lesser number of minterms that are not shared by the child with
+ * more minterms
+ */
+struct NodeData {
+    double *mintermPointer;
+    int *nodesPointer;
+    int *lightChildNodesPointer;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct NodeData NodeData_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.35 2004/08/13 18:04:51 fabio Exp $";
+#endif
+
+static int memOut;
+#ifdef DEBUG
+static	int		num_calls;
+#endif
+
+static	DdNode	        *zero, *one; /* constant functions */
+static	double		**mintermPages;	/* pointers to the pages */
+static	int		**nodePages; /* pointers to the pages */
+static	int		**lightNodePages; /* pointers to the pages */
+static	double		*currentMintermPage; /* pointer to the current
+						   page */
+static  double 		max; /* to store the 2^n value of the number
+			      * of variables */
+
+static	int		*currentNodePage; /* pointer to the current
+						   page */
+static	int		*currentLightNodePage; /* pointer to the
+						*  current page */
+static	int		pageIndex; /* index to next element */
+static	int		page; /* index to current page */
+static	int		pageSize = DEFAULT_PAGE_SIZE; /* page size */
+static  int             maxPages; /* number of page pointers */
+
+static	NodeData_t	*currentNodeDataPage; /* pointer to the current
+						 page */
+static	int		nodeDataPage; /* index to next element */
+static	int		nodeDataPageIndex; /* index to next element */
+static	NodeData_t	**nodeDataPages; /* index to current page */
+static	int		nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE;
+                                                     /* page size */
+static  int             maxNodeDataPages; /* number of page pointers */
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ResizeNodeDataPages (void);
+static void ResizeCountMintermPages (void);
+static void ResizeCountNodePages (void);
+static double SubsetCountMintermAux (DdNode *node, double max, st_table *table);
+static st_table * SubsetCountMinterm (DdNode *node, int nvars);
+static int SubsetCountNodesAux (DdNode *node, st_table *table, double max);
+static int SubsetCountNodes (DdNode *node, st_table *table, int nvars);
+static void StoreNodes (st_table *storeTable, DdManager *dd, DdNode *node);
+static DdNode * BuildSubsetBdd (DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense subset from a BDD with the heavy branch
+  heuristic.]
+
+  Description [Extracts a dense subset from a BDD. This procedure
+  builds a subset by throwing away one of the children of each node,
+  starting from the root, until the result is small enough. The child
+  that is eliminated from the result is the one that contributes the
+  fewer minterms.  Returns a pointer to the BDD of the subset if
+  successful. NULL if the procedure runs out of memory. The parameter
+  numVars is the maximum number of variables to be used in minterm
+  calculation and node count calculation.  The optimal number should
+  be as close as possible to the size of the support of f.  However,
+  it is safe to pass the value returned by Cudd_ReadSize for numVars
+  when the number of variables is under 1023.  If numVars is larger
+  than 1023, it will overflow. If a 0 parameter is passed then the
+  procedure will compute a value which will avoid overflow but will
+  cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetHeavyBranch(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */)
+{
+    DdNode *subset;
+
+    memOut = 0;
+    do {
+	dd->reordered = 0;
+	subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold);
+    } while ((dd->reordered == 1) && (!memOut));
+
+    return(subset);
+
+} /* end of Cudd_SubsetHeavyBranch */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the heavy branch
+  heuristic.]
+
+  Description [Extracts a dense superset from a BDD. The procedure is
+  identical to the subset procedure except for the fact that it
+  receives the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function. This procedure builds a superset by throwing away
+  one of the children of each node starting from the root of the
+  complement function, until the result is small enough. The child
+  that is eliminated from the result is the one that contributes the
+  fewer minterms.
+  Returns a pointer to the BDD of the superset if successful. NULL if
+  intermediate result causes the procedure to run out of memory. The
+  parameter numVars is the maximum number of variables to be used in
+  minterm calculation and node count calculation.  The optimal number
+  should be as close as possible to the size of the support of f.
+  However, it is safe to pass the value returned by Cudd_ReadSize for
+  numVars when the number of variables is under 1023.  If numVars is
+  larger than 1023, it will overflow. If a 0 parameter is passed then
+  the procedure will compute a value which will avoid overflow but
+  will cause underflow with 2046 variables or more.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SupersetHeavyBranch(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the superset */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);    
+    memOut = 0;
+    do {
+	dd->reordered = 0;
+	subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold);
+    } while ((dd->reordered == 1) && (!memOut));
+    
+    return(Cudd_NotCond(subset, (subset != NULL)));
+    
+} /* end of Cudd_SupersetHeavyBranch */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [The main procedure that returns a subset by choosing the heavier
+  branch in the BDD.]
+
+  Description [Here a subset BDD is built by throwing away one of the
+  children. Starting at root, annotate each node with the number of
+  minterms (in terms of the total number of variables specified -
+  numVars), number of nodes taken by the DAG rooted at this node and
+  number of additional nodes taken by the child that has the lesser
+  minterms. The child with the lower number of minterms is thrown away
+  and a dyanmic count of the nodes of the subset is kept. Once the
+  threshold is reached the subset is returned to the calling
+  procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetHeavyBranch]
+
+******************************************************************************/
+DdNode *
+cuddSubsetHeavyBranch(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* current DD */,
+  int  numVars /* maximum number of variables */,
+  int  threshold /* threshold size for the subset */)
+{
+
+    int i, *size;
+    st_table *visitedTable;
+    int numNodes;
+    NodeData_t *currNodeQual;
+    DdNode *subset;
+    st_table *storeTable, *approxTable;
+    char *key, *value;
+    st_generator *stGen;
+    
+    if (f == NULL) {
+	fprintf(dd->err, "Cannot subset, nil object\n");
+	dd->errorCode = CUDD_INVALID_ARG;
+	return(NULL);
+    }
+
+    one	 = Cudd_ReadOne(dd);
+    zero = Cudd_Not(one);
+
+    /* If user does not know numVars value, set it to the maximum
+     * exponent that the pow function can take. The -1 is due to the
+     * discrepancy in the value that pow takes and the value that
+     * log gives.
+     */
+    if (numVars == 0) {
+	/* set default value */
+	numVars = DBL_MAX_EXP - 1;
+    }
+
+    if (Cudd_IsConstant(f)) {
+	return(f);
+    }
+
+    max = pow(2.0, (double)numVars);
+
+    /* Create visited table where structures for node data are allocated and
+       stored in a st_table */
+    visitedTable = SubsetCountMinterm(f, numVars);
+    if ((visitedTable == NULL) || memOut) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    numNodes = SubsetCountNodes(f, visitedTable, numVars);
+    if (memOut) {
+	(void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+
+    if (st_lookup(visitedTable, f, &currNodeQual) == 0) {
+	fprintf(dd->err,
+		"Something is wrong, ought to be node quality table\n");
+	dd->errorCode = CUDD_INTERNAL_ERROR;
+    }
+
+    size = ALLOC(int, 1);
+    if (size == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    *size = numNodes;
+
+#ifdef DEBUG
+    num_calls = 0;
+#endif
+    /* table to store nodes being created. */
+    storeTable = st_init_table(st_ptrcmp, st_ptrhash);
+    /* insert the constant */
+    cuddRef(one);
+    if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) ==
+	ST_OUT_OF_MEM) {
+	fprintf(dd->out, "Something wrong, st_table insert failed\n");
+    }
+    /* table to store approximations of nodes */
+    approxTable = st_init_table(st_ptrcmp, st_ptrhash);
+    subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold,
+				      storeTable, approxTable);
+    if (subset != NULL) {
+	cuddRef(subset);
+    }
+
+    stGen = st_init_gen(approxTable);
+    if (stGen == NULL) {
+	st_free_table(approxTable);
+	return(NULL);
+    }
+    while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	Cudd_RecursiveDeref(dd, (DdNode *)value);
+    }
+    st_free_gen(stGen); stGen = NULL;
+    st_free_table(approxTable);
+
+    stGen = st_init_gen(storeTable);
+    if (stGen == NULL) {
+	st_free_table(storeTable);
+	return(NULL);
+    }
+    while(st_gen(stGen, (char **)&key, (char **)&value)) {
+	Cudd_RecursiveDeref(dd, (DdNode *)key);
+    }
+    st_free_gen(stGen); stGen = NULL;
+    st_free_table(storeTable);
+
+    for (i = 0; i <= page; i++) {
+	FREE(mintermPages[i]);
+    }
+    FREE(mintermPages);
+    for (i = 0; i <= page; i++) {
+	FREE(nodePages[i]);
+    }
+    FREE(nodePages);
+    for (i = 0; i <= page; i++) {
+	FREE(lightNodePages[i]);
+    }
+    FREE(lightNodePages);
+    for (i = 0; i <= nodeDataPage; i++) {
+	FREE(nodeDataPages[i]);
+    }
+    FREE(nodeDataPages);
+    st_free_table(visitedTable);
+    FREE(size);
+#if 0
+    (void) Cudd_DebugCheck(dd);
+    (void) Cudd_CheckKeys(dd);
+#endif
+
+    if (subset != NULL) {
+#ifdef DD_DEBUG
+      if (!Cudd_bddLeq(dd, subset, f)) {
+	    fprintf(dd->err, "Wrong subset\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+      }
+#endif
+        cuddDeref(subset);
+        return(subset);
+    } else {
+        return(NULL);
+    }
+} /* end of cuddSubsetHeavyBranch */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the node data.]
+
+  Description [Resize the number of pages allocated to store the node data
+  The procedure  moves the counter to the next page when the end of
+  the page is reached and allocates new pages when necessary.]
+
+  SideEffects [Changes the size of pages, page, page index, maximum
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeNodeDataPages(void)
+{
+    int i;
+    NodeData_t **newNodeDataPages;
+
+    nodeDataPage++;
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by
+     * INITIAL_PAGES
+     */
+    if (nodeDataPage == maxNodeDataPages) {
+	newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES);
+	if (newNodeDataPages == NULL) {
+	    for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
+	    FREE(nodeDataPages);
+	    memOut = 1;
+	    return;
+	} else {
+	    for (i = 0; i < maxNodeDataPages; i++) {
+		newNodeDataPages[i] = nodeDataPages[i];
+	    }
+	    /* Increase total page count */
+	    maxNodeDataPages += INITIAL_PAGES;
+	    FREE(nodeDataPages);
+	    nodeDataPages = newNodeDataPages;
+	}
+    }
+    /* Allocate a new page */
+    currentNodeDataPage = nodeDataPages[nodeDataPage] =
+	ALLOC(NodeData_t ,nodeDataPageSize);
+    if (currentNodeDataPage == NULL) {
+	for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
+	FREE(nodeDataPages);
+	memOut = 1;
+	return;
+    }
+    /* reset page index */
+    nodeDataPageIndex = 0;
+    return;
+
+} /* end of ResizeNodeDataPages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the minterm
+  counts. ]
+
+  Description [Resize the number of pages allocated to store the minterm
+  counts.  The procedure  moves the counter to the next page when the
+  end of the page is reached and allocates new pages when necessary.]
+
+  SideEffects [Changes the size of minterm pages, page, page index, maximum 
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeCountMintermPages(void)
+{
+    int i;
+    double **newMintermPages;
+
+    page++;
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by
+     * INITIAL_PAGES
+     */
+    if (page == maxPages) {
+	newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES);
+	if (newMintermPages == NULL) {
+	    for (i = 0; i < page; i++) FREE(mintermPages[i]);
+	    FREE(mintermPages);
+	    memOut = 1;
+	    return;
+	} else {
+	    for (i = 0; i < maxPages; i++) {
+		newMintermPages[i] = mintermPages[i];
+	    }
+	    /* Increase total page count */
+	    maxPages += INITIAL_PAGES;
+	    FREE(mintermPages);
+	    mintermPages = newMintermPages;
+	}
+    }
+    /* Allocate a new page */
+    currentMintermPage = mintermPages[page] = ALLOC(double,pageSize);
+    if (currentMintermPage == NULL) {
+	for (i = 0; i < page; i++) FREE(mintermPages[i]);
+	FREE(mintermPages);
+	memOut = 1;
+	return;
+    }
+    /* reset page index */
+    pageIndex = 0;
+    return;
+
+} /* end of ResizeCountMintermPages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the node counts.]
+
+  Description [Resize the number of pages allocated to store the node counts.
+  The procedure  moves the counter to the next page when the end of
+  the page is reached and allocates new pages when necessary.]
+
+  SideEffects [Changes the size of pages, page, page index, maximum
+  number of pages freeing stuff in case of memory out.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeCountNodePages(void)
+{
+    int i;
+    int **newNodePages;
+
+    page++;
+
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. The number of pages is incremented
+     * by INITIAL_PAGES.
+     */
+    if (page == maxPages) {
+	newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
+	if (newNodePages == NULL) {
+	    for (i = 0; i < page; i++) FREE(nodePages[i]);
+	    FREE(nodePages);
+	    for (i = 0; i < page; i++) FREE(lightNodePages[i]);
+	    FREE(lightNodePages);
+	    memOut = 1;
+	    return;
+	} else {
+	    for (i = 0; i < maxPages; i++) {
+		newNodePages[i] = nodePages[i];
+	    }
+	    FREE(nodePages);
+	    nodePages = newNodePages;
+	}
+
+	newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
+	if (newNodePages == NULL) {
+	    for (i = 0; i < page; i++) FREE(nodePages[i]);
+	    FREE(nodePages);
+	    for (i = 0; i < page; i++) FREE(lightNodePages[i]);
+	    FREE(lightNodePages);
+	    memOut = 1;
+	    return;
+	} else {
+	    for (i = 0; i < maxPages; i++) {
+		newNodePages[i] = lightNodePages[i];
+	    }
+	    FREE(lightNodePages);
+	    lightNodePages = newNodePages;
+	}
+	/* Increase total page count */
+	maxPages += INITIAL_PAGES;
+    }
+    /* Allocate a new page */
+    currentNodePage = nodePages[page] = ALLOC(int,pageSize);
+    if (currentNodePage == NULL) {
+	for (i = 0; i < page; i++) FREE(nodePages[i]);
+	FREE(nodePages);
+	for (i = 0; i < page; i++) FREE(lightNodePages[i]);
+	FREE(lightNodePages);
+	memOut = 1;
+	return;
+    }
+    /* Allocate a new page */
+    currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
+    if (currentLightNodePage == NULL) {
+	for (i = 0; i <= page; i++) FREE(nodePages[i]);
+	FREE(nodePages);
+	for (i = 0; i < page; i++) FREE(lightNodePages[i]);
+	FREE(lightNodePages);
+	memOut = 1;
+	return;
+    }
+    /* reset page index */
+    pageIndex = 0;
+    return;
+
+} /* end of ResizeCountNodePages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively counts minterms of each node in the DAG.]
+
+  Description [Recursively counts minterms of each node in the DAG.
+  Similar to the cuddCountMintermAux which recursively counts the
+  number of minterms for the dag rooted at each node in terms of the
+  total number of variables (max). This procedure creates the node
+  data structure and stores the minterm count as part of the node
+  data structure. ]
+
+  SideEffects [Creates structures of type node quality and fills the st_table]
+
+  SeeAlso     [SubsetCountMinterm]
+
+******************************************************************************/
+static double
+SubsetCountMintermAux(
+  DdNode * node /* function to analyze */,
+  double  max /* number of minterms of constant 1 */,
+  st_table * table /* visitedTable table */)
+{
+
+    DdNode	*N,*Nv,*Nnv; /* nodes to store cofactors  */
+    double	min,*pmin; /* minterm count */
+    double	min1, min2; /* minterm count */
+    NodeData_t *dummy;
+    NodeData_t *newEntry;
+    int i;
+
+#ifdef DEBUG
+    num_calls++;
+#endif
+
+    /* Constant case */
+    if (Cudd_IsConstant(node)) {
+	if (node == zero) {
+	    return(0.0);
+	} else {
+	    return(max);
+	}
+    } else {
+
+	/* check if entry for this node exists */
+	if (st_lookup(table, node, &dummy)) {
+	    min = *(dummy->mintermPointer);
+	    return(min);
+	}
+
+	/* Make the node regular to extract cofactors */
+	N = Cudd_Regular(node);
+
+	/* store the cofactors */
+	Nv = Cudd_T(N);
+	Nnv = Cudd_E(N);
+	
+	Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+	Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+	min1 =  SubsetCountMintermAux(Nv, max,table)/2.0;
+	if (memOut) return(0.0);
+	min2 =  SubsetCountMintermAux(Nnv,max,table)/2.0;
+	if (memOut) return(0.0);
+	min = (min1+min2);
+
+	/* if page index is at the bottom, then create a new page */
+	if (pageIndex == pageSize) ResizeCountMintermPages();
+	if (memOut) {
+	    for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
+	    FREE(nodeDataPages);
+	    st_free_table(table);
+	    return(0.0);
+	}
+
+	/* point to the correct location in the page */
+	pmin = currentMintermPage+pageIndex;
+	pageIndex++;
+
+	/* store the minterm count of this node in the page */
+	*pmin = min;
+
+	/* Note I allocate the struct here. Freeing taken care of later */
+	if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages();
+	if (memOut) {
+	    for (i = 0; i <= page; i++) FREE(mintermPages[i]);
+	    FREE(mintermPages);
+	    st_free_table(table);
+	    return(0.0);
+	}
+
+	newEntry = currentNodeDataPage + nodeDataPageIndex;
+	nodeDataPageIndex++;
+
+	/* points to the correct location in the page */
+	newEntry->mintermPointer = pmin;
+	/* initialize this field of the Node Quality structure */
+	newEntry->nodesPointer = NULL;
+
+	/* insert entry for the node in the table */
+	if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) {
+	    memOut = 1;
+	    for (i = 0; i <= page; i++) FREE(mintermPages[i]);
+	    FREE(mintermPages);
+	    for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
+	    FREE(nodeDataPages);
+	    st_free_table(table);
+	    return(0.0);
+	}
+	return(min);
+    }
+
+} /* end of SubsetCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts minterms of each node in the DAG]
+
+  Description [Counts minterms of each node in the DAG. Similar to the
+  Cudd_CountMinterm procedure except this returns the minterm count for
+  all the nodes in the bdd in an st_table.]
+
+  SideEffects [none]
+
+  SeeAlso     [SubsetCountMintermAux]
+
+******************************************************************************/
+static st_table *
+SubsetCountMinterm(
+  DdNode * node /* function to be analyzed */,
+  int nvars /* number of variables node depends on */)
+{
+    st_table	*table;
+    int i;
+
+
+#ifdef DEBUG
+    num_calls = 0;
+#endif
+
+    max = pow(2.0,(double) nvars);
+    table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (table == NULL) goto OUT_OF_MEM;
+    maxPages = INITIAL_PAGES;
+    mintermPages = ALLOC(double *,maxPages);
+    if (mintermPages == NULL) {
+	st_free_table(table);
+	goto OUT_OF_MEM;
+    }
+    page = 0;
+    currentMintermPage = ALLOC(double,pageSize);
+    mintermPages[page] = currentMintermPage;
+    if (currentMintermPage == NULL) {
+	FREE(mintermPages);
+	st_free_table(table);
+	goto OUT_OF_MEM;
+    }
+    pageIndex = 0;
+    maxNodeDataPages = INITIAL_PAGES;
+    nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages);
+    if (nodeDataPages == NULL) {
+	for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
+	FREE(mintermPages);
+	st_free_table(table);
+	goto OUT_OF_MEM;
+    }
+    nodeDataPage = 0;
+    currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize);
+    nodeDataPages[nodeDataPage] = currentNodeDataPage;
+    if (currentNodeDataPage == NULL) {
+	for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
+	FREE(mintermPages);
+	FREE(nodeDataPages);
+	st_free_table(table);
+	goto OUT_OF_MEM;
+    }
+    nodeDataPageIndex = 0;
+
+    (void) SubsetCountMintermAux(node,max,table);
+    if (memOut) goto OUT_OF_MEM;
+    return(table);
+
+OUT_OF_MEM:
+    memOut = 1;
+    return(NULL);
+
+} /* end of SubsetCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively counts the number of nodes under the dag.
+  Also counts the number of nodes under the lighter child of
+  this node.]
+
+  Description [Recursively counts the number of nodes under the dag.
+  Also counts the number of nodes under the lighter child of
+  this node. . Note that the same dag may be the lighter child of two
+  different nodes and have different counts. As with the minterm counts,
+  the node counts are stored in pages to be space efficient and the
+  address for these node counts are stored in an st_table associated
+  to each node. ]
+
+  SideEffects [Updates the node data table with node counts]
+
+  SeeAlso     [SubsetCountNodes]
+
+******************************************************************************/
+static int
+SubsetCountNodesAux(
+  DdNode * node /* current node */,
+  st_table * table /* table to update node count, also serves as visited table. */,
+  double  max /* maximum number of variables */)
+{
+    int tval, eval, i;
+    DdNode *N, *Nv, *Nnv;
+    double minNv, minNnv;
+    NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar;
+    int *pmin, *pminBar, *val;
+
+    if ((node == NULL) || Cudd_IsConstant(node))
+	return(0);
+
+    /* if this node has been processed do nothing */
+    if (st_lookup(table, node, &dummyN) == 1) {
+	val = dummyN->nodesPointer;
+	if (val != NULL)
+	    return(0);
+    } else {
+	return(0);
+    }
+
+    N  = Cudd_Regular(node);
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+    
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* find the minterm counts for the THEN and ELSE branches */
+    if (Cudd_IsConstant(Nv)) {
+	if (Nv == zero) {
+	    minNv = 0.0;
+	} else {
+	    minNv = max;
+	}
+    } else {
+	if (st_lookup(table, Nv, &dummyNv) == 1)
+	    minNv = *(dummyNv->mintermPointer);
+	else {
+	    return(0);
+	}
+    }
+    if (Cudd_IsConstant(Nnv)) {
+	if (Nnv == zero) {
+	    minNnv = 0.0;
+	} else {
+	    minNnv = max;
+	}
+    } else {
+	if (st_lookup(table, Nnv, &dummyNnv) == 1) {
+	    minNnv = *(dummyNnv->mintermPointer);
+	}
+	else {
+	    return(0);
+	}
+    }
+
+
+    /* recur based on which has larger minterm, */
+    if (minNv >= minNnv) {
+	tval = SubsetCountNodesAux(Nv, table, max);
+	if (memOut) return(0);
+	eval = SubsetCountNodesAux(Nnv, table, max);
+	if (memOut) return(0);
+
+	/* store the node count of the lighter child. */
+	if (pageIndex == pageSize) ResizeCountNodePages();
+	if (memOut) {
+	    for (i = 0; i <= page; i++) FREE(mintermPages[i]);
+	    FREE(mintermPages);
+	    for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
+	    FREE(nodeDataPages);
+	    st_free_table(table);
+	    return(0);
+	}
+	pmin = currentLightNodePage + pageIndex;
+	*pmin = eval; /* Here the ELSE child is lighter */
+	dummyN->lightChildNodesPointer = pmin;
+
+    } else {
+	eval = SubsetCountNodesAux(Nnv, table, max);
+	if (memOut) return(0);
+	tval = SubsetCountNodesAux(Nv, table, max);
+	if (memOut) return(0);
+
+	/* store the node count of the lighter child. */
+	if (pageIndex == pageSize) ResizeCountNodePages();
+	if (memOut) {
+	    for (i = 0; i <= page; i++) FREE(mintermPages[i]);
+	    FREE(mintermPages);
+	    for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
+	    FREE(nodeDataPages);
+	    st_free_table(table);
+	    return(0);
+	}
+	pmin = currentLightNodePage + pageIndex;
+	*pmin = tval; /* Here the THEN child is lighter */
+	dummyN->lightChildNodesPointer = pmin;
+
+    }
+    /* updating the page index for node count storage. */
+    pmin = currentNodePage + pageIndex;
+    *pmin = tval + eval + 1;
+    dummyN->nodesPointer = pmin;
+
+    /* pageIndex is parallel page index for count_nodes and count_lightNodes */
+    pageIndex++;
+
+    /* if this node has been reached first, it belongs to a heavier
+       branch. Its complement will be reached later on a lighter branch.
+       Hence the complement has zero node count. */
+
+    if (st_lookup(table, Cudd_Not(node), &dummyNBar) == 1)  {
+	if (pageIndex == pageSize) ResizeCountNodePages();
+	if (memOut) {
+	    for (i = 0; i < page; i++) FREE(mintermPages[i]);
+	    FREE(mintermPages);
+	    for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
+	    FREE(nodeDataPages);
+	    st_free_table(table);
+	    return(0);
+	}
+	pminBar = currentLightNodePage + pageIndex;
+	*pminBar = 0;
+	dummyNBar->lightChildNodesPointer = pminBar;
+	/* The lighter child has less nodes than the parent.
+	 * So if parent 0 then lighter child zero
+	 */
+	if (pageIndex == pageSize) ResizeCountNodePages();
+	if (memOut) {
+	    for (i = 0; i < page; i++) FREE(mintermPages[i]);
+	    FREE(mintermPages);
+	    for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
+	    FREE(nodeDataPages);
+	    st_free_table(table);
+	    return(0);
+	}
+	pminBar = currentNodePage + pageIndex;
+	*pminBar = 0;
+	dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */
+
+	pageIndex++;
+    }
+    return(*pmin);
+} /*end of SubsetCountNodesAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the nodes under the current node and its lighter child]
+
+  Description [Counts the nodes under the current node and its lighter
+  child. Calls a recursive procedure to count the number of nodes of
+  a DAG rooted at a particular node and the number of nodes taken by its
+  lighter child.]
+
+  SideEffects [None]
+
+  SeeAlso     [SubsetCountNodesAux]
+
+******************************************************************************/
+static int
+SubsetCountNodes(
+  DdNode * node /* function to be analyzed */,
+  st_table * table /* node quality table */,
+  int  nvars /* number of variables node depends on */)
+{
+    int	num;
+    int i;
+
+#ifdef DEBUG
+    num_calls = 0;
+#endif
+
+    max = pow(2.0,(double) nvars);
+    maxPages = INITIAL_PAGES;
+    nodePages = ALLOC(int *,maxPages);
+    if (nodePages == NULL)  {
+	goto OUT_OF_MEM;
+    }
+
+    lightNodePages = ALLOC(int *,maxPages);
+    if (lightNodePages == NULL) {
+	for (i = 0; i <= page; i++) FREE(mintermPages[i]);
+	FREE(mintermPages);
+	for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
+	FREE(nodeDataPages);
+	FREE(nodePages);
+	goto OUT_OF_MEM;
+    }
+
+    page = 0;
+    currentNodePage = nodePages[page] = ALLOC(int,pageSize);
+    if (currentNodePage == NULL) {
+	for (i = 0; i <= page; i++) FREE(mintermPages[i]);
+	FREE(mintermPages);
+	for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
+	FREE(nodeDataPages);
+	FREE(lightNodePages);
+	FREE(nodePages);
+	goto OUT_OF_MEM;
+    }
+
+    currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
+    if (currentLightNodePage == NULL) {
+	for (i = 0; i <= page; i++) FREE(mintermPages[i]);
+	FREE(mintermPages);
+	for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
+	FREE(nodeDataPages);
+	FREE(currentNodePage);
+	FREE(lightNodePages);
+	FREE(nodePages);
+	goto OUT_OF_MEM;
+    }
+
+    pageIndex = 0;
+    num = SubsetCountNodesAux(node,table,max);
+    if (memOut) goto OUT_OF_MEM;
+    return(num);
+
+OUT_OF_MEM:
+    memOut = 1;
+    return(0);
+
+} /* end of SubsetCountNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Procedure to recursively store nodes that are retained in the subset.]
+
+  Description [rocedure to recursively store nodes that are retained in the subset.]
+
+  SideEffects [None]
+
+  SeeAlso     [StoreNodes]
+
+******************************************************************************/
+static void
+StoreNodes(
+  st_table * storeTable,
+  DdManager * dd,
+  DdNode * node)
+{
+    DdNode *N, *Nt, *Ne;
+    if (Cudd_IsConstant(dd)) {
+	return;
+    }
+    N = Cudd_Regular(node);
+    if (st_lookup(storeTable, (char *)N, NIL(char *))) {
+	return;
+    }
+    cuddRef(N);
+    if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) {
+	fprintf(dd->err,"Something wrong, st_table insert failed\n");
+    }
+
+    Nt = Cudd_T(N);
+    Ne = Cudd_E(N);
+
+    StoreNodes(storeTable, dd, Nt);
+    StoreNodes(storeTable, dd, Ne);
+    return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the subset BDD using the heavy branch method.] 
+
+  Description [The procedure carries out the building of the subset BDD
+  starting at the root. Using the three different counts labelling each node,
+  the procedure chooses the heavier branch starting from the root and keeps
+  track of the number of nodes it discards at each step, thus keeping count
+  of the size of the subset BDD dynamically. Once the threshold is satisfied,
+  the procedure then calls ITE to build the BDD.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+BuildSubsetBdd(
+  DdManager * dd /* DD manager */,
+  DdNode * node /* current node */,
+  int * size /* current size of the subset */,
+  st_table * visitedTable /* visited table storing all node data */,
+  int  threshold,
+  st_table * storeTable,
+  st_table * approxTable)
+{
+
+    DdNode *Nv, *Nnv, *N, *topv, *neW;
+    double minNv, minNnv;
+    NodeData_t *currNodeQual;
+    NodeData_t *currNodeQualT;
+    NodeData_t *currNodeQualE;
+    DdNode *ThenBranch, *ElseBranch;
+    unsigned int topid;
+    char *dummy;
+
+#ifdef DEBUG
+    num_calls++;
+#endif
+    /*If the size of the subset is below the threshold, dont do
+      anything. */
+    if ((*size) <= threshold) {
+      /* store nodes below this, so we can recombine if possible */
+      StoreNodes(storeTable, dd, node);
+      return(node);
+    }
+
+    if (Cudd_IsConstant(node))
+	return(node);
+
+    /* Look up minterm count for this node. */
+    if (!st_lookup(visitedTable, node, &currNodeQual)) {
+	fprintf(dd->err,
+		"Something is wrong, ought to be in node quality table\n");
+    }
+
+    /* Get children. */
+    N = Cudd_Regular(node);
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+
+    /* complement if necessary */
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    if (!Cudd_IsConstant(Nv)) {
+        /* find out minterms and nodes contributed by then child */
+        if (!st_lookup(visitedTable, Nv, &currNodeQualT)) {
+		fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
+		dd->errorCode = CUDD_INTERNAL_ERROR;
+		return(NULL);
+	    }
+	else {
+	    minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer);
+	}
+    } else {
+	if (Nv == zero) {
+	    minNv = 0;
+	} else  {
+	    minNv = max;
+	}
+    }
+    if (!Cudd_IsConstant(Nnv)) {
+        /* find out minterms and nodes contributed by else child */
+	if (!st_lookup(visitedTable, Nnv, &currNodeQualE)) {
+	    fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+	} else {
+	    minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer);
+	}
+    } else {
+	if (Nnv == zero) {
+	    minNnv = 0;
+	} else {
+	    minNnv = max;
+	}
+    }
+
+    /* keep track of size of subset by subtracting the number of
+     * differential nodes contributed by lighter child
+     */
+    *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer);
+    if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes
+			     the Then branch in case of a tie */
+
+        /* recur with the Then branch */
+	ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size,
+	      visitedTable, threshold, storeTable, approxTable);
+	if (ThenBranch == NULL) {
+	    return(NULL);
+	}
+	cuddRef(ThenBranch);
+	/* The Else branch is either a node that already exists in the
+	 * subset, or one whose approximation has been computed, or
+	 * Zero.
+	 */
+	if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), &dummy)) {
+	  ElseBranch = Nnv;
+	  cuddRef(ElseBranch);
+	} else {
+	  if (st_lookup(approxTable, (char *)Nnv, &dummy)) {
+	    ElseBranch = (DdNode *)dummy;
+	    cuddRef(ElseBranch);
+	  } else {
+	    ElseBranch = zero;
+	    cuddRef(ElseBranch);
+	  }
+	}
+	
+    }
+    else {
+        /* recur with the Else branch */
+        ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size,
+		      visitedTable, threshold, storeTable, approxTable);
+	if (ElseBranch == NULL) {
+	    return(NULL);
+	}
+	cuddRef(ElseBranch);
+	/* The Then branch is either a node that already exists in the
+	 * subset, or one whose approximation has been computed, or
+	 * Zero.
+	 */
+	if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), &dummy)) {
+	  ThenBranch = Nv;
+	  cuddRef(ThenBranch);
+	} else {
+	  if (st_lookup(approxTable, (char *)Nv, &dummy)) {
+	    ThenBranch = (DdNode *)dummy;
+	    cuddRef(ThenBranch);
+	  } else {
+	    ThenBranch = zero;
+	    cuddRef(ThenBranch);
+	  }
+	}
+    }
+
+    /* construct the Bdd with the top variable and the two children */
+    topid = Cudd_NodeReadIndex(N);
+    topv = Cudd_ReadVars(dd, topid);
+    cuddRef(topv);
+    neW =  cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
+    if (neW != NULL) {
+      cuddRef(neW);
+    }
+    Cudd_RecursiveDeref(dd, topv);
+    Cudd_RecursiveDeref(dd, ThenBranch);
+    Cudd_RecursiveDeref(dd, ElseBranch);
+
+      
+    if (neW == NULL)
+	return(NULL);
+    else {
+        /* store this node in the store table */
+        if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), &dummy)) {
+	  cuddRef(neW);
+	  st_insert(storeTable, (char *)Cudd_Regular(neW), NIL(char));
+        }
+	/* store the approximation for this node */
+	if (N !=  Cudd_Regular(neW)) {
+  	    if (st_lookup(approxTable, (char *)node, &dummy)) {
+	        fprintf(dd->err, "This node should not be in the approximated table\n");
+	    } else {
+	        cuddRef(neW);
+	        st_insert(approxTable, (char *)node, (char *)neW);
+	    }
+	}
+        cuddDeref(neW);
+        return(neW);
+    }
+} /* end of BuildSubsetBdd */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddSubsetSP.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddSubsetSP.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddSubsetSP.c	(revision 8)
@@ -0,0 +1,1655 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSubsetSP.c]
+
+  PackageName [cudd]
+
+  Synopsis [Procedure to subset the given BDD choosing the shortest paths
+            (largest cubes) in the BDD.]
+
+
+  Description  [External procedures included in this module:
+		<ul>
+		<li> Cudd_SubsetShortPaths()
+		<li> Cudd_SupersetShortPaths()
+		</ul>
+		Internal procedures included in this module:
+		<ul>
+		<li> cuddSubsetShortPaths()
+		</ul> 
+		Static procedures included in this module:
+		<ul>
+		<li> BuildSubsetBdd()
+		<li> CreatePathTable()
+		<li> AssessPathLength()
+		<li> CreateTopDist()
+		<li> CreateBotDist()
+		<li> ResizeNodeDistPages()
+		<li> ResizeQueuePages()
+		<li> stPathTableDdFree()
+		</ul>
+		]
+
+  SeeAlso     [cuddSubsetHB.c]
+
+  Author      [Kavita Ravi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DEFAULT_PAGE_SIZE 2048 /* page size to store the BFS queue element type */
+#define DEFAULT_NODE_DIST_PAGE_SIZE 2048 /*  page sizesto store NodeDist_t type */
+#define MAXSHORTINT    	((DdHalfWord) ~0) /* constant defined to store
+					   * maximum distance of a node
+					   * from the root or the
+					   * constant
+					   */
+#define INITIAL_PAGES 128 /* number of initial pages for the
+			   * queue/NodeDist_t type */
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* structure created to store subset results for each node and distances with 
+ * odd and even parity of the node from the root and sink. Main data structure
+ * in this procedure.
+ */
+struct NodeDist{
+    DdHalfWord oddTopDist;
+    DdHalfWord evenTopDist;
+    DdHalfWord oddBotDist;
+    DdHalfWord evenBotDist;
+    DdNode *regResult;
+    DdNode *compResult;
+};
+
+/* assorted information needed by the BuildSubsetBdd procedure. */
+struct AssortedInfo {
+    unsigned int maxpath;
+    int findShortestPath;
+    int thresholdReached;
+    st_table *maxpathTable;
+    int threshold;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct NodeDist NodeDist_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.32 2004/08/13 18:04:51 fabio Exp $";
+#endif
+
+#ifdef DD_DEBUG
+static int numCalls;
+static int hits;
+static int thishit;
+#endif
+
+
+static 	int 		memOut; /* flag to indicate out of memory */
+static  DdNode          *zero, *one; /* constant functions */
+
+static  NodeDist_t      **nodeDistPages; /* pointers to the pages */
+static	int		nodeDistPageIndex; /* index to next element */
+static	int		nodeDistPage; /* index to current page */
+static	int		nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE; /* page size */
+static	int		maxNodeDistPages; /* number of page pointers */
+static  NodeDist_t      *currentNodeDistPage; /* current page */
+
+static  DdNode          ***queuePages; /* pointers to the pages */
+static	int		queuePageIndex;	/* index to next element */
+static	int		queuePage; /* index to current page */
+static	int		queuePageSize = DEFAULT_PAGE_SIZE; /* page size */
+static	int		maxQueuePages; /* number of page pointers */
+static  DdNode          **currentQueuePage; /* current page */
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ResizeNodeDistPages (void);
+static void ResizeQueuePages (void);
+static void CreateTopDist (st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp);
+static int CreateBotDist (DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp);
+static st_table * CreatePathTable (DdNode *node, unsigned int *pathLengthArray, FILE *fp);
+static unsigned int AssessPathLength (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp);
+static DdNode * BuildSubsetBdd (DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable);
+static enum st_retval stPathTableDdFree (char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of Exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense subset from a BDD with the shortest paths
+  heuristic.]
+
+  Description [Extracts a dense subset from a BDD.  This procedure
+  tries to preserve the shortest paths of the input BDD, because they
+  give many minterms and contribute few nodes.  This procedure may
+  increase the number of nodes in trying to create the subset or
+  reduce the number of nodes due to recombination as compared to the
+  original BDD. Hence the threshold may not be strictly adhered to. In
+  practice, recombination overshadows the increase in the number of
+  nodes and results in small BDDs as compared to the threshold. The
+  hardlimit specifies whether threshold needs to be strictly adhered
+  to. If it is set to 1, the procedure ensures that result is never
+  larger than the specified limit but may be considerably less than
+  the threshold.  Returns a pointer to the BDD for the subset if
+  successful; NULL otherwise.  The value for numVars should be as
+  close as possible to the size of the support of f for better
+  efficiency. However, it is safe to pass the value returned by
+  Cudd_ReadSize for numVars. If 0 is passed, then the value returned
+  by Cudd_ReadSize is used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetShortPaths(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */,
+  int  hardlimit /* flag: 1 if threshold is a hard limit */)
+{
+    DdNode *subset;
+
+    memOut = 0;
+    do {
+	dd->reordered = 0;
+	subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit);
+    } while((dd->reordered ==1) && (!memOut));
+
+    return(subset);
+
+} /* end of Cudd_SubsetShortPaths */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a dense superset from a BDD with the shortest paths
+  heuristic.]
+
+  Description [Extracts a dense superset from a BDD.  The procedure is
+  identical to the subset procedure except for the fact that it
+  receives the complement of the given function. Extracting the subset
+  of the complement function is equivalent to extracting the superset
+  of the function.  This procedure tries to preserve the shortest
+  paths of the complement BDD, because they give many minterms and
+  contribute few nodes.  This procedure may increase the number of
+  nodes in trying to create the superset or reduce the number of nodes
+  due to recombination as compared to the original BDD. Hence the
+  threshold may not be strictly adhered to. In practice, recombination
+  overshadows the increase in the number of nodes and results in small
+  BDDs as compared to the threshold.  The hardlimit specifies whether
+  threshold needs to be strictly adhered to. If it is set to 1, the
+  procedure ensures that result is never larger than the specified
+  limit but may be considerably less than the threshold. Returns a
+  pointer to the BDD for the superset if successful; NULL
+  otherwise. The value for numVars should be as close as possible to
+  the size of the support of f for better efficiency.  However, it is
+  safe to pass the value returned by Cudd_ReadSize for numVar.  If 0
+  is passed, then the value returned by Cudd_ReadSize is used.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]
+
+******************************************************************************/
+DdNode *
+Cudd_SupersetShortPaths(
+  DdManager * dd /* manager */,
+  DdNode * f /* function to be superset */,
+  int  numVars /* number of variables in the support of f */,
+  int  threshold /* maximum number of nodes in the subset */,
+  int  hardlimit /* flag: 1 if threshold is a hard limit */)
+{
+    DdNode *subset, *g;
+
+    g = Cudd_Not(f);
+    memOut = 0;
+    do {
+	dd->reordered = 0;
+	subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit);
+    } while((dd->reordered ==1) && (!memOut));
+
+    return(Cudd_NotCond(subset, (subset != NULL)));
+
+} /* end of Cudd_SupersetShortPaths */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [The outermost procedure to return a subset of the given BDD
+  with the shortest path lengths.]
+
+  Description [The outermost procedure to return a subset of the given
+  BDD with the largest cubes. The path lengths are calculated, the maximum
+  allowable path length is determined and the number of nodes of this
+  path length that can be used to build a subset. If the threshold is
+  larger than the size of the original BDD, the original BDD is
+  returned. ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SubsetShortPaths]
+
+******************************************************************************/
+DdNode *
+cuddSubsetShortPaths(
+  DdManager * dd /* DD manager */,
+  DdNode * f /* function to be subset */,
+  int  numVars /* total number of variables in consideration */,
+  int  threshold /* maximum number of nodes allowed in the subset */,
+  int  hardlimit /* flag determining whether thershold should be respected strictly */)
+{
+    st_table *pathTable;
+    DdNode *N, *subset;
+
+    unsigned int  *pathLengthArray;
+    unsigned int maxpath, oddLen, evenLen, pathLength, *excess;
+    int i;
+    NodeDist_t 	*nodeStat;
+    struct AssortedInfo *info;
+    st_table *subsetNodeTable;
+
+    one = DD_ONE(dd);
+    zero = Cudd_Not(one);
+
+    if (numVars == 0) {
+      /* set default value */
+      numVars = Cudd_ReadSize(dd);
+    }
+    
+    if (threshold > numVars) {
+	threshold = threshold - numVars;
+    }
+    if (f == NULL) {
+	fprintf(dd->err, "Cannot partition, nil object\n");
+	dd->errorCode = CUDD_INVALID_ARG;
+	return(NULL);
+    }
+    if (Cudd_IsConstant(f))
+	return (f);
+
+    pathLengthArray = ALLOC(unsigned int, numVars+1);
+    for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0;
+
+
+#ifdef DD_DEBUG
+    numCalls = 0;
+#endif
+
+    pathTable = CreatePathTable(f, pathLengthArray, dd->err);
+
+    if ((pathTable == NULL) || (memOut)) {
+	if (pathTable != NULL)
+	    st_free_table(pathTable);
+	FREE(pathLengthArray);
+	return (NIL(DdNode));
+    }
+
+    excess = ALLOC(unsigned int, 1);
+    *excess = 0;
+    maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess,
+			       dd->err);
+
+    if (maxpath != (unsigned) (numVars + 1)) {
+
+	info = ALLOC(struct AssortedInfo, 1);
+	info->maxpath = maxpath;
+	info->findShortestPath = 0;
+	info->thresholdReached = *excess;
+	info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash);
+	info->threshold = threshold;
+
+#ifdef DD_DEBUG
+	(void) fprintf(dd->out, "Path length array\n");
+	for (i = 0; i < (numVars+1); i++) {
+	    if (pathLengthArray[i])
+		(void) fprintf(dd->out, "%d ",i);
+	}
+	(void) fprintf(dd->out, "\n");
+	for (i = 0; i < (numVars+1); i++) {
+	    if (pathLengthArray[i])
+		(void) fprintf(dd->out, "%d ",pathLengthArray[i]);
+	}
+	(void) fprintf(dd->out, "\n");
+	(void) fprintf(dd->out, "Maxpath  = %d, Thresholdreached = %d\n",
+		       maxpath, info->thresholdReached);
+#endif
+
+	N = Cudd_Regular(f);
+	if (!st_lookup(pathTable, N, &nodeStat)) {
+	    fprintf(dd->err, "Something wrong, root node must be in table\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+	} else {
+	    if ((nodeStat->oddTopDist != MAXSHORTINT) &&
+		(nodeStat->oddBotDist != MAXSHORTINT))
+		oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
+	    else
+		oddLen = MAXSHORTINT;
+
+	    if ((nodeStat->evenTopDist != MAXSHORTINT) &&
+		(nodeStat->evenBotDist != MAXSHORTINT))
+		evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
+	    else
+		evenLen = MAXSHORTINT;
+
+	    pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+	    if (pathLength > maxpath) {
+		(void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %d, %d\n", maxpath, pathLength);
+		dd->errorCode = CUDD_INTERNAL_ERROR;
+		return(NULL);
+	    }
+	}
+
+#ifdef DD_DEBUG
+	numCalls = 0;
+	hits = 0;
+	thishit = 0;
+#endif
+	/* initialize a table to store computed nodes */
+	if (hardlimit) {
+	    subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
+	} else {
+	    subsetNodeTable = NIL(st_table);
+	}
+	subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable);
+	if (subset != NULL) {
+	    cuddRef(subset);
+	}
+	/* record the number of times a computed result for a node is hit */
+
+#ifdef DD_DEBUG
+	(void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n",
+		hits, thishit, numCalls);
+#endif
+
+	if (subsetNodeTable != NIL(st_table)) {
+	    st_free_table(subsetNodeTable);
+	}
+	st_free_table(info->maxpathTable);
+	st_foreach(pathTable, stPathTableDdFree, (char *)dd);
+
+	FREE(info);
+
+    } else {/* if threshold larger than size of dd */
+	subset = f;
+	cuddRef(subset);
+    }
+    FREE(excess);
+    st_free_table(pathTable);
+    FREE(pathLengthArray);
+    for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
+    FREE(nodeDistPages);
+
+#ifdef DD_DEBUG
+    /* check containment of subset in f */
+    if (subset != NULL) {
+	DdNode *check;
+	check = Cudd_bddIteConstant(dd, subset, f, one);
+	if (check != one) {
+	    (void) fprintf(dd->err, "Wrong partition\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+	}
+    }
+#endif
+
+    if (subset != NULL) {
+	cuddDeref(subset);
+	return(subset);
+    } else {
+	return(NULL);
+    }
+
+} /* end of cuddSubsetShortPaths */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store the distances
+  related to each node.]
+
+  Description [Resize the number of pages allocated to store the distances
+  related to each node. The procedure  moves the counter to the
+  next page when the end of the page is reached and allocates new
+  pages when necessary. ]
+
+  SideEffects [Changes the size of  pages, page, page index, maximum 
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeNodeDistPages(void)
+{
+    int i;
+    NodeDist_t **newNodeDistPages;
+
+    /* move to next page */
+    nodeDistPage++;
+
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by 
+     * INITIAL_PAGES
+     */
+    if (nodeDistPage == maxNodeDistPages) {
+	newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES);
+	if (newNodeDistPages == NULL) {
+	    for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]);
+	    FREE(nodeDistPages);
+	    memOut = 1;
+	    return;
+	} else {
+	    for (i = 0; i < maxNodeDistPages; i++) {
+		newNodeDistPages[i] = nodeDistPages[i];
+	    }
+	    /* Increase total page count */
+	    maxNodeDistPages += INITIAL_PAGES;
+	    FREE(nodeDistPages);
+	    nodeDistPages = newNodeDistPages;
+	}
+    }
+    /* Allocate a new page */
+    currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t,
+							      nodeDistPageSize);
+    if (currentNodeDistPage == NULL) {
+	for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]);
+	FREE(nodeDistPages);
+	memOut = 1;
+	return;
+    }
+    /* reset page index */
+    nodeDistPageIndex = 0;
+    return;
+
+} /* end of ResizeNodeDistPages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resize the number of pages allocated to store nodes in the BFS 
+  traversal of the Bdd  .]
+
+  Description [Resize the number of pages allocated to store nodes in the BFS 
+  traversal of the Bdd. The procedure  moves the counter to the
+  next page when the end of the page is reached and allocates new
+  pages when necessary.]
+
+  SideEffects [Changes the size of pages, page, page index, maximum 
+  number of pages freeing stuff in case of memory out. ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ResizeQueuePages(void)
+{
+    int i;
+    DdNode ***newQueuePages;
+
+    queuePage++;
+    /* If the current page index is larger than the number of pages
+     * allocated, allocate a new page array. Page numbers are incremented by 
+     * INITIAL_PAGES
+     */
+    if (queuePage == maxQueuePages) {
+	newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES);
+	if (newQueuePages == NULL) {
+	    for (i = 0; i < queuePage; i++) FREE(queuePages[i]);
+	    FREE(queuePages);
+	    memOut = 1;
+	    return;
+	} else {
+	    for (i = 0; i < maxQueuePages; i++) {
+		newQueuePages[i] = queuePages[i];
+	    }
+	    /* Increase total page count */
+	    maxQueuePages += INITIAL_PAGES;
+	    FREE(queuePages);
+	    queuePages = newQueuePages;
+	}
+    }
+    /* Allocate a new page */
+    currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize);
+    if (currentQueuePage == NULL) {
+	for (i = 0; i < queuePage; i++) FREE(queuePages[i]);
+	FREE(queuePages);
+	memOut = 1;
+	return;
+    }
+    /* reset page index */
+    queuePageIndex = 0;
+    return;
+
+} /* end of ResizeQueuePages */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Labels each node with its shortest distance from the root]
+
+  Description [ Labels each node with its shortest distance from the root.
+  This is done in a BFS search of the BDD. The nodes are processed
+  in a queue implemented as pages(array) to reduce memory fragmentation.
+  An entry is created for each node visited. The distance from the root
+  to the node with the corresponding  parity is updated. The procedure
+  is called recursively each recusion level handling nodes at a given
+  level from the root.]
+
+
+  SideEffects [Creates entries in the pathTable]
+
+  SeeAlso     [CreatePathTable CreateBotDist]
+
+******************************************************************************/
+static void
+CreateTopDist(
+  st_table * pathTable /* hast table to store path lengths */,
+  int  parentPage /* the pointer to the page on which the first parent in the queue is to be found. */,
+  int  parentQueueIndex /* pointer to the first parent on the page */,
+  int  topLen /* current distance from the root */,
+  DdNode ** childPage /* pointer to the page on which the first child is to be added. */,
+  int  childQueueIndex /* pointer to the first child */,
+  int  numParents /* number of parents to process in this recursive call */,
+  FILE *fp /* where to write messages */)
+{
+    NodeDist_t *nodeStat;
+    DdNode *N, *Nv, *Nnv, *node, *child, *regChild;
+    int  i;
+    int processingDone, childrenCount;
+
+#ifdef DD_DEBUG
+    numCalls++;
+
+    /* assume this procedure comes in with only the root node*/
+    /* set queue index to the next available entry for addition */
+    /* set queue page to page of addition */
+    if ((queuePages[parentPage] == childPage) && (parentQueueIndex ==
+						  childQueueIndex)) {
+	fprintf(fp, "Should not happen that they are equal\n");
+    }
+    assert(queuePageIndex == childQueueIndex);
+    assert(currentQueuePage == childPage);
+#endif
+    /* number children added to queue is initialized , needed for
+     * numParents in the next call 
+     */
+    childrenCount = 0;
+    /* process all the nodes in this level */
+    while (numParents) {
+	numParents--;
+	if (parentQueueIndex == queuePageSize) {
+	    parentPage++;
+	    parentQueueIndex = 0;
+	}
+	/* a parent to process */
+	node = *(queuePages[parentPage] + parentQueueIndex);
+	parentQueueIndex++;
+	/* get its children */
+	N = Cudd_Regular(node);
+	Nv = Cudd_T(N);
+	Nnv = Cudd_E(N);
+
+	Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+	Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+	processingDone = 2;
+	while (processingDone) {
+	    /* processing the THEN and the ELSE children, the THEN
+	     * child first
+	     */
+	    if (processingDone == 2) {
+		child = Nv;
+	    } else {
+		child = Nnv;
+	    }
+
+	    regChild = Cudd_Regular(child);
+	    /* dont process if the child is a constant */
+	    if (!Cudd_IsConstant(child)) {
+		/* check is already visited, if not add a new entry in
+		 * the path Table
+		 */
+		if (!st_lookup(pathTable, regChild, &nodeStat)) {
+		    /* if not in table, has never been visited */
+		    /* create entry for table */
+		    if (nodeDistPageIndex == nodeDistPageSize)
+			ResizeNodeDistPages();
+		    if (memOut) {
+			for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
+			FREE(queuePages);
+			st_free_table(pathTable);
+			return;
+		    }
+		    /* New entry for child in path Table is created here */
+		    nodeStat = currentNodeDistPage + nodeDistPageIndex;
+		    nodeDistPageIndex++;
+
+		    /* Initialize fields of the node data */
+		    nodeStat->oddTopDist = MAXSHORTINT;
+		    nodeStat->evenTopDist = MAXSHORTINT;
+		    nodeStat->evenBotDist = MAXSHORTINT;
+		    nodeStat->oddBotDist = MAXSHORTINT;
+		    nodeStat->regResult = NULL;
+		    nodeStat->compResult = NULL;
+		    /* update the table entry element, the distance keeps
+		     * track of the parity of the path from the root
+		     */
+		    if (Cudd_IsComplement(child)) {
+			nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
+		    } else {
+			nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
+		    }
+
+		    /* insert entry element for  child in the table */
+		    if (st_insert(pathTable, (char *)regChild,
+				  (char *)nodeStat) == ST_OUT_OF_MEM) {
+			memOut = 1;
+			for (i = 0; i <= nodeDistPage; i++)
+			    FREE(nodeDistPages[i]);
+			FREE(nodeDistPages);
+			for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
+			FREE(queuePages);
+			st_free_table(pathTable);
+			return;
+		    }
+
+		    /* Create list element for this child to process its children.
+		     * If this node has been processed already, then it appears
+		     * in the path table and hence is never added to the list
+		     * again.
+		     */
+
+		    if (queuePageIndex == queuePageSize) ResizeQueuePages();
+		    if (memOut) {
+			for (i = 0; i <= nodeDistPage; i++)
+			    FREE(nodeDistPages[i]);
+			FREE(nodeDistPages);
+			st_free_table(pathTable);
+			return;
+		    }
+		    *(currentQueuePage + queuePageIndex) = child;
+		    queuePageIndex++;
+
+		    childrenCount++;
+		} else {
+		    /* if not been met in a path with this parity before */
+		    /* put in list */
+		    if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist ==
+			  MAXSHORTINT)) || ((!Cudd_IsComplement(child)) &&
+				  (nodeStat->evenTopDist == MAXSHORTINT))) {
+
+			if (queuePageIndex == queuePageSize) ResizeQueuePages();
+			if (memOut) {
+			    for (i = 0; i <= nodeDistPage; i++)
+				FREE(nodeDistPages[i]);
+			    FREE(nodeDistPages);
+			    st_free_table(pathTable);
+			    return;
+
+			}
+			*(currentQueuePage + queuePageIndex) = child;
+			queuePageIndex++;
+
+			/* update the distance with the appropriate parity */
+			if (Cudd_IsComplement(child)) {
+			    nodeStat->oddTopDist = (DdHalfWord) topLen + 1;
+			} else {
+			    nodeStat->evenTopDist = (DdHalfWord) topLen + 1;
+			}
+			childrenCount++;
+		    }
+
+		} /* end of else (not found in st_table) */
+	    } /*end of if Not constant child */
+	    processingDone--;
+	} /*end of while processing Nv, Nnv */
+    }  /*end of while numParents */
+
+#ifdef DD_DEBUG
+    assert(queuePages[parentPage] == childPage);
+    assert(parentQueueIndex == childQueueIndex);
+#endif
+
+    if (childrenCount != 0) {
+	topLen++;
+	childPage = currentQueuePage;
+	childQueueIndex = queuePageIndex;
+	CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen,
+		      childPage, childQueueIndex, childrenCount, fp);
+    }
+
+    return;
+
+} /* end of CreateTopDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Labels each node with the shortest distance from the constant.]
+
+  Description [Labels each node with the shortest distance from the constant.
+  This is done in a DFS search of the BDD. Each node has an odd
+  and even parity distance from the sink (since there exists paths to both
+  zero and one) which is less than MAXSHORTINT. At each node these distances
+  are updated using the minimum distance of its children from the constant.
+  SInce now both the length from the root and child is known, the minimum path
+  length(length of the shortest path between the root and the constant that
+  this node lies on) of this node can be calculated and used to update the
+  pathLengthArray]
+
+  SideEffects [Updates Path Table and path length array]
+
+  SeeAlso     [CreatePathTable CreateTopDist AssessPathLength]
+
+******************************************************************************/
+static int
+CreateBotDist(
+  DdNode * node /* current node */,
+  st_table * pathTable /* path table with path lengths */,
+  unsigned int * pathLengthArray /* array that stores number of nodes belonging to a particular path length. */,
+  FILE *fp /* where to write messages */)
+{
+    DdNode *N, *Nv, *Nnv;
+    DdNode *realChild;
+    DdNode *child, *regChild;
+    NodeDist_t *nodeStat, *nodeStatChild;
+    unsigned int  oddLen, evenLen, pathLength;
+    DdHalfWord botDist;
+    int processingDone;
+
+    if (Cudd_IsConstant(node))
+	return(1);
+    N = Cudd_Regular(node);
+    /* each node has one table entry */
+    /* update as you go down the min dist of each node from
+       the root in each (odd and even) parity */
+    if (!st_lookup(pathTable, N, &nodeStat)) {
+	fprintf(fp, "Something wrong, the entry doesn't exist\n");
+	return(0);
+    }
+
+    /* compute length of odd parity distances */
+    if ((nodeStat->oddTopDist != MAXSHORTINT) &&
+	(nodeStat->oddBotDist != MAXSHORTINT))
+	oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
+    else
+	oddLen = MAXSHORTINT;
+
+    /* compute length of even parity distances */
+    if (!((nodeStat->evenTopDist == MAXSHORTINT) ||
+	  (nodeStat->evenBotDist == MAXSHORTINT)))
+	evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
+    else
+	evenLen = MAXSHORTINT;
+
+    /* assign pathlength to minimum of the two */
+    pathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+
+    /* process each child */
+    processingDone = 0;
+    while (processingDone != 2) {
+	if (!processingDone) {
+	    child = Nv;
+	} else {
+	    child = Nnv;
+	}
+
+	realChild = Cudd_NotCond(child, Cudd_IsComplement(node));
+	regChild = Cudd_Regular(child);
+	if (Cudd_IsConstant(realChild)) {
+	    /* Found a minterm; count parity and shortest distance
+	    ** from the constant.
+	    */
+	    if (Cudd_IsComplement(child))
+		nodeStat->oddBotDist = 1;
+	    else
+		nodeStat->evenBotDist = 1;
+	} else { 
+	    /* If node not in table, recur. */
+	    if (!st_lookup(pathTable, regChild, &nodeStatChild)) {
+		fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n");
+		return(0);
+	    }
+
+	    if (nodeStatChild->oddBotDist == MAXSHORTINT) {
+		if (nodeStatChild->evenBotDist == MAXSHORTINT) {
+		    if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp))
+			return(0);
+		} else {
+		    fprintf(fp, "Something wrong, both bot nodeStats should be there\n");
+		    return(0);
+		}
+	    }
+
+	    /* Update shortest distance from the constant depending on
+	    **  parity. */
+
+	    if (Cudd_IsComplement(child)) {
+		/* If parity on the edge then add 1 to even distance
+		** of child to get odd parity distance and add 1 to
+		** odd distance of child to get even parity
+		** distance. Change distance of current node only if
+		** the calculated distance is less than existing
+		** distance. */
+		if (nodeStatChild->oddBotDist != MAXSHORTINT)
+		    botDist = nodeStatChild->oddBotDist + 1;
+		else
+		    botDist = MAXSHORTINT;
+		if (nodeStat->evenBotDist > botDist )
+		    nodeStat->evenBotDist = botDist;
+
+		if (nodeStatChild->evenBotDist != MAXSHORTINT)
+		    botDist = nodeStatChild->evenBotDist + 1;
+		else
+		    botDist = MAXSHORTINT;
+		if (nodeStat->oddBotDist > botDist)
+		    nodeStat->oddBotDist = botDist;
+
+	    } else {
+		/* If parity on the edge then add 1 to even distance
+		** of child to get even parity distance and add 1 to
+		** odd distance of child to get odd parity distance.
+		** Change distance of current node only if the
+		** calculated distance is lesser than existing
+		** distance. */
+		if (nodeStatChild->evenBotDist != MAXSHORTINT)
+		    botDist = nodeStatChild->evenBotDist + 1;
+		else
+		    botDist = MAXSHORTINT;
+		if (nodeStat->evenBotDist > botDist)
+		    nodeStat->evenBotDist = botDist;
+
+		if (nodeStatChild->oddBotDist != MAXSHORTINT)
+		    botDist = nodeStatChild->oddBotDist + 1;
+		else
+		    botDist = MAXSHORTINT;
+		if (nodeStat->oddBotDist > botDist)
+		    nodeStat->oddBotDist = botDist;
+	    }
+	} /* end of else (if not constant child ) */
+	processingDone++;
+    } /* end of while processing Nv, Nnv */
+
+    /* Compute shortest path length on the fly. */
+    if ((nodeStat->oddTopDist != MAXSHORTINT) &&
+	(nodeStat->oddBotDist != MAXSHORTINT))
+	oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist);
+    else
+	oddLen = MAXSHORTINT;
+
+    if ((nodeStat->evenTopDist != MAXSHORTINT) &&
+	(nodeStat->evenBotDist != MAXSHORTINT))
+	evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist);
+    else
+	evenLen = MAXSHORTINT;
+
+    /* Update path length array that has number of nodes of a particular
+    ** path length. */
+    if (oddLen < pathLength ) {
+	if (pathLength != MAXSHORTINT)
+	    pathLengthArray[pathLength]--;
+	if (oddLen != MAXSHORTINT)
+	    pathLengthArray[oddLen]++;
+	pathLength = oddLen;
+    }
+    if (evenLen < pathLength ) {
+	if (pathLength != MAXSHORTINT)
+	    pathLengthArray[pathLength]--;
+	if (evenLen != MAXSHORTINT)
+	    pathLengthArray[evenLen]++;
+    }
+
+    return(1);
+
+} /*end of CreateBotDist */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ The outer procedure to label each node with its shortest
+  distance from the root and constant]
+
+  Description [ The outer procedure to label each node with its shortest
+  distance from the root and constant. Calls CreateTopDist and CreateBotDist.
+  The basis for computing the distance between root and constant is that
+  the distance may be the sum of even distances from the node to the root
+  and constant or the sum of odd distances from the node to the root and
+  constant.  Both CreateTopDist and CreateBotDist create the odd and
+  even parity distances from the root and constant respectively.]
+
+  SideEffects [None]
+
+  SeeAlso     [CreateTopDist CreateBotDist]
+
+******************************************************************************/
+static st_table *
+CreatePathTable(
+  DdNode * node /* root of function */,
+  unsigned int * pathLengthArray /* array of path lengths to store nodes labeled with the various path lengths */,
+  FILE *fp /* where to write messages */)
+{
+
+    st_table *pathTable;
+    NodeDist_t *nodeStat;
+    DdHalfWord topLen;
+    DdNode *N;
+    int i, numParents;
+    int insertValue;
+    DdNode **childPage;
+    int parentPage;
+    int childQueueIndex, parentQueueIndex;
+
+    /* Creating path Table for storing data about nodes */
+    pathTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+    /* initializing pages for info about each node */
+    maxNodeDistPages = INITIAL_PAGES;
+    nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages);
+    if (nodeDistPages == NULL) {
+	goto OUT_OF_MEM;
+    }
+    nodeDistPage = 0;
+    currentNodeDistPage = nodeDistPages[nodeDistPage] =
+	ALLOC(NodeDist_t, nodeDistPageSize);
+    if (currentNodeDistPage == NULL) {
+	for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
+	FREE(nodeDistPages);
+	goto OUT_OF_MEM;
+    }
+    nodeDistPageIndex = 0;
+
+    /* Initializing pages for the BFS search queue, implemented as an array. */
+    maxQueuePages = INITIAL_PAGES;
+    queuePages = ALLOC(DdNode **, maxQueuePages);
+    if (queuePages == NULL) {
+	goto OUT_OF_MEM;
+    }
+    queuePage = 0;
+    currentQueuePage  = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize);
+    if (currentQueuePage == NULL) {
+	for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
+	FREE(queuePages);
+	goto OUT_OF_MEM;
+    }
+    queuePageIndex = 0;
+
+    /* Enter the root node into the queue to start with. */
+    parentPage = queuePage;
+    parentQueueIndex = queuePageIndex;
+    topLen = 0;
+    *(currentQueuePage + queuePageIndex) = node;
+    queuePageIndex++;
+    childPage = currentQueuePage;
+    childQueueIndex = queuePageIndex;
+
+    N = Cudd_Regular(node);
+
+    if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages();
+    if (memOut) {
+	for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
+	FREE(nodeDistPages);
+	for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
+	FREE(queuePages);
+	st_free_table(pathTable);
+	goto OUT_OF_MEM;
+    }
+
+    nodeStat = currentNodeDistPage + nodeDistPageIndex;
+    nodeDistPageIndex++;
+
+    nodeStat->oddTopDist = MAXSHORTINT;
+    nodeStat->evenTopDist = MAXSHORTINT;
+    nodeStat->evenBotDist = MAXSHORTINT;
+    nodeStat->oddBotDist = MAXSHORTINT;
+    nodeStat->regResult = NULL;
+    nodeStat->compResult = NULL;
+
+    insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat);
+    if (insertValue == ST_OUT_OF_MEM) {
+	memOut = 1;
+	for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]);
+	FREE(nodeDistPages);
+	for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
+	FREE(queuePages);
+	st_free_table(pathTable);
+	goto OUT_OF_MEM;
+    } else if (insertValue == 1) {
+	fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n");
+	return(NULL);
+    }
+
+    if (Cudd_IsComplement(node)) {
+	nodeStat->oddTopDist = 0;
+    } else {
+	nodeStat->evenTopDist = 0;
+    }
+    numParents = 1;
+    /* call the function that counts the distance of each node from the
+     * root
+     */
+#ifdef DD_DEBUG
+    numCalls = 0;
+#endif
+    CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen,
+		  childPage, childQueueIndex, numParents, fp);
+    if (memOut) {
+	fprintf(fp, "Out of Memory and cant count path lengths\n");
+	goto OUT_OF_MEM;
+    }
+
+#ifdef DD_DEBUG
+    numCalls = 0;
+#endif
+    /* call the function that counts the distance of each node from the
+     * constant
+     */
+    if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL);
+
+    /* free BFS queue pages as no longer required */
+    for (i = 0; i <= queuePage; i++) FREE(queuePages[i]);
+    FREE(queuePages);
+    return(pathTable);
+
+OUT_OF_MEM:
+    (void) fprintf(fp, "Out of Memory, cannot allocate pages\n");
+    memOut = 1;
+    return(NULL);
+
+} /*end of CreatePathTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Chooses the maximum allowable path length of nodes under the
+  threshold.]
+
+  Description [Chooses the maximum allowable path length under each node.
+  The corner cases are when the threshold is larger than the number
+  of nodes in the BDD iself, in which case 'numVars + 1' is returned.
+  If all nodes of a particular path length are needed, then the
+  maxpath returned is the next one with excess nodes = 0;]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static unsigned int
+AssessPathLength(
+  unsigned int * pathLengthArray /* array determining number of nodes belonging to the different path lengths */,
+  int  threshold /* threshold to determine maximum allowable nodes in the subset */,
+  int  numVars /* maximum number of variables */,
+  unsigned int * excess /* number of nodes labeled maxpath required in the subset */,
+  FILE *fp /* where to write messages */)
+{
+    unsigned int i, maxpath;
+    int temp;
+
+    temp = threshold;
+    i = 0;
+    maxpath = 0;
+    /* quit loop if i reaches max number of variables or if temp reaches
+     * below zero
+     */
+    while ((i < (unsigned) numVars+1) && (temp > 0)) {
+	if (pathLengthArray[i] > 0) {
+	    maxpath = i;
+	    temp = temp - pathLengthArray[i];
+	}
+	i++;
+    }
+    /* if all nodes of max path are needed */
+    if (temp >= 0) {
+	maxpath++; /* now maxpath  becomes the next maxppath or max number
+		      of variables */
+	*excess = 0;
+    } else { /* normal case when subset required is less than size of
+		original BDD */
+	*excess = temp + pathLengthArray[maxpath];
+    }
+
+    if (maxpath == 0) {
+	fprintf(fp, "Path Length array seems to be all zeroes, check\n");
+    }
+    return(maxpath);
+
+} /* end of AssessPathLength */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the BDD with nodes labeled with path length less than or equal to maxpath]
+
+  Description [Builds the BDD with nodes labeled with path length
+  under maxpath and as many nodes labeled maxpath as determined by the
+  threshold. The procedure uses the path table to determine which nodes
+  in the original bdd need to be retained. This procedure picks a
+  shortest path (tie break decided by taking the child with the shortest
+  distance to the constant) and recurs down the path till it reaches the
+  constant. the procedure then starts building the subset upward from
+  the constant. All nodes labeled by path lengths less than the given
+  maxpath are used to build the subset.  However, in the case of nodes
+  that have label equal to maxpath, as many are chosen as required by
+  the threshold. This number is stored in the info structure in the
+  field thresholdReached. This field is decremented whenever a node
+  labeled maxpath is encountered and the nodes labeled maxpath are
+  aggregated in a maxpath table. As soon as the thresholdReached count
+  goes to 0, the shortest path from this node to the constant is found.
+  The extraction of nodes with the above labeling is based on the fact
+  that each node, labeled with a path length, P, has at least one child
+  labeled P or less. So extracting all nodes labeled a given path length
+  P ensures complete paths between the root and the constant. Extraction
+  of a partial number of nodes with a given path length may result in
+  incomplete paths and hence the additional number of nodes are grabbed
+  to complete the path. Since the Bdd is built bottom-up, other nodes
+  labeled maxpath do lie on complete paths.  The procedure may cause the
+  subset to have a larger or smaller number of nodes than the specified
+  threshold. The increase in the number of nodes is caused by the
+  building of a subset and the reduction by recombination. However in
+  most cases, the recombination overshadows the increase and the
+  procedure returns a result with lower number of nodes than specified.
+  The subsetNodeTable is NIL when there is no hard limit on the number
+  of nodes. Further efforts towards keeping the subset closer to the
+  threshold number were abandoned in favour of keeping the procedure
+  simple and fast.]
+
+  SideEffects [SubsetNodeTable is changed if it is not NIL.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+BuildSubsetBdd(
+  DdManager * dd /* DD manager */,
+  st_table * pathTable /* path table with path lengths and computed results */,
+  DdNode * node /* current node */,
+  struct AssortedInfo * info /* assorted information structure */,
+  st_table * subsetNodeTable /* table storing computed results */)
+{
+    DdNode *N, *Nv, *Nnv;
+    DdNode *ThenBranch, *ElseBranch, *childBranch;
+    DdNode *child, *regChild, *regNnv, *regNv;
+    NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv;
+    DdNode *neW, *topv, *regNew;
+    char *entry;
+    unsigned int topid;
+    unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength;
+    unsigned int NvBotDist, NnvBotDist;
+    int tiebreakChild;
+    int  processingDone, thenDone, elseDone;
+
+
+#ifdef DD_DEBUG
+    numCalls++;
+#endif
+    if (Cudd_IsConstant(node))
+	return(node);
+
+    N = Cudd_Regular(node);
+    /* Find node in table. */
+    if (!st_lookup(pathTable, N, &nodeStat)) {
+	(void) fprintf(dd->err, "Something wrong, node must be in table \n");
+	dd->errorCode = CUDD_INTERNAL_ERROR;
+	return(NULL);
+    }
+    /* If the node in the table has been visited, then return the corresponding
+    ** Dd. Since a node can become a subset of itself, its
+    ** complement (that is te same node reached by a different parity) will
+    ** become a superset of the original node and result in some minterms
+    ** that were not in the original set. Hence two different results are
+    ** maintained, corresponding to the odd and even parities.
+    */
+
+    /* If this node is reached with an odd parity, get odd parity results. */
+    if (Cudd_IsComplement(node)) {
+	if  (nodeStat->compResult != NULL) {
+#ifdef DD_DEBUG
+	    hits++;
+#endif
+	    return(nodeStat->compResult);
+	}
+    } else {
+	/* if this node is reached with an even parity, get even parity
+	 * results
+	 */
+	if (nodeStat->regResult != NULL) {
+#ifdef DD_DEBUG
+	    hits++;
+#endif
+	    return(nodeStat->regResult);
+	}
+    }
+
+
+    /* get children */
+    Nv = Cudd_T(N);
+    Nnv = Cudd_E(N);
+
+    Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
+    Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
+
+    /* no child processed */
+    processingDone = 0;
+    /* then child not processed */
+    thenDone = 0;
+    ThenBranch = NULL;
+    /* else child not processed */
+    elseDone = 0;
+    ElseBranch = NULL;
+    /* if then child constant, branch is the child */
+    if (Cudd_IsConstant(Nv)) {
+	/*shortest path found */
+	if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) {
+	    info->findShortestPath = 0;
+	}
+
+	ThenBranch = Nv;
+	cuddRef(ThenBranch);
+	if (ThenBranch == NULL) {
+	    return(NULL);
+	}
+
+	thenDone++;
+	processingDone++;
+	NvBotDist = MAXSHORTINT;
+    } else {
+	/* Derive regular child for table lookup. */
+	regNv = Cudd_Regular(Nv);
+	/* Get node data for shortest path length. */
+	if (!st_lookup(pathTable, regNv, &nodeStatNv) ) {
+	    (void) fprintf(dd->err, "Something wrong, node must be in table\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+	}
+	/* Derive shortest path length for child. */
+	if ((nodeStatNv->oddTopDist != MAXSHORTINT) &&
+	    (nodeStatNv->oddBotDist != MAXSHORTINT)) {
+	    oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist);
+	} else {
+	    oddLen = MAXSHORTINT;
+	}
+
+	if ((nodeStatNv->evenTopDist != MAXSHORTINT) &&
+	    (nodeStatNv->evenBotDist != MAXSHORTINT)) {
+	    evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist);
+	} else {
+	    evenLen = MAXSHORTINT;
+	}
+
+	NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+	NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist:
+	                                           nodeStatNv->evenBotDist;
+    }
+    /* if else child constant, branch is the child */
+    if (Cudd_IsConstant(Nnv)) {
+	/*shortest path found */
+	if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) {
+	    info->findShortestPath = 0;
+	}
+
+	ElseBranch = Nnv;
+	cuddRef(ElseBranch);
+	if (ElseBranch == NULL) {
+	    return(NULL);
+	}
+
+	elseDone++;
+	processingDone++;
+	NnvBotDist = MAXSHORTINT;
+    } else {
+	/* Derive regular child for table lookup. */
+	regNnv = Cudd_Regular(Nnv);
+	/* Get node data for shortest path length. */
+	if (!st_lookup(pathTable, regNnv, &nodeStatNnv) ) {
+	    (void) fprintf(dd->err, "Something wrong, node must be in table\n");
+	    dd->errorCode = CUDD_INTERNAL_ERROR;
+	    return(NULL);
+	}
+	/* Derive shortest path length for child. */
+	if ((nodeStatNnv->oddTopDist != MAXSHORTINT) &&
+	    (nodeStatNnv->oddBotDist != MAXSHORTINT)) {
+	    oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist);
+	} else {
+	    oddLen = MAXSHORTINT;
+	}
+
+	if ((nodeStatNnv->evenTopDist != MAXSHORTINT) &&
+	    (nodeStatNnv->evenBotDist != MAXSHORTINT)) {
+	    evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist);
+	} else {
+	    evenLen = MAXSHORTINT;
+	}
+
+	NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen;
+	NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist :
+	                                           nodeStatNnv->evenBotDist;
+    }
+
+    tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0;
+    /* while both children not processed */
+    while (processingDone != 2) {
+	if (!processingDone) {
+	    /* if no child processed */
+	    /* pick the child with shortest path length and record which one
+	     * picked
+	     */
+	    if ((NvPathLength < NnvPathLength) ||
+		((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) {
+		child = Nv;
+		regChild = regNv;
+		thenDone = 1;
+		childPathLength = NvPathLength;
+	    } else {
+		child = Nnv;
+		regChild = regNnv;
+		elseDone = 1;
+		childPathLength = NnvPathLength;
+	    } /* then path length less than else path length */
+	} else {
+	    /* if one child processed, process the other */
+	    if (thenDone) {
+		child = Nnv;
+		regChild = regNnv;
+		elseDone = 1;
+		childPathLength = NnvPathLength;
+	    } else {
+		child = Nv;
+		regChild = regNv;
+		thenDone = 1;
+		childPathLength = NvPathLength;
+	    } /* end of else pick the Then child if ELSE child processed */
+	} /* end of else one child has been processed */
+
+	/* ignore (replace with constant 0) all nodes which lie on paths larger
+	 * than the maximum length of the path required
+	 */
+	if (childPathLength > info->maxpath) {
+	    /* record nodes visited */
+	    childBranch = zero;
+	} else {
+	    if (childPathLength < info->maxpath) {
+		if (info->findShortestPath) {
+		    info->findShortestPath = 0;
+		}
+		childBranch = BuildSubsetBdd(dd, pathTable, child, info,
+					     subsetNodeTable);
+
+	    } else { /* Case: path length of node = maxpath */
+		/* If the node labeled with maxpath is found in the
+		** maxpathTable, use it to build the subset BDD.  */
+		if (st_lookup(info->maxpathTable, (char *)regChild,
+			      (char **)&entry)) {
+		    /* When a node that is already been chosen is hit,
+		    ** the quest for a complete path is over.  */
+		    if (info->findShortestPath) {
+			info->findShortestPath = 0;
+		    }
+		    childBranch = BuildSubsetBdd(dd, pathTable, child, info,
+						 subsetNodeTable);
+		} else {
+		    /* If node is not found in the maxpathTable and
+		    ** the threshold has been reached, then if the
+		    ** path needs to be completed, continue. Else
+		    ** replace the node with a zero.  */
+		    if (info->thresholdReached <= 0) {
+			if (info->findShortestPath) {
+			    if (st_insert(info->maxpathTable, (char *)regChild,
+					  (char *)NIL(char)) == ST_OUT_OF_MEM) {
+				memOut = 1;
+				(void) fprintf(dd->err, "OUT of memory\n");
+				info->thresholdReached = 0;
+				childBranch = zero;
+			    } else {
+				info->thresholdReached--;
+				childBranch = BuildSubsetBdd(dd, pathTable,
+						    child, info,subsetNodeTable);
+			    }
+			} else { /* not find shortest path, we dont need this
+				    node */
+			    childBranch = zero;
+			}
+		    } else { /* Threshold hasn't been reached,
+			     ** need the node. */
+			if (st_insert(info->maxpathTable, (char *)regChild,
+				      (char *)NIL(char)) == ST_OUT_OF_MEM) {
+			    memOut = 1;
+			    (void) fprintf(dd->err, "OUT of memory\n");
+			    info->thresholdReached = 0;
+			    childBranch = zero;
+			} else {
+			    info->thresholdReached--;
+			    if (info->thresholdReached <= 0) {
+				info->findShortestPath = 1;
+			    }
+			    childBranch = BuildSubsetBdd(dd, pathTable,
+						 child, info, subsetNodeTable);
+
+			} /* end of st_insert successful */
+		    } /* end of threshold hasnt been reached yet */
+		} /* end of else node not found in maxpath table */
+	    } /* end of if (path length of node = maxpath) */
+	} /* end if !(childPathLength > maxpath) */
+	if (childBranch == NULL) {
+	    /* deref other stuff incase reordering has taken place */
+	    if (ThenBranch != NULL) {
+		Cudd_RecursiveDeref(dd, ThenBranch);
+		ThenBranch = NULL;
+	    }
+	    if (ElseBranch != NULL) {
+		Cudd_RecursiveDeref(dd, ElseBranch);
+		ElseBranch = NULL;
+	    }
+	    return(NULL);
+	}
+
+	cuddRef(childBranch);
+
+	if (child == Nv) {
+	    ThenBranch = childBranch;
+	} else {
+	    ElseBranch = childBranch;
+	}
+	processingDone++;
+
+    } /*end of while processing Nv, Nnv */  	
+
+    info->findShortestPath = 0;
+    topid = Cudd_NodeReadIndex(N);
+    topv = Cudd_ReadVars(dd, topid);
+    cuddRef(topv);
+    neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
+    if (neW != NULL) {
+	cuddRef(neW);
+    }
+    Cudd_RecursiveDeref(dd, topv);
+    Cudd_RecursiveDeref(dd, ThenBranch);
+    Cudd_RecursiveDeref(dd, ElseBranch);
+
+
+    /* Hard Limit of threshold has been imposed */
+    if (subsetNodeTable != NIL(st_table)) {
+	/* check if a new node is created */
+	regNew = Cudd_Regular(neW);
+	/* subset node table keeps all new nodes that have been created to keep
+	 * a running count of how many nodes have been built in the subset.
+	 */
+	if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) {
+	    if (!Cudd_IsConstant(regNew)) {
+		if (st_insert(subsetNodeTable, (char *)regNew,
+			      (char *)NULL) == ST_OUT_OF_MEM) {
+		    (void) fprintf(dd->err, "Out of memory\n");
+		    return (NULL);
+		}
+		if (st_count(subsetNodeTable) > info->threshold) {
+		    info->thresholdReached = 0;
+		}
+	    }
+	}
+    }
+
+
+    if (neW == NULL) {
+	return(NULL);
+    } else {
+	/*store computed result in regular form*/
+	if (Cudd_IsComplement(node)) {
+	    nodeStat->compResult = neW;
+	    cuddRef(nodeStat->compResult);
+	    /* if the new node is the same as the corresponding node in the
+	     * original bdd then its complement need not be computed as it
+	     * cannot be larger than the node itself
+	     */
+	    if (neW == node) {
+#ifdef DD_DEBUG
+		thishit++;
+#endif
+		/* if a result for the node has already been computed, then
+		 * it can only be smaller than teh node itself. hence store
+		 * the node result in order not to break recombination
+		 */
+		if (nodeStat->regResult != NULL) {
+		    Cudd_RecursiveDeref(dd, nodeStat->regResult);
+		}
+		nodeStat->regResult = Cudd_Not(neW);
+		cuddRef(nodeStat->regResult);
+	    }
+
+	} else {
+	    nodeStat->regResult = neW;
+	    cuddRef(nodeStat->regResult);
+	    if (neW == node) {
+#ifdef DD_DEBUG
+		thishit++;
+#endif
+		if (nodeStat->compResult != NULL) {
+		    Cudd_RecursiveDeref(dd, nodeStat->compResult);
+		}
+		nodeStat->compResult = Cudd_Not(neW);
+		cuddRef(nodeStat->compResult);
+	    }
+	} 
+
+	cuddDeref(neW);
+	return(neW);
+    } /* end of else i.e. Subset != NULL */
+} /* end of BuildSubsetBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis     [Procedure to free te result dds stored in the NodeDist pages.]
+
+  Description [None]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static enum st_retval
+stPathTableDdFree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    NodeDist_t *nodeStat;
+    DdManager *dd;
+
+    nodeStat = (NodeDist_t *)value;
+    dd = (DdManager *)arg;
+    if (nodeStat->regResult != NULL) {
+	Cudd_RecursiveDeref(dd, nodeStat->regResult);
+    }
+    if (nodeStat->compResult != NULL) {
+	Cudd_RecursiveDeref(dd, nodeStat->compResult);
+    }
+    return(ST_CONTINUE);
+
+} /* end of stPathTableFree */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddSymmetry.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddSymmetry.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddSymmetry.c	(revision 8)
@@ -0,0 +1,1695 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddSymmetry.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for symmetry-based variable reordering.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_SymmProfile()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddSymmCheck()
+		<li> cuddSymmSifting()
+		<li> cuddSymmSiftingConv()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddSymmUniqueCompare()
+		<li> ddSymmSiftingAux()
+		<li> ddSymmSiftingConvAux()
+		<li> ddSymmSiftingUp()
+		<li> ddSymmSiftingDown()
+		<li> ddSymmGroupMove()
+		<li> ddSymmGroupMoveBackward()
+		<li> ddSymmSiftingBackward()
+		<li> ddSymmSummary()
+		</ul>]
+
+  Author      [Shipra Panda, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define MV_OOM (Move *)1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.25 2004/08/13 18:04:51 fabio Exp $";
+#endif
+
+static	int	*entry;
+
+extern  int	ddTotalNumberSwapping;
+#ifdef DD_STATS
+extern	int	ddTotalNISwaps;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddSymmUniqueCompare (int *ptrX, int *ptrY);
+static int ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static int ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * ddSymmSiftingUp (DdManager *table, int y, int xLow);
+static Move * ddSymmSiftingDown (DdManager *table, int x, int xHigh);
+static int ddSymmGroupMove (DdManager *table, int x, int y, Move **moves);
+static int ddSymmGroupMoveBackward (DdManager *table, int x, int y);
+static int ddSymmSiftingBackward (DdManager *table, Move *moves, int size);
+static void ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics on symmetric variables.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+Cudd_SymmProfile(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int i,x,gbot;
+    int TotalSymm = 0;
+    int TotalSymmGroups = 0;
+
+    for (i = lower; i <= upper; i++) {
+	if (table->subtables[i].next != (unsigned) i) {
+	    x = i;
+	    (void) fprintf(table->out,"Group:");
+	    do {
+		(void) fprintf(table->out,"  %d",table->invperm[x]);
+		TotalSymm++;
+		gbot = x;
+		x = table->subtables[x].next;
+	    } while (x != i);
+	    TotalSymmGroups++;
+#ifdef DD_DEBUG
+	    assert(table->subtables[gbot].next == (unsigned) i);
+#endif
+	    i = gbot;
+	    (void) fprintf(table->out,"\n");
+	}
+    }
+    (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm);
+    (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups);
+
+} /* end of Cudd_SymmProfile */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for symmetry of x and y.]
+
+  Description [Checks for symmetry of x and y. Ignores projection
+  functions, unless they are isolated. Returns 1 in case of symmetry; 0
+  otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddSymmCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
+    int comple;		/* f0 is complemented */
+    int xsymmy;		/* x and y may be positively symmetric */
+    int xsymmyp;	/* x and y may be negatively symmetric */
+    int arccount;	/* number of arcs from layer x to layer y */
+    int TotalRefCount;	/* total reference count of layer y minus 1 */
+    int yindex;
+    int i;
+    DdNodePtr *list;
+    int slots;
+    DdNode *sentinel = &(table->sentinel);
+#ifdef DD_DEBUG
+    int xindex;
+#endif
+
+    /* Checks that x and y are not the projection functions.
+    ** For x it is sufficient to check whether there is only one
+    ** node; indeed, if there is one node, it is the projection function
+    ** and it cannot point to y. Hence, if y isn't just the projection
+    ** function, it has one arc coming from a layer different from x.
+    */
+    if (table->subtables[x].keys == 1) {
+	return(0);
+    }
+    yindex = table->invperm[y];
+    if (table->subtables[y].keys == 1) {
+	if (table->vars[yindex]->ref == 1)
+	    return(0);
+    }
+
+    xsymmy = xsymmyp = 1;
+    arccount = 0;
+    slots = table->subtables[x].slots;
+    list = table->subtables[x].nodelist;
+    for (i = 0; i < slots; i++) {
+	f = list[i];
+	while (f != sentinel) {
+	    /* Find f1, f0, f11, f10, f01, f00. */
+	    f1 = cuddT(f);
+	    f0 = Cudd_Regular(cuddE(f));
+	    comple = Cudd_IsComplement(cuddE(f));
+	    if ((int) f1->index == yindex) {
+		arccount++;
+		f11 = cuddT(f1); f10 = cuddE(f1);
+	    } else {
+		if ((int) f0->index != yindex) {
+		    /* If f is an isolated projection function it is
+		    ** allowed to bypass layer y.
+		    */
+		    if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
+			return(0); /* f bypasses layer y */
+		}
+		f11 = f10 = f1;
+	    }
+	    if ((int) f0->index == yindex) {
+		arccount++;
+		f01 = cuddT(f0); f00 = cuddE(f0);
+	    } else {
+		f01 = f00 = f0;
+	    }
+	    if (comple) {
+		f01 = Cudd_Not(f01);
+		f00 = Cudd_Not(f00);
+	    }
+
+	    if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
+		xsymmy &= f01 == f10;
+		xsymmyp &= f11 == f00;
+		if ((xsymmy == 0) && (xsymmyp == 0))
+		    return(0);
+	    }
+
+	    f = f->next;
+	} /* while */
+    } /* for */
+
+    /* Calculate the total reference counts of y */
+    TotalRefCount = -1; /* -1 for projection function */
+    slots = table->subtables[y].slots;
+    list = table->subtables[y].nodelist;
+    for (i = 0; i < slots; i++) {
+	f = list[i];
+	while (f != sentinel) {
+	    TotalRefCount += f->ref;
+	    f = f->next;
+	}
+    }
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if (arccount == TotalRefCount) {
+	xindex = table->invperm[x];
+	(void) fprintf(table->out,
+		       "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
+		       xindex,yindex,x,y);
+    }
+#endif
+
+    return(arccount == TotalRefCount);
+
+} /* end of cuddSymmCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Symmetric sifting algorithm.]
+
+  Description [Symmetric sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the DD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddSymmSiftingConv]
+
+******************************************************************************/
+int
+cuddSymmSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int		i;
+    int		*var;
+    int		size;
+    int		x;
+    int		result;
+    int		symvars;
+    int		symgroups;
+#ifdef DD_STATS
+    int		previousSize;
+#endif
+
+    size = table->size;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    entry = ALLOC(int,size);
+    if (entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto ddSymmSiftingOutOfMem;
+    }
+    var = ALLOC(int,size);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto ddSymmSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+	x = table->perm[i];
+	entry[i] = table->subtables[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself. */
+    for (i = lower; i <= upper; i++) {
+	table->subtables[i].next = i;
+    }
+
+    for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
+	if (ddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	x = table->perm[var[i]];
+#ifdef DD_STATS
+	previousSize = table->keys - table->isolated;
+#endif
+	if (x < lower || x > upper) continue;
+	if (table->subtables[x].next == (unsigned) x) {
+	    result = ddSymmSiftingAux(table,x,lower,upper);
+	    if (!result) goto ddSymmSiftingOutOfMem;
+#ifdef DD_STATS
+	    if (table->keys < (unsigned) previousSize + table->isolated) {
+		(void) fprintf(table->out,"-");
+	    } else if (table->keys > (unsigned) previousSize +
+		       table->isolated) {
+		(void) fprintf(table->out,"+"); /* should never happen */
+	    } else {
+		(void) fprintf(table->out,"=");
+	    }
+	    fflush(table->out);
+#endif
+	}
+    }
+
+    FREE(var);
+    FREE(entry);
+
+    ddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
+		   symvars);
+    (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
+		   symgroups);
+#endif
+
+    return(1+symvars);
+
+ddSymmSiftingOutOfMem:
+
+    if (entry != NULL) FREE(entry);
+    if (var != NULL) FREE(var);
+
+    return(0);
+
+} /* end of cuddSymmSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Symmetric sifting to convergence algorithm.]
+
+  Description [Symmetric sifting to convergence algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the DD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    <li> Repeat 1-4 until no further improvement.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddSymmSifting]
+
+******************************************************************************/
+int
+cuddSymmSiftingConv(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int		i;
+    int		*var;
+    int		size;
+    int		x;
+    int		result;
+    int		symvars;
+    int		symgroups;
+    int		classes;
+    int		initialSize;
+#ifdef DD_STATS
+    int		previousSize;
+#endif
+
+    initialSize = table->keys - table->isolated;
+
+    size = table->size;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    entry = ALLOC(int,size);
+    if (entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto ddSymmSiftingConvOutOfMem;
+    }
+    var = ALLOC(int,size);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto ddSymmSiftingConvOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+	x = table->perm[i];
+	entry[i] = table->subtables[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself
+    ** for first pass of converging symmetric sifting.
+    */
+    for (i = lower; i <= upper; i++) {
+	table->subtables[i].next = i;
+    }
+
+    for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
+	if (ddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	x = table->perm[var[i]];
+	if (x < lower || x > upper) continue;
+	/* Only sift if not in symmetry group already. */
+	if (table->subtables[x].next == (unsigned) x) {
+#ifdef DD_STATS
+	    previousSize = table->keys - table->isolated;
+#endif
+	    result = ddSymmSiftingAux(table,x,lower,upper);
+	    if (!result) goto ddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+	    if (table->keys < (unsigned) previousSize + table->isolated) {
+		(void) fprintf(table->out,"-");
+	    } else if (table->keys > (unsigned) previousSize +
+		       table->isolated) {
+		(void) fprintf(table->out,"+");
+	    } else {
+		(void) fprintf(table->out,"=");
+	    }
+	    fflush(table->out);
+#endif
+	}
+    }
+
+    /* Sifting now until convergence. */
+    while ((unsigned) initialSize > table->keys - table->isolated) {
+	initialSize = table->keys - table->isolated;
+#ifdef DD_STATS
+	(void) fprintf(table->out,"\n");
+#endif
+        /* Here we consider only one representative for each symmetry class. */
+	for (x = lower, classes = 0; x <= upper; x++, classes++) {
+	    while ((unsigned) x < table->subtables[x].next) {
+		x = table->subtables[x].next;
+	    }
+	    /* Here x is the largest index in a group.
+	    ** Groups consist of adjacent variables.
+	    ** Hence, the next increment of x will move it to a new group.
+	    */
+	    i = table->invperm[x];
+	    entry[i] = table->subtables[x].keys;
+	    var[classes] = i;
+	}
+
+	qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
+
+	/* Now sift. */
+	for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
+	    if (ddTotalNumberSwapping >= table->siftMaxSwap)
+		break;
+	    x = table->perm[var[i]];
+	    if ((unsigned) x >= table->subtables[x].next) {
+#ifdef DD_STATS
+		previousSize = table->keys - table->isolated;
+#endif
+		result = ddSymmSiftingConvAux(table,x,lower,upper);
+		if (!result ) goto ddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+		if (table->keys < (unsigned) previousSize + table->isolated) {
+		    (void) fprintf(table->out,"-");
+		} else if (table->keys > (unsigned) previousSize +
+			   table->isolated) {
+		    (void) fprintf(table->out,"+");
+		} else {
+		    (void) fprintf(table->out,"=");
+		}
+		fflush(table->out);
+#endif
+	    }
+	} /* for */
+    }
+
+    ddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
+		   symvars);
+    (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
+		   symgroups);
+#endif
+
+    FREE(var);
+    FREE(entry);
+
+    return(1+symvars);
+
+ddSymmSiftingConvOutOfMem:
+
+    if (entry != NULL) FREE(entry);
+    if (var != NULL) FREE(var);
+
+    return(0);
+
+} /* end of cuddSymmSiftingConv */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the variables
+  according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmUniqueCompare(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+	return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of ddSymmUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is not part of a symmetry group. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move *move;
+    Move *moveUp;	/* list of up moves */
+    Move *moveDown;	/* list of down moves */
+    int	 initialSize;
+    int	 result;
+    int  i;
+    int  topbot;	/* index to either top or bottom of symmetry group */
+    int  initGroupSize, finalGroupSize;
+
+
+#ifdef DD_DEBUG
+    /* check for previously detected symmetry */
+    assert(table->subtables[x].next == (unsigned) x);
+#endif
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if ((x - xLow) > (xHigh - x)) {
+	/* Will go down first, unless x == xHigh:
+	** Look for consecutive symmetries above x.
+	*/
+	for (i = x; i > xLow; i--) {
+	    if (!cuddSymmCheck(table,i-1,i))
+		break;
+	    topbot = table->subtables[i-1].next; /* find top of i-1's group */
+	    table->subtables[i-1].next = i;
+	    table->subtables[x].next = topbot; /* x is bottom of group so its */
+					       /* next is top of i-1's group */
+	    i = topbot + 1; /* add 1 for i--; new i is top of symm group */
+	}
+    } else {
+	/* Will go up first unless x == xlow:
+	** Look for consecutive symmetries below x.
+	*/
+	for (i = x; i < xHigh; i++) {
+	    if (!cuddSymmCheck(table,i,i+1))
+		break;
+	    /* find bottom of i+1's symm group */
+	    topbot = i + 1;
+	    while ((unsigned) topbot < table->subtables[topbot].next) {
+		topbot = table->subtables[topbot].next;
+	    }
+	    table->subtables[topbot].next = table->subtables[i].next;
+	    table->subtables[i].next = i + 1;
+	    i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */
+	}
+    }
+
+    /* Now x may be in the middle of a symmetry group.
+    ** Find bottom of x's symm group.
+    */
+    while ((unsigned) x < table->subtables[x].next)
+	x = table->subtables[x].next;
+
+    if (x == xLow) { /* Sift down */
+
+#ifdef DD_DEBUG
+	/* x must be a singleton */
+	assert((unsigned) x == table->subtables[x].next);
+#endif
+	if (x == xHigh) return(1);	/* just one variable */
+
+	initGroupSize = 1;
+
+	moveDown = ddSymmSiftingDown(table,x,xHigh);
+	    /* after this point x --> xHigh, unless early term */
+	if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+	if (moveDown == NULL) return(1);
+
+	x = moveDown->y;
+	/* Find bottom of x's group */
+	i = x;
+	while ((unsigned) i < table->subtables[i].next) {
+	    i = table->subtables[i].next;
+	}
+#ifdef DD_DEBUG
+	/* x should be the top of the symmetry group and i the bottom */
+	assert((unsigned) i >= table->subtables[i].next);
+	assert((unsigned) x == table->subtables[i].next);
+#endif
+	finalGroupSize = i - x + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetry groups detected, return to best position */
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	} else {
+	    initialSize = table->keys - table->isolated;
+	    moveUp = ddSymmSiftingUp(table,x,xLow);
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	}
+	if (!result) goto ddSymmSiftingAuxOutOfMem;
+
+    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
+	/* Find top of x's symm group */
+	i = x;				/* bottom */
+	x = table->subtables[x].next;	/* top */
+
+	if (x == xLow) return(1); /* just one big group */
+
+	initGroupSize = i - x + 1;
+
+	moveUp = ddSymmSiftingUp(table,x,xLow);
+	    /* after this point x --> xLow, unless early term */
+	if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+	if (moveUp == NULL) return(1);
+
+	x = moveUp->x;
+	/* Find top of x's group */
+	i = table->subtables[x].next;
+#ifdef DD_DEBUG
+	/* x should be the bottom of the symmetry group and i the top */
+	assert((unsigned) x >= table->subtables[x].next);
+	assert((unsigned) i == table->subtables[x].next);
+#endif
+	finalGroupSize = x - i + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetry groups detected, return to best position */
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	} else {
+	    initialSize = table->keys - table->isolated;
+	    moveDown = ddSymmSiftingDown(table,x,xHigh);
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	}
+	if (!result) goto ddSymmSiftingAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+
+	moveDown = ddSymmSiftingDown(table,x,xHigh);
+	/* at this point x == xHigh, unless early term */
+	if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+	if (moveDown != NULL) {
+	    x = moveDown->y;	/* x is top here */
+	    i = x;
+	    while ((unsigned) i < table->subtables[i].next) {
+		i = table->subtables[i].next;
+	    }
+	} else {
+	    i = x;
+	    while ((unsigned) i < table->subtables[i].next) {
+		i = table->subtables[i].next;
+	    }
+	    x = table->subtables[i].next;
+	}
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetry group and i the bottom */
+	assert((unsigned) i >= table->subtables[i].next);
+	assert((unsigned) x == table->subtables[i].next);
+#endif
+	initGroupSize = i - x + 1;
+
+	moveUp = ddSymmSiftingUp(table,x,xLow);
+	if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+	if (moveUp != NULL) {
+	    x = moveUp->x;
+	    i = table->subtables[x].next;
+	} else {
+	    i = x;
+	    while ((unsigned) x < table->subtables[x].next)
+		x = table->subtables[x].next;
+	}
+#ifdef DD_DEBUG
+	/* x should be the bottom of the symmetry group and i the top */
+	assert((unsigned) x >= table->subtables[x].next);
+	assert((unsigned) i == table->subtables[x].next);
+#endif
+	finalGroupSize = x - i + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetry groups detected, return to best position */
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	} else {
+	    while (moveDown != NULL) {
+		move = moveDown->next;
+		cuddDeallocMove(table, moveDown);
+		moveDown = move;
+	    }
+	    initialSize = table->keys - table->isolated;
+	    moveDown = ddSymmSiftingDown(table,x,xHigh);
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	}
+	if (!result) goto ddSymmSiftingAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+        /* Find top of x's symmetry group */
+	x = table->subtables[x].next;
+
+	moveUp = ddSymmSiftingUp(table,x,xLow);
+	/* at this point x == xHigh, unless early term */
+	if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+	if (moveUp != NULL) {
+	    x = moveUp->x;
+	    i = table->subtables[x].next;
+	} else {
+	    while ((unsigned) x < table->subtables[x].next)
+		x = table->subtables[x].next;
+	    i = table->subtables[x].next;
+	}
+#ifdef DD_DEBUG
+        /* x is bottom of the symmetry group and i is top */
+	assert((unsigned) x >= table->subtables[x].next);
+	assert((unsigned) i == table->subtables[x].next);
+#endif
+	initGroupSize = x - i + 1;
+
+	moveDown = ddSymmSiftingDown(table,x,xHigh);
+	if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
+
+	if (moveDown != NULL) {
+	    x = moveDown->y;
+	    i = x;
+	    while ((unsigned) i < table->subtables[i].next) {
+		i = table->subtables[i].next;
+	    }
+	} else {
+	    i = x;
+	    x = table->subtables[x].next;
+	}
+#ifdef DD_DEBUG
+	/* x should be the top of the symmetry group and i the bottom */
+	assert((unsigned) i >= table->subtables[i].next);
+	assert((unsigned) x == table->subtables[i].next);
+#endif
+	finalGroupSize = i - x + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetries detected, go back to best position */
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	} else {
+	    while (moveUp != NULL) {
+		move = moveUp->next;
+		cuddDeallocMove(table, moveUp);
+		moveUp = move;
+	    }
+	    initialSize = table->keys - table->isolated;
+	    moveUp = ddSymmSiftingUp(table,x,xLow);
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	}
+	if (!result) goto ddSymmSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(1);
+
+ddSymmSiftingAuxOutOfMem:
+    if (moveDown != MV_OOM) {
+	while (moveDown != NULL) {
+	    move = moveDown->next;
+	    cuddDeallocMove(table, moveDown);
+	    moveDown = move;
+	}
+    }
+    if (moveUp != MV_OOM) {
+	while (moveUp != NULL) {
+	    move = moveUp->next;
+	    cuddDeallocMove(table, moveUp);
+	    moveUp = move;
+	}
+    }
+
+    return(0);
+
+} /* end of ddSymmSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is either an isolated variable, or it is the bottom of
+  a symmetry group. All symmetries may not have been found, because of
+  exceeded growth limit. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmSiftingConvAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move *move;
+    Move *moveUp;	/* list of up moves */
+    Move *moveDown;	/* list of down moves */
+    int	 initialSize;
+    int	 result;
+    int  i;
+    int  initGroupSize, finalGroupSize;
+
+
+    initialSize = table->keys - table->isolated;
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) { /* Sift down */
+#ifdef DD_DEBUG
+	/* x is bottom of symmetry group */
+	assert((unsigned) x >= table->subtables[x].next);
+#endif
+        i = table->subtables[x].next;
+	initGroupSize = x - i + 1;
+
+	moveDown = ddSymmSiftingDown(table,x,xHigh);
+	/* at this point x == xHigh, unless early term */
+	if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+	if (moveDown == NULL) return(1);
+
+	x = moveDown->y;
+	i = x;
+	while ((unsigned) i < table->subtables[i].next) {
+	    i = table->subtables[i].next;
+	}
+#ifdef DD_DEBUG
+	/* x should be the top of the symmetric group and i the bottom */
+	assert((unsigned) i >= table->subtables[i].next);
+	assert((unsigned) x == table->subtables[i].next);
+#endif
+	finalGroupSize = i - x + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetries detected, go back to best position */
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	} else {
+	    initialSize = table->keys - table->isolated;
+	    moveUp = ddSymmSiftingUp(table,x,xLow);
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	}
+	if (!result) goto ddSymmSiftingConvAuxOutOfMem;
+
+    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
+	/* Find top of x's symm group */
+	while ((unsigned) x < table->subtables[x].next)
+	    x = table->subtables[x].next;
+	i = x;				/* bottom */
+	x = table->subtables[x].next;	/* top */
+
+	if (x == xLow) return(1);
+
+	initGroupSize = i - x + 1;
+
+	moveUp = ddSymmSiftingUp(table,x,xLow);
+	    /* at this point x == xLow, unless early term */
+	if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+	if (moveUp == NULL) return(1);
+
+	x = moveUp->x;
+	i = table->subtables[x].next;
+#ifdef DD_DEBUG
+	/* x should be the bottom of the symmetry group and i the top */
+	assert((unsigned) x >= table->subtables[x].next);
+	assert((unsigned) i == table->subtables[x].next);
+#endif
+	finalGroupSize = x - i + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetry groups detected, return to best position */
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	} else {
+	    initialSize = table->keys - table->isolated;
+	    moveDown = ddSymmSiftingDown(table,x,xHigh);
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	}
+	if (!result)
+	    goto ddSymmSiftingConvAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+	moveDown = ddSymmSiftingDown(table,x,xHigh);
+	    /* at this point x == xHigh, unless early term */
+	if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+	if (moveDown != NULL) {
+	    x = moveDown->y;
+	    i = x;
+	    while ((unsigned) i < table->subtables[i].next) {
+		i = table->subtables[i].next;
+	    }
+	} else {
+	    while ((unsigned) x < table->subtables[x].next)
+		x = table->subtables[x].next;
+	    i = x;
+	    x = table->subtables[x].next;
+	}
+#ifdef DD_DEBUG
+        /* x should be the top of the symmetry group and i the bottom */
+	assert((unsigned) i >= table->subtables[i].next);
+	assert((unsigned) x == table->subtables[i].next);
+#endif
+	initGroupSize = i - x + 1;
+
+	moveUp = ddSymmSiftingUp(table,x,xLow);
+	if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+	if (moveUp != NULL) {
+	    x = moveUp->x;
+	    i = table->subtables[x].next;
+	} else {
+	    i = x;
+	    while ((unsigned) x < table->subtables[x].next)
+		x = table->subtables[x].next;
+	}
+#ifdef DD_DEBUG
+	/* x should be the bottom of the symmetry group and i the top */
+	assert((unsigned) x >= table->subtables[x].next);
+	assert((unsigned) i == table->subtables[x].next);
+#endif
+	finalGroupSize = x - i + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetry groups detected, return to best position */
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	} else {
+	    while (moveDown != NULL) {
+		move = moveDown->next;
+		cuddDeallocMove(table, moveDown);
+		moveDown = move;
+	    }
+	    initialSize = table->keys - table->isolated;
+	    moveDown = ddSymmSiftingDown(table,x,xHigh);
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	}
+	if (!result) goto ddSymmSiftingConvAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+	/* Find top of x's symmetry group */
+	x = table->subtables[x].next;
+
+	moveUp = ddSymmSiftingUp(table,x,xLow);
+	/* at this point x == xHigh, unless early term */
+	if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+	if (moveUp != NULL) {
+	    x = moveUp->x;
+	    i = table->subtables[x].next;
+	} else {
+	    i = x;
+	    while ((unsigned) x < table->subtables[x].next)
+		x = table->subtables[x].next;
+	}
+#ifdef DD_DEBUG
+        /* x is bottom of the symmetry group and i is top */
+        assert((unsigned) x >= table->subtables[x].next);
+        assert((unsigned) i == table->subtables[x].next);
+#endif
+        initGroupSize = x - i + 1;
+
+	moveDown = ddSymmSiftingDown(table,x,xHigh);
+	if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
+
+	if (moveDown != NULL) {
+	    x = moveDown->y;
+	    i = x;
+	    while ((unsigned) i < table->subtables[i].next) {
+		i = table->subtables[i].next;
+	    }
+	} else {
+	    i = x;
+	    x = table->subtables[x].next;
+	}
+#ifdef DD_DEBUG
+	/* x should be the top of the symmetry group and i the bottom */
+	assert((unsigned) i >= table->subtables[i].next);
+	assert((unsigned) x == table->subtables[i].next);
+#endif
+	finalGroupSize = i - x + 1;
+
+	if (initGroupSize == finalGroupSize) {
+	    /* No new symmetries detected, go back to best position */
+	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
+	} else {
+	    while (moveUp != NULL) {
+		move = moveUp->next;
+		cuddDeallocMove(table, moveUp);
+		moveUp = move;
+	    }
+	    initialSize = table->keys - table->isolated;
+	    moveUp = ddSymmSiftingUp(table,x,xLow);
+	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
+	}
+	if (!result) goto ddSymmSiftingConvAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(1);
+
+ddSymmSiftingConvAuxOutOfMem:
+    if (moveDown != MV_OOM) {
+	while (moveDown != NULL) {
+	    move = moveDown->next;
+	    cuddDeallocMove(table, moveDown);
+	    moveDown = move;
+	}
+    }
+    if (moveUp != MV_OOM) {
+	while (moveUp != NULL) {
+	    move = moveUp->next;
+	    cuddDeallocMove(table, moveUp);
+	    moveUp = move;
+	}
+    }
+
+    return(0);
+
+} /* end of ddSymmSiftingConvAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves x up until either it reaches the bound (xLow) or
+  the size of the DD heap increases too much.]
+
+  Description [Moves x up until either it reaches the bound (xLow) or
+  the size of the DD heap increases too much. Assumes that x is the top
+  of a symmetry group.  Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSymmSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow)
+{
+    Move *moves;
+    Move *move;
+    int	 x;
+    int	 size;
+    int  i;
+    int  gxtop,gybot;
+    int  limitSize;
+    int  xindex, yindex;
+    int  zindex;
+    int  z;
+    int  isolated;
+    int  L;	/* lower bound on DD size */
+#ifdef DD_DEBUG
+    int  checkL;
+#endif
+
+
+    moves = NULL;
+    yindex = table->invperm[y];
+
+    /* Initialize the lower bound.
+    ** The part of the DD below the bottom of y' group will not change.
+    ** The part of the DD above y that does not interact with y will not
+    ** change. The rest may vanish in the best case, except for
+    ** the nodes at level xLow, which will not vanish, regardless.
+    */
+    limitSize = L = table->keys - table->isolated;
+    gybot = y;
+    while ((unsigned) gybot < table->subtables[gybot].next)
+	gybot = table->subtables[gybot].next;
+    for (z = xLow + 1; z <= gybot; z++) {
+	zindex = table->invperm[z];
+	if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+	    isolated = table->vars[zindex]->ref == 1;
+	    L -= table->subtables[z].keys - isolated;
+	}
+    }
+
+    x = cuddNextLow(table,y);
+    while (x >= xLow && L <= limitSize) {
+#ifdef DD_DEBUG
+	gybot = y;
+	while ((unsigned) gybot < table->subtables[gybot].next)
+	    gybot = table->subtables[gybot].next;
+	checkL = table->keys - table->isolated;
+	for (z = xLow + 1; z <= gybot; z++) {
+	    zindex = table->invperm[z];
+	    if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkL -= table->subtables[z].keys - isolated;
+	    }
+	}
+	assert(L == checkL);
+#endif
+	gxtop = table->subtables[x].next;
+	if (cuddSymmCheck(table,x,y)) {
+	    /* Symmetry found, attach symm groups */
+	    table->subtables[x].next = y;
+	    i = table->subtables[y].next;
+	    while (table->subtables[i].next != (unsigned) y)
+		i = table->subtables[i].next;
+	    table->subtables[i].next = gxtop;
+	} else if (table->subtables[x].next == (unsigned) x &&
+		   table->subtables[y].next == (unsigned) y) {
+	    /* x and y have self symmetry */
+	    xindex = table->invperm[x];
+	    size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+	    assert(table->subtables[x].next == (unsigned) x);
+	    assert(table->subtables[y].next == (unsigned) y);
+#endif
+	    if (size == 0) goto ddSymmSiftingUpOutOfMem;
+	    /* Update the lower bound. */
+	    if (cuddTestInteract(table,xindex,yindex)) {
+		isolated = table->vars[xindex]->ref == 1;
+		L += table->subtables[y].keys - isolated;
+	    }
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddSymmSiftingUpOutOfMem;
+	    move->x = x;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    if ((double) size > (double) limitSize * table->maxGrowth)
+		return(moves);
+	    if (size < limitSize) limitSize = size;
+	} else { /* Group move */
+	    size = ddSymmGroupMove(table,x,y,&moves);
+	    if (size == 0) goto ddSymmSiftingUpOutOfMem;
+	    /* Update the lower bound. */
+	    z = moves->y;
+	    do {
+		zindex = table->invperm[z];
+		if (cuddTestInteract(table,zindex,yindex)) {
+		    isolated = table->vars[zindex]->ref == 1;
+		    L += table->subtables[z].keys - isolated;
+		}
+		z = table->subtables[z].next;
+	    } while (z != (int) moves->y);
+	    if ((double) size > (double) limitSize * table->maxGrowth)
+		return(moves);
+	    if (size < limitSize) limitSize = size;
+	}
+	y = gxtop;
+	x = cuddNextLow(table,y);
+    }
+
+    return(moves);
+
+ddSymmSiftingUpOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(MV_OOM);
+
+} /* end of ddSymmSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves x down until either it reaches the bound (xHigh) or
+  the size of the DD heap increases too much.]
+
+  Description [Moves x down until either it reaches the bound (xHigh)
+  or the size of the DD heap increases too much. Assumes that x is the
+  bottom of a symmetry group. Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move *
+ddSymmSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh)
+{
+    Move *moves;
+    Move *move;
+    int	 y;
+    int	 size;
+    int  limitSize;
+    int  gxtop,gybot;
+    int  R;	/* upper bound on node decrease */
+    int  xindex, yindex;
+    int  isolated;
+    int  z;
+    int  zindex;
+#ifdef DD_DEBUG
+    int  checkR;
+#endif
+
+    moves = NULL;
+    /* Initialize R */
+    xindex = table->invperm[x];
+    gxtop = table->subtables[x].next;
+    limitSize = size = table->keys - table->isolated;
+    R = 0;
+    for (z = xHigh; z > gxtop; z--) {
+	zindex = table->invperm[z];
+	if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+	    isolated = table->vars[zindex]->ref == 1;
+	    R += table->subtables[z].keys - isolated;
+	}
+    }
+
+    y = cuddNextHigh(table,x);
+    while (y <= xHigh && size - R < limitSize) {
+#ifdef DD_DEBUG
+	gxtop = table->subtables[x].next;
+	checkR = 0;
+	for (z = xHigh; z > gxtop; z--) {
+	    zindex = table->invperm[z];
+	    if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+		isolated = table->vars[zindex]->ref == 1;
+		checkR += table->subtables[z].keys - isolated;
+	    }
+	}
+	assert(R == checkR);
+#endif
+	gybot = table->subtables[y].next;
+	while (table->subtables[gybot].next != (unsigned) y)
+	    gybot = table->subtables[gybot].next;
+	if (cuddSymmCheck(table,x,y)) {
+	    /* Symmetry found, attach symm groups */
+	    gxtop = table->subtables[x].next;
+	    table->subtables[x].next = y;
+	    table->subtables[gybot].next = gxtop;
+	} else if (table->subtables[x].next == (unsigned) x &&
+		   table->subtables[y].next == (unsigned) y) {
+	    /* x and y have self symmetry */
+	    /* Update upper bound on node decrease. */
+	    yindex = table->invperm[y];
+	    if (cuddTestInteract(table,xindex,yindex)) {
+		isolated = table->vars[yindex]->ref == 1;
+		R -= table->subtables[y].keys - isolated;
+	    }
+	    size = cuddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+	    assert(table->subtables[x].next == (unsigned) x);
+	    assert(table->subtables[y].next == (unsigned) y);
+#endif
+	    if (size == 0) goto ddSymmSiftingDownOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL) goto ddSymmSiftingDownOutOfMem;
+	    move->x = x;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    if ((double) size > (double) limitSize * table->maxGrowth)
+		return(moves);
+	    if (size < limitSize) limitSize = size;
+	} else { /* Group move */
+	    /* Update upper bound on node decrease: first phase. */
+	    gxtop = table->subtables[x].next;
+	    z = gxtop + 1;
+	    do {
+		zindex = table->invperm[z];
+		if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+		    isolated = table->vars[zindex]->ref == 1;
+		    R -= table->subtables[z].keys - isolated;
+		}
+		z++;
+	    } while (z <= gybot);
+	    size = ddSymmGroupMove(table,x,y,&moves);
+	    if (size == 0) goto ddSymmSiftingDownOutOfMem;
+	    if ((double) size > (double) limitSize * table->maxGrowth)
+		return(moves);
+	    if (size < limitSize) limitSize = size;
+	    /* Update upper bound on node decrease: second phase. */
+	    gxtop = table->subtables[gybot].next;
+	    for (z = gxtop + 1; z <= gybot; z++) {
+		zindex = table->invperm[z];
+		if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
+		    isolated = table->vars[zindex]->ref == 1;
+		    R += table->subtables[z].keys - isolated;
+		}
+	    }
+	}
+	x = gybot;
+	y = cuddNextHigh(table,x);
+    }
+
+    return(moves);
+
+ddSymmSiftingDownOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(MV_OOM);
+
+} /* end of ddSymmSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two groups.]
+
+  Description [Swaps two groups. x is assumed to be the bottom variable
+  of the first group. y is assumed to be the top variable of the second
+  group.  Updates the list of moves. Returns the number of keys in the
+  table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmGroupMove(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move *move;
+    int	 size;
+    int  i,j;
+    int  xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+    int  swapx,swapy;
+
+#if DD_DEBUG
+    assert(x < y);	/* we assume that x < y */
+#endif
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+	ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group. */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+	    size = cuddSwapInPlace(table,x,y);
+	    if (size == 0) return(0);
+	    swapx = x; swapy = y;
+	    y = x;
+	    x = y - 1;
+	}
+	y = ytop + i;
+	x = y - 1;
+    }
+
+    /* fix symmetries */
+    y = xtop; /* ytop is now where xtop used to be */
+    for (i = 0; i < ysize-1 ; i++) {
+	table->subtables[y].next = y + 1;
+	y = y + 1;
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+    				     /* its symmetry to top of its group */
+    x = y + 1;
+    newxtop = x;
+    for (i = 0; i < xsize - 1 ; i++) {
+	table->subtables[x].next = x + 1;
+	x = x + 1;
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+    					/* its symmetry to top of its group */
+    /* Store group move */
+    move = (Move *) cuddDynamicAllocNode(table);
+    if (move == NULL) return(0);
+    move->x = swapx;
+    move->y = swapy;
+    move->size = size;
+    move->next = *moves;
+    *moves = move;
+
+    return(size);
+
+} /* end of ddSymmGroupMove */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Undoes the swap of two groups.]
+
+  Description [Undoes the swap of two groups. x is assumed to be the
+  bottom variable of the first group. y is assumed to be the top
+  variable of the second group.  Returns the number of keys in the table
+  if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmGroupMoveBackward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int	size;
+    int i,j;
+    int	xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+
+#if DD_DEBUG
+    assert(x < y); /* We assume that x < y */
+#endif
+
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtables[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtables[ybot].next)
+	ybot = table->subtables[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group. */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+	    size = cuddSwapInPlace(table,x,y);
+	    if (size == 0) return(0);
+	    y = x;
+	    x = cuddNextLow(table,y);
+	}
+	y = ytop + i;
+	x = y - 1;
+    }
+
+    /* Fix symmetries. */
+    y = xtop;
+    for (i = 0; i < ysize-1 ; i++) {
+	table->subtables[y].next = y + 1;
+	y = y + 1;
+    }
+    table->subtables[y].next = xtop; /* y is bottom of its group, join */
+    				     /* its symmetry to top of its group */
+    x = y + 1;
+    newxtop = x;
+    for (i = 0; i < xsize-1 ; i++) {
+	table->subtables[x].next = x + 1;
+	x = x + 1;
+    }
+    table->subtables[x].next = newxtop; /* x is bottom of its group, join */
+					/* its symmetry to top of its group */
+
+    return(size);
+
+} /* end of ddSymmGroupMoveBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the DD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the DD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddSymmSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    Move *move;
+    int  res;
+
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size < size) {
+	    size = move->size;
+	}
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size == size) return(1);
+	if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
+	    res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
+#ifdef DD_DEBUG
+	    assert(table->subtables[move->x].next == move->x);
+	    assert(table->subtables[move->y].next == move->y);
+#endif
+	} else { /* Group move necessary */
+	    res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
+	}
+	if (!res) return(0);
+    }
+
+    return(1);
+
+} /* end of ddSymmSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts numbers of symmetric variables and symmetry
+  groups.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddSymmSummary(
+  DdManager * table,
+  int  lower,
+  int  upper,
+  int * symvars,
+  int * symgroups)
+{
+    int i,x,gbot;
+    int TotalSymm = 0;
+    int TotalSymmGroups = 0;
+
+    for (i = lower; i <= upper; i++) {
+	if (table->subtables[i].next != (unsigned) i) {
+	    TotalSymmGroups++;
+	    x = i;
+	    do {
+		TotalSymm++;
+		gbot = x;
+		x = table->subtables[x].next;
+	    } while (x != i);
+#ifdef DD_DEBUG
+	    assert(table->subtables[gbot].next == (unsigned) i);
+#endif
+	    i = gbot;
+	}
+    }
+    *symvars = TotalSymm;
+    *symgroups = TotalSymmGroups;
+
+    return;
+
+} /* end of ddSymmSummary */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddTable.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddTable.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddTable.c	(revision 8)
@@ -0,0 +1,3098 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddTable.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Unique table management functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_Prime()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddAllocNode()
+		<li> cuddInitTable()
+		<li> cuddFreeTable()
+		<li> cuddGarbageCollect()
+		<li> cuddZddGetNode()
+		<li> cuddZddGetNodeIVO()
+		<li> cuddUniqueInter()
+		<li> cuddUniqueInterIVO()
+		<li> cuddUniqueInterZdd()
+		<li> cuddUniqueConst()
+		<li> cuddRehash()
+		<li> cuddShrinkSubtable()
+		<li> cuddInsertSubtables()
+		<li> cuddDestroySubtables()
+		<li> cuddResizeTableZdd()
+		<li> cuddSlowTableGrowth()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddRehashZdd()
+		<li> ddResizeTable()
+		<li> cuddFindParent()
+		<li> cuddOrderedInsert()
+		<li> cuddOrderedThread()
+		<li> cuddRotateLeft()
+		<li> cuddRotateRight()
+		<li> cuddDoRebalance()
+		<li> cuddCheckCollisionOrdering()
+		</ul>]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+/* Constants for red/black trees. */
+#define DD_STACK_SIZE 128
+#define DD_RED   0
+#define DD_BLACK 1
+#define DD_PAGE_SIZE 8192
+#define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1)
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* This is a hack for when CUDD_VALUE_TYPE is double */
+typedef union hack {
+    CUDD_VALUE_TYPE value;
+    unsigned int bits[2];
+} hack;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddTable.c,v 1.119 2004/08/13 18:04:52 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+/* Macros for red/black trees. */
+#define DD_INSERT_COMPARE(x,y) \
+	(((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK))
+#define DD_COLOR(p)  ((p)->index)
+#define DD_IS_BLACK(p) ((p)->index == DD_BLACK)
+#define DD_IS_RED(p) ((p)->index == DD_RED)
+#define DD_LEFT(p) cuddT(p)
+#define DD_RIGHT(p) cuddE(p)
+#define DD_NEXT(p) ((p)->next)
+#endif
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ddRehashZdd (DdManager *unique, int i);
+static int ddResizeTable (DdManager *unique, int index);
+static int cuddFindParent (DdManager *table, DdNode *node);
+DD_INLINE static void ddFixLimits (DdManager *unique);
+#ifdef DD_RED_BLACK_FREE_LIST
+static void cuddOrderedInsert (DdNodePtr *root, DdNodePtr node);
+static DdNode * cuddOrderedThread (DdNode *root, DdNode *list);
+static void cuddRotateLeft (DdNodePtr *nodeP);
+static void cuddRotateRight (DdNodePtr *nodeP);
+static void cuddDoRebalance (DdNodePtr **stack, int stackN);
+#endif
+static void ddPatchTree (DdManager *dd, MtrNode *treenode);
+#ifdef DD_DEBUG
+static int cuddCheckCollisionOrdering (DdManager *unique, int i, int j);
+#endif
+static void ddReportRefMess (DdManager *unique, int i, const char *caller);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the next prime &gt;= p.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+unsigned int
+Cudd_Prime(
+  unsigned int  p)
+{
+    int i,pn;
+
+    p--;
+    do {
+        p++;
+        if (p&1) {
+	    pn = 1;
+	    i = 3;
+	    while ((unsigned) (i * i) <= p) {
+		if (p % i == 0) {
+		    pn = 0;
+		    break;
+		}
+		i += 2;
+	    }
+	} else {
+	    pn = 0;
+	}
+    } while (!pn);
+    return(p);
+
+} /* end of Cudd_Prime */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fast storage allocation for DdNodes in the table.]
+
+  Description [Fast storage allocation for DdNodes in the table. The
+  first 4 bytes of a chunk contain a pointer to the next block; the
+  rest contains DD_MEM_CHUNK spaces for DdNodes.  Returns a pointer to
+  a new node if successful; NULL is memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddDynamicAllocNode]
+
+******************************************************************************/
+DdNode *
+cuddAllocNode(
+  DdManager * unique)
+{
+    int i;
+    DdNodePtr *mem;
+    DdNode *list, *node;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (unique->nextFree == NULL) {	/* free list is empty */
+	/* Check for exceeded limits. */
+	if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) >
+	    unique->maxLive) {
+	    unique->errorCode = CUDD_TOO_MANY_NODES;
+	    return(NULL);
+	}
+	if (unique->stash == NULL || unique->memused > unique->maxmemhard) {
+	    (void) cuddGarbageCollect(unique,1);
+	    mem = NULL;
+	}
+	if (unique->nextFree == NULL) {
+	    if (unique->memused > unique->maxmemhard) {
+		unique->errorCode = CUDD_MAX_MEM_EXCEEDED;
+		return(NULL);
+	    }
+	    /* Try to allocate a new block. */
+	    saveHandler = MMoutOfMemory;
+	    MMoutOfMemory = Cudd_OutOfMem;
+	    mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
+	    MMoutOfMemory = saveHandler;
+	    if (mem == NULL) {
+		/* No more memory: Try collecting garbage. If this succeeds,
+		** we end up with mem still NULL, but unique->nextFree !=
+		** NULL. */
+		if (cuddGarbageCollect(unique,1) == 0) {
+		    /* Last resort: Free the memory stashed away, if there
+		    ** any. If this succeeeds, mem != NULL and
+		    ** unique->nextFree still NULL. */
+		    if (unique->stash != NULL) {
+			FREE(unique->stash);
+			unique->stash = NULL;
+			/* Inhibit resizing of tables. */
+			cuddSlowTableGrowth(unique);
+			/* Now try again. */
+			mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
+		    }
+		    if (mem == NULL) {
+			/* Out of luck. Call the default handler to do
+			** whatever it specifies for a failed malloc.
+			** If this handler returns, then set error code,
+			** print warning, and return. */
+			(*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
+			unique->errorCode = CUDD_MEMORY_OUT;
+#ifdef DD_VERBOSE
+			(void) fprintf(unique->err,
+				       "cuddAllocNode: out of memory");
+			(void) fprintf(unique->err, "Memory in use = %lu\n",
+				       unique->memused);
+#endif
+			return(NULL);
+		    }
+		}
+	    }
+	    if (mem != NULL) {	/* successful allocation; slice memory */
+		ptruint offset;
+		unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
+		mem[0] = (DdNodePtr) unique->memoryList;
+		unique->memoryList = mem;
+
+		/* Here we rely on the fact that a DdNode is as large
+		** as 4 pointers.  */
+		offset = (ptruint) mem & (sizeof(DdNode) - 1);
+		mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
+		assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0);
+		list = (DdNode *) mem;
+
+		i = 1;
+		do {
+		    list[i - 1].ref = 0;
+		    list[i - 1].next = &list[i];
+		} while (++i < DD_MEM_CHUNK);
+
+		list[DD_MEM_CHUNK-1].ref = 0;
+		list[DD_MEM_CHUNK-1].next = NULL;
+
+		unique->nextFree = &list[0];
+	    }
+	}
+    }
+    unique->allocated++;
+    node = unique->nextFree;
+    unique->nextFree = node->next;
+    return(node);
+
+} /* end of cuddAllocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates and initializes the unique table.]
+
+  Description [Creates and initializes the unique table. Returns a pointer
+  to the table if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Init cuddFreeTable]
+
+******************************************************************************/
+DdManager *
+cuddInitTable(
+  unsigned int numVars  /* Initial number of BDD variables (and subtables) */,
+  unsigned int numVarsZ /* Initial number of ZDD variables (and subtables) */,
+  unsigned int numSlots /* Initial size of the BDD subtables */,
+  unsigned int looseUpTo /* Limit for fast table growth */)
+{
+    DdManager	*unique = ALLOC(DdManager,1);
+    int		i, j;
+    DdNodePtr	*nodelist;
+    DdNode	*sentinel;
+    unsigned int slots;
+    int shift;
+
+    if (unique == NULL) {
+	return(NULL);
+    }
+    sentinel = &(unique->sentinel);
+    sentinel->ref = 0;
+    sentinel->index = 0;
+    cuddT(sentinel) = NULL;
+    cuddE(sentinel) = NULL;
+    sentinel->next = NULL;
+    unique->epsilon = DD_EPSILON;
+    unique->maxGrowth = DD_MAX_REORDER_GROWTH;
+    unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH;
+    unique->reordCycle = 0;	/* do not use alternate threshold */
+    unique->size = numVars;
+    unique->sizeZ = numVarsZ;
+    unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars);
+    unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ);
+
+    /* Adjust the requested number of slots to a power of 2. */
+    slots = 8;
+    while (slots < numSlots) {
+	slots <<= 1;
+    }
+    unique->initSlots = slots;
+    shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots);
+
+    unique->slots = (numVars + numVarsZ + 1) * slots;
+    unique->keys = 0;
+    unique->maxLive = ~0;	/* very large number */
+    unique->keysZ = 0;
+    unique->dead = 0;
+    unique->deadZ = 0;
+    unique->gcFrac = DD_GC_FRAC_HI;
+    unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
+    unique->looseUpTo = looseUpTo;
+    unique->gcEnabled = 1;
+    unique->allocated = 0;
+    unique->reclaimed = 0;
+    unique->subtables = ALLOC(DdSubtable,unique->maxSize);
+    if (unique->subtables == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ);
+    if (unique->subtableZ == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    unique->perm = ALLOC(int,unique->maxSize);
+    if (unique->perm == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    unique->invperm = ALLOC(int,unique->maxSize);
+    if (unique->invperm == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    unique->permZ = ALLOC(int,unique->maxSizeZ);
+    if (unique->permZ == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    unique->invpermZ = ALLOC(int,unique->maxSizeZ);
+    if (unique->invpermZ == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    unique->map = NULL;
+    unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1);
+    if (unique->stack == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    unique->stack[0] = NULL; /* to suppress harmless UMR */
+
+#ifndef DD_NO_DEATH_ROW
+    unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2);
+    unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth);
+    if (unique->deathRow == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < unique->deathRowDepth; i++) {
+	unique->deathRow[i] = NULL;
+    }
+    unique->nextDead = 0;
+    unique->deadMask = unique->deathRowDepth - 1;
+#endif
+
+    for (i = 0; (unsigned) i < numVars; i++) {
+	unique->subtables[i].slots = slots;
+	unique->subtables[i].shift = shift;
+	unique->subtables[i].keys = 0;
+	unique->subtables[i].dead = 0;
+	unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+	unique->subtables[i].bindVar = 0;
+	unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+	unique->subtables[i].pairIndex = 0;
+	unique->subtables[i].varHandled = 0;
+	unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+	nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots);
+	if (nodelist == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(NULL);
+	}
+	for (j = 0; (unsigned) j < slots; j++) {
+	    nodelist[j] = sentinel;
+	}
+	unique->perm[i] = i;
+	unique->invperm[i] = i;
+    }
+    for (i = 0; (unsigned) i < numVarsZ; i++) {
+	unique->subtableZ[i].slots = slots;
+	unique->subtableZ[i].shift = shift;
+	unique->subtableZ[i].keys = 0;
+	unique->subtableZ[i].dead = 0;
+	unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+	nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots);
+	if (nodelist == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(NULL);
+	}
+	for (j = 0; (unsigned) j < slots; j++) {
+	    nodelist[j] = NULL;
+	}
+	unique->permZ[i] = i;
+	unique->invpermZ[i] = i;
+    }
+    unique->constants.slots = slots;
+    unique->constants.shift = shift;
+    unique->constants.keys = 0;
+    unique->constants.dead = 0;
+    unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+    nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots);
+    if (nodelist == NULL) {
+	unique->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (j = 0; (unsigned) j < slots; j++) {
+	nodelist[j] = NULL;
+    }
+
+    unique->memoryList = NULL;
+    unique->nextFree = NULL;
+
+    unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ)
+	* (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) *
+	slots * sizeof(DdNodePtr) +
+	(ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr);
+#ifndef DD_NO_DEATH_ROW
+    unique->memused += unique->deathRowDepth * sizeof(DdNodePtr);
+#endif
+
+    /* Initialize fields concerned with automatic dynamic reordering */
+    unique->reorderings = 0;
+    unique->autoDyn = 0;	/* initially disabled */
+    unique->autoDynZ = 0;	/* initially disabled */
+    unique->realign = 0;	/* initially disabled */
+    unique->realignZ = 0;	/* initially disabled */
+    unique->reordered = 0;
+    unique->autoMethod = CUDD_REORDER_SIFT;
+    unique->autoMethodZ = CUDD_REORDER_SIFT;
+    unique->nextDyn = DD_FIRST_REORDER;
+    unique->countDead = ~0;
+    unique->siftMaxVar = DD_SIFT_MAX_VAR;
+    unique->siftMaxSwap = DD_SIFT_MAX_SWAPS;
+    unique->tree = NULL;
+    unique->treeZ = NULL;
+    unique->groupcheck = CUDD_GROUP_CHECK7;
+    unique->recomb = DD_DEFAULT_RECOMB;
+    unique->symmviolation = 0;
+    unique->arcviolation = 0;
+    unique->populationSize = 0;
+    unique->numberXovers = 0;
+    unique->linear = NULL;
+    unique->linearSize = 0;
+
+    /* Initialize ZDD universe. */
+    unique->univ = (DdNodePtr *)NULL;
+
+    /* Initialize auxiliary fields. */
+    unique->localCaches = NULL;
+    unique->preGCHook = NULL;
+    unique->postGCHook = NULL;
+    unique->preReorderingHook = NULL;
+    unique->postReorderingHook = NULL;
+    unique->out = stdout;
+    unique->err = stderr;
+    unique->errorCode = CUDD_NO_ERROR;
+
+    /* Initialize statistical counters. */
+    unique->maxmemhard = (unsigned long) ((~ (unsigned long) 0) >> 1);
+    unique->garbageCollections = 0;
+    unique->GCTime = 0;
+    unique->reordTime = 0;
+#ifdef DD_STATS
+    unique->nodesDropped = 0;
+    unique->nodesFreed = 0;
+#endif
+    unique->peakLiveNodes = 0;
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps = 0;
+    unique->uniqueLinks = 0;
+#endif
+#ifdef DD_COUNT
+    unique->recursiveCalls = 0;
+    unique->swapSteps = 0;
+#ifdef DD_STATS
+    unique->nextSample = 250000;
+#endif
+#endif
+
+    return(unique);
+
+} /* end of cuddInitTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the resources associated to a unique table.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddInitTable]
+
+******************************************************************************/
+void
+cuddFreeTable(
+  DdManager * unique)
+{
+    DdNodePtr *next;
+    DdNodePtr *memlist = unique->memoryList;
+    int i;
+
+    if (unique->univ != NULL) cuddZddFreeUniv(unique);
+    while (memlist != NULL) {
+        next = (DdNodePtr *) memlist[0];	/* link to next block */
+	FREE(memlist);
+	memlist = next;
+    }
+    unique->nextFree = NULL;
+    unique->memoryList = NULL;
+
+    for (i = 0; i < unique->size; i++) {
+	FREE(unique->subtables[i].nodelist);
+    }
+    for (i = 0; i < unique->sizeZ; i++) {
+	FREE(unique->subtableZ[i].nodelist);
+    }
+    FREE(unique->constants.nodelist);
+    FREE(unique->subtables);
+    FREE(unique->subtableZ);
+    FREE(unique->acache);
+    FREE(unique->perm);
+    FREE(unique->permZ);
+    FREE(unique->invperm);
+    FREE(unique->invpermZ);
+    FREE(unique->vars);
+    if (unique->map != NULL) FREE(unique->map);
+    FREE(unique->stack);
+#ifndef DD_NO_DEATH_ROW
+    FREE(unique->deathRow);
+#endif
+    if (unique->tree != NULL) Mtr_FreeTree(unique->tree);
+    if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ);
+    if (unique->linear != NULL) FREE(unique->linear);
+    while (unique->preGCHook != NULL)
+	Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK);
+    while (unique->postGCHook != NULL)
+	Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK);
+    while (unique->preReorderingHook != NULL)
+	Cudd_RemoveHook(unique,unique->preReorderingHook->f,
+			CUDD_PRE_REORDERING_HOOK);
+    while (unique->postReorderingHook != NULL)
+	Cudd_RemoveHook(unique,unique->postReorderingHook->f,
+			CUDD_POST_REORDERING_HOOK);
+    FREE(unique);
+
+} /* end of cuddFreeTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs garbage collection on the unique tables.]
+
+  Description [Performs garbage collection on the BDD and ZDD unique tables.
+  If clearCache is 0, the cache is not cleared. This should only be
+  specified if the cache has been cleared right before calling
+  cuddGarbageCollect. (As in the case of dynamic reordering.)
+  Returns the total number of deleted nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddGarbageCollect(
+  DdManager * unique,
+  int  clearCache)
+{
+    DdHook	*hook;
+    DdCache	*cache = unique->cache;
+    DdNode	*sentinel = &(unique->sentinel);
+    DdNodePtr	*nodelist;
+    int		i, j, deleted, totalDeleted, totalDeletedZ;
+    DdCache	*c;
+    DdNode	*node,*next;
+    DdNodePtr	*lastP;
+    int		slots;
+    long	localTime;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+    DdNodePtr	tree;
+#else
+    DdNodePtr *memListTrav, *nxtNode;
+    DdNode *downTrav, *sentry;
+    int k;
+#endif
+#endif
+
+#ifndef DD_NO_DEATH_ROW
+    cuddClearDeathRow(unique);
+#endif
+
+    hook = unique->preGCHook;
+    while (hook != NULL) {
+	int res = (hook->f)(unique,"DD",NULL);
+	if (res == 0) return(0);
+	hook = hook->next;
+    }
+
+    if (unique->dead + unique->deadZ == 0) {
+	hook = unique->postGCHook;
+	while (hook != NULL) {
+	    int res = (hook->f)(unique,"DD",NULL);
+	    if (res == 0) return(0);
+	    hook = hook->next;
+	}
+        return(0);
+    }
+
+    /* If many nodes are being reclaimed, we want to resize the tables
+    ** more aggressively, to reduce the frequency of garbage collection.
+    */
+    if (clearCache && unique->gcFrac == DD_GC_FRAC_LO &&
+	unique->slots <= unique->looseUpTo && unique->stash != NULL) {
+	unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI);
+	(void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+#endif
+	unique->gcFrac = DD_GC_FRAC_HI;
+	return(0);
+    }
+
+    localTime = util_cpu_time();
+
+    unique->garbageCollections++;
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err,
+		   "garbage collecting (%d dead BDD nodes out of %d, min %d)...",
+    		   unique->dead, unique->keys, unique->minDead);
+    (void) fprintf(unique->err,
+		   "                   (%d dead ZDD nodes out of %d)...",
+    		   unique->deadZ, unique->keysZ);
+#endif
+
+    /* Remove references to garbage collected nodes from the cache. */
+    if (clearCache) {
+	slots = unique->cacheSlots;
+	for (i = 0; i < slots; i++) {
+	    c = &cache[i];
+	    if (c->data != NULL) {
+		if (cuddClean(c->f)->ref == 0 ||
+		cuddClean(c->g)->ref == 0 ||
+		(((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) ||
+		(c->data != DD_NON_CONSTANT &&
+		Cudd_Regular(c->data)->ref == 0)) {
+		    c->data = NULL;
+		    unique->cachedeletions++;
+		}
+	    }
+	}
+	cuddLocalCacheClearDead(unique);
+    }
+
+    /* Now return dead nodes to free list. Count them for sanity check. */
+    totalDeleted = 0;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+    tree = NULL;
+#endif
+#endif
+
+    for (i = 0; i < unique->size; i++) {
+	if (unique->subtables[i].dead == 0) continue;
+	nodelist = unique->subtables[i].nodelist;
+
+	deleted = 0;
+	slots = unique->subtables[i].slots;
+	for (j = 0; j < slots; j++) {
+	    lastP = &(nodelist[j]);
+	    node = *lastP;
+	    while (node != sentinel) {
+		next = node->next;
+		if (node->ref == 0) {
+		    deleted++;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+		    cuddOrderedInsert(&tree,node);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+#endif
+#else
+		    cuddDeallocNode(unique,node);
+#endif
+		} else {
+		    *lastP = node;
+		    lastP = &(node->next);
+		}
+		node = next;
+	    }
+	    *lastP = sentinel;
+	}
+	if ((unsigned) deleted != unique->subtables[i].dead) {
+	    ddReportRefMess(unique, i, "cuddGarbageCollect");
+	}
+	totalDeleted += deleted;
+	unique->subtables[i].keys -= deleted;
+	unique->subtables[i].dead = 0;
+    }
+    if (unique->constants.dead != 0) {
+	nodelist = unique->constants.nodelist;
+	deleted = 0;
+	slots = unique->constants.slots;
+	for (j = 0; j < slots; j++) {
+	    lastP = &(nodelist[j]);
+	    node = *lastP;
+	    while (node != NULL) {
+		next = node->next;
+		if (node->ref == 0) {
+		    deleted++;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+		    cuddOrderedInsert(&tree,node);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+#endif
+#else
+		    cuddDeallocNode(unique,node);
+#endif
+		} else {
+		    *lastP = node;
+		    lastP = &(node->next);
+		}
+		node = next;
+	    }
+	    *lastP = NULL;
+	}
+	if ((unsigned) deleted != unique->constants.dead) {
+	    ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect");
+	}
+	totalDeleted += deleted;
+	unique->constants.keys -= deleted;
+	unique->constants.dead = 0;
+    }
+    if ((unsigned) totalDeleted != unique->dead) {
+	ddReportRefMess(unique, -1, "cuddGarbageCollect");
+    }
+    unique->keys -= totalDeleted;
+    unique->dead = 0;
+#ifdef DD_STATS
+    unique->nodesFreed += (double) totalDeleted;
+#endif
+
+    totalDeletedZ = 0;
+
+    for (i = 0; i < unique->sizeZ; i++) {
+	if (unique->subtableZ[i].dead == 0) continue;
+	nodelist = unique->subtableZ[i].nodelist;
+
+	deleted = 0;
+	slots = unique->subtableZ[i].slots;
+	for (j = 0; j < slots; j++) {
+	    lastP = &(nodelist[j]);
+	    node = *lastP;
+	    while (node != NULL) {
+		next = node->next;
+		if (node->ref == 0) {
+		    deleted++;
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+#ifdef __osf__
+#pragma pointer_size save
+#pragma pointer_size short
+#endif
+		    cuddOrderedInsert(&tree,node);
+#ifdef __osf__
+#pragma pointer_size restore
+#endif
+#endif
+#else
+		    cuddDeallocNode(unique,node);
+#endif
+		} else {
+		    *lastP = node;
+		    lastP = &(node->next);
+		}
+		node = next;
+	    }
+	    *lastP = NULL;
+	}
+	if ((unsigned) deleted != unique->subtableZ[i].dead) {
+	    ddReportRefMess(unique, i, "cuddGarbageCollect");
+	}
+	totalDeletedZ += deleted;
+	unique->subtableZ[i].keys -= deleted;
+	unique->subtableZ[i].dead = 0;
+    }
+
+    /* No need to examine the constant table for ZDDs.
+    ** If we did we should be careful not to count whatever dead
+    ** nodes we found there among the dead ZDD nodes. */
+    if ((unsigned) totalDeletedZ != unique->deadZ) {
+	ddReportRefMess(unique, -1, "cuddGarbageCollect");
+    }
+    unique->keysZ -= totalDeletedZ;
+    unique->deadZ = 0;
+#ifdef DD_STATS
+    unique->nodesFreed += (double) totalDeletedZ;
+#endif
+
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+    unique->nextFree = cuddOrderedThread(tree,unique->nextFree);
+#else
+    memListTrav = unique->memoryList;
+    sentry = NULL;
+    while (memListTrav != NULL) {
+        ptruint offset;
+        nxtNode = (DdNodePtr *)memListTrav[0];
+	offset = (ptruint) memListTrav & (sizeof(DdNode) - 1);
+	memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
+	downTrav = (DdNode *)memListTrav;
+	k = 0;
+	do {
+	    if (downTrav[k].ref == 0) {
+	        if (sentry == NULL) {
+		    unique->nextFree = sentry = &downTrav[k];
+		} else {
+		    /* First hook sentry->next to the dead node and then
+		    ** reassign sentry to the dead node. */
+		    sentry = (sentry->next = &downTrav[k]);
+		}
+	    }
+	} while (++k < DD_MEM_CHUNK);
+	memListTrav = nxtNode;
+    }
+    sentry->next = NULL;
+#endif
+#endif
+
+    unique->GCTime += util_cpu_time() - localTime;
+
+    hook = unique->postGCHook;
+    while (hook != NULL) {
+	int res = (hook->f)(unique,"DD",NULL);
+	if (res == 0) return(0);
+	hook = hook->next;
+    }
+
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err," done\n");
+#endif
+
+    return(totalDeleted+totalDeletedZ);
+
+} /* end of cuddGarbageCollect */
+
+
+/**Function********************************************************************
+
+  Synopsis [Wrapper for cuddUniqueInterZdd.]
+
+  Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD
+  reduction rule. Returns a pointer to the result node under normal
+  conditions; NULL if reordering occurred or memory was exhausted.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInterZdd]
+
+******************************************************************************/
+DdNode *
+cuddZddGetNode(
+  DdManager * zdd,
+  int  id,
+  DdNode * T,
+  DdNode * E)
+{
+    DdNode	*node;
+
+    if (T == DD_ZERO(zdd))
+	return(E);
+    node = cuddUniqueInterZdd(zdd, id, T, E);
+    return(node);
+
+} /* end of cuddZddGetNode */
+
+
+/**Function********************************************************************
+
+  Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable
+  ordering.]
+
+  Description [Wrapper for cuddUniqueInterZdd that is independent of
+  variable ordering (IVO). This function does not require parameter
+  index to precede the indices of the top nodes of g and h in the
+  variable order.  Returns a pointer to the result node under normal
+  conditions; NULL if reordering occurred or memory was exhausted.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddGetNode cuddZddIsop]
+
+******************************************************************************/
+DdNode *
+cuddZddGetNodeIVO(
+  DdManager * dd,
+  int  index,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode	*f, *r, *t;
+    DdNode	*zdd_one = DD_ONE(dd);
+    DdNode	*zdd_zero = DD_ZERO(dd);
+
+    f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero);
+    if (f == NULL) {
+	return(NULL);
+    }
+    cuddRef(f);
+    t = cuddZddProduct(dd, f, g);
+    if (t == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f);
+	return(NULL);
+    }
+    cuddRef(t);
+    Cudd_RecursiveDerefZdd(dd, f);
+    r = cuddZddUnion(dd, t, h);
+    if (r == NULL) {
+	Cudd_RecursiveDerefZdd(dd, t);
+	return(NULL);
+    }
+    cuddRef(r);
+    Cudd_RecursiveDerefZdd(dd, t);
+
+    cuddDeref(r);
+    return(r);
+
+} /* end of cuddZddGetNodeIVO */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of an internal node.]
+
+  Description [Checks the unique table for the existence of an internal
+  node. If it does not exist, it creates a new one.  Does not
+  modify the reference count of whatever is returned.  A newly created
+  internal node comes back with a reference count 0.  For a newly
+  created node, increments the reference counts of what T and E point
+  to.  Returns a pointer to the new node if successful; NULL if memory
+  is exhausted or if reordering took place.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInterZdd]
+
+******************************************************************************/
+DdNode *
+cuddUniqueInter(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    int pos;
+    unsigned int level;
+    int retval;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    DdNodePtr *previousP;
+    DdSubtable *subtable;
+    int gcNumber;
+
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps++;
+#endif
+
+    if (index >= unique->size) {
+	if (!ddResizeTable(unique,index)) return(NULL);
+    }
+
+    level = unique->perm[index];
+    subtable = &(unique->subtables[level]);
+
+#ifdef DD_DEBUG
+    assert(level < (unsigned) cuddI(unique,T->index));
+    assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
+#endif
+
+    pos = ddHash(T, E, subtable->shift);
+    nodelist = subtable->nodelist;
+    previousP = &(nodelist[pos]);
+    looking = *previousP;
+
+    while (T < cuddT(looking)) {
+	previousP = &(looking->next);
+	looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+	unique->uniqueLinks++;
+#endif
+    }
+    while (T == cuddT(looking) && E < cuddE(looking)) {
+	previousP = &(looking->next);
+	looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+	unique->uniqueLinks++;
+#endif
+    }
+    if (T == cuddT(looking) && E == cuddE(looking)) {
+	if (looking->ref == 0) {
+	    cuddReclaim(unique,looking);
+	}
+	return(looking);
+    }
+
+    /* countDead is 0 if deads should be counted and ~0 if they should not. */
+    if (unique->autoDyn &&
+    unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) {
+#ifdef DD_DEBUG
+	retval = Cudd_DebugCheck(unique);
+	if (retval != 0) return(NULL);
+	retval = Cudd_CheckKeys(unique);
+	if (retval != 0) return(NULL);
+#endif
+	retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */
+	if (retval == 0) unique->reordered = 2;
+#ifdef DD_DEBUG
+	retval = Cudd_DebugCheck(unique);
+	if (retval != 0) unique->reordered = 2;
+	retval = Cudd_CheckKeys(unique);
+	if (retval != 0) unique->reordered = 2;
+#endif
+	return(NULL);
+    }
+
+    if (subtable->keys > subtable->maxKeys) {
+        if (unique->gcEnabled &&
+	    ((unique->dead > unique->minDead) ||
+	    ((unique->dead > unique->minDead / 2) &&
+	    (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */
+	    (void) cuddGarbageCollect(unique,1);
+	} else {
+	    cuddRehash(unique,(int)level);
+	}
+	/* Update pointer to insertion point. In the case of rehashing,
+	** the slot may have changed. In the case of garbage collection,
+	** the predecessor may have been dead. */
+	pos = ddHash(T, E, subtable->shift);
+	nodelist = subtable->nodelist;
+	previousP = &(nodelist[pos]);
+	looking = *previousP;
+
+	while (T < cuddT(looking)) {
+	    previousP = &(looking->next);
+	    looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+	    unique->uniqueLinks++;
+#endif
+	}
+	while (T == cuddT(looking) && E < cuddE(looking)) {
+	    previousP = &(looking->next);
+	    looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+	    unique->uniqueLinks++;
+#endif
+	}
+    }
+
+    gcNumber = unique->garbageCollections;
+    looking = cuddAllocNode(unique);
+    if (looking == NULL) {
+	return(NULL);
+    }
+    unique->keys++;
+    subtable->keys++;
+
+    if (gcNumber != unique->garbageCollections) {
+	DdNode *looking2;
+	pos = ddHash(T, E, subtable->shift);
+	nodelist = subtable->nodelist;
+	previousP = &(nodelist[pos]);
+	looking2 = *previousP;
+
+	while (T < cuddT(looking2)) {
+	    previousP = &(looking2->next);
+	    looking2 = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+	    unique->uniqueLinks++;
+#endif
+	}
+	while (T == cuddT(looking2) && E < cuddE(looking2)) {
+	    previousP = &(looking2->next);
+	    looking2 = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+	    unique->uniqueLinks++;
+#endif
+	}
+    }
+    looking->index = index;
+    cuddT(looking) = T;
+    cuddE(looking) = E;
+    looking->next = *previousP;
+    *previousP = looking;
+    cuddSatInc(T->ref);		/* we know T is a regular pointer */
+    cuddRef(E);
+
+#ifdef DD_DEBUG
+    cuddCheckCollisionOrdering(unique,level,pos);
+#endif
+
+    return(looking);
+
+} /* end of cuddUniqueInter */
+
+
+/**Function********************************************************************
+
+  Synopsis [Wrapper for cuddUniqueInter that is independent of variable
+  ordering.]
+
+  Description [Wrapper for cuddUniqueInter that is independent of
+  variable ordering (IVO). This function does not require parameter
+  index to precede the indices of the top nodes of T and E in the
+  variable order.  Returns a pointer to the result node under normal
+  conditions; NULL if reordering occurred or memory was exhausted.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInter Cudd_MakeBddFromZddCover]
+
+******************************************************************************/
+DdNode *
+cuddUniqueInterIVO(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    DdNode *result;
+    DdNode *v;
+
+    v = cuddUniqueInter(unique, index, DD_ONE(unique),
+			Cudd_Not(DD_ONE(unique)));
+    if (v == NULL)
+	return(NULL);
+    cuddRef(v);
+    result = cuddBddIteRecur(unique, v, T, E);
+    Cudd_RecursiveDeref(unique, v);
+    return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of an internal
+  ZDD node.]
+
+  Description [Checks the unique table for the existence of an internal
+  ZDD node. If it does not exist, it creates a new one.  Does not
+  modify the reference count of whatever is returned.  A newly created
+  internal node comes back with a reference count 0.  For a newly
+  created node, increments the reference counts of what T and E point
+  to.  Returns a pointer to the new node if successful; NULL if memory
+  is exhausted or if reordering took place.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInter]
+
+******************************************************************************/
+DdNode *
+cuddUniqueInterZdd(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    int pos;
+    unsigned int level;
+    int retval;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    DdSubtable *subtable;
+
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps++;
+#endif
+
+    if (index >= unique->sizeZ) {
+	if (!cuddResizeTableZdd(unique,index)) return(NULL);
+    }
+
+    level = unique->permZ[index];
+    subtable = &(unique->subtableZ[level]);
+
+#ifdef DD_DEBUG
+    assert(level < (unsigned) cuddIZ(unique,T->index));
+    assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index));
+#endif
+
+    if (subtable->keys > subtable->maxKeys) {
+        if (unique->gcEnabled && ((unique->deadZ > unique->minDead) ||
+	(10 * subtable->dead > 9 * subtable->keys))) { 	/* too many dead */
+	    (void) cuddGarbageCollect(unique,1);
+	} else {
+	    ddRehashZdd(unique,(int)level);
+	}
+    }
+
+    pos = ddHash(T, E, subtable->shift);
+    nodelist = subtable->nodelist;
+    looking = nodelist[pos];
+
+    while (looking != NULL) {
+        if (cuddT(looking) == T && cuddE(looking) == E) {
+	    if (looking->ref == 0) {
+		cuddReclaimZdd(unique,looking);
+	    }
+	    return(looking);
+	}
+	looking = looking->next;
+#ifdef DD_UNIQUE_PROFILE
+	unique->uniqueLinks++;
+#endif
+    }
+
+    /* countDead is 0 if deads should be counted and ~0 if they should not. */
+    if (unique->autoDynZ &&
+    unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) {
+#ifdef DD_DEBUG
+	retval = Cudd_DebugCheck(unique);
+	if (retval != 0) return(NULL);
+	retval = Cudd_CheckKeys(unique);
+	if (retval != 0) return(NULL);
+#endif
+	retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */
+	if (retval == 0) unique->reordered = 2;
+#ifdef DD_DEBUG
+	retval = Cudd_DebugCheck(unique);
+	if (retval != 0) unique->reordered = 2;
+	retval = Cudd_CheckKeys(unique);
+	if (retval != 0) unique->reordered = 2;
+#endif
+	return(NULL);
+    }
+
+    unique->keysZ++;
+    subtable->keys++;
+
+    looking = cuddAllocNode(unique);
+    if (looking == NULL) return(NULL);
+    looking->index = index;
+    cuddT(looking) = T;
+    cuddE(looking) = E;
+    looking->next = nodelist[pos];
+    nodelist[pos] = looking;
+    cuddRef(T);
+    cuddRef(E);
+
+    return(looking);
+
+} /* end of cuddUniqueInterZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of a constant node.]
+
+  Description [Checks the unique table for the existence of a constant node.
+  If it does not exist, it creates a new one.  Does not
+  modify the reference count of whatever is returned.  A newly created
+  internal node comes back with a reference count 0.  Returns a
+  pointer to the new node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+DdNode *
+cuddUniqueConst(
+  DdManager * unique,
+  CUDD_VALUE_TYPE  value)
+{
+    int pos;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    hack split;
+
+#ifdef DD_UNIQUE_PROFILE
+    unique->uniqueLookUps++;
+#endif
+
+    if (unique->constants.keys > unique->constants.maxKeys) {
+        if (unique->gcEnabled && ((unique->dead > unique->minDead) ||
+	(10 * unique->constants.dead > 9 * unique->constants.keys))) { 	/* too many dead */
+	    (void) cuddGarbageCollect(unique,1);
+	} else {
+	    cuddRehash(unique,CUDD_CONST_INDEX);
+	}
+    }
+
+    cuddAdjust(value); /* for the case of crippled infinities */
+
+    if (ddAbs(value) < unique->epsilon) {
+	value = 0.0;
+    }
+    split.value = value;
+
+    pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift);
+    nodelist = unique->constants.nodelist;
+    looking = nodelist[pos];
+
+    /* Here we compare values both for equality and for difference less
+     * than epsilon. The first comparison is required when values are
+     * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for
+     * every X.
+     */
+    while (looking != NULL) {
+        if (looking->type.value == value ||
+	ddEqualVal(looking->type.value,value,unique->epsilon)) {
+	    if (looking->ref == 0) {
+		cuddReclaim(unique,looking);
+	    }
+	    return(looking);
+	}
+	looking = looking->next;
+#ifdef DD_UNIQUE_PROFILE
+	unique->uniqueLinks++;
+#endif
+    }
+
+    unique->keys++;
+    unique->constants.keys++;
+
+    looking = cuddAllocNode(unique);
+    if (looking == NULL) return(NULL);
+    looking->index = CUDD_CONST_INDEX;
+    looking->type.value = value;
+    looking->next = nodelist[pos];
+    nodelist[pos] = looking;
+
+    return(looking);
+
+} /* end of cuddUniqueConst */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rehashes a unique subtable.]
+
+  Description [Doubles the size of a unique subtable and rehashes its
+  contents.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddRehash(
+  DdManager * unique,
+  int i)
+{
+    unsigned int slots, oldslots;
+    int shift, oldshift;
+    int j, pos;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    DdNode *sentinel = &(unique->sentinel);
+    hack split;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) {
+	unique->gcFrac = DD_GC_FRAC_LO;
+	unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO);
+	(void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+#endif
+    }
+
+    if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) {
+	unique->gcFrac = DD_GC_FRAC_MIN;
+	unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN);
+	(void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+#endif
+	cuddShrinkDeathRow(unique);
+	if (cuddGarbageCollect(unique,1) > 0) return;
+    }
+
+    if (i != CUDD_CONST_INDEX) {
+	oldslots = unique->subtables[i].slots;
+	oldshift = unique->subtables[i].shift;
+	oldnodelist = unique->subtables[i].nodelist;
+
+	/* Compute the new size of the subtable. */
+	slots = oldslots << 1;
+	shift = oldshift - 1;
+
+	saveHandler = MMoutOfMemory;
+	MMoutOfMemory = Cudd_OutOfMem;
+	nodelist = ALLOC(DdNodePtr, slots);
+	MMoutOfMemory = saveHandler;
+	if (nodelist == NULL) {
+	    (void) fprintf(unique->err,
+			   "Unable to resize subtable %d for lack of memory\n",
+			   i);
+	    /* Prevent frequent resizing attempts. */
+	    (void) cuddGarbageCollect(unique,1);
+	    if (unique->stash != NULL) {
+		FREE(unique->stash);
+		unique->stash = NULL;
+		/* Inhibit resizing of tables. */
+		cuddSlowTableGrowth(unique);
+	    }
+	    return;
+	}
+	unique->subtables[i].nodelist = nodelist;
+	unique->subtables[i].slots = slots;
+	unique->subtables[i].shift = shift;
+	unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+
+	/* Move the nodes from the old table to the new table.
+	** This code depends on the type of hash function.
+	** It assumes that the effect of doubling the size of the table
+	** is to retain one more bit of the 32-bit hash value.
+	** The additional bit is the LSB. */
+	for (j = 0; (unsigned) j < oldslots; j++) {
+	    DdNodePtr *evenP, *oddP;
+	    node = oldnodelist[j];
+	    evenP = &(nodelist[j<<1]);
+	    oddP = &(nodelist[(j<<1)+1]);
+	    while (node != sentinel) {
+		next = node->next;
+		pos = ddHash(cuddT(node), cuddE(node), shift);
+		if (pos & 1) {
+		    *oddP = node;
+		    oddP = &(node->next);
+		} else {
+		    *evenP = node;
+		    evenP = &(node->next);
+		}
+		node = next;
+	    }
+	    *evenP = *oddP = sentinel;
+	}
+	FREE(oldnodelist);
+
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,
+		       "rehashing layer %d: keys %d dead %d new size %d\n",
+		       i, unique->subtables[i].keys,
+		       unique->subtables[i].dead, slots);
+#endif
+    } else {
+	oldslots = unique->constants.slots;
+	oldshift = unique->constants.shift;
+	oldnodelist = unique->constants.nodelist;
+
+	/* The constant subtable is never subjected to reordering.
+	** Therefore, when it is resized, it is because it has just
+	** reached the maximum load. We can safely just double the size,
+	** with no need for the loop we use for the other tables.
+	*/
+	slots = oldslots << 1;
+	shift = oldshift - 1;
+	saveHandler = MMoutOfMemory;
+	MMoutOfMemory = Cudd_OutOfMem;
+	nodelist = ALLOC(DdNodePtr, slots);
+	MMoutOfMemory = saveHandler;
+	if (nodelist == NULL) {
+	    int j;
+	    (void) fprintf(unique->err,
+			   "Unable to resize constant subtable for lack of memory\n");
+	    (void) cuddGarbageCollect(unique,1);
+	    for (j = 0; j < unique->size; j++) {
+		unique->subtables[j].maxKeys <<= 1;
+	    }
+	    unique->constants.maxKeys <<= 1;
+	    return;
+	}
+	unique->constants.slots = slots;
+	unique->constants.shift = shift;
+	unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+	unique->constants.nodelist = nodelist;
+	for (j = 0; (unsigned) j < slots; j++) {
+	    nodelist[j] = NULL;
+	}
+	for (j = 0; (unsigned) j < oldslots; j++) {
+	    node = oldnodelist[j];
+	    while (node != NULL) {
+		next = node->next;
+		split.value = cuddV(node);
+		pos = ddHash(split.bits[0], split.bits[1], shift);
+		node->next = nodelist[pos];
+		nodelist[pos] = node;
+		node = next;
+	    }
+	}
+	FREE(oldnodelist);
+
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,
+		       "rehashing constants: keys %d dead %d new size %d\n",
+		       unique->constants.keys,unique->constants.dead,slots);
+#endif
+    }
+
+    /* Update global data */
+
+    unique->memused += (slots - oldslots) * sizeof(DdNodePtr);
+    unique->slots += (slots - oldslots);
+    ddFixLimits(unique);
+
+} /* end of cuddRehash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shrinks a subtable.]
+
+  Description [Shrinks a subtable.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRehash]
+
+******************************************************************************/
+void
+cuddShrinkSubtable(
+  DdManager *unique,
+  int i)
+{
+    int j;
+    int shift, posn;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    DdNode *sentinel = &(unique->sentinel);
+    unsigned int slots, oldslots;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    oldnodelist = unique->subtables[i].nodelist;
+    oldslots = unique->subtables[i].slots;
+    slots = oldslots >> 1;
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    nodelist = ALLOC(DdNodePtr, slots);
+    MMoutOfMemory = saveHandler;
+    if (nodelist == NULL) {
+	return;
+    }
+    unique->subtables[i].nodelist = nodelist;
+    unique->subtables[i].slots = slots;
+    unique->subtables[i].shift++;
+    unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err,
+		   "shrunk layer %d (%d keys) from %d to %d slots\n",
+		   i, unique->subtables[i].keys, oldslots, slots);
+#endif
+
+    for (j = 0; (unsigned) j < slots; j++) {
+	nodelist[j] = sentinel;
+    }
+    shift = unique->subtables[i].shift;
+    for (j = 0; (unsigned) j < oldslots; j++) {
+	node = oldnodelist[j];
+	while (node != sentinel) {
+	    DdNode *looking, *T, *E;
+	    DdNodePtr *previousP;
+	    next = node->next;
+	    posn = ddHash(cuddT(node), cuddE(node), shift);
+	    previousP = &(nodelist[posn]);
+	    looking = *previousP;
+	    T = cuddT(node);
+	    E = cuddE(node);
+	    while (T < cuddT(looking)) {
+		previousP = &(looking->next);
+		looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+		unique->uniqueLinks++;
+#endif
+	    }
+	    while (T == cuddT(looking) && E < cuddE(looking)) {
+		previousP = &(looking->next);
+		looking = *previousP;
+#ifdef DD_UNIQUE_PROFILE
+		unique->uniqueLinks++;
+#endif
+	    }
+	    node->next = *previousP;
+	    *previousP = node;
+	    node = next;
+	}
+    }
+    FREE(oldnodelist);
+
+    unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *);
+    unique->slots += slots - oldslots;
+    unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
+    unique->cacheSlack = (int)
+	ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots)
+	- 2 * (int) unique->cacheSlots;
+
+} /* end of cuddShrinkSubtable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Inserts n new subtables in a unique table at level.]
+
+  Description [Inserts n new subtables in a unique table at level.
+  The number n should be positive, and level should be an existing level.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddDestroySubtables]
+
+******************************************************************************/
+int
+cuddInsertSubtables(
+  DdManager * unique,
+  int  n,
+  int  level)
+{
+    DdSubtable *newsubtables;
+    DdNodePtr *newnodelist;
+    DdNodePtr *newvars;
+    DdNode *sentinel = &(unique->sentinel);
+    int oldsize,newsize;
+    int i,j,index,reorderSave;
+    unsigned int numSlots = unique->initSlots;
+    int *newperm, *newinvperm, *newmap;
+    DdNode *one, *zero;
+
+#ifdef DD_DEBUG
+    assert(n > 0 && level < unique->size);
+#endif
+
+    oldsize = unique->size;
+    /* Easy case: there is still room in the current table. */
+    if (oldsize + n <= unique->maxSize) {
+	/* Shift the tables at and below level. */
+	for (i = oldsize - 1; i >= level; i--) {
+	    unique->subtables[i+n].slots    = unique->subtables[i].slots;
+	    unique->subtables[i+n].shift    = unique->subtables[i].shift;
+	    unique->subtables[i+n].keys     = unique->subtables[i].keys;
+	    unique->subtables[i+n].maxKeys  = unique->subtables[i].maxKeys;
+	    unique->subtables[i+n].dead     = unique->subtables[i].dead;
+	    unique->subtables[i+n].nodelist = unique->subtables[i].nodelist;
+	    unique->subtables[i+n].bindVar  = unique->subtables[i].bindVar;
+	    unique->subtables[i+n].varType  = unique->subtables[i].varType;
+	    unique->subtables[i+n].pairIndex  = unique->subtables[i].pairIndex;
+	    unique->subtables[i+n].varHandled = unique->subtables[i].varHandled;
+	    unique->subtables[i+n].varToBeGrouped =
+		unique->subtables[i].varToBeGrouped;
+
+	    index                           = unique->invperm[i];
+	    unique->invperm[i+n]            = index;
+	    unique->perm[index]            += n;
+	}
+	/* Create new subtables. */
+	for (i = 0; i < n; i++) {
+	    unique->subtables[level+i].slots = numSlots;
+	    unique->subtables[level+i].shift = sizeof(int) * 8 -
+		cuddComputeFloorLog2(numSlots);
+	    unique->subtables[level+i].keys = 0;
+	    unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+	    unique->subtables[level+i].dead = 0;
+	    unique->subtables[level+i].bindVar = 0;
+	    unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT;
+	    unique->subtables[level+i].pairIndex = 0;
+	    unique->subtables[level+i].varHandled = 0;
+	    unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE;
+
+	    unique->perm[oldsize+i] = level + i;
+	    unique->invperm[level+i] = oldsize + i;
+	    newnodelist = unique->subtables[level+i].nodelist =
+		ALLOC(DdNodePtr, numSlots);
+	    if (newnodelist == NULL) {
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    for (j = 0; (unsigned) j < numSlots; j++) {
+		newnodelist[j] = sentinel;
+	    }
+	}
+	if (unique->map != NULL) {
+	    for (i = 0; i < n; i++) {
+		unique->map[oldsize+i] = oldsize + i;
+	    }
+	}
+    } else {
+	/* The current table is too small: we need to allocate a new,
+	** larger one; move all old subtables, and initialize the new
+	** subtables.
+	*/
+	newsize = oldsize + n + DD_DEFAULT_RESIZE;
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,
+		       "Increasing the table size from %d to %d\n",
+	    unique->maxSize, newsize);
+#endif
+	/* Allocate memory for new arrays (except nodelists). */
+	newsubtables = ALLOC(DdSubtable,newsize);
+	if (newsubtables == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	newvars = ALLOC(DdNodePtr,newsize);
+	if (newvars == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    FREE(newsubtables);
+	    return(0);
+	}
+	newperm = ALLOC(int,newsize);
+	if (newperm == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    FREE(newsubtables);
+	    FREE(newvars);
+	    return(0);
+	}
+	newinvperm = ALLOC(int,newsize);
+	if (newinvperm == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    FREE(newsubtables);
+	    FREE(newvars);
+	    FREE(newperm);
+	    return(0);
+	}
+	if (unique->map != NULL) {
+	    newmap = ALLOC(int,newsize);
+	    if (newmap == NULL) {
+		unique->errorCode = CUDD_MEMORY_OUT;
+		FREE(newsubtables);
+		FREE(newvars);
+		FREE(newperm);
+		FREE(newinvperm);
+		return(0);
+	    }
+	    unique->memused += (newsize - unique->maxSize) * sizeof(int);
+	}
+	unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
+	    sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
+	/* Copy levels before insertion points from old tables. */
+	for (i = 0; i < level; i++) {
+	    newsubtables[i].slots = unique->subtables[i].slots;
+	    newsubtables[i].shift = unique->subtables[i].shift;
+	    newsubtables[i].keys = unique->subtables[i].keys;
+	    newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
+	    newsubtables[i].dead = unique->subtables[i].dead;
+	    newsubtables[i].nodelist = unique->subtables[i].nodelist;
+	    newsubtables[i].bindVar = unique->subtables[i].bindVar;
+	    newsubtables[i].varType = unique->subtables[i].varType;
+	    newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
+	    newsubtables[i].varHandled = unique->subtables[i].varHandled;
+	    newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
+
+	    newvars[i] = unique->vars[i];
+	    newperm[i] = unique->perm[i];
+	    newinvperm[i] = unique->invperm[i];
+	}
+	/* Finish initializing permutation for new table to old one. */
+	for (i = level; i < oldsize; i++) {
+	    newperm[i] = unique->perm[i];
+	}
+	/* Initialize new levels. */
+	for (i = level; i < level + n; i++) {
+	    newsubtables[i].slots = numSlots;
+	    newsubtables[i].shift = sizeof(int) * 8 -
+		cuddComputeFloorLog2(numSlots);
+	    newsubtables[i].keys = 0;
+	    newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+	    newsubtables[i].dead = 0;
+	    newsubtables[i].bindVar = 0;
+	    newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+	    newsubtables[i].pairIndex = 0;
+	    newsubtables[i].varHandled = 0;
+	    newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+	    newperm[oldsize + i - level] = i;
+	    newinvperm[i] = oldsize + i - level;
+	    newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
+	    if (newnodelist == NULL) {
+		/* We are going to leak some memory.  We should clean up. */
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    for (j = 0; (unsigned) j < numSlots; j++) {
+		newnodelist[j] = sentinel;
+	    }
+	}
+	/* Copy the old tables for levels past the insertion point. */
+	for (i = level; i < oldsize; i++) {
+	    newsubtables[i+n].slots    = unique->subtables[i].slots;
+	    newsubtables[i+n].shift    = unique->subtables[i].shift;
+	    newsubtables[i+n].keys     = unique->subtables[i].keys;
+	    newsubtables[i+n].maxKeys  = unique->subtables[i].maxKeys;
+	    newsubtables[i+n].dead     = unique->subtables[i].dead;
+	    newsubtables[i+n].nodelist = unique->subtables[i].nodelist;
+	    newsubtables[i+n].bindVar  = unique->subtables[i].bindVar;
+	    newsubtables[i+n].varType  = unique->subtables[i].varType;
+	    newsubtables[i+n].pairIndex  = unique->subtables[i].pairIndex;
+	    newsubtables[i+n].varHandled  = unique->subtables[i].varHandled;
+	    newsubtables[i+n].varToBeGrouped  =
+		unique->subtables[i].varToBeGrouped;
+
+	    newvars[i]                 = unique->vars[i];
+	    index                      = unique->invperm[i];
+	    newinvperm[i+n]            = index;
+	    newperm[index]            += n;
+	}
+	/* Update the map. */
+	if (unique->map != NULL) {
+	    for (i = 0; i < oldsize; i++) {
+		newmap[i] = unique->map[i];
+	    }
+	    for (i = oldsize; i < oldsize + n; i++) {
+		newmap[i] = i;
+	    }
+	    FREE(unique->map);
+	    unique->map = newmap;
+	}
+	/* Install the new tables and free the old ones. */
+	FREE(unique->subtables);
+	unique->subtables = newsubtables;
+	unique->maxSize = newsize;
+	FREE(unique->vars);
+	unique->vars = newvars;
+	FREE(unique->perm);
+	unique->perm = newperm;
+	FREE(unique->invperm);
+	unique->invperm = newinvperm;
+	/* Update the stack for iterative procedures. */
+	if (newsize > unique->maxSizeZ) {
+	    FREE(unique->stack);
+	    unique->stack = ALLOC(DdNodePtr,newsize + 1);
+	    if (unique->stack == NULL) {
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    unique->stack[0] = NULL; /* to suppress harmless UMR */
+	    unique->memused +=
+		(newsize - ddMax(unique->maxSize,unique->maxSizeZ))
+		* sizeof(DdNode *);
+	}
+    }
+    /* Update manager parameters to account for the new subtables. */
+    unique->slots += n * numSlots;
+    ddFixLimits(unique);
+    unique->size += n;
+
+    /* Now that the table is in a coherent state, create the new
+    ** projection functions. We need to temporarily disable reordering,
+    ** because we cannot reorder without projection functions in place.
+    **/
+    one = unique->one;
+    zero = Cudd_Not(one);
+
+    reorderSave = unique->autoDyn;
+    unique->autoDyn = 0;
+    for (i = oldsize; i < oldsize + n; i++) {
+	unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
+	if (unique->vars[i] == NULL) {
+	    unique->autoDyn = reorderSave;
+	    /* Shift everything back so table remains coherent. */
+	    for (j = oldsize; j < i; j++) {
+		Cudd_IterDerefBdd(unique,unique->vars[j]);
+		cuddDeallocNode(unique,unique->vars[j]);
+		unique->vars[j] = NULL;
+	    }
+	    for (j = level; j < oldsize; j++) {
+		unique->subtables[j].slots    = unique->subtables[j+n].slots;
+		unique->subtables[j].slots    = unique->subtables[j+n].slots;
+		unique->subtables[j].shift    = unique->subtables[j+n].shift;
+		unique->subtables[j].keys     = unique->subtables[j+n].keys;
+		unique->subtables[j].maxKeys  =
+		    unique->subtables[j+n].maxKeys;
+		unique->subtables[j].dead     = unique->subtables[j+n].dead;
+		FREE(unique->subtables[j].nodelist);
+		unique->subtables[j].nodelist =
+		    unique->subtables[j+n].nodelist;
+		unique->subtables[j+n].nodelist = NULL;
+		unique->subtables[j].bindVar  =
+		    unique->subtables[j+n].bindVar;
+		unique->subtables[j].varType  =
+		    unique->subtables[j+n].varType;
+		unique->subtables[j].pairIndex =
+		    unique->subtables[j+n].pairIndex;
+		unique->subtables[j].varHandled =
+		    unique->subtables[j+n].varHandled;
+		unique->subtables[j].varToBeGrouped =
+		    unique->subtables[j+n].varToBeGrouped;
+		index                         = unique->invperm[j+n];
+		unique->invperm[j]            = index;
+		unique->perm[index]          -= n;
+	    }
+	    unique->size = oldsize;
+	    unique->slots -= n * numSlots;
+	    ddFixLimits(unique);
+	    (void) Cudd_DebugCheck(unique);
+	    return(0);
+	}
+	cuddRef(unique->vars[i]);
+    }
+    if (unique->tree != NULL) {
+	unique->tree->size += n;
+	unique->tree->index = unique->invperm[0];
+	ddPatchTree(unique,unique->tree);
+    }
+    unique->autoDyn = reorderSave;
+
+    return(1);
+
+} /* end of cuddInsertSubtables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Destroys the n most recently created subtables in a unique table.]
+
+  Description [Destroys the n most recently created subtables in a unique
+  table.  n should be positive. The subtables should not contain any live
+  nodes, except the (isolated) projection function. The projection
+  functions are freed.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [The variable map used for fast variable substitution is
+  destroyed if it exists. In this case the cache is also cleared.]
+
+  SeeAlso     [cuddInsertSubtables Cudd_SetVarMap]
+
+******************************************************************************/
+int
+cuddDestroySubtables(
+  DdManager * unique,
+  int  n)
+{
+    DdSubtable *subtables;
+    DdNodePtr *nodelist;
+    DdNodePtr *vars;
+    int firstIndex, lastIndex;
+    int index, level, newlevel;
+    int lowestLevel;
+    int shift;
+    int found;
+
+    /* Sanity check and set up. */
+    if (n <= 0) return(0);
+    if (n > unique->size) n = unique->size;
+
+    subtables = unique->subtables;
+    vars = unique->vars;
+    firstIndex = unique->size - n;
+    lastIndex  = unique->size;
+
+    /* Check for nodes labeled by the variables being destroyed
+    ** that may still be in use.  It is allowed to destroy a variable
+    ** only if there are no such nodes. Also, find the lowest level
+    ** among the variables being destroyed. This will make further
+    ** processing more efficient.
+    */
+    lowestLevel = unique->size;
+    for (index = firstIndex; index < lastIndex; index++) {
+	level = unique->perm[index];
+	if (level < lowestLevel) lowestLevel = level;
+	nodelist = subtables[level].nodelist;
+	if (subtables[level].keys - subtables[level].dead != 1) return(0);
+	/* The projection function should be isolated. If the ref count
+	** is 1, everything is OK. If the ref count is saturated, then
+	** we need to make sure that there are no nodes pointing to it.
+	** As for the external references, we assume the application is
+	** responsible for them.
+	*/
+	if (vars[index]->ref != 1) {
+	    if (vars[index]->ref != DD_MAXREF) return(0);
+	    found = cuddFindParent(unique,vars[index]);
+	    if (found) {
+		return(0);
+	    } else {
+		vars[index]->ref = 1;
+	    }
+	}
+	Cudd_RecursiveDeref(unique,vars[index]);
+    }
+
+    /* Collect garbage, because we cannot afford having dead nodes pointing
+    ** to the dead nodes in the subtables being destroyed.
+    */
+    (void) cuddGarbageCollect(unique,1);
+
+    /* Here we know we can destroy our subtables. */
+    for (index = firstIndex; index < lastIndex; index++) {
+	level = unique->perm[index];
+	nodelist = subtables[level].nodelist;
+#ifdef DD_DEBUG
+	assert(subtables[level].keys == 0);
+#endif
+	FREE(nodelist);
+	unique->memused -= sizeof(DdNodePtr) * subtables[level].slots;
+	unique->slots -= subtables[level].slots;
+	unique->dead -= subtables[level].dead;
+    }
+
+    /* Here all subtables to be destroyed have their keys field == 0 and
+    ** their hash tables have been freed.
+    ** We now scan the subtables from level lowestLevel + 1 to level size - 1,
+    ** shifting the subtables as required. We keep a running count of
+    ** how many subtables have been moved, so that we know by how many
+    ** positions each subtable should be shifted.
+    */
+    shift = 1;
+    for (level = lowestLevel + 1; level < unique->size; level++) {
+	if (subtables[level].keys == 0) {
+	    shift++;
+	    continue;
+	}
+	newlevel = level - shift;
+	subtables[newlevel].slots = subtables[level].slots;
+	subtables[newlevel].shift = subtables[level].shift;
+	subtables[newlevel].keys = subtables[level].keys;
+	subtables[newlevel].maxKeys = subtables[level].maxKeys;
+	subtables[newlevel].dead = subtables[level].dead;
+	subtables[newlevel].nodelist = subtables[level].nodelist;
+	index = unique->invperm[level];
+	unique->perm[index] = newlevel;
+	unique->invperm[newlevel]  = index;
+	subtables[newlevel].bindVar = subtables[level].bindVar;
+	subtables[newlevel].varType = subtables[level].varType;
+	subtables[newlevel].pairIndex = subtables[level].pairIndex;
+	subtables[newlevel].varHandled = subtables[level].varHandled;
+	subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped;
+    }
+    /* Destroy the map. If a surviving variable is
+    ** mapped to a dying variable, and the map were used again,
+    ** an out-of-bounds access to unique->vars would result. */
+    if (unique->map != NULL) {
+	cuddCacheFlush(unique);
+	FREE(unique->map);
+	unique->map = NULL;
+    }
+
+    unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
+    unique->size -= n;
+
+    return(1);
+
+} /* end of cuddDestroySubtables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Increases the number of ZDD subtables in a unique table so
+  that it meets or exceeds index.]
+
+  Description [Increases the number of ZDD subtables in a unique table so
+  that it meets or exceeds index.  When new ZDD variables are created, it
+  is possible to preserve the functions unchanged, or it is possible to
+  preserve the covers unchanged, but not both. cuddResizeTableZdd preserves
+  the covers.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddResizeTable]
+
+******************************************************************************/
+int
+cuddResizeTableZdd(
+  DdManager * unique,
+  int  index)
+{
+    DdSubtable *newsubtables;
+    DdNodePtr *newnodelist;
+    int oldsize,newsize;
+    int i,j,reorderSave;
+    unsigned int numSlots = unique->initSlots;
+    int *newperm, *newinvperm;
+
+    oldsize = unique->sizeZ;
+    /* Easy case: there is still room in the current table. */
+    if (index < unique->maxSizeZ) {
+	for (i = oldsize; i <= index; i++) {
+	    unique->subtableZ[i].slots = numSlots;
+	    unique->subtableZ[i].shift = sizeof(int) * 8 -
+		cuddComputeFloorLog2(numSlots);
+	    unique->subtableZ[i].keys = 0;
+	    unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+	    unique->subtableZ[i].dead = 0;
+	    unique->permZ[i] = i;
+	    unique->invpermZ[i] = i;
+	    newnodelist = unique->subtableZ[i].nodelist =
+		ALLOC(DdNodePtr, numSlots);
+	    if (newnodelist == NULL) {
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    for (j = 0; (unsigned) j < numSlots; j++) {
+		newnodelist[j] = NULL;
+	    }
+	}
+    } else {
+	/* The current table is too small: we need to allocate a new,
+	** larger one; move all old subtables, and initialize the new
+	** subtables up to index included.
+	*/
+	newsize = index + DD_DEFAULT_RESIZE;
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,
+		       "Increasing the ZDD table size from %d to %d\n",
+	    unique->maxSizeZ, newsize);
+#endif
+	newsubtables = ALLOC(DdSubtable,newsize);
+	if (newsubtables == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	newperm = ALLOC(int,newsize);
+	if (newperm == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	newinvperm = ALLOC(int,newsize);
+	if (newinvperm == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) *
+	    sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
+	if (newsize > unique->maxSize) {
+	    FREE(unique->stack);
+	    unique->stack = ALLOC(DdNodePtr,newsize + 1);
+	    if (unique->stack == NULL) {
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    unique->stack[0] = NULL; /* to suppress harmless UMR */
+	    unique->memused +=
+		(newsize - ddMax(unique->maxSize,unique->maxSizeZ))
+		* sizeof(DdNode *);
+	}
+	for (i = 0; i < oldsize; i++) {
+	    newsubtables[i].slots = unique->subtableZ[i].slots;
+	    newsubtables[i].shift = unique->subtableZ[i].shift;
+	    newsubtables[i].keys = unique->subtableZ[i].keys;
+	    newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys;
+	    newsubtables[i].dead = unique->subtableZ[i].dead;
+	    newsubtables[i].nodelist = unique->subtableZ[i].nodelist;
+	    newperm[i] = unique->permZ[i];
+	    newinvperm[i] = unique->invpermZ[i];
+	}
+	for (i = oldsize; i <= index; i++) {
+	    newsubtables[i].slots = numSlots;
+	    newsubtables[i].shift = sizeof(int) * 8 -
+		cuddComputeFloorLog2(numSlots);
+	    newsubtables[i].keys = 0;
+	    newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+	    newsubtables[i].dead = 0;
+	    newperm[i] = i;
+	    newinvperm[i] = i;
+	    newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
+	    if (newnodelist == NULL) {
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    for (j = 0; (unsigned) j < numSlots; j++) {
+		newnodelist[j] = NULL;
+	    }
+	}
+	FREE(unique->subtableZ);
+	unique->subtableZ = newsubtables;
+	unique->maxSizeZ = newsize;
+	FREE(unique->permZ);
+	unique->permZ = newperm;
+	FREE(unique->invpermZ);
+	unique->invpermZ = newinvperm;
+    }
+    unique->slots += (index + 1 - unique->sizeZ) * numSlots;
+    ddFixLimits(unique);
+    unique->sizeZ = index + 1;
+
+    /* Now that the table is in a coherent state, update the ZDD
+    ** universe. We need to temporarily disable reordering,
+    ** because we cannot reorder without universe in place.
+    */
+
+    reorderSave = unique->autoDynZ;
+    unique->autoDynZ = 0;
+    cuddZddFreeUniv(unique);
+    if (!cuddZddInitUniv(unique)) {
+	unique->autoDynZ = reorderSave;
+	return(0);
+    }
+    unique->autoDynZ = reorderSave;
+
+    return(1);
+
+} /* end of cuddResizeTableZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adjusts parameters of a table to slow down its growth.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+cuddSlowTableGrowth(
+  DdManager *unique)
+{
+    int i;
+
+    unique->maxCacheHard = unique->cacheSlots - 1;
+    unique->cacheSlack = -(unique->cacheSlots + 1);
+    for (i = 0; i < unique->size; i++) {
+	unique->subtables[i].maxKeys <<= 2;
+    }
+    unique->gcFrac = DD_GC_FRAC_MIN;
+    unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
+    cuddShrinkDeathRow(unique);
+    (void) fprintf(unique->err,"Slowing down table growth: ");
+    (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac);
+    (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+
+} /* end of cuddSlowTableGrowth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rehashes a ZDD unique subtable.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRehash]
+
+******************************************************************************/
+static void
+ddRehashZdd(
+  DdManager * unique,
+  int  i)
+{
+    unsigned int slots, oldslots;
+    int shift, oldshift;
+    int j, pos;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+    if (unique->slots > unique->looseUpTo) {
+	unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
+#ifdef DD_VERBOSE
+	if (unique->gcFrac == DD_GC_FRAC_HI) {
+	    (void) fprintf(unique->err,"GC fraction = %.2f\t",
+			   DD_GC_FRAC_LO);
+	    (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
+	}
+#endif
+	unique->gcFrac = DD_GC_FRAC_LO;
+    }
+
+    assert(i != CUDD_MAXINDEX);
+    oldslots = unique->subtableZ[i].slots;
+    oldshift = unique->subtableZ[i].shift;
+    oldnodelist = unique->subtableZ[i].nodelist;
+
+    /* Compute the new size of the subtable. Normally, we just
+    ** double.  However, after reordering, a table may be severely
+    ** overloaded. Therefore, we iterate. */
+    slots = oldslots;
+    shift = oldshift;
+    do {
+	slots <<= 1;
+	shift--;
+    } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys);
+
+    saveHandler = MMoutOfMemory;
+    MMoutOfMemory = Cudd_OutOfMem;
+    nodelist = ALLOC(DdNodePtr, slots);
+    MMoutOfMemory = saveHandler;
+    if (nodelist == NULL) {
+	int j;
+	(void) fprintf(unique->err,
+		       "Unable to resize ZDD subtable %d for lack of memory.\n",
+		       i);
+	(void) cuddGarbageCollect(unique,1);
+	for (j = 0; j < unique->sizeZ; j++) {
+	    unique->subtableZ[j].maxKeys <<= 1;
+	}
+	return;
+    }
+    unique->subtableZ[i].nodelist = nodelist;
+    unique->subtableZ[i].slots = slots;
+    unique->subtableZ[i].shift = shift;
+    unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+    for (j = 0; (unsigned) j < slots; j++) {
+	nodelist[j] = NULL;
+    }
+    for (j = 0; (unsigned) j < oldslots; j++) {
+	node = oldnodelist[j];
+	while (node != NULL) {
+	    next = node->next;
+	    pos = ddHash(cuddT(node), cuddE(node), shift);
+	    node->next = nodelist[pos];
+	    nodelist[pos] = node;
+	    node = next;
+	}
+    }
+    FREE(oldnodelist);
+
+#ifdef DD_VERBOSE
+    (void) fprintf(unique->err,
+		   "rehashing layer %d: keys %d dead %d new size %d\n",
+		   i, unique->subtableZ[i].keys,
+		   unique->subtableZ[i].dead, slots);
+#endif
+
+    /* Update global data. */
+    unique->memused += (slots - oldslots) * sizeof(DdNode *);
+    unique->slots += (slots - oldslots);
+    ddFixLimits(unique);
+
+} /* end of ddRehashZdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Increases the number of subtables in a unique table so
+  that it meets or exceeds index.]
+
+  Description [Increases the number of subtables in a unique table so
+  that it meets or exceeds index. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddResizeTableZdd]
+
+******************************************************************************/
+static int
+ddResizeTable(
+  DdManager * unique,
+  int index)
+{
+    DdSubtable *newsubtables;
+    DdNodePtr *newnodelist;
+    DdNodePtr *newvars;
+    DdNode *sentinel = &(unique->sentinel);
+    int oldsize,newsize;
+    int i,j,reorderSave;
+    int numSlots = unique->initSlots;
+    int *newperm, *newinvperm, *newmap;
+    DdNode *one, *zero;
+
+    oldsize = unique->size;
+    /* Easy case: there is still room in the current table. */
+    if (index < unique->maxSize) {
+	for (i = oldsize; i <= index; i++) {
+	    unique->subtables[i].slots = numSlots;
+	    unique->subtables[i].shift = sizeof(int) * 8 -
+		cuddComputeFloorLog2(numSlots);
+	    unique->subtables[i].keys = 0;
+	    unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+	    unique->subtables[i].dead = 0;
+	    unique->subtables[i].bindVar = 0;
+	    unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+	    unique->subtables[i].pairIndex = 0;
+	    unique->subtables[i].varHandled = 0;
+	    unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+	    unique->perm[i] = i;
+	    unique->invperm[i] = i;
+	    newnodelist = unique->subtables[i].nodelist =
+		ALLOC(DdNodePtr, numSlots);
+	    if (newnodelist == NULL) {
+		for (j = oldsize; j < i; j++) {
+		    FREE(unique->subtables[j].nodelist);
+		}
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    for (j = 0; j < numSlots; j++) {
+		newnodelist[j] = sentinel;
+	    }
+	}
+	if (unique->map != NULL) {
+	    for (i = oldsize; i <= index; i++) {
+		unique->map[i] = i;
+	    }
+	}
+    } else {
+	/* The current table is too small: we need to allocate a new,
+	** larger one; move all old subtables, and initialize the new
+	** subtables up to index included.
+	*/
+	newsize = index + DD_DEFAULT_RESIZE;
+#ifdef DD_VERBOSE
+	(void) fprintf(unique->err,
+		       "Increasing the table size from %d to %d\n",
+		       unique->maxSize, newsize);
+#endif
+	newsubtables = ALLOC(DdSubtable,newsize);
+	if (newsubtables == NULL) {
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	newvars = ALLOC(DdNodePtr,newsize);
+	if (newvars == NULL) {
+	    FREE(newsubtables);
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	newperm = ALLOC(int,newsize);
+	if (newperm == NULL) {
+	    FREE(newsubtables);
+	    FREE(newvars);
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	newinvperm = ALLOC(int,newsize);
+	if (newinvperm == NULL) {
+	    FREE(newsubtables);
+	    FREE(newvars);
+	    FREE(newperm);
+	    unique->errorCode = CUDD_MEMORY_OUT;
+	    return(0);
+	}
+	if (unique->map != NULL) {
+	    newmap = ALLOC(int,newsize);
+	    if (newmap == NULL) {
+		FREE(newsubtables);
+		FREE(newvars);
+		FREE(newperm);
+		FREE(newinvperm);
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    unique->memused += (newsize - unique->maxSize) * sizeof(int);
+	}
+	unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
+	    sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
+	if (newsize > unique->maxSizeZ) {
+	    FREE(unique->stack);
+	    unique->stack = ALLOC(DdNodePtr,newsize + 1);
+	    if (unique->stack == NULL) {
+		FREE(newsubtables);
+		FREE(newvars);
+		FREE(newperm);
+		FREE(newinvperm);
+		if (unique->map != NULL) {
+		    FREE(newmap);
+		}
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    unique->stack[0] = NULL; /* to suppress harmless UMR */
+	    unique->memused +=
+		(newsize - ddMax(unique->maxSize,unique->maxSizeZ))
+		* sizeof(DdNode *);
+	}
+	for (i = 0; i < oldsize; i++) {
+	    newsubtables[i].slots = unique->subtables[i].slots;
+	    newsubtables[i].shift = unique->subtables[i].shift;
+	    newsubtables[i].keys = unique->subtables[i].keys;
+	    newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
+	    newsubtables[i].dead = unique->subtables[i].dead;
+	    newsubtables[i].nodelist = unique->subtables[i].nodelist;
+	    newsubtables[i].bindVar = unique->subtables[i].bindVar;
+	    newsubtables[i].varType = unique->subtables[i].varType;
+	    newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
+	    newsubtables[i].varHandled = unique->subtables[i].varHandled;
+	    newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
+
+	    newvars[i] = unique->vars[i];
+	    newperm[i] = unique->perm[i];
+	    newinvperm[i] = unique->invperm[i];
+	}
+	for (i = oldsize; i <= index; i++) {
+	    newsubtables[i].slots = numSlots;
+	    newsubtables[i].shift = sizeof(int) * 8 -
+		cuddComputeFloorLog2(numSlots);
+	    newsubtables[i].keys = 0;
+	    newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
+	    newsubtables[i].dead = 0;
+	    newsubtables[i].bindVar = 0;
+	    newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
+	    newsubtables[i].pairIndex = 0;
+	    newsubtables[i].varHandled = 0;
+	    newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
+
+	    newperm[i] = i;
+	    newinvperm[i] = i;
+	    newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
+	    if (newnodelist == NULL) {
+		unique->errorCode = CUDD_MEMORY_OUT;
+		return(0);
+	    }
+	    for (j = 0; j < numSlots; j++) {
+		newnodelist[j] = sentinel;
+	    }
+	}
+	if (unique->map != NULL) {
+	    for (i = 0; i < oldsize; i++) {
+		newmap[i] = unique->map[i];
+	    }
+	    for (i = oldsize; i <= index; i++) {
+		newmap[i] = i;
+	    }
+	    FREE(unique->map);
+	    unique->map = newmap;
+	}
+	FREE(unique->subtables);
+	unique->subtables = newsubtables;
+	unique->maxSize = newsize;
+	FREE(unique->vars);
+	unique->vars = newvars;
+	FREE(unique->perm);
+	unique->perm = newperm;
+	FREE(unique->invperm);
+	unique->invperm = newinvperm;
+    }
+
+    /* Now that the table is in a coherent state, create the new
+    ** projection functions. We need to temporarily disable reordering,
+    ** because we cannot reorder without projection functions in place.
+    **/
+    one = unique->one;
+    zero = Cudd_Not(one);
+
+    unique->size = index + 1;
+    unique->slots += (index + 1 - oldsize) * numSlots;
+    ddFixLimits(unique);
+
+    reorderSave = unique->autoDyn;
+    unique->autoDyn = 0;
+    for (i = oldsize; i <= index; i++) {
+	unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
+	if (unique->vars[i] == NULL) {
+	    unique->autoDyn = reorderSave;
+	    for (j = oldsize; j < i; j++) {
+		Cudd_IterDerefBdd(unique,unique->vars[j]);
+		cuddDeallocNode(unique,unique->vars[j]);
+		unique->vars[j] = NULL;
+	    }
+	    for (j = oldsize; j <= index; j++) {
+		FREE(unique->subtables[j].nodelist);
+		unique->subtables[j].nodelist = NULL;
+	    }
+	    unique->size = oldsize;
+	    unique->slots -= (index + 1 - oldsize) * numSlots;
+	    ddFixLimits(unique);
+	    return(0);
+	}
+	cuddRef(unique->vars[i]);
+    }
+    unique->autoDyn = reorderSave;
+
+    return(1);
+
+} /* end of ddResizeTable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Searches the subtables above node for a parent.]
+
+  Description [Searches the subtables above node for a parent. Returns 1
+  as soon as one parent is found. Returns 0 is the search is fruitless.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddFindParent(
+  DdManager * table,
+  DdNode * node)
+{
+    int         i,j;
+    int		slots;
+    DdNodePtr	*nodelist;
+    DdNode	*f;
+
+    for (i = cuddI(table,node->index) - 1; i >= 0; i--) {
+	nodelist = table->subtables[i].nodelist;
+	slots = table->subtables[i].slots;
+
+	for (j = 0; j < slots; j++) {
+	    f = nodelist[j];
+	    while (cuddT(f) > node) {
+		f = f->next;
+	    }
+	    while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) {
+		f = f->next;
+	    }
+	    if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) {
+		return(1);
+	    }
+	}
+    }
+
+    return(0);
+
+} /* end of cuddFindParent */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adjusts the values of table limits.]
+
+  Description [Adjusts the values of table fields controlling the.
+  sizes of subtables and computed table. If the computed table is too small
+  according to the new values, it is resized.]
+
+  SideEffects [Modifies manager fields. May resize computed table.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DD_INLINE
+static void
+ddFixLimits(
+  DdManager *unique)
+{
+    unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
+    unique->cacheSlack = (int) ddMin(unique->maxCacheHard,
+	DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) -
+	2 * (int) unique->cacheSlots;
+    if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0)
+	cuddCacheResize(unique);
+    return;
+
+} /* end of ddFixLimits */
+
+
+#ifndef DD_UNSORTED_FREE_LIST
+#ifdef DD_RED_BLACK_FREE_LIST
+/**Function********************************************************************
+
+  Synopsis    [Inserts a DdNode in a red/black search tree.]
+
+  Description [Inserts a DdNode in a red/black search tree. Nodes from
+  the same "page" (defined by DD_PAGE_MASK) are linked in a LIFO list.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddOrderedThread]
+
+******************************************************************************/
+static void
+cuddOrderedInsert(
+  DdNodePtr * root,
+  DdNodePtr node)
+{
+    DdNode *scan;
+    DdNodePtr *scanP;
+    DdNodePtr *stack[DD_STACK_SIZE];
+    int stackN = 0;
+
+    scanP = root;
+    while ((scan = *scanP) != NULL) {
+	stack[stackN++] = scanP;
+	if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */
+	    DD_NEXT(node) = DD_NEXT(scan);
+	    DD_NEXT(scan) = node;
+	    return;
+	}
+	scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan);
+    }
+    DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL;
+    DD_COLOR(node) = DD_RED;
+    *scanP = node;
+    stack[stackN] = &node;
+    cuddDoRebalance(stack,stackN);
+
+} /* end of cuddOrderedInsert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Threads all the nodes of a search tree into a linear list.]
+
+  Description [Threads all the nodes of a search tree into a linear
+  list. For each node of the search tree, the "left" child, if non-null, has
+  a lower address than its parent, and the "right" child, if non-null, has a
+  higher address than its parent.
+  The list is sorted in order of increasing addresses. The search
+  tree is destroyed as a result of this operation. The last element of
+  the linear list is made to point to the address passed in list. Each
+  node if the search tree is a linearly-linked list of nodes from the
+  same memory page (as defined in DD_PAGE_MASK). When a node is added to
+  the linear list, all the elements of the linked list are added.]
+
+  SideEffects [The search tree is destroyed as a result of this operation.]
+
+  SeeAlso     [cuddOrderedInsert]
+
+******************************************************************************/
+static DdNode *
+cuddOrderedThread(
+  DdNode * root,
+  DdNode * list)
+{
+    DdNode *current, *next, *prev, *end;
+
+    current = root;
+    /* The first word in the node is used to implement a stack that holds
+    ** the nodes from the root of the tree to the current node. Here we
+    ** put the root of the tree at the bottom of the stack.
+    */
+    *((DdNodePtr *) current) = NULL;
+
+    while (current != NULL) {
+	if (DD_RIGHT(current) != NULL) {
+	    /* If possible, we follow the "right" link. Eventually we'll
+	    ** find the node with the largest address in the current tree.
+	    ** In this phase we use the first word of a node to implemen
+	    ** a stack of the nodes on the path from the root to "current".
+	    ** Also, we disconnect the "right" pointers to indicate that
+	    ** we have already followed them.
+	    */
+	    next = DD_RIGHT(current);
+	    DD_RIGHT(current) = NULL;
+	    *((DdNodePtr *)next) = current;
+	    current = next;
+	} else {
+	    /* We can't proceed along the "right" links any further.
+	    ** Hence "current" is the largest element in the current tree.
+	    ** We make this node the new head of "list". (Repeating this
+	    ** operation until the tree is empty yields the desired linear
+	    ** threading of all nodes.)
+	    */
+	    prev = *((DdNodePtr *) current); /* save prev node on stack in prev */
+	    /* Traverse the linked list of current until the end. */
+	    for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end));
+	    DD_NEXT(end) = list; /* attach "list" at end and make */
+	    list = current;   /* "current" the new head of "list" */
+	    /* Now, if current has a "left" child, we push it on the stack.
+	    ** Otherwise, we just continue with the parent of "current".
+	    */
+	    if (DD_LEFT(current) != NULL) {
+		next = DD_LEFT(current);
+		*((DdNodePtr *) next) = prev;
+		current = next;
+	    } else {
+		current = prev;
+	    }
+	}
+    }
+
+    return(list);
+
+} /* end of cuddOrderedThread */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the left rotation for red/black trees.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRotateRight]
+
+******************************************************************************/
+DD_INLINE
+static void
+cuddRotateLeft(
+  DdNodePtr * nodeP)
+{
+    DdNode *newRoot;
+    DdNode *oldRoot = *nodeP;
+
+    *nodeP = newRoot = DD_RIGHT(oldRoot);
+    DD_RIGHT(oldRoot) = DD_LEFT(newRoot);
+    DD_LEFT(newRoot) = oldRoot;
+
+} /* end of cuddRotateLeft */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the right rotation for red/black trees.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddRotateLeft]
+
+******************************************************************************/
+DD_INLINE
+static void
+cuddRotateRight(
+  DdNodePtr * nodeP)
+{
+    DdNode *newRoot;
+    DdNode *oldRoot = *nodeP;
+
+    *nodeP = newRoot = DD_LEFT(oldRoot);
+    DD_LEFT(oldRoot) = DD_RIGHT(newRoot);
+    DD_RIGHT(newRoot) = oldRoot;
+
+} /* end of cuddRotateRight */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rebalances a red/black tree.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+cuddDoRebalance(
+  DdNodePtr ** stack,
+  int  stackN)
+{
+    DdNodePtr *xP, *parentP, *grandpaP;
+    DdNode *x, *y, *parent, *grandpa;
+
+    xP = stack[stackN];
+    x = *xP;
+    /* Work our way back up, re-balancing the tree. */
+    while (--stackN >= 0) {
+	parentP = stack[stackN];
+	parent = *parentP;
+	if (DD_IS_BLACK(parent)) break;
+	/* Since the root is black, here a non-null grandparent exists. */
+	grandpaP = stack[stackN-1];
+	grandpa = *grandpaP;
+	if (parent == DD_LEFT(grandpa)) {
+	    y = DD_RIGHT(grandpa);
+	    if (y != NULL && DD_IS_RED(y)) {
+		DD_COLOR(parent) = DD_BLACK;
+		DD_COLOR(y) = DD_BLACK;
+		DD_COLOR(grandpa) = DD_RED;
+		x = grandpa;
+		stackN--;
+	    } else {
+		if (x == DD_RIGHT(parent)) {
+		    cuddRotateLeft(parentP);
+		    DD_COLOR(x) = DD_BLACK;
+		} else {
+		    DD_COLOR(parent) = DD_BLACK;
+		}
+		DD_COLOR(grandpa) = DD_RED;
+		cuddRotateRight(grandpaP);
+		break;
+	    }
+	} else {
+	    y = DD_LEFT(grandpa);
+	    if (y != NULL && DD_IS_RED(y)) {
+		DD_COLOR(parent) = DD_BLACK;
+		DD_COLOR(y) = DD_BLACK;
+		DD_COLOR(grandpa) = DD_RED;
+		x = grandpa;
+		stackN--;
+	    } else {
+		if (x == DD_LEFT(parent)) {
+		    cuddRotateRight(parentP);
+		    DD_COLOR(x) = DD_BLACK;
+		} else {
+		    DD_COLOR(parent) = DD_BLACK;
+		}
+		DD_COLOR(grandpa) = DD_RED;
+		cuddRotateLeft(grandpaP);
+	    }
+	}
+    }
+    DD_COLOR(*(stack[0])) = DD_BLACK;
+
+} /* end of cuddDoRebalance */
+#endif
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes a variable tree after the insertion of new subtables.]
+
+  Description [Fixes a variable tree after the insertion of new subtables.
+  After such an insertion, the low fields of the tree below the insertion
+  point are inconsistent.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ddPatchTree(
+  DdManager *dd,
+  MtrNode *treenode)
+{
+    MtrNode *auxnode = treenode;
+
+    while (auxnode != NULL) {
+	auxnode->low = dd->perm[auxnode->index];
+	if (auxnode->child != NULL) {
+	    ddPatchTree(dd, auxnode->child);
+	}
+	auxnode = auxnode->younger;
+    }
+
+    return;
+
+} /* end of ddPatchTree */
+
+
+#ifdef DD_DEBUG
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a collision list is ordered.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddCheckCollisionOrdering(
+  DdManager *unique,
+  int i,
+  int j)
+{
+    int slots;
+    DdNode *node, *next;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(unique->sentinel);
+
+    nodelist = unique->subtables[i].nodelist;
+    slots = unique->subtables[i].slots;
+    node = nodelist[j];
+    if (node == sentinel) return(1);
+    next = node->next;
+    while (next != sentinel) {
+	if (cuddT(node) < cuddT(next) ||
+	    (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) {
+	    (void) fprintf(unique->err,
+			   "Unordered list: index %u, position %d\n", i, j);
+	    return(0);
+	}
+	node = next;
+	next = node->next;
+    }
+    return(1);
+
+} /* end of cuddCheckCollisionOrdering */
+#endif
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports problem in garbage collection.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [cuddGarbageCollect cuddGarbageCollectZdd]
+
+******************************************************************************/
+static void
+ddReportRefMess(
+  DdManager *unique /* manager */,
+  int i /* table in which the problem occurred */,
+  const char *caller /* procedure that detected the problem */)
+{
+    if (i == CUDD_CONST_INDEX) {
+	(void) fprintf(unique->err,
+			   "%s: problem in constants\n", caller);
+    } else if (i != -1) {
+	(void) fprintf(unique->err,
+			   "%s: problem in table %d\n", caller, i);
+    }
+    (void) fprintf(unique->err, "  dead count != deleted\n");
+    (void) fprintf(unique->err, "  This problem is often due to a missing \
+call to Cudd_Ref\n  or to an extra call to Cudd_RecursiveDeref.\n  \
+See the CUDD Programmer's Guide for additional details.");
+    abort();
+
+} /* end of ddReportRefMess */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddUtil.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddUtil.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddUtil.c	(revision 8)
@@ -0,0 +1,3921 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddUtil.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Utility functions.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Cudd_PrintMinterm()
+		<li> Cudd_bddPrintCover()
+		<li> Cudd_PrintDebug()
+		<li> Cudd_DagSize()
+		<li> Cudd_EstimateCofactor()
+		<li> Cudd_EstimateCofactorSimple()
+		<li> Cudd_SharingSize()
+		<li> Cudd_CountMinterm()
+		<li> Cudd_EpdCountMinterm()
+		<li> Cudd_CountPath()
+		<li> Cudd_CountPathsToNonZero()
+		<li> Cudd_Support()
+		<li> Cudd_SupportIndex()
+		<li> Cudd_SupportSize()
+		<li> Cudd_VectorSupport()
+		<li> Cudd_VectorSupportIndex()
+		<li> Cudd_VectorSupportSize()
+		<li> Cudd_ClassifySupport()
+		<li> Cudd_CountLeaves()
+		<li> Cudd_bddPickOneCube()
+		<li> Cudd_bddPickOneMinterm()
+		<li> Cudd_bddPickArbitraryMinterms()
+		<li> Cudd_SubsetWithMaskVars()
+		<li> Cudd_FirstCube()
+		<li> Cudd_NextCube()
+		<li> Cudd_bddComputeCube()
+		<li> Cudd_addComputeCube()
+		<li> Cudd_FirstNode()
+		<li> Cudd_NextNode()
+		<li> Cudd_GenFree()
+		<li> Cudd_IsGenEmpty()
+		<li> Cudd_IndicesToCube()
+		<li> Cudd_PrintVersion()
+		<li> Cudd_AverageDistance()
+		<li> Cudd_Random()
+		<li> Cudd_Srandom()
+		<li> Cudd_Density()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> cuddP()
+		<li> cuddStCountfree()
+		<li> cuddCollectNodes()
+		<li> cuddNodeArray()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> dp2()
+		<li> ddPrintMintermAux()
+		<li> ddDagInt()
+		<li> ddCountMintermAux()
+		<li> ddEpdCountMintermAux()
+		<li> ddCountPathAux()
+		<li> ddSupportStep()
+		<li> ddClearFlag()
+		<li> ddLeavesInt()
+		<li> ddPickArbitraryMinterms()
+		<li> ddPickRepresentativeCube()
+		<li> ddEpdFree()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Random generator constants. */
+#define MODULUS1 2147483563
+#define LEQA1 40014
+#define LEQQ1 53668
+#define LEQR1 12211
+#define MODULUS2 2147483399
+#define LEQA2 40692
+#define LEQQ2 52774
+#define LEQR2 3791
+#define STAB_SIZE 64
+#define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.78 2005/05/14 17:27:12 fabio Exp $";
+#endif
+
+static	DdNode	*background, *zero;
+
+static	long cuddRand = 0;
+static	long cuddRand2;
+static	long shuffleSelect;
+static 	long shuffleTable[STAB_SIZE];
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define bang(f)	((Cudd_IsComplement(f)) ? '!' : ' ')
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int dp2 (DdManager *dd, DdNode *f, st_table *t);
+static void ddPrintMintermAux (DdManager *dd, DdNode *node, int *list);
+static int ddDagInt (DdNode *n);
+static int cuddNodeArrayRecur (DdNode *f, DdNodePtr *table, int index);
+static int cuddEstimateCofactor (DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr);
+static DdNode * cuddUniqueLookup (DdManager * unique, int  index, DdNode * T, DdNode * E);
+static int cuddEstimateCofactorSimple (DdNode * node, int i);
+static double ddCountMintermAux (DdNode *node, double max, DdHashTable *table);
+static int ddEpdCountMintermAux (DdNode *node, EpDouble *max, EpDouble *epd, st_table *table);
+static double ddCountPathAux (DdNode *node, st_table *table);
+static double ddCountPathsToNonZero (DdNode * N, st_table * table);
+static void ddSupportStep (DdNode *f, int *support);
+static void ddClearFlag (DdNode *f);
+static int ddLeavesInt (DdNode *n);
+static int ddPickArbitraryMinterms (DdManager *dd, DdNode *node, int nvars, int nminterms, char **string);
+static int ddPickRepresentativeCube (DdManager *dd, DdNode *node, int nvars, double *weight, char *string);
+static enum st_retval ddEpdFree (char * key, char * value, char * arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a disjoint sum of products.]
+
+  Description [Prints a disjoint sum of product cover for the function
+  rooted at node. Each product corresponds to a path from node to a
+  leaf node different from the logical zero, and different from the
+  background value. Uses the package default output file.  Returns 1
+  if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug Cudd_bddPrintCover]
+
+******************************************************************************/
+int
+Cudd_PrintMinterm(
+  DdManager * manager,
+  DdNode * node)
+{
+    int		i, *list;
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+    list = ALLOC(int,manager->size);
+    if (list == NULL) {
+	manager->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < manager->size; i++) list[i] = 2;
+    ddPrintMintermAux(manager,node,list);
+    FREE(list);
+    return(1);
+
+} /* end of Cudd_PrintMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a sum of prime implicants of a BDD.]
+
+  Description [Prints a sum of product cover for an incompletely
+  specified function given by a lower bound and an upper bound.  Each
+  product is a prime implicant obtained by expanding the product
+  corresponding to a path from node to the constant one.  Uses the
+  package default output file.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintMinterm]
+
+******************************************************************************/
+int
+Cudd_bddPrintCover(
+  DdManager *dd,
+  DdNode *l,
+  DdNode *u)
+{
+    int *array;
+    int q, result;
+    DdNode *lb;
+#ifdef DD_DEBUG
+    DdNode *cover;
+#endif
+
+    array = ALLOC(int, Cudd_ReadSize(dd));
+    if (array == NULL) return(0);
+    lb = l;
+    cuddRef(lb);
+#ifdef DD_DEBUG
+    cover = Cudd_ReadLogicZero(dd);
+    cuddRef(cover);
+#endif
+    while (lb != Cudd_ReadLogicZero(dd)) {
+	DdNode *implicant, *prime, *tmp;
+	int length;
+	implicant = Cudd_LargestCube(dd,lb,&length);
+	if (implicant == NULL) {
+	    Cudd_RecursiveDeref(dd,lb);
+	    FREE(array);
+	    return(0);
+	}
+	cuddRef(implicant);
+	prime = Cudd_bddMakePrime(dd,implicant,u);
+	if (prime == NULL) {
+	    Cudd_RecursiveDeref(dd,lb);
+	    Cudd_RecursiveDeref(dd,implicant);
+	    FREE(array);
+	    return(0);
+	}
+	cuddRef(prime);
+	Cudd_RecursiveDeref(dd,implicant);
+	tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime));
+	if (tmp == NULL) {
+	    Cudd_RecursiveDeref(dd,lb);
+	    Cudd_RecursiveDeref(dd,prime);
+	    FREE(array);
+	    return(0);
+	}
+	cuddRef(tmp);
+	Cudd_RecursiveDeref(dd,lb);
+	lb = tmp;
+	result = Cudd_BddToCubeArray(dd,prime,array);
+	if (result == 0) {
+	    Cudd_RecursiveDeref(dd,lb);
+	    Cudd_RecursiveDeref(dd,prime);
+	    FREE(array);
+	    return(0);
+	}
+	for (q = 0; q < dd->size; q++) {
+	    switch (array[q]) {
+	    case 0:
+		(void) fprintf(dd->out, "0");
+		break;
+	    case 1:
+		(void) fprintf(dd->out, "1");
+		break;
+	    case 2:
+		(void) fprintf(dd->out, "-");
+		break;
+	    default:
+		(void) fprintf(dd->out, "?");
+	    }
+	}
+	(void) fprintf(dd->out, " 1\n");
+#ifdef DD_DEBUG
+	tmp = Cudd_bddOr(dd,prime,cover);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDeref(dd,cover);
+	    Cudd_RecursiveDeref(dd,lb);
+	    Cudd_RecursiveDeref(dd,prime);
+	    FREE(array);
+	    return(0);
+	}
+	cuddRef(tmp);
+	Cudd_RecursiveDeref(dd,cover);
+	cover = tmp;
+#endif
+	Cudd_RecursiveDeref(dd,prime);
+    }
+    (void) fprintf(dd->out, "\n");
+    Cudd_RecursiveDeref(dd,lb);
+    FREE(array);
+#ifdef DD_DEBUG
+    if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) {
+        Cudd_RecursiveDeref(dd,cover);
+        return(0);
+    }
+    Cudd_RecursiveDeref(dd,cover);
+#endif
+    return(1);
+
+} /* end of Cudd_bddPrintCover */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints to the standard output a DD and its statistics.]
+
+  Description [Prints to the standard output a DD and its statistics.
+  The statistics include the number of nodes, the number of leaves, and
+  the number of minterms. (The number of minterms is the number of
+  assignments to the variables that cause the function to be different
+  from the logical zero (for BDDs) and from the background value (for
+  ADDs.) The statistics are printed if pr &gt; 0. Specifically:
+  <ul>
+  <li> pr = 0 : prints nothing
+  <li> pr = 1 : prints counts of nodes and minterms
+  <li> pr = 2 : prints counts + disjoint sum of product
+  <li> pr = 3 : prints counts + list of nodes
+  <li> pr &gt; 3 : prints counts + disjoint sum of product + list of nodes
+  </ul>
+  For the purpose of counting the number of minterms, the function is
+  supposed to depend on n variables. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm
+  Cudd_PrintMinterm]
+
+******************************************************************************/
+int
+Cudd_PrintDebug(
+  DdManager * dd,
+  DdNode * f,
+  int  n,
+  int  pr)
+{
+    DdNode *azero, *bzero;
+    int	   nodes;
+    int	   leaves;
+    double minterms;
+    int    retval = 1;
+
+    if (f == NULL) {
+	(void) fprintf(dd->out,": is the NULL DD\n");
+	(void) fflush(dd->out);
+	return(0);
+    }
+    azero = DD_ZERO(dd);
+    bzero = Cudd_Not(DD_ONE(dd));
+    if ((f == azero || f == bzero) && pr > 0){
+       (void) fprintf(dd->out,": is the zero DD\n");
+       (void) fflush(dd->out);
+       return(1);
+    }
+    if (pr > 0) {
+	nodes = Cudd_DagSize(f);
+	if (nodes == CUDD_OUT_OF_MEM) retval = 0;
+	leaves = Cudd_CountLeaves(f);
+	if (leaves == CUDD_OUT_OF_MEM) retval = 0;
+	minterms = Cudd_CountMinterm(dd, f, n);
+	if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0;
+	(void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n",
+		       nodes, leaves, minterms);
+        if (pr > 2) {
+	    if (!cuddP(dd, f)) retval = 0;
+	}
+	if (pr == 2 || pr > 3) {
+	    if (!Cudd_PrintMinterm(dd,f)) retval = 0;
+	    (void) fprintf(dd->out,"\n");
+	}
+        (void) fflush(dd->out);
+    }
+    return(retval);
+
+} /* end of Cudd_PrintDebug */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in a DD.]
+
+  Description [Counts the number of nodes in a DD. Returns the number
+  of nodes in the graph rooted at node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SharingSize Cudd_PrintDebug]
+
+******************************************************************************/
+int
+Cudd_DagSize(
+  DdNode * node)
+{
+    int	i;	
+
+    i = ddDagInt(Cudd_Regular(node));
+    ddClearFlag(Cudd_Regular(node));
+
+    return(i);
+
+} /* end of Cudd_DagSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Estimates the number of nodes in a cofactor of a DD.]
+
+  Description [Estimates the number of nodes in a cofactor of a DD.
+  Returns an estimate of the number of nodes in a cofactor of
+  the graph rooted at node with respect to the variable whose index is i.
+  In case of failure, returns CUDD_OUT_OF_MEM.
+  This function uses a refinement of the algorithm of Cabodi et al.
+  (ICCAD96). The refinement allows the procedure to account for part
+  of the recombination that may occur in the part of the cofactor above
+  the cofactoring variable. This procedure does no create any new node.
+  It does keep a small table of results; therefore it may run out of memory.
+  If this is a concern, one should use Cudd_EstimateCofactorSimple, which
+  is faster, does not allocate any memory, but is less accurate.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize Cudd_EstimateCofactorSimple]
+
+******************************************************************************/
+int
+Cudd_EstimateCofactor(
+  DdManager *dd /* manager */,
+  DdNode * f	/* function */,
+  int i		/* index of variable */,
+  int phase	/* 1: positive; 0: negative */
+  )
+{
+    int	val;
+    DdNode *ptr;
+    st_table *table;
+
+    table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (table == NULL) return(CUDD_OUT_OF_MEM);
+    val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr);
+    ddClearFlag(Cudd_Regular(f));
+    st_free_table(table);
+
+    return(val);
+
+} /* end of Cudd_EstimateCofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Estimates the number of nodes in a cofactor of a DD.]
+
+  Description [Estimates the number of nodes in a cofactor of a DD.
+  Returns an estimate of the number of nodes in the positive cofactor of
+  the graph rooted at node with respect to the variable whose index is i.
+  This procedure implements with minor changes the algorithm of Cabodi et al.
+  (ICCAD96). It does not allocate any memory, it does not change the
+  state of the manager, and it is fast. However, it has been observed to
+  overestimate the size of the cofactor by as much as a factor of 2.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize]
+
+******************************************************************************/
+int
+Cudd_EstimateCofactorSimple(
+  DdNode * node,
+  int i)
+{
+    int	val;	
+
+    val = cuddEstimateCofactorSimple(Cudd_Regular(node),i);
+    ddClearFlag(Cudd_Regular(node));
+
+    return(val);
+
+} /* end of Cudd_EstimateCofactorSimple */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in an array of DDs.]
+
+  Description [Counts the number of nodes in an array of DDs. Shared
+  nodes are counted only once.  Returns the total number of nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize]
+
+******************************************************************************/
+int
+Cudd_SharingSize(
+  DdNode ** nodeArray,
+  int  n)
+{
+    int	i,j;	
+
+    i = 0;
+    for (j = 0; j < n; j++) {
+	i += ddDagInt(Cudd_Regular(nodeArray[j]));
+    }
+    for (j = 0; j < n; j++) {
+	ddClearFlag(Cudd_Regular(nodeArray[j]));
+    }
+    return(i);
+
+} /* end of Cudd_SharingSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a DD.]
+
+  Description [Counts the number of minterms of a DD. The function is
+  assumed to depend on nvars variables. The minterm count is
+  represented as a double, to allow for a larger number of variables.
+  Returns the number of minterms of the function rooted at node if
+  successful; (double) CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug Cudd_CountPath]
+
+******************************************************************************/
+double
+Cudd_CountMinterm(
+  DdManager * manager,
+  DdNode * node,
+  int  nvars)
+{
+    double	max;
+    DdHashTable	*table;
+    double	res;
+    CUDD_VALUE_TYPE epsilon;
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+    
+    max = pow(2.0,(double)nvars);
+    table = cuddHashTableInit(manager,1,2);
+    if (table == NULL) {
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    epsilon = Cudd_ReadEpsilon(manager);
+    Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0);
+    res = ddCountMintermAux(node,max,table);
+    cuddHashTableQuit(table);
+    Cudd_SetEpsilon(manager,epsilon);
+
+    return(res);
+
+} /* end of Cudd_CountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of paths of a DD.]
+
+  Description [Counts the number of paths of a DD.  Paths to all
+  terminal nodes are counted. The path count is represented as a
+  double, to allow for a larger number of variables.  Returns the
+  number of paths of the function rooted at node if successful;
+  (double) CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountMinterm]
+
+******************************************************************************/
+double
+Cudd_CountPath(
+  DdNode * node)
+{
+
+    st_table	*table;
+    double	i;	
+
+    table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (table == NULL) {
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    i = ddCountPathAux(Cudd_Regular(node),table);
+    st_foreach(table, cuddStCountfree, NULL);
+    st_free_table(table);
+    return(i);
+
+} /* end of Cudd_CountPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a DD with extended precision.]
+
+  Description [Counts the number of minterms of a DD with extended precision.
+  The function is assumed to depend on nvars variables. The minterm count is
+  represented as an EpDouble, to allow any number of variables.
+  Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug Cudd_CountPath]
+
+******************************************************************************/
+int
+Cudd_EpdCountMinterm(
+  DdManager * manager,
+  DdNode * node,
+  int  nvars,
+  EpDouble * epd)
+{
+    EpDouble	max, tmp;
+    st_table	*table;
+    int		status;
+
+    background = manager->background;
+    zero = Cudd_Not(manager->one);
+    
+    EpdPow2(nvars, &max);
+    table = st_init_table(EpdCmp, st_ptrhash);
+    if (table == NULL) {
+	EpdMakeZero(epd, 0);
+	return(CUDD_OUT_OF_MEM);
+    }
+    status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table);
+    st_foreach(table, ddEpdFree, NULL);
+    st_free_table(table);
+    if (status == CUDD_OUT_OF_MEM) {
+	EpdMakeZero(epd, 0);
+	return(CUDD_OUT_OF_MEM);
+    }
+    if (Cudd_IsComplement(node)) {
+    	EpdSubtract3(&max, epd, &tmp);
+    	EpdCopy(&tmp, epd);
+    }
+    return(0);
+
+} /* end of Cudd_EpdCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of paths to a non-zero terminal of a DD.]
+
+  Description [Counts the number of paths to a non-zero terminal of a
+  DD.  The path count is
+  represented as a double, to allow for a larger number of variables.
+  Returns the number of paths of the function rooted at node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountMinterm Cudd_CountPath]
+
+******************************************************************************/
+double
+Cudd_CountPathsToNonZero(
+  DdNode * node)
+{
+
+    st_table	*table;
+    double	i;	
+
+    table = st_init_table(st_ptrcmp,st_ptrhash);
+    if (table == NULL) {
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    i = ddCountPathsToNonZero(node,table);
+    st_foreach(table, cuddStCountfree, NULL);
+    st_free_table(table);
+    return(i);
+
+} /* end of Cudd_CountPathsToNonZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a DD depends.]
+
+  Description [Finds the variables on which a DD depends.
+  Returns a BDD consisting of the product of the variables if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+DdNode *
+Cudd_Support(
+  DdManager * dd /* manager */,
+  DdNode * f /* DD whose support is sought */)
+{
+    int	*support;
+    DdNode *res, *tmp, *var;
+    int	i,j;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ALLOC(int,size);
+    if (support == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+	support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),support);
+    ddClearFlag(Cudd_Regular(f));
+
+    /* Transform support from array to cube. */
+    do {
+	dd->reordered = 0;
+	res = DD_ONE(dd);
+	cuddRef(res);
+	for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
+	    i = (j >= dd->size) ? j : dd->invperm[j];
+	    if (support[i] == 1) {
+	        /* The following call to cuddUniqueInter is guaranteed
+		** not to trigger reordering because the node we look up
+		** already exists. */ 
+		var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+		cuddRef(var);
+		tmp = cuddBddAndRecur(dd,res,var);
+		if (tmp == NULL) {
+		    Cudd_RecursiveDeref(dd,res);
+		    Cudd_RecursiveDeref(dd,var);
+		    res = NULL;
+		    break;
+		}
+		cuddRef(tmp);
+		Cudd_RecursiveDeref(dd,res);
+		Cudd_RecursiveDeref(dd,var);
+		res = tmp;
+	    }
+	}
+    } while (dd->reordered == 1);
+
+    FREE(support);
+    if (res != NULL) cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_Support */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a DD depends.]
+
+  Description [Finds the variables on which a DD depends.  Returns an
+  index array of the variables if successful; NULL otherwise.  The
+  size of the array equals the number of variables in the manager.
+  Each entry of the array is 1 if the corresponding variable is in the
+  support of the DD and 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+int *
+Cudd_SupportIndex(
+  DdManager * dd /* manager */,
+  DdNode * f /* DD whose support is sought */)
+{
+    int	*support;
+    int	i;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ALLOC(int,size);
+    if (support == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+	support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),support);
+    ddClearFlag(Cudd_Regular(f));
+
+    return(support);
+
+} /* end of Cudd_SupportIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the variables on which a DD depends.]
+
+  Description [Counts the variables on which a DD depends.
+  Returns the number of the variables if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support]
+
+******************************************************************************/
+int
+Cudd_SupportSize(
+  DdManager * dd /* manager */,
+  DdNode * f /* DD whose support size is sought */)
+{
+    int	*support;
+    int	i;
+    int size;
+    int count;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ALLOC(int,size);
+    if (support == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(CUDD_OUT_OF_MEM);
+    }
+    for (i = 0; i < size; i++) {
+	support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),support);
+    ddClearFlag(Cudd_Regular(f));
+
+    /* Count support variables. */
+    count = 0;
+    for (i = 0; i < size; i++) {
+	if (support[i] == 1) count++;
+    }
+
+    FREE(support);
+    return(count);
+
+} /* end of Cudd_SupportSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a set of DDs depends.]
+
+  Description [Finds the variables on which a set of DDs depends.
+  The set must contain either BDDs and ADDs, or ZDDs.
+  Returns a BDD consisting of the product of the variables if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Support Cudd_ClassifySupport]
+
+******************************************************************************/
+DdNode *
+Cudd_VectorSupport(
+  DdManager * dd /* manager */,
+  DdNode ** F /* array of DDs whose support is sought */,
+  int  n /* size of the array */)
+{
+    int	*support;
+    DdNode *res, *tmp, *var;
+    int	i,j;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ALLOC(int,size);
+    if (support == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+	support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    for (i = 0; i < n; i++) {
+	ddSupportStep(Cudd_Regular(F[i]),support);
+    }
+    for (i = 0; i < n; i++) {
+	ddClearFlag(Cudd_Regular(F[i]));
+    }
+
+    /* Transform support from array to cube. */
+    res = DD_ONE(dd);
+    cuddRef(res);
+    for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
+	i = (j >= dd->size) ? j : dd->invperm[j];
+	if (support[i] == 1) {
+	    var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+	    cuddRef(var);
+	    tmp = Cudd_bddAnd(dd,res,var);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(dd,res);
+		Cudd_RecursiveDeref(dd,var);
+		FREE(support);
+		return(NULL);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(dd,res);
+	    Cudd_RecursiveDeref(dd,var);
+	    res = tmp;
+	}
+    }
+
+    FREE(support);
+    cuddDeref(res);
+    return(res);
+
+} /* end of Cudd_VectorSupport */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the variables on which a set of DDs depends.]
+
+  Description [Finds the variables on which a set of DDs depends.
+  The set must contain either BDDs and ADDs, or ZDDs.
+  Returns an index array of the variables if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+int *
+Cudd_VectorSupportIndex(
+  DdManager * dd /* manager */,
+  DdNode ** F /* array of DDs whose support is sought */,
+  int  n /* size of the array */)
+{
+    int	*support;
+    int	i;
+    int size;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ALLOC(int,size);
+    if (support == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+	support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    for (i = 0; i < n; i++) {
+	ddSupportStep(Cudd_Regular(F[i]),support);
+    }
+    for (i = 0; i < n; i++) {
+	ddClearFlag(Cudd_Regular(F[i]));
+    }
+
+    return(support);
+
+} /* end of Cudd_VectorSupportIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the variables on which a set of DDs depends.]
+
+  Description [Counts the variables on which a set of DDs depends.
+  The set must contain either BDDs and ADDs, or ZDDs.
+  Returns the number of the variables if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_VectorSupport Cudd_SupportSize]
+
+******************************************************************************/
+int
+Cudd_VectorSupportSize(
+  DdManager * dd /* manager */,
+  DdNode ** F /* array of DDs whose support is sought */,
+  int  n /* size of the array */)
+{
+    int	*support;
+    int	i;
+    int size;
+    int count;
+
+    /* Allocate and initialize support array for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    support = ALLOC(int,size);
+    if (support == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(CUDD_OUT_OF_MEM);
+    }
+    for (i = 0; i < size; i++) {
+	support[i] = 0;
+    }
+
+    /* Compute support and clean up markers. */
+    for (i = 0; i < n; i++) {
+	ddSupportStep(Cudd_Regular(F[i]),support);
+    }
+    for (i = 0; i < n; i++) {
+	ddClearFlag(Cudd_Regular(F[i]));
+    }
+
+    /* Count vriables in support. */
+    count = 0;
+    for (i = 0; i < size; i++) {
+	if (support[i] == 1) count++;
+    }
+
+    FREE(support);
+    return(count);
+
+} /* end of Cudd_VectorSupportSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Classifies the variables in the support of two DDs.]
+
+  Description [Classifies the variables in the support of two DDs
+  <code>f</code> and <code>g</code>, depending on whther they appear
+  in both DDs, only in <code>f</code>, or only in <code>g</code>.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [The cubes of the three classes of variables are
+  returned as side effects.]
+
+  SeeAlso     [Cudd_Support Cudd_VectorSupport]
+
+******************************************************************************/
+int
+Cudd_ClassifySupport(
+  DdManager * dd /* manager */,
+  DdNode * f /* first DD */,
+  DdNode * g /* second DD */,
+  DdNode ** common /* cube of shared variables */,
+  DdNode ** onlyF /* cube of variables only in f */,
+  DdNode ** onlyG /* cube of variables only in g */)
+{
+    int	*supportF, *supportG;
+    DdNode *tmp, *var;
+    int	i,j;
+    int size;
+
+    /* Allocate and initialize support arrays for ddSupportStep. */
+    size = ddMax(dd->size, dd->sizeZ);
+    supportF = ALLOC(int,size);
+    if (supportF == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    supportG = ALLOC(int,size);
+    if (supportG == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(supportF);
+	return(0);
+    }
+    for (i = 0; i < size; i++) {
+	supportF[i] = 0;
+	supportG[i] = 0;
+    }
+
+    /* Compute supports and clean up markers. */
+    ddSupportStep(Cudd_Regular(f),supportF);
+    ddClearFlag(Cudd_Regular(f));
+    ddSupportStep(Cudd_Regular(g),supportG);
+    ddClearFlag(Cudd_Regular(g));
+
+    /* Classify variables and create cubes. */
+    *common = *onlyF = *onlyG = DD_ONE(dd);
+    cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG);
+    for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
+	i = (j >= dd->size) ? j : dd->invperm[j];
+	if (supportF[i] == 0 && supportG[i] == 0) continue;
+	var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
+	cuddRef(var);
+	if (supportG[i] == 0) {
+	    tmp = Cudd_bddAnd(dd,*onlyF,var);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(dd,*common);
+		Cudd_RecursiveDeref(dd,*onlyF);
+		Cudd_RecursiveDeref(dd,*onlyG);
+		Cudd_RecursiveDeref(dd,var);
+		FREE(supportF); FREE(supportG);
+		return(0);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(dd,*onlyF);
+	    *onlyF = tmp;
+	} else if (supportF[i] == 0) {
+	    tmp = Cudd_bddAnd(dd,*onlyG,var);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(dd,*common);
+		Cudd_RecursiveDeref(dd,*onlyF);
+		Cudd_RecursiveDeref(dd,*onlyG);
+		Cudd_RecursiveDeref(dd,var);
+		FREE(supportF); FREE(supportG);
+		return(0);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(dd,*onlyG);
+	    *onlyG = tmp;
+	} else {
+	    tmp = Cudd_bddAnd(dd,*common,var);
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(dd,*common);
+		Cudd_RecursiveDeref(dd,*onlyF);
+		Cudd_RecursiveDeref(dd,*onlyG);
+		Cudd_RecursiveDeref(dd,var);
+		FREE(supportF); FREE(supportG);
+		return(0);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(dd,*common);
+	    *common = tmp;
+	}
+	Cudd_RecursiveDeref(dd,var);
+    }
+
+    FREE(supportF); FREE(supportG);
+    cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG);
+    return(1);
+
+} /* end of Cudd_ClassifySupport */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of leaves in a DD.]
+
+  Description [Counts the number of leaves in a DD. Returns the number
+  of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug]
+
+******************************************************************************/
+int
+Cudd_CountLeaves(
+  DdNode * node)
+{
+    int	i;	
+
+    i = ddLeavesInt(Cudd_Regular(node));
+    ddClearFlag(Cudd_Regular(node));
+    return(i);
+
+} /* end of Cudd_CountLeaves */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Picks one on-set cube randomly from the given DD.]
+
+  Description [Picks one on-set cube randomly from the given DD. The
+  cube is written into an array of characters.  The array must have at
+  least as many entries as there are variables. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPickOneMinterm]
+
+******************************************************************************/
+int
+Cudd_bddPickOneCube(
+  DdManager * ddm,
+  DdNode * node,
+  char * string)
+{
+    DdNode *N, *T, *E;
+    DdNode *one, *bzero;
+    char   dir;
+    int    i;
+
+    if (string == NULL || node == NULL) return(0);
+
+    /* The constant 0 function has no on-set cubes. */
+    one = DD_ONE(ddm);
+    bzero = Cudd_Not(one);
+    if (node == bzero) return(0);
+
+    for (i = 0; i < ddm->size; i++) string[i] = 2;
+
+    for (;;) {
+
+	if (node == one) break;
+
+	N = Cudd_Regular(node);
+
+	T = cuddT(N); E = cuddE(N);
+	if (Cudd_IsComplement(node)) {
+	    T = Cudd_Not(T); E = Cudd_Not(E);
+	}
+	if (T == bzero) {
+	    string[N->index] = 0;
+	    node = E;
+	} else if (E == bzero) {
+	    string[N->index] = 1;
+	    node = T;
+	} else {
+	    dir = (char) ((Cudd_Random() & 0x2000) >> 13);
+	    string[N->index] = dir;
+	    node = dir ? T : E;
+	}
+    }
+    return(1);
+
+} /* end of Cudd_bddPickOneCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Picks one on-set minterm randomly from the given DD.]
+
+  Description [Picks one on-set minterm randomly from the given
+  DD. The minterm is in terms of <code>vars</code>. The array
+  <code>vars</code> should contain at least all variables in the
+  support of <code>f</code>; if this condition is not met the minterm
+  built by this procedure may not be contained in
+  <code>f</code>. Builds a BDD for the minterm and returns a pointer
+  to it if successful; NULL otherwise. There are three reasons why the
+  procedure may fail:
+  <ul>
+  <li> It may run out of memory;
+  <li> the function <code>f</code> may be the constant 0;
+  <li> the minterm may not be contained in <code>f</code>.
+  </ul>]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPickOneCube]
+
+******************************************************************************/
+DdNode *
+Cudd_bddPickOneMinterm(
+  DdManager * dd /* manager */,
+  DdNode * f /* function from which to pick one minterm */,
+  DdNode ** vars /* array of variables */,
+  int  n /* size of <code>vars</code> */)
+{
+    char *string;
+    int i, size;
+    int *indices;
+    int result;
+    DdNode *old, *neW;
+
+    size = dd->size;
+    string = ALLOC(char, size);
+    if (string == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    indices = ALLOC(int,n);
+    if (indices == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(string);
+	return(NULL);
+    }
+
+    for (i = 0; i < n; i++) {
+        indices[i] = vars[i]->index;
+    }
+
+    result = Cudd_bddPickOneCube(dd,f,string);
+    if (result == 0) {
+	FREE(string);
+	FREE(indices);
+	return(NULL);
+    }
+
+    /* Randomize choice for don't cares. */
+    for (i = 0; i < n; i++) {
+	if (string[indices[i]] == 2) 
+	    string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5);
+    }
+
+    /* Build result BDD. */
+    old = Cudd_ReadOne(dd);
+    cuddRef(old);
+
+    for (i = n-1; i >= 0; i--) {
+	neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0));
+	if (neW == NULL) {
+	    FREE(string);
+	    FREE(indices);
+	    Cudd_RecursiveDeref(dd,old);
+	    return(NULL);
+	}
+	cuddRef(neW);
+	Cudd_RecursiveDeref(dd,old);
+	old = neW;
+    }
+
+#ifdef DD_DEBUG
+    /* Test. */
+    if (Cudd_bddLeq(dd,old,f)) {
+	cuddDeref(old);
+    } else {
+	Cudd_RecursiveDeref(dd,old);
+	old = NULL;
+    }
+#else
+    cuddDeref(old);
+#endif
+
+    FREE(string);
+    FREE(indices);
+    return(old);
+
+}  /* end of Cudd_bddPickOneMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Picks k on-set minterms evenly distributed from given DD.]
+
+  Description [Picks k on-set minterms evenly distributed from given DD.
+  The minterms are in terms of <code>vars</code>. The array
+  <code>vars</code> should contain at least all variables in the
+  support of <code>f</code>; if this condition is not met the minterms
+  built by this procedure may not be contained in
+  <code>f</code>. Builds an array of BDDs for the minterms and returns a
+  pointer to it if successful; NULL otherwise. There are three reasons
+  why the procedure may fail:
+  <ul>
+  <li> It may run out of memory;
+  <li> the function <code>f</code> may be the constant 0;
+  <li> the minterms may not be contained in <code>f</code>.
+  </ul>]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddPickOneMinterm Cudd_bddPickOneCube]
+
+******************************************************************************/
+DdNode **
+Cudd_bddPickArbitraryMinterms(
+  DdManager * dd /* manager */,
+  DdNode * f /* function from which to pick k minterms */,
+  DdNode ** vars /* array of variables */,
+  int  n /* size of <code>vars</code> */,
+  int  k /* number of minterms to find */)
+{
+    char **string;
+    int i, j, l, size;
+    int *indices;
+    int result;
+    DdNode **old, *neW;
+    double minterms;
+    char *saveString;
+    int saveFlag, savePoint, isSame;
+
+    minterms = Cudd_CountMinterm(dd,f,n);
+    if ((double)k > minterms) {
+	return(NULL);
+    }
+
+    size = dd->size;
+    string = ALLOC(char *, k);
+    if (string == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < k; i++) {
+	string[i] = ALLOC(char, size + 1);
+	if (string[i] == NULL) {
+	    for (j = 0; j < i; j++)
+		FREE(string[i]);
+	    FREE(string);
+	    dd->errorCode = CUDD_MEMORY_OUT;
+	    return(NULL);
+	}
+	for (j = 0; j < size; j++) string[i][j] = '2';
+	string[i][size] = '\0';
+    }
+    indices = ALLOC(int,n);
+    if (indices == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	for (i = 0; i < k; i++)
+	    FREE(string[i]);
+	FREE(string);
+	return(NULL);
+    }
+
+    for (i = 0; i < n; i++) {
+        indices[i] = vars[i]->index;
+    }
+
+    result = ddPickArbitraryMinterms(dd,f,n,k,string);
+    if (result == 0) {
+	for (i = 0; i < k; i++)
+	    FREE(string[i]);
+	FREE(string);
+	FREE(indices);
+	return(NULL);
+    }
+
+    old = ALLOC(DdNode *, k);
+    if (old == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	for (i = 0; i < k; i++)
+	    FREE(string[i]);
+	FREE(string);
+	FREE(indices);
+	return(NULL);
+    }
+    saveString = ALLOC(char, size + 1);
+    if (saveString == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	for (i = 0; i < k; i++)
+	    FREE(string[i]);
+	FREE(string);
+	FREE(indices);
+	FREE(old);
+	return(NULL);
+    }
+    saveFlag = 0;
+
+    /* Build result BDD array. */
+    for (i = 0; i < k; i++) {
+	isSame = 0;
+	if (!saveFlag) {
+	    for (j = i + 1; j < k; j++) {
+		if (strcmp(string[i], string[j]) == 0) {
+		    savePoint = i;
+		    strcpy(saveString, string[i]);
+		    saveFlag = 1;
+		    break;
+		}
+	    }
+	} else {
+	    if (strcmp(string[i], saveString) == 0) {
+		isSame = 1;
+	    } else {
+		saveFlag = 0;
+		for (j = i + 1; j < k; j++) {
+		    if (strcmp(string[i], string[j]) == 0) {
+			savePoint = i;
+			strcpy(saveString, string[i]);
+			saveFlag = 1;
+			break;
+		    }
+		}
+	    }
+	}
+	/* Randomize choice for don't cares. */
+	for (j = 0; j < n; j++) {
+	    if (string[i][indices[j]] == '2')
+		string[i][indices[j]] = (Cudd_Random() & 0x20) ? '1' : '0';
+	}
+
+	while (isSame) {
+	    isSame = 0;
+	    for (j = savePoint; j < i; j++) {
+		if (strcmp(string[i], string[j]) == 0) {
+		    isSame = 1;
+		    break;
+		}
+	    }
+	    if (isSame) {
+		strcpy(string[i], saveString);
+		/* Randomize choice for don't cares. */
+		for (j = 0; j < n; j++) {
+		    if (string[i][indices[j]] == '2') 
+			string[i][indices[j]] = (Cudd_Random() & 0x20) ?
+			    '1' : '0';
+		}
+	    }
+	}
+
+	old[i] = Cudd_ReadOne(dd);
+	cuddRef(old[i]);
+
+	for (j = 0; j < n; j++) {
+	    if (string[i][indices[j]] == '0') {
+		neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j]));
+	    } else {
+		neW = Cudd_bddAnd(dd,old[i],vars[j]);
+	    }
+	    if (neW == NULL) {
+		FREE(saveString);
+		for (l = 0; l < k; l++)
+		    FREE(string[l]);
+		FREE(string);
+		FREE(indices);
+		for (l = 0; l <= i; l++)
+		    Cudd_RecursiveDeref(dd,old[l]);
+		FREE(old);
+		return(NULL);
+	    }
+	    cuddRef(neW);
+	    Cudd_RecursiveDeref(dd,old[i]);
+	    old[i] = neW;
+	}
+
+	/* Test. */
+	if (!Cudd_bddLeq(dd,old[i],f)) {
+	    FREE(saveString);
+	    for (l = 0; l < k; l++)
+		FREE(string[l]);
+	    FREE(string);
+	    FREE(indices);
+	    for (l = 0; l <= i; l++)
+		Cudd_RecursiveDeref(dd,old[l]);
+	    FREE(old);
+	    return(NULL);
+	}
+    }
+
+    FREE(saveString);
+    for (i = 0; i < k; i++) {
+	cuddDeref(old[i]);
+	FREE(string[i]);
+    }
+    FREE(string);
+    FREE(indices);
+    return(old);
+
+}  /* end of Cudd_bddPickArbitraryMinterms */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a subset from a BDD.]
+
+  Description [Extracts a subset from a BDD in the following procedure.
+  1. Compute the weight for each mask variable by counting the number of
+     minterms for both positive and negative cofactors of the BDD with
+     respect to each mask variable. (weight = #positive - #negative)
+  2. Find a representative cube of the BDD by using the weight. From the
+     top variable of the BDD, for each variable, if the weight is greater
+     than 0.0, choose THEN branch, othereise ELSE branch, until meeting
+     the constant 1.
+  3. Quantify out the variables not in maskVars from the representative
+     cube and if a variable in maskVars is don't care, replace the
+     variable with a constant(1 or 0) depending on the weight.
+  4. Make a subset of the BDD by multiplying with the modified cube.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_SubsetWithMaskVars(
+  DdManager * dd /* manager */,
+  DdNode * f /* function from which to pick a cube */,
+  DdNode ** vars /* array of variables */,
+  int  nvars /* size of <code>vars</code> */,
+  DdNode ** maskVars /* array of variables */,
+  int  mvars /* size of <code>maskVars</code> */)
+{
+    double	*weight;
+    char	*string;
+    int		i, size;
+    int		*indices, *mask;
+    int		result;
+    DdNode	*zero, *cube, *newCube, *subset;
+    DdNode	*cof;
+
+    DdNode	*support;
+    support = Cudd_Support(dd,f);
+    cuddRef(support);
+    Cudd_RecursiveDeref(dd,support);
+
+    zero = Cudd_Not(dd->one);
+    size = dd->size;
+    
+    weight = ALLOC(double,size);
+    if (weight == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+        weight[i] = 0.0;
+    }
+    for (i = 0; i < mvars; i++) {
+	cof = Cudd_Cofactor(dd, f, maskVars[i]);
+	cuddRef(cof);
+	weight[i] = Cudd_CountMinterm(dd, cof, nvars);
+	Cudd_RecursiveDeref(dd,cof);
+
+	cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i]));
+	cuddRef(cof);
+	weight[i] -= Cudd_CountMinterm(dd, cof, nvars);
+	Cudd_RecursiveDeref(dd,cof);
+    }
+
+    string = ALLOC(char, size + 1);
+    if (string == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    mask = ALLOC(int, size);
+    if (mask == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(string);
+	return(NULL);
+    }
+    for (i = 0; i < size; i++) {
+	string[i] = '2';
+	mask[i] = 0;
+    }
+    string[size] = '\0';
+    indices = ALLOC(int,nvars);
+    if (indices == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(string);
+	FREE(mask);
+	return(NULL);
+    }
+    for (i = 0; i < nvars; i++) {
+        indices[i] = vars[i]->index;
+    }
+
+    result = ddPickRepresentativeCube(dd,f,nvars,weight,string);
+    if (result == 0) {
+	FREE(string);
+	FREE(mask);
+	FREE(indices);
+	return(NULL);
+    }
+
+    cube = Cudd_ReadOne(dd);
+    cuddRef(cube);
+    zero = Cudd_Not(Cudd_ReadOne(dd));
+    for (i = 0; i < nvars; i++) {
+	if (string[indices[i]] == '0') {
+	    newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
+	} else if (string[indices[i]] == '1') {
+	    newCube = Cudd_bddIte(dd,cube,vars[i],zero);
+	} else
+	    continue;
+	if (newCube == NULL) {
+	    FREE(string);
+	    FREE(mask);
+	    FREE(indices);
+	    Cudd_RecursiveDeref(dd,cube);
+	    return(NULL);
+	}
+	cuddRef(newCube);
+	Cudd_RecursiveDeref(dd,cube);
+	cube = newCube;
+    }
+    Cudd_RecursiveDeref(dd,cube);
+
+    for (i = 0; i < mvars; i++) {
+	mask[maskVars[i]->index] = 1;
+    }
+    for (i = 0; i < nvars; i++) {
+	if (mask[indices[i]]) {
+	    if (string[indices[i]] == '2') {
+		if (weight[indices[i]] >= 0.0)
+		    string[indices[i]] = '1';
+		else
+		    string[indices[i]] = '0';
+	    }
+	} else {
+	    string[indices[i]] = '2';
+	}
+    }
+
+    cube = Cudd_ReadOne(dd);
+    cuddRef(cube);
+    zero = Cudd_Not(Cudd_ReadOne(dd));
+
+    /* Build result BDD. */
+    for (i = 0; i < nvars; i++) {
+	if (string[indices[i]] == '0') {
+	    newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
+	} else if (string[indices[i]] == '1') {
+	    newCube = Cudd_bddIte(dd,cube,vars[i],zero);
+	} else
+	    continue;
+	if (newCube == NULL) {
+	    FREE(string);
+	    FREE(mask);
+	    FREE(indices);
+	    Cudd_RecursiveDeref(dd,cube);
+	    return(NULL);
+	}
+	cuddRef(newCube);
+	Cudd_RecursiveDeref(dd,cube);
+	cube = newCube;
+    }
+
+    subset = Cudd_bddAnd(dd,f,cube);
+    cuddRef(subset);
+    Cudd_RecursiveDeref(dd,cube);
+
+    /* Test. */
+    if (Cudd_bddLeq(dd,subset,f)) {
+	cuddDeref(subset);
+    } else {
+	Cudd_RecursiveDeref(dd,subset);
+	subset = NULL;
+    }
+
+    FREE(string);
+    FREE(mask);
+    FREE(indices);
+    FREE(weight);
+    return(subset);
+
+} /* end of Cudd_SubsetWithMaskVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first cube of a decision diagram.]
+
+  Description [Defines an iterator on the onset of a decision diagram
+  and finds its first cube. Returns a generator that contains the
+  information necessary to continue the enumeration if successful; NULL
+  otherwise.<p>
+  A cube is represented as an array of literals, which are integers in
+  {0, 1, 2}; 0 represents a complemented literal, 1 represents an
+  uncomplemented literal, and 2 stands for don't care. The enumeration
+  produces a disjoint cover of the function associated with the diagram.
+  The size of the array equals the number of variables in the manager at
+  the time Cudd_FirstCube is called.<p>
+  For each cube, a value is also returned. This value is always 1 for a
+  BDD, while it may be different from 1 for an ADD.
+  For BDDs, the offset is the set of cubes whose value is the logical zero.
+  For ADDs, the offset is the set of cubes whose value is the
+  background value. The cubes of the offset are not enumerated.]
+
+  SideEffects [The first cube and its value are returned as side effects.]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_FirstNode]
+
+******************************************************************************/
+DdGen *
+Cudd_FirstCube(
+  DdManager * dd,
+  DdNode * f,
+  int ** cube,
+  CUDD_VALUE_TYPE * value)
+{
+    DdGen *gen;
+    DdNode *top, *treg, *next, *nreg, *prev, *preg;
+    int i;
+    int nvars;
+
+    /* Sanity Check. */
+    if (dd == NULL || f == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ALLOC(DdGen,1);
+    if (gen == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    gen->manager = dd;
+    gen->type = CUDD_GEN_CUBES;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->gen.cubes.cube = NULL;
+    gen->gen.cubes.value = DD_ZERO_VAL;
+    gen->stack.sp = 0;
+    gen->stack.stack = NULL;
+    gen->node = NULL;
+
+    nvars = dd->size;
+    gen->gen.cubes.cube = ALLOC(int,nvars);
+    if (gen->gen.cubes.cube == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(gen);
+	return(NULL);
+    }
+    for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
+
+    /* The maximum stack depth is one plus the number of variables.
+    ** because a path may have nodes at all levels, including the
+    ** constant level.
+    */
+    gen->stack.stack = ALLOC(DdNodePtr, nvars+1);
+    if (gen->stack.stack == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(gen->gen.cubes.cube);
+	FREE(gen);
+	return(NULL);
+    }
+    for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
+
+    /* Find the first cube of the onset. */
+    gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
+
+    while (1) {
+	top = gen->stack.stack[gen->stack.sp-1];
+	treg = Cudd_Regular(top);
+	if (!cuddIsConstant(treg)) {
+	    /* Take the else branch first. */
+	    gen->gen.cubes.cube[treg->index] = 0;
+	    next = cuddE(treg);
+	    if (top != treg) next = Cudd_Not(next);
+	    gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
+	} else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
+	    /* Backtrack */
+	    while (1) {
+		if (gen->stack.sp == 1) {
+		    /* The current node has no predecessor. */
+		    gen->status = CUDD_GEN_EMPTY;
+		    gen->stack.sp--;
+		    goto done;
+		}
+		prev = gen->stack.stack[gen->stack.sp-2];
+		preg = Cudd_Regular(prev);
+		nreg = cuddT(preg);
+		if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
+		if (next != top) { /* follow the then branch next */
+		    gen->gen.cubes.cube[preg->index] = 1;
+		    gen->stack.stack[gen->stack.sp-1] = next;
+		    break;
+		}
+		/* Pop the stack and try again. */
+		gen->gen.cubes.cube[preg->index] = 2;
+		gen->stack.sp--;
+		top = gen->stack.stack[gen->stack.sp-1];
+		treg = Cudd_Regular(top);
+	    }
+	} else {
+	    gen->status = CUDD_GEN_NONEMPTY;
+	    gen->gen.cubes.value = cuddV(top);
+	    goto done;
+	}
+    }
+
+done:
+    *cube = gen->gen.cubes.cube;
+    *value = gen->gen.cubes.value;
+    return(gen);
+
+} /* end of Cudd_FirstCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the next cube of a decision diagram onset.]
+
+  Description [Generates the next cube of a decision diagram onset,
+  using generator gen. Returns 0 if the enumeration is completed; 1
+  otherwise.]
+
+  SideEffects [The cube and its value are returned as side effects. The
+  generator is modified.]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_NextNode]
+
+******************************************************************************/
+int
+Cudd_NextCube(
+  DdGen * gen,
+  int ** cube,
+  CUDD_VALUE_TYPE * value)
+{
+    DdNode *top, *treg, *next, *nreg, *prev, *preg;
+    DdManager *dd = gen->manager;
+
+    /* Backtrack from previously reached terminal node. */
+    while (1) {
+	if (gen->stack.sp == 1) {
+	    /* The current node has no predecessor. */
+	    gen->status = CUDD_GEN_EMPTY;
+	    gen->stack.sp--;
+	    goto done;
+	}
+	top = gen->stack.stack[gen->stack.sp-1];
+	treg = Cudd_Regular(top);
+	prev = gen->stack.stack[gen->stack.sp-2];
+	preg = Cudd_Regular(prev);
+	nreg = cuddT(preg);
+	if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
+	if (next != top) { /* follow the then branch next */
+	    gen->gen.cubes.cube[preg->index] = 1;
+	    gen->stack.stack[gen->stack.sp-1] = next;
+	    break;
+	}
+	/* Pop the stack and try again. */
+	gen->gen.cubes.cube[preg->index] = 2;
+	gen->stack.sp--;
+    }
+
+    while (1) {
+	top = gen->stack.stack[gen->stack.sp-1];
+	treg = Cudd_Regular(top);
+	if (!cuddIsConstant(treg)) {
+	    /* Take the else branch first. */
+	    gen->gen.cubes.cube[treg->index] = 0;
+	    next = cuddE(treg);
+	    if (top != treg) next = Cudd_Not(next);
+	    gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
+	} else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
+	    /* Backtrack */
+	    while (1) {
+		if (gen->stack.sp == 1) {
+		    /* The current node has no predecessor. */
+		    gen->status = CUDD_GEN_EMPTY;
+		    gen->stack.sp--;
+		    goto done;
+		}
+		prev = gen->stack.stack[gen->stack.sp-2];
+		preg = Cudd_Regular(prev);
+		nreg = cuddT(preg);
+		if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
+		if (next != top) { /* follow the then branch next */
+		    gen->gen.cubes.cube[preg->index] = 1;
+		    gen->stack.stack[gen->stack.sp-1] = next;
+		    break;
+		}
+		/* Pop the stack and try again. */
+		gen->gen.cubes.cube[preg->index] = 2;
+		gen->stack.sp--;
+		top = gen->stack.stack[gen->stack.sp-1];
+		treg = Cudd_Regular(top);
+	    }
+	} else {
+	    gen->status = CUDD_GEN_NONEMPTY;
+	    gen->gen.cubes.value = cuddV(top);
+	    goto done;
+	}
+    }
+
+done:
+    if (gen->status == CUDD_GEN_EMPTY) return(0);
+    *cube = gen->gen.cubes.cube;
+    *value = gen->gen.cubes.value;
+    return(1);
+
+} /* end of Cudd_NextCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first prime of a Boolean function.]
+
+  Description [Defines an iterator on a pair of BDDs describing a
+  (possibly incompletely specified) Boolean functions and finds the
+  first cube of a cover of the function.  Returns a generator
+  that contains the information necessary to continue the enumeration
+  if successful; NULL otherwise.<p>
+
+  The two argument BDDs are the lower and upper bounds of an interval.
+  It is a mistake to call this function with a lower bound that is not
+  less than or equal to the upper bound.<p>
+
+  A cube is represented as an array of literals, which are integers in
+  {0, 1, 2}; 0 represents a complemented literal, 1 represents an
+  uncomplemented literal, and 2 stands for don't care. The enumeration
+  produces a prime and irredundant cover of the function associated
+  with the two BDDs.  The size of the array equals the number of
+  variables in the manager at the time Cudd_FirstCube is called.<p>
+
+  This iterator can only be used on BDDs.]
+
+  SideEffects [The first cube is returned as side effect.]
+
+  SeeAlso     [Cudd_ForeachPrime Cudd_NextPrime Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_FirstCube Cudd_FirstNode]
+
+******************************************************************************/
+DdGen *
+Cudd_FirstPrime(
+  DdManager *dd,
+  DdNode *l,
+  DdNode *u,
+  int **cube)
+{
+    DdGen *gen;
+    DdNode *implicant, *prime, *tmp;
+    int length, result;
+
+    /* Sanity Check. */
+    if (dd == NULL || l == NULL || u == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ALLOC(DdGen,1);
+    if (gen == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    gen->manager = dd;
+    gen->type = CUDD_GEN_PRIMES;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->gen.primes.cube = NULL;
+    gen->gen.primes.ub = u;
+    gen->stack.sp = 0;
+    gen->stack.stack = NULL;
+    gen->node = l;
+    cuddRef(l);
+
+    gen->gen.primes.cube = ALLOC(int,dd->size);
+    if (gen->gen.primes.cube == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	FREE(gen);
+	return(NULL);
+    }
+
+    if (gen->node == Cudd_ReadLogicZero(dd)) {
+	gen->status = CUDD_GEN_EMPTY;
+    } else {
+	implicant = Cudd_LargestCube(dd,gen->node,&length);
+	if (implicant == NULL) {
+	    Cudd_RecursiveDeref(dd,gen->node);
+	    FREE(gen->gen.primes.cube);
+	    FREE(gen);
+	    return(NULL);
+	}
+	cuddRef(implicant);
+	prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
+	if (prime == NULL) {
+	    Cudd_RecursiveDeref(dd,gen->node);
+	    Cudd_RecursiveDeref(dd,implicant);
+	    FREE(gen->gen.primes.cube);
+	    FREE(gen);
+	    return(NULL);
+	}
+	cuddRef(prime);
+	Cudd_RecursiveDeref(dd,implicant);
+	tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
+	if (tmp == NULL) {
+	    Cudd_RecursiveDeref(dd,gen->node);
+	    Cudd_RecursiveDeref(dd,prime);
+	    FREE(gen->gen.primes.cube);
+	    FREE(gen);
+	    return(NULL);
+	}
+	cuddRef(tmp);
+	Cudd_RecursiveDeref(dd,gen->node);
+	gen->node = tmp;
+	result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
+	if (result == 0) {
+	    Cudd_RecursiveDeref(dd,gen->node);
+	    Cudd_RecursiveDeref(dd,prime);
+	    FREE(gen->gen.primes.cube);
+	    FREE(gen);
+	    return(NULL);
+	}
+	Cudd_RecursiveDeref(dd,prime);
+	gen->status = CUDD_GEN_NONEMPTY;
+    }
+    *cube = gen->gen.primes.cube;
+    return(gen);
+
+} /* end of Cudd_FirstPrime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the next prime of a Boolean function.]
+
+  Description [Generates the next cube of a Boolean function,
+  using generator gen. Returns 0 if the enumeration is completed; 1
+  otherwise.]
+
+  SideEffects [The cube and is returned as side effects. The
+  generator is modified.]
+
+  SeeAlso     [Cudd_ForeachPrime Cudd_FirstPrime Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_NextCube Cudd_NextNode]
+
+******************************************************************************/
+int
+Cudd_NextPrime(
+  DdGen *gen,
+  int **cube)
+{
+    DdNode *implicant, *prime, *tmp;
+    DdManager *dd = gen->manager;
+    int length, result;
+
+    if (gen->node == Cudd_ReadLogicZero(dd)) {
+	gen->status = CUDD_GEN_EMPTY;
+    } else {
+	implicant = Cudd_LargestCube(dd,gen->node,&length);
+	if (implicant == NULL) {
+	    gen->status = CUDD_GEN_EMPTY;
+	    return(0);
+	}
+	cuddRef(implicant);
+	prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
+	if (prime == NULL) {
+	    Cudd_RecursiveDeref(dd,implicant);
+	    gen->status = CUDD_GEN_EMPTY;
+	    return(0);
+	}
+	cuddRef(prime);
+	Cudd_RecursiveDeref(dd,implicant);
+	tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
+	if (tmp == NULL) {
+	    Cudd_RecursiveDeref(dd,prime);
+	    gen->status = CUDD_GEN_EMPTY;
+	    return(0);
+	}
+	cuddRef(tmp);
+	Cudd_RecursiveDeref(dd,gen->node);
+	gen->node = tmp;
+	result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
+	if (result == 0) {
+	    Cudd_RecursiveDeref(dd,prime);
+	    gen->status = CUDD_GEN_EMPTY;
+	    return(0);
+	}
+	Cudd_RecursiveDeref(dd,prime);
+	gen->status = CUDD_GEN_NONEMPTY;
+    }
+    if (gen->status == CUDD_GEN_EMPTY) return(0);
+    *cube = gen->gen.primes.cube;
+    return(1);
+
+} /* end of Cudd_NextPrime */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cube of an array of BDD variables.]
+
+  Description [Computes the cube of an array of BDD variables. If
+  non-null, the phase argument indicates which literal of each
+  variable should appear in the cube. If phase\[i\] is nonzero, then the
+  positive literal is used. If phase is NULL, the cube is positive unate.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd]
+
+******************************************************************************/
+DdNode *
+Cudd_bddComputeCube(
+  DdManager * dd,
+  DdNode ** vars,
+  int * phase,
+  int  n)
+{
+    DdNode	*cube;
+    DdNode 	*fn;
+    int         i;
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+
+    for (i = n - 1; i >= 0; i--) {
+	if (phase == NULL || phase[i] != 0) {
+	    fn = Cudd_bddAnd(dd,vars[i],cube);
+	} else {
+	    fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube);
+	}
+	if (fn == NULL) {
+	    Cudd_RecursiveDeref(dd,cube);
+	    return(NULL);
+	}
+	cuddRef(fn);
+	Cudd_RecursiveDeref(dd,cube);
+	cube = fn;
+    }
+    cuddDeref(cube);
+
+    return(cube);
+
+}  /* end of Cudd_bddComputeCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cube of an array of ADD variables.]
+
+  Description [Computes the cube of an array of ADD variables.  If
+  non-null, the phase argument indicates which literal of each
+  variable should appear in the cube. If phase\[i\] is nonzero, then the
+  positive literal is used. If phase is NULL, the cube is positive unate.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso     [Cudd_bddComputeCube]
+
+******************************************************************************/
+DdNode *
+Cudd_addComputeCube(
+  DdManager * dd,
+  DdNode ** vars,
+  int * phase,
+  int  n)
+{
+    DdNode	*cube, *zero;
+    DdNode 	*fn;
+    int         i;
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    zero = DD_ZERO(dd);
+
+    for (i = n - 1; i >= 0; i--) {
+	if (phase == NULL || phase[i] != 0) {
+	    fn = Cudd_addIte(dd,vars[i],cube,zero);
+	} else {
+	    fn = Cudd_addIte(dd,vars[i],zero,cube);
+	}
+	if (fn == NULL) {
+	    Cudd_RecursiveDeref(dd,cube);
+	    return(NULL);
+	}
+	cuddRef(fn);
+	Cudd_RecursiveDeref(dd,cube);
+	cube = fn;
+    }
+    cuddDeref(cube);
+
+    return(cube);
+
+} /* end of Cudd_addComputeCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the BDD of a cube from a positional array.]
+
+  Description [Builds a cube from a positional array.  The array must
+  have one integer entry for each BDD variable.  If the i-th entry is
+  1, the variable of index i appears in true form in the cube; If the
+  i-th entry is 0, the variable of index i appears complemented in the
+  cube; otherwise the variable does not appear in the cube.  Returns a
+  pointer to the BDD for the cube if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray]
+
+******************************************************************************/
+DdNode *
+Cudd_CubeArrayToBdd(
+  DdManager *dd,
+  int *array)
+{
+    DdNode *cube, *var, *tmp;
+    int i;
+    int size = Cudd_ReadSize(dd);
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    for (i = size - 1; i >= 0; i--) {
+	if ((array[i] & ~1) == 0) {
+	    var = Cudd_bddIthVar(dd,i);
+	    tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0));
+	    if (tmp == NULL) {
+		Cudd_RecursiveDeref(dd,cube);
+		return(NULL);
+	    }
+	    cuddRef(tmp);
+	    Cudd_RecursiveDeref(dd,cube);
+	    cube = tmp;
+	}
+    }
+    cuddDeref(cube);
+    return(cube);
+
+} /* end of Cudd_CubeArrayToBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a positional array from the BDD of a cube.]
+
+  Description [Builds a positional array from the BDD of a cube.
+  Array must have one entry for each BDD variable.  The positional
+  array has 1 in i-th position if the variable of index i appears in
+  true form in the cube; it has 0 in i-th position if the variable of
+  index i appears in complemented form in the cube; finally, it has 2
+  in i-th position if the variable of index i does not appear in the
+  cube.  Returns 1 if successful (the BDD is indeed a cube); 0
+  otherwise.]
+
+  SideEffects [The result is in the array passed by reference.]
+
+  SeeAlso     [Cudd_CubeArrayToBdd]
+
+******************************************************************************/
+int
+Cudd_BddToCubeArray(
+  DdManager *dd,
+  DdNode *cube,
+  int *array)
+{
+    DdNode *scan, *t, *e;
+    int i;
+    int size = Cudd_ReadSize(dd);
+    DdNode *zero = Cudd_Not(DD_ONE(dd));
+
+    for (i = size-1; i >= 0; i--) {
+	array[i] = 2;
+    }
+    scan = cube;
+    while (!Cudd_IsConstant(scan)) {
+	int index = Cudd_Regular(scan)->index;
+	cuddGetBranches(scan,&t,&e);
+	if (t == zero) {
+	    array[index] = 0;
+	    scan = e;
+	} else if (e == zero) {
+	    array[index] = 1;
+	    scan = t;
+	} else {
+	    return(0);	/* cube is not a cube */
+	}
+    }
+    if (scan == zero) {
+	return(0);
+    } else {
+	return(1);
+    }
+
+} /* end of Cudd_BddToCubeArray */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first node of a decision diagram.]
+
+  Description [Defines an iterator on the nodes of a decision diagram
+  and finds its first node. Returns a generator that contains the
+  information necessary to continue the enumeration if successful;
+  NULL otherwise.  The nodes are enumerated in a reverse topological
+  order, so that a node is always preceded in the enumeration by its
+  descendants.]
+
+  SideEffects [The first node is returned as a side effect.]
+
+  SeeAlso     [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_FirstCube]
+
+******************************************************************************/
+DdGen *
+Cudd_FirstNode(
+  DdManager * dd,
+  DdNode * f,
+  DdNode ** node)
+{
+    DdGen *gen;
+    int size;
+
+    /* Sanity Check. */
+    if (dd == NULL || f == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ALLOC(DdGen,1);
+    if (gen == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    gen->manager = dd;
+    gen->type = CUDD_GEN_NODES;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->stack.sp = 0;
+    gen->node = NULL;
+
+    /* Collect all the nodes on the generator stack for later perusal. */
+    gen->stack.stack = cuddNodeArray(Cudd_Regular(f), &size);
+    if (gen->stack.stack == NULL) {
+	FREE(gen);
+	dd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+    gen->gen.nodes.size = size;
+
+    /* Find the first node. */
+    if (gen->stack.sp < gen->gen.nodes.size) {
+	gen->status = CUDD_GEN_NONEMPTY;
+	gen->node = gen->stack.stack[gen->stack.sp];
+	*node = gen->node;
+    }
+
+    return(gen);
+
+} /* end of Cudd_FirstNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next node of a decision diagram.]
+
+  Description [Finds the node of a decision diagram, using generator
+  gen. Returns 0 if the enumeration is completed; 1 otherwise.]
+
+  SideEffects [The next node is returned as a side effect.]
+
+  SeeAlso     [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty
+  Cudd_NextCube]
+
+******************************************************************************/
+int
+Cudd_NextNode(
+  DdGen * gen,
+  DdNode ** node)
+{
+    /* Find the next node. */
+    gen->stack.sp++;
+    if (gen->stack.sp < gen->gen.nodes.size) {
+	gen->node = gen->stack.stack[gen->stack.sp];
+	*node = gen->node;
+	return(1);
+    } else {
+	gen->status = CUDD_GEN_EMPTY;
+	return(0);
+    }
+
+} /* end of Cudd_NextNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a CUDD generator.]
+
+  Description [Frees a CUDD generator. Always returns 0, so that it can
+  be used in mis-like foreach constructs.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
+  Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty]
+
+******************************************************************************/
+int
+Cudd_GenFree(
+  DdGen * gen)
+{
+    if (gen == NULL) return(0);
+    switch (gen->type) {
+    case CUDD_GEN_CUBES:
+    case CUDD_GEN_ZDD_PATHS:
+	FREE(gen->gen.cubes.cube);
+	FREE(gen->stack.stack);
+	break;
+    case CUDD_GEN_PRIMES:
+	FREE(gen->gen.primes.cube);
+	Cudd_RecursiveDeref(gen->manager,gen->node);
+	break;
+    case CUDD_GEN_NODES:
+	FREE(gen->stack.stack);
+	break;
+    default:
+	return(0);
+    }
+    FREE(gen);
+    return(0);
+
+} /* end of Cudd_GenFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Queries the status of a generator.]
+
+  Description [Queries the status of a generator. Returns 1 if the
+  generator is empty or NULL; 0 otherswise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
+  Cudd_FirstNode Cudd_NextNode Cudd_GenFree]
+
+******************************************************************************/
+int
+Cudd_IsGenEmpty(
+  DdGen * gen)
+{
+    if (gen == NULL) return(1);
+    return(gen->status == CUDD_GEN_EMPTY);
+
+} /* end of Cudd_IsGenEmpty */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a cube of BDD variables from an array of indices.]
+
+  Description [Builds a cube of BDD variables from an array of indices.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddComputeCube Cudd_CubeArrayToBdd]
+
+******************************************************************************/
+DdNode *
+Cudd_IndicesToCube(
+  DdManager * dd,
+  int * array,
+  int  n)
+{
+    DdNode *cube, *tmp;
+    int i;
+
+    cube = DD_ONE(dd);
+    cuddRef(cube);
+    for (i = n - 1; i >= 0; i--) {
+	tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDeref(dd,cube);
+	    return(NULL);
+	}
+	cuddRef(tmp);
+	Cudd_RecursiveDeref(dd,cube);
+	cube = tmp;
+    }
+
+    cuddDeref(cube);
+    return(cube);
+
+} /* end of Cudd_IndicesToCube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the package version number.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_PrintVersion(
+  FILE * fp)
+{
+    (void) fprintf(fp, "%s\n", CUDD_VERSION);
+
+} /* end of Cudd_PrintVersion */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the average distance between adjacent nodes.]
+
+  Description [Computes the average distance between adjacent nodes in
+  the manager. Adjacent nodes are node pairs such that the second node
+  is the then child, else child, or next node in the collision list.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+double
+Cudd_AverageDistance(
+  DdManager * dd)
+{
+    double tetotal, nexttotal;
+    double tesubtotal, nextsubtotal;
+    double temeasured, nextmeasured;
+    int i, j;
+    int slots, nvars;
+    long diff;
+    DdNode *scan;
+    DdNodePtr *nodelist;
+    DdNode *sentinel = &(dd->sentinel);
+
+    nvars = dd->size;
+    if (nvars == 0) return(0.0);
+
+    /* Initialize totals. */
+    tetotal = 0.0;
+    nexttotal = 0.0;
+    temeasured = 0.0;
+    nextmeasured = 0.0;
+
+    /* Scan the variable subtables. */
+    for (i = 0; i < nvars; i++) {
+	nodelist = dd->subtables[i].nodelist;
+	tesubtotal = 0.0;
+	nextsubtotal = 0.0;
+	slots = dd->subtables[i].slots;
+	for (j = 0; j < slots; j++) {
+	    scan = nodelist[j];
+	    while (scan != sentinel) {
+		diff = (long) scan - (long) cuddT(scan);
+		tesubtotal += (double) ddAbs(diff);
+		diff = (long) scan - (long) Cudd_Regular(cuddE(scan));
+		tesubtotal += (double) ddAbs(diff);
+		temeasured += 2.0;
+		if (scan->next != NULL) {
+		    diff = (long) scan - (long) scan->next;
+		    nextsubtotal += (double) ddAbs(diff);
+		    nextmeasured += 1.0;
+		}
+		scan = scan->next;
+	    }
+	}
+	tetotal += tesubtotal;
+	nexttotal += nextsubtotal;
+    }
+
+    /* Scan the constant table. */
+    nodelist = dd->constants.nodelist;
+    nextsubtotal = 0.0;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+	scan = nodelist[j];
+	while (scan != NULL) {
+	    if (scan->next != NULL) {
+		diff = (long) scan - (long) scan->next;
+		nextsubtotal += (double) ddAbs(diff);
+		nextmeasured += 1.0;
+	    }
+	    scan = scan->next;
+	}
+    }
+    nexttotal += nextsubtotal;
+
+    return((tetotal + nexttotal) / (temeasured + nextmeasured));
+
+} /* end of Cudd_AverageDistance */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Portable random number generator.]
+
+  Description [Portable number generator based on ran2 from "Numerical
+  Recipes in C." It is a long period (> 2 * 10^18) random number generator
+  of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly
+  distributed between 0 and 2147483561 (inclusive of the endpoint values).
+  The random generator can be explicitly initialized by calling
+  Cudd_Srandom. If no explicit initialization is performed, then the
+  seed 1 is assumed.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Srandom]
+
+******************************************************************************/
+long
+Cudd_Random(void)
+{
+    int i;	/* index in the shuffle table */
+    long int w; /* work variable */
+
+    /* cuddRand == 0 if the geneartor has not been initialized yet. */
+    if (cuddRand == 0) Cudd_Srandom(1);
+
+    /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = cuddRand / LEQQ1;
+    cuddRand   = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
+    cuddRand  += (cuddRand < 0) * MODULUS1;
+
+    /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = cuddRand2 / LEQQ2;
+    cuddRand2  = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2;
+    cuddRand2 += (cuddRand2 < 0) * MODULUS2;
+
+    /* cuddRand is shuffled with the Bays-Durham algorithm.
+    ** shuffleSelect and cuddRand2 are combined to generate the output.
+    */
+
+    /* Pick one element from the shuffle table; "i" will be in the range
+    ** from 0 to STAB_SIZE-1.
+    */
+    i = (int) (shuffleSelect / STAB_DIV);
+    /* Mix the element of the shuffle table with the current iterate of
+    ** the second sub-generator, and replace the chosen element of the
+    ** shuffle table with the current iterate of the first sub-generator.
+    */
+    shuffleSelect   = shuffleTable[i] - cuddRand2;
+    shuffleTable[i] = cuddRand;
+    shuffleSelect  += (shuffleSelect < 1) * (MODULUS1 - 1);
+    /* Since shuffleSelect != 0, and we want to be able to return 0,
+    ** here we subtract 1 before returning.
+    */
+    return(shuffleSelect - 1);
+
+} /* end of Cudd_Random */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializer for the portable random number generator.]
+
+  Description [Initializer for the portable number generator based on
+  ran2 in "Numerical Recipes in C." The input is the seed for the
+  generator. If it is negative, its absolute value is taken as seed.
+  If it is 0, then 1 is taken as seed. The initialized sets up the two
+  recurrences used to generate a long-period stream, and sets up the
+  shuffle table.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_Random]
+
+******************************************************************************/
+void
+Cudd_Srandom(
+  long  seed)
+{
+    int i;
+
+    if (seed < 0)       cuddRand = -seed;
+    else if (seed == 0) cuddRand = 1;
+    else                cuddRand = seed;
+    cuddRand2 = cuddRand;
+    /* Load the shuffle table (after 11 warm-ups). */
+    for (i = 0; i < STAB_SIZE + 11; i++) {
+	long int w;
+	w = cuddRand / LEQQ1;
+	cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
+	cuddRand += (cuddRand < 0) * MODULUS1;
+	shuffleTable[i % STAB_SIZE] = cuddRand;
+    }
+    shuffleSelect = shuffleTable[1 % STAB_SIZE];
+
+} /* end of Cudd_Srandom */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the density of a BDD or ADD.]
+
+  Description [Computes the density of a BDD or ADD. The density is
+  the ratio of the number of minterms to the number of nodes. If 0 is
+  passed as number of variables, the number of variables existing in
+  the manager is used. Returns the density if successful; (double)
+  CUDD_OUT_OF_MEM otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountMinterm Cudd_DagSize]
+
+******************************************************************************/
+double
+Cudd_Density(
+  DdManager * dd /* manager */,
+  DdNode * f /* function whose density is sought */,
+  int  nvars /* size of the support of f */)
+{
+    double minterms;
+    int nodes;
+    double density;
+
+    if (nvars == 0) nvars = dd->size;
+    minterms = Cudd_CountMinterm(dd,f,nvars);
+    if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms);
+    nodes = Cudd_DagSize(f);
+    density = minterms / (double) nodes;
+    return(density);
+
+} /* end of Cudd_Density */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Warns that a memory allocation failed.]
+
+  Description [Warns that a memory allocation failed.
+  This function can be used as replacement of MMout_of_memory to prevent
+  the safe_mem functions of the util package from exiting when malloc
+  returns NULL. One possible use is in case of discretionary allocations;
+  for instance, the allocation of memory to enlarge the computed table.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_OutOfMem(
+  long size /* size of the allocation that failed */)
+{
+    (void) fflush(stdout);
+    (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size);
+    return;
+
+} /* end of Cudd_OutOfMem */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a DD to the standard output. One line per node is
+  printed.]
+
+  Description [Prints a DD to the standard output. One line per node is
+  printed. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_PrintDebug]
+
+******************************************************************************/
+int
+cuddP(
+  DdManager * dd,
+  DdNode * f)
+{
+    int retval;
+    st_table *table = st_init_table(st_ptrcmp,st_ptrhash);
+
+    if (table == NULL) return(0);
+
+    retval = dp2(dd,f,table);
+    st_free_table(table);
+    (void) fputc('\n',dd->out);
+    return(retval);
+
+} /* end of cuddP */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory used to store the minterm counts recorded
+  in the visited table.]
+
+  Description [Frees the memory used to store the minterm counts
+  recorded in the visited table. Returns ST_CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+enum st_retval
+cuddStCountfree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    double	*d;
+
+    d = (double *)value;
+    FREE(d);
+    return(ST_CONTINUE);
+
+} /* end of cuddStCountfree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively collects all the nodes of a DD in a symbol
+  table.]
+
+  Description [Traverses the DD f and collects all its nodes in a
+  symbol table.  f is assumed to be a regular pointer and
+  cuddCollectNodes guarantees this assumption in the recursive calls.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddCollectNodes(
+  DdNode * f,
+  st_table * visited)
+{
+    DdNode	*T, *E;
+    int		retval;
+
+#ifdef DD_DEBUG
+    assert(!Cudd_IsComplement(f));
+#endif
+
+    /* If already visited, nothing to do. */
+    if (st_is_member(visited, (char *) f) == 1)
+        return(1);
+
+    /* Check for abnormal condition that should never happen. */
+    if (f == NULL)
+        return(0);
+
+    /* Mark node as visited. */
+    if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
+        return(0);
+
+    /* Check terminal case. */
+    if (cuddIsConstant(f))
+	return(1);
+
+    /* Recursive calls. */
+    T = cuddT(f);
+    retval = cuddCollectNodes(T,visited);
+    if (retval != 1) return(retval);
+    E = Cudd_Regular(cuddE(f));
+    retval = cuddCollectNodes(E,visited);
+    return(retval);
+
+} /* end of cuddCollectNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively collects all the nodes of a DD in an array.]
+
+  Description [Traverses the DD f and collects all its nodes in an array.
+  The caller should free the array returned by cuddNodeArray.
+  Returns a pointer to the array of nodes in case of success; NULL
+  otherwise.  The nodes are collected in reverse topological order, so
+  that a node is always preceded in the array by all its descendants.]
+
+  SideEffects [The number of nodes is returned as a side effect.]
+
+  SeeAlso     [Cudd_FirstNode]
+
+******************************************************************************/
+DdNodePtr *
+cuddNodeArray(
+  DdNode *f,
+  int *n)
+{
+    DdNodePtr *table;
+    int size, retval;
+
+    size = ddDagInt(Cudd_Regular(f));
+    table = ALLOC(DdNodePtr, size);
+    if (table == NULL) {
+	ddClearFlag(Cudd_Regular(f));
+	return(NULL);
+    }
+
+    retval = cuddNodeArrayRecur(f, table, 0);
+    assert(retval == size);
+
+    *n = size;
+    return(table);
+  
+} /* cuddNodeArray */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of cuddP.]
+
+  Description [Performs the recursive step of cuddP. Returns 1 in case
+  of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+dp2(
+  DdManager *dd,
+  DdNode * f,
+  st_table * t)
+{
+    DdNode *g, *n, *N;
+    int T,E;
+    
+    if (f == NULL) {
+        return(0);
+    }
+    g = Cudd_Regular(f);
+    if (cuddIsConstant(g)) {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f),
+		(unsigned long) g / (unsigned long) sizeof(DdNode),cuddV(g));
+#else
+        (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f),
+		(unsigned) g / (unsigned) sizeof(DdNode),cuddV(g));
+#endif
+	return(1);
+    }
+    if (st_is_member(t,(char *) g) == 1) {
+        return(1);
+    }
+    if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM)
+	return(0);
+#ifdef DD_STATS
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f),
+		(unsigned long) g / (unsigned long) sizeof(DdNode), g->index, g->ref);
+#else
+    (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f),
+		(unsigned) g / (unsigned) sizeof(DdNode),g->index,g->ref);
+#endif
+#else
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\t", bang(f),
+		(unsigned long) g / (unsigned long) sizeof(DdNode),g->index);
+#else
+    (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\t", bang(f),
+		(unsigned) g / (unsigned) sizeof(DdNode),g->index);
+#endif
+#endif
+    n = cuddT(g);
+    if (cuddIsConstant(n)) {
+        (void) fprintf(dd->out,"T = %-9g\t",cuddV(n));
+	T = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(dd->out,"T = 0x%lx\t",(unsigned long) n / (unsigned long) sizeof(DdNode));
+#else
+        (void) fprintf(dd->out,"T = 0x%x\t",(unsigned) n / (unsigned) sizeof(DdNode));
+#endif
+	T = 0;
+    }
+
+    n = cuddE(g);
+    N = Cudd_Regular(n);
+    if (cuddIsConstant(N)) {
+        (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N));
+	E = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (unsigned long) N/(unsigned long) sizeof(DdNode));
+#else
+        (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (unsigned) N/(unsigned) sizeof(DdNode));
+#endif
+	E = 0;
+    }
+    if (E == 0) {
+        if (dp2(dd,N,t) == 0)
+	    return(0);
+    }
+    if (T == 0) {
+        if (dp2(dd,cuddT(g),t) == 0)
+	    return(0);
+    }
+    return(1);
+
+} /* end of dp2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_PrintMinterm.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+ddPrintMintermAux(
+  DdManager * dd /* manager */,
+  DdNode * node /* current node */,
+  int * list /* current recursion path */)
+{
+    DdNode	*N,*Nv,*Nnv;
+    int		i,v,index;
+
+    N = Cudd_Regular(node);
+
+    if (cuddIsConstant(N)) {
+	/* Terminal case: Print one cube based on the current recursion
+	** path, unless we have reached the background value (ADDs) or
+	** the logical zero (BDDs).
+	*/
+	if (node != background && node != zero) {
+	    for (i = 0; i < dd->size; i++) {
+		v = list[i];
+		if (v == 0) (void) fprintf(dd->out,"0");
+		else if (v == 1) (void) fprintf(dd->out,"1");
+		else (void) fprintf(dd->out,"-");
+	    }
+	    (void) fprintf(dd->out," % g\n", cuddV(node));
+	}
+    } else {
+	Nv  = cuddT(N);
+	Nnv = cuddE(N);
+	if (Cudd_IsComplement(node)) {
+	    Nv  = Cudd_Not(Nv);
+	    Nnv = Cudd_Not(Nnv);
+	}
+	index = N->index;
+	list[index] = 0;
+	ddPrintMintermAux(dd,Nnv,list); 
+	list[index] = 1;
+	ddPrintMintermAux(dd,Nv,list);
+	list[index] = 2;
+    }
+    return;
+
+} /* end of ddPrintMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_DagSize.]
+
+  Description [Performs the recursive step of Cudd_DagSize. Returns the
+  number of nodes in the graph rooted at n.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddDagInt(
+  DdNode * n)
+{
+    int tval, eval;
+
+    if (Cudd_IsComplement(n->next)) {
+	return(0);
+    }
+    n->next = Cudd_Not(n->next);
+    if (cuddIsConstant(n)) {
+	return(1);
+    }
+    tval = ddDagInt(cuddT(n));
+    eval = ddDagInt(Cudd_Regular(cuddE(n)));
+    return(1 + tval + eval);
+
+} /* end of ddDagInt */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of cuddNodeArray.]
+
+  Description [Performs the recursive step of cuddNodeArray.  Returns
+  an the number of nodes in the DD.  Clear the least significant bit
+  of the next field that was used as visited flag by
+  cuddNodeArrayRecur when counting the nodes.  node is supposed to be
+  regular; the invariant is maintained by this procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddNodeArrayRecur(
+  DdNode *f,
+  DdNodePtr *table,
+  int index)
+{
+    int tindex, eindex;
+
+    if (!Cudd_IsComplement(f->next)) {
+	return(index);
+    }
+    /* Clear visited flag. */
+    f->next = Cudd_Regular(f->next);
+    if (cuddIsConstant(f)) {
+	table[index] = f;
+	return(index + 1);
+    }
+    tindex = cuddNodeArrayRecur(cuddT(f), table, index);
+    eindex = cuddNodeArrayRecur(Cudd_Regular(cuddE(f)), table, tindex);
+    table[eindex] = f;
+    return(eindex + 1);
+
+} /* end of cuddNodeArrayRecur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CofactorEstimate.]
+
+  Description [Performs the recursive step of Cudd_CofactorEstimate.
+  Returns an estimate of the number of nodes in the DD of a
+  cofactor of node. Uses the least significant bit of the next field as
+  visited flag. node is supposed to be regular; the invariant is maintained
+  by this procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddEstimateCofactor(
+  DdManager *dd,
+  st_table *table,
+  DdNode * node,
+  int i,
+  int phase,
+  DdNode ** ptr)
+{
+    int tval, eval, val;
+    DdNode *ptrT, *ptrE;
+
+    if (Cudd_IsComplement(node->next)) {
+	if (!st_lookup(table,(char *)node,(char **)ptr)) {
+	    st_add_direct(table,(char *)node,(char *)node);
+	    *ptr = node;
+	}
+	return(0);
+    }
+    node->next = Cudd_Not(node->next);
+    if (cuddIsConstant(node)) {
+	*ptr = node;
+	if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM)
+	    return(CUDD_OUT_OF_MEM);
+	return(1);
+    }
+    if ((int) node->index == i) {
+	if (phase == 1) {
+	    *ptr = cuddT(node);
+	    val = ddDagInt(cuddT(node));
+	} else {
+	    *ptr = cuddE(node);
+	    val = ddDagInt(Cudd_Regular(cuddE(node)));
+	}
+	if (node->ref > 1) {
+	    if (st_add_direct(table,(char *)node,(char *)*ptr) ==
+		ST_OUT_OF_MEM)
+		return(CUDD_OUT_OF_MEM);
+	}
+	return(val);
+    }
+    if (dd->perm[node->index] > dd->perm[i]) {
+	*ptr = node;
+	tval = ddDagInt(cuddT(node));
+	eval = ddDagInt(Cudd_Regular(cuddE(node)));
+	if (node->ref > 1) {
+	    if (st_add_direct(table,(char *)node,(char *)node) ==
+		ST_OUT_OF_MEM)
+		return(CUDD_OUT_OF_MEM);
+	}
+	val = 1 + tval + eval;
+	return(val);
+    }
+    tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT);
+    eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i,
+				phase,&ptrE);
+    ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node)));
+    if (ptrT == ptrE) {		/* recombination */
+	*ptr = ptrT;
+	val = tval;
+	if (node->ref > 1) {
+	    if (st_add_direct(table,(char *)node,(char *)*ptr) ==
+		    ST_OUT_OF_MEM)
+		return(CUDD_OUT_OF_MEM);
+	}
+    } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) &&
+	       (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) {
+	if (Cudd_IsComplement((*ptr)->next)) {
+	    val = 0;
+	} else {
+	    val = 1 + tval + eval;
+	}
+	if (node->ref > 1) {
+	    if (st_add_direct(table,(char *)node,(char *)*ptr) ==
+		    ST_OUT_OF_MEM)
+		return(CUDD_OUT_OF_MEM);
+	}
+    } else {
+	*ptr = node;
+	val = 1 + tval + eval;
+    }
+    return(val);
+
+} /* end of cuddEstimateCofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the unique table for the existence of an internal node.]
+
+  Description [Checks the unique table for the existence of an internal
+  node. Returns a pointer to the node if it is in the table; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddUniqueInter]
+
+******************************************************************************/
+static DdNode *
+cuddUniqueLookup(
+  DdManager * unique,
+  int  index,
+  DdNode * T,
+  DdNode * E)
+{
+    int posn;
+    unsigned int level;
+    DdNodePtr *nodelist;
+    DdNode *looking;
+    DdSubtable *subtable;
+
+    if (index >= unique->size) {
+	return(NULL);
+    }
+
+    level = unique->perm[index];
+    subtable = &(unique->subtables[level]);
+
+#ifdef DD_DEBUG
+    assert(level < (unsigned) cuddI(unique,T->index));
+    assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
+#endif
+
+    posn = ddHash(T, E, subtable->shift);
+    nodelist = subtable->nodelist;
+    looking = nodelist[posn];
+
+    while (T < cuddT(looking)) {
+	looking = Cudd_Regular(looking->next);
+    }
+    while (T == cuddT(looking) && E < cuddE(looking)) {
+	looking = Cudd_Regular(looking->next);
+    }
+    if (cuddT(looking) == T && cuddE(looking) == E) {
+	return(looking);
+    }
+
+    return(NULL);
+
+} /* end of cuddUniqueLookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CofactorEstimateSimple.]
+
+  Description [Performs the recursive step of Cudd_CofactorEstimateSimple.
+  Returns an estimate of the number of nodes in the DD of the positive
+  cofactor of node. Uses the least significant bit of the next field as
+  visited flag. node is supposed to be regular; the invariant is maintained
+  by this procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddEstimateCofactorSimple(
+  DdNode * node,
+  int i)
+{
+    int tval, eval;
+
+    if (Cudd_IsComplement(node->next)) {
+	return(0);
+    }
+    node->next = Cudd_Not(node->next);
+    if (cuddIsConstant(node)) {
+	return(1);
+    }
+    tval = cuddEstimateCofactorSimple(cuddT(node),i);
+    if ((int) node->index == i) return(tval);
+    eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i);
+    return(1 + tval + eval);
+
+} /* end of cuddEstimateCofactorSimple */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountMinterm.]
+
+  Description [Performs the recursive step of Cudd_CountMinterm.
+  It is based on the following identity. Let |f| be the
+  number of minterms of f. Then:
+  <xmp>
+    |f| = (|f0|+|f1|)/2
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Does not use the
+  identity |f'| = max - |f|, to minimize loss of accuracy due to
+  roundoff.  Returns the number of minterms of the function rooted at
+  node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static double
+ddCountMintermAux(
+  DdNode * node,
+  double  max,
+  DdHashTable * table)
+{
+    DdNode	*N, *Nt, *Ne;
+    double	min, minT, minE;
+    DdNode	*res;
+
+    N = Cudd_Regular(node);
+
+    if (cuddIsConstant(N)) {
+	if (node == background || node == zero) {
+	    return(0.0);
+	} else {
+	    return(max);
+	}
+    }
+    if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
+	min = cuddV(res);
+	if (res->ref == 0) {
+	    table->manager->dead++;
+	    table->manager->constants.dead++;
+	}
+	return(min);
+    }
+
+    Nt = cuddT(N); Ne = cuddE(N);
+    if (Cudd_IsComplement(node)) {
+	Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
+    }
+
+    minT = ddCountMintermAux(Nt,max,table);
+    if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    minT *= 0.5;
+    minE = ddCountMintermAux(Ne,max,table);
+    if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    minE *= 0.5;
+    min = minT + minE;
+
+    if (N->ref != 1) {
+	ptrint fanout = (ptrint) N->ref;
+	cuddSatDec(fanout);
+	res = cuddUniqueConst(table->manager,min);
+	if (!cuddHashTableInsert1(table,node,res,fanout)) {
+	    cuddRef(res); Cudd_RecursiveDeref(table->manager, res);
+	    return((double)CUDD_OUT_OF_MEM);
+	}
+    }
+
+    return(min);
+
+} /* end of ddCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountPath.]
+
+  Description [Performs the recursive step of Cudd_CountPath.
+  It is based on the following identity. Let |f| be the
+  number of paths of f. Then:
+  <xmp>
+    |f| = |f0|+|f1|
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Uses the
+  identity |f'| = |f|, to improve the utilization of the (local) cache.
+  Returns the number of paths of the function rooted at node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static double
+ddCountPathAux(
+  DdNode * node,
+  st_table * table)
+{
+
+    DdNode	*Nv, *Nnv;
+    double	paths, *ppaths, paths1, paths2;
+    double	*dummy;
+
+
+    if (cuddIsConstant(node)) {
+	return(1.0);
+    }
+    if (st_lookup(table, node, &dummy)) {
+	paths = *dummy;
+	return(paths);
+    }
+
+    Nv = cuddT(node); Nnv = cuddE(node);
+
+    paths1 = ddCountPathAux(Nv,table);
+    if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths2 = ddCountPathAux(Cudd_Regular(Nnv),table);
+    if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths = paths1 + paths2;
+    
+    ppaths = ALLOC(double,1);
+    if (ppaths == NULL) {
+	return((double)CUDD_OUT_OF_MEM);
+    }
+
+    *ppaths = paths;
+
+    if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) {
+	FREE(ppaths);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    return(paths);
+
+} /* end of ddCountPathAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_EpdCountMinterm.]
+
+  Description [Performs the recursive step of Cudd_EpdCountMinterm.
+  It is based on the following identity. Let |f| be the
+  number of minterms of f. Then:
+  <xmp>
+    |f| = (|f0|+|f1|)/2
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Does not use the
+  identity |f'| = max - |f|, to minimize loss of accuracy due to
+  roundoff.  Returns the number of minterms of the function rooted at
+  node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddEpdCountMintermAux(
+  DdNode * node,
+  EpDouble * max,
+  EpDouble * epd,
+  st_table * table)
+{
+    DdNode	*Nt, *Ne;
+    EpDouble	*min, minT, minE;
+    EpDouble	*res;
+    int		status;
+
+    /* node is assumed to be regular */
+    if (cuddIsConstant(node)) {
+	if (node == background || node == zero) {
+	    EpdMakeZero(epd, 0);
+	} else {
+	    EpdCopy(max, epd);
+	}
+	return(0);
+    }
+    if (node->ref != 1 && st_lookup(table, node, &res)) {
+	EpdCopy(res, epd);
+	return(0);
+    }
+
+    Nt = cuddT(node); Ne = cuddE(node);
+
+    status = ddEpdCountMintermAux(Nt,max,&minT,table);
+    if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    EpdMultiply(&minT, (double)0.5);
+    status = ddEpdCountMintermAux(Cudd_Regular(Ne),max,&minE,table);
+    if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
+    if (Cudd_IsComplement(Ne)) {
+    	EpdSubtract3(max, &minE, epd);
+    	EpdCopy(epd, &minE);
+    }
+    EpdMultiply(&minE, (double)0.5);
+    EpdAdd3(&minT, &minE, epd);
+
+    if (node->ref > 1) {
+	min = EpdAlloc();
+	if (!min)
+	    return(CUDD_OUT_OF_MEM);
+	EpdCopy(epd, min);
+	if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) {
+	    EpdFree(min);
+	    return(CUDD_OUT_OF_MEM);
+	}
+    }
+
+    return(0);
+
+} /* end of ddEpdCountMintermAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountPathsToNonZero.]
+
+  Description [Performs the recursive step of Cudd_CountPathsToNonZero.
+  It is based on the following identity. Let |f| be the
+  number of paths of f. Then:
+  <xmp>
+    |f| = |f0|+|f1|
+  </xmp>
+  where f0 and f1 are the two cofactors of f.  Returns the number of
+  paths of the function rooted at node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static double
+ddCountPathsToNonZero(
+  DdNode * N,
+  st_table * table)
+{
+
+    DdNode	*node, *Nt, *Ne;
+    double	paths, *ppaths, paths1, paths2;
+    double	*dummy;
+
+    node = Cudd_Regular(N);
+    if (cuddIsConstant(node)) {
+	return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL));
+    }
+    if (st_lookup(table, N, &dummy)) {
+	paths = *dummy;
+	return(paths);
+    }
+
+    Nt = cuddT(node); Ne = cuddE(node);
+    if (node != N) {
+	Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
+    }
+
+    paths1 = ddCountPathsToNonZero(Nt,table);
+    if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths2 = ddCountPathsToNonZero(Ne,table);
+    if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
+    paths = paths1 + paths2;
+
+    ppaths = ALLOC(double,1);
+    if (ppaths == NULL) {
+	return((double)CUDD_OUT_OF_MEM);
+    }
+
+    *ppaths = paths;
+
+    if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) {
+	FREE(ppaths);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    return(paths);
+
+} /* end of ddCountPathsToNonZero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_Support.]
+
+  Description [Performs the recursive step of Cudd_Support. Performs a
+  DFS from f. The support is accumulated in supp as a side effect. Uses
+  the LSB of the then pointer as visited flag.]
+
+  SideEffects [None]
+
+  SeeAlso     [ddClearFlag]
+
+******************************************************************************/
+static void
+ddSupportStep(
+  DdNode * f,
+  int * support)
+{
+    if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
+	return;
+    }
+
+    support[f->index] = 1;
+    ddSupportStep(cuddT(f),support);
+    ddSupportStep(Cudd_Regular(cuddE(f)),support);
+    /* Mark as visited. */
+    f->next = Cudd_Not(f->next);
+    return;
+
+} /* end of ddSupportStep */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a DFS from f, clearing the LSB of the next
+  pointers.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [ddSupportStep ddDagInt]
+
+******************************************************************************/
+static void
+ddClearFlag(
+  DdNode * f)
+{
+    if (!Cudd_IsComplement(f->next)) {
+	return;
+    }
+    /* Clear visited flag. */
+    f->next = Cudd_Regular(f->next);
+    if (cuddIsConstant(f)) {
+	return;
+    }
+    ddClearFlag(cuddT(f));
+    ddClearFlag(Cudd_Regular(cuddE(f)));
+    return;
+
+} /* end of ddClearFlag */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_CountLeaves.]
+
+  Description [Performs the recursive step of Cudd_CountLeaves. Returns
+  the number of leaves in the DD rooted at n.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_CountLeaves]
+
+******************************************************************************/
+static int
+ddLeavesInt(
+  DdNode * n)
+{
+    int tval, eval;
+
+    if (Cudd_IsComplement(n->next)) {
+	return(0);
+    }
+    n->next = Cudd_Not(n->next);
+    if (cuddIsConstant(n)) {
+	return(1);
+    }
+    tval = ddLeavesInt(cuddT(n));
+    eval = ddLeavesInt(Cudd_Regular(cuddE(n)));
+    return(tval + eval);
+
+} /* end of ddLeavesInt */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_bddPickArbitraryMinterms.]
+
+  Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [none]
+
+  SeeAlso [Cudd_bddPickArbitraryMinterms]
+
+******************************************************************************/
+static int
+ddPickArbitraryMinterms(
+  DdManager *dd,
+  DdNode *node,
+  int nvars,
+  int nminterms,
+  char **string)
+{
+    DdNode *N, *T, *E;
+    DdNode *one, *bzero;
+    int    i, t, result;
+    double min1, min2;
+
+    if (string == NULL || node == NULL) return(0);
+
+    /* The constant 0 function has no on-set cubes. */
+    one = DD_ONE(dd);
+    bzero = Cudd_Not(one);
+    if (nminterms == 0 || node == bzero) return(1);
+    if (node == one) {
+	return(1);
+    }
+
+    N = Cudd_Regular(node);
+    T = cuddT(N); E = cuddE(N);
+    if (Cudd_IsComplement(node)) {
+	T = Cudd_Not(T); E = Cudd_Not(E);
+    }
+
+    min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0;
+    if (min1 == (double)CUDD_OUT_OF_MEM) return(0);
+    min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0;
+    if (min2 == (double)CUDD_OUT_OF_MEM) return(0);
+
+    t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5);
+    for (i = 0; i < t; i++)
+	string[i][N->index] = '1';
+    for (i = t; i < nminterms; i++)
+	string[i][N->index] = '0';
+
+    result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]);
+    if (result == 0)
+	return(0);
+    result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]);
+    return(result);
+
+} /* end of ddPickArbitraryMinterms */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a representative cube of a BDD.]
+
+  Description [Finds a representative cube of a BDD with the weight of
+  each variable. From the top variable, if the weight is greater than or
+  equal to 0.0, choose THEN branch unless the child is the constant 0.
+  Otherwise, choose ELSE branch unless the child is the constant 0.]
+
+  SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube]
+
+******************************************************************************/
+static int
+ddPickRepresentativeCube(
+  DdManager *dd,
+  DdNode *node,
+  int nvars,
+  double *weight,
+  char *string)
+{
+    DdNode *N, *T, *E;
+    DdNode *one, *bzero;
+
+    if (string == NULL || node == NULL) return(0);
+
+    /* The constant 0 function has no on-set cubes. */
+    one = DD_ONE(dd);
+    bzero = Cudd_Not(one);
+    if (node == bzero) return(0);
+
+    if (node == DD_ONE(dd)) return(1);
+
+    for (;;) {
+	N = Cudd_Regular(node);
+	if (N == one)
+	    break;
+	T = cuddT(N);
+	E = cuddE(N);
+	if (Cudd_IsComplement(node)) {
+	    T = Cudd_Not(T);
+	    E = Cudd_Not(E);
+	}
+	if (weight[N->index] >= 0.0) {
+	    if (T == bzero) {
+		node = E;
+		string[N->index] = '0';
+	    } else {
+		node = T;
+		string[N->index] = '1';
+	    }
+	} else {
+	    if (E == bzero) {
+		node = T;
+		string[N->index] = '1';
+	    } else {
+		node = E;
+		string[N->index] = '0';
+	    }
+	}
+    }
+    return(1);
+
+} /* end of ddPickRepresentativeCube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory used to store the minterm counts recorded
+  in the visited table.]
+
+  Description [Frees the memory used to store the minterm counts
+  recorded in the visited table. Returns ST_CONTINUE.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static enum st_retval
+ddEpdFree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    EpDouble	*epd;
+
+    epd = (EpDouble *) value;
+    EpdFree(epd);
+    return(ST_CONTINUE);
+
+} /* end of ddEpdFree */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddWindow.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddWindow.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddWindow.c	(revision 8)
@@ -0,0 +1,1024 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddWindow.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for window permutation]
+
+  Description [Internal procedures included in this module:
+		<ul>
+		<li> cuddWindowReorder()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> ddWindow2()
+		<li> ddWindowConv2()
+		<li> ddPermuteWindow3()
+		<li> ddWindow3()
+		<li> ddWindowConv3()
+		<li> ddPermuteWindow4()
+		<li> ddWindow4()
+		<li> ddWindowConv4()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.13 2004/08/13 18:04:52 fabio Exp $";
+#endif
+
+#ifdef DD_STATS
+extern  int     ddTotalNumberSwapping;
+extern  int     ddTotalNISwaps;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ddWindow2 (DdManager *table, int low, int high);
+static int ddWindowConv2 (DdManager *table, int low, int high);
+static int ddPermuteWindow3 (DdManager *table, int x);
+static int ddWindow3 (DdManager *table, int low, int high);
+static int ddWindowConv3 (DdManager *table, int low, int high);
+static int ddPermuteWindow4 (DdManager *table, int w);
+static int ddWindow4 (DdManager *table, int low, int high);
+static int ddWindowConv4 (DdManager *table, int low, int high);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying the method of the sliding window.]
+
+  Description [Reorders by applying the method of the sliding window.
+  Tries all possible permutations to the variables in a window that
+  slides from low to high. The size of the window is determined by
+  submethod.  Assumes that no dead nodes are present.  Returns 1 in
+  case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddWindowReorder(
+  DdManager * table /* DD table */,
+  int low /* lowest index to reorder */,
+  int high /* highest index to reorder */,
+  Cudd_ReorderingType submethod /* window reordering option */)
+{
+
+    int res;
+#ifdef DD_DEBUG
+    int supposedOpt;
+#endif
+
+    switch (submethod) {
+    case CUDD_REORDER_WINDOW2:
+	res = ddWindow2(table,low,high);
+	break;
+    case CUDD_REORDER_WINDOW3:
+	res = ddWindow3(table,low,high);
+	break;
+    case CUDD_REORDER_WINDOW4:
+	res = ddWindow4(table,low,high);
+	break;
+    case CUDD_REORDER_WINDOW2_CONV:
+	res = ddWindowConv2(table,low,high);
+	break;
+    case CUDD_REORDER_WINDOW3_CONV:
+	res = ddWindowConv3(table,low,high);
+#ifdef DD_DEBUG
+	supposedOpt = table->keys - table->isolated;
+	res = ddWindow3(table,low,high);
+	if (table->keys - table->isolated != (unsigned) supposedOpt) {
+	    (void) fprintf(table->err, "Convergence failed! (%d != %d)\n",
+			   table->keys - table->isolated, supposedOpt);
+	}
+#endif
+	break;
+    case CUDD_REORDER_WINDOW4_CONV:
+	res = ddWindowConv4(table,low,high);
+#ifdef DD_DEBUG
+	supposedOpt = table->keys - table->isolated;
+	res = ddWindow4(table,low,high);
+	if (table->keys - table->isolated != (unsigned) supposedOpt) {
+	    (void) fprintf(table->err,"Convergence failed! (%d != %d)\n",
+			   table->keys - table->isolated, supposedOpt);
+	}
+#endif
+	break;
+    default: return(0);
+    }
+
+    return(res);
+
+} /* end of cuddWindowReorder */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying a sliding window of width 2.]
+
+  Description [Reorders by applying a sliding window of width 2.
+  Tries both permutations of the variables in a window
+  that slides from low to high.  Assumes that no dead nodes are
+  present.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindow2(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+
+    int x;
+    int res;
+    int size;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 1) return(0);
+
+    res = table->keys - table->isolated;
+    for (x = low; x < high; x++) {
+	size = res;
+	res = cuddSwapInPlace(table,x,x+1);
+	if (res == 0) return(0);
+	if (res >= size) { /* no improvement: undo permutation */
+	    res = cuddSwapInPlace(table,x,x+1);
+	    if (res == 0) return(0);
+	}
+#ifdef DD_STATS
+	if (res < size) {
+	    (void) fprintf(table->out,"-");
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+} /* end of ddWindow2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by repeatedly applying a sliding window of width 2.]
+
+  Description [Reorders by repeatedly applying a sliding window of width
+  2. Tries both permutations of the variables in a window
+  that slides from low to high.  Assumes that no dead nodes are
+  present.  Uses an event-driven approach to determine convergence.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindowConv2(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+    int x;
+    int res;
+    int nwin;
+    int newevent;
+    int *events;
+    int size;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 1) return(ddWindowConv2(table,low,high));
+
+    nwin = high-low;
+    events = ALLOC(int,nwin);
+    if (events == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (x=0; x<nwin; x++) {
+	events[x] = 1;
+    }
+
+    res = table->keys - table->isolated;
+    do {
+	newevent = 0;
+	for (x=0; x<nwin; x++) {
+	    if (events[x]) {
+		size = res;
+		res = cuddSwapInPlace(table,x+low,x+low+1);
+		if (res == 0) {
+		    FREE(events);
+		    return(0);
+		}
+		if (res >= size) { /* no improvement: undo permutation */
+		    res = cuddSwapInPlace(table,x+low,x+low+1);
+		    if (res == 0) {
+			FREE(events);
+			return(0);
+		    }
+		}
+		if (res < size) {
+		    if (x < nwin-1)	events[x+1] = 1;
+		    if (x > 0)		events[x-1] = 1;
+		    newevent = 1;
+		}
+		events[x] = 0;
+#ifdef DD_STATS
+		if (res < size) {
+		    (void) fprintf(table->out,"-");
+		} else {
+		    (void) fprintf(table->out,"=");
+		}
+		fflush(table->out);
+#endif
+	    }
+	}
+#ifdef DD_STATS
+	if (newevent) {
+	    (void) fprintf(table->out,"|");
+	    fflush(table->out);
+	}
+#endif
+    } while (newevent);
+
+    FREE(events);
+
+    return(1);
+
+} /* end of ddWindowConv3 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Tries all the permutations of the three variables between
+  x and x+2 and retains the best.]
+
+  Description [Tries all the permutations of the three variables between
+  x and x+2 and retains the best. Assumes that no dead nodes are
+  present.  Returns the index of the best permutation (1-6) in case of
+  success; 0 otherwise.Assumes that no dead nodes are present.  Returns
+  the index of the best permutation (1-6) in case of success; 0
+  otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddPermuteWindow3(
+  DdManager * table,
+  int  x)
+{
+    int y,z;
+    int	size,sizeNew;
+    int	best;
+
+#ifdef DD_DEBUG
+    assert(table->dead == 0);
+    assert(x+2 < table->size);
+#endif
+
+    size = table->keys - table->isolated;
+    y = x+1; z = y+1;
+    
+    /* The permutation pattern is:
+    ** (x,y)(y,z)
+    ** repeated three times to get all 3! = 6 permutations.
+    */
+#define ABC 1
+    best = ABC;
+
+#define	BAC 2
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = BAC;
+	size = sizeNew;
+    }
+#define BCA 3
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = BCA;
+	size = sizeNew;
+    }
+#define CBA 4
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = CBA;
+	size = sizeNew;
+    }
+#define CAB 5
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = CAB;
+	size = sizeNew;
+    }
+#define ACB 6
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = ACB;
+	size = sizeNew;
+    }
+
+    /* Now take the shortest route to the best permuytation.
+    ** The initial permutation is ACB.
+    */
+    switch(best) {
+    case BCA: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case CBA: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case ABC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ACB: break;
+    case BAC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case CAB: if (!cuddSwapInPlace(table,x,y)) return(0);
+	       break;
+    default: return(0);
+    }
+
+#ifdef DD_DEBUG
+    assert(table->keys - table->isolated == (unsigned) size);
+#endif
+
+    return(best);
+
+} /* end of ddPermuteWindow3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying a sliding window of width 3.]
+
+  Description [Reorders by applying a sliding window of width 3.
+  Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindow3(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+
+    int x;
+    int res;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 2) return(ddWindow2(table,low,high));
+
+    for (x = low; x+1 < high; x++) {
+	res = ddPermuteWindow3(table,x);
+	if (res == 0) return(0);
+#ifdef DD_STATS
+	if (res == ABC) {
+	    (void) fprintf(table->out,"=");
+	} else {
+	    (void) fprintf(table->out,"-");
+	}
+	fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+} /* end of ddWindow3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by repeatedly applying a sliding window of width 3.]
+
+  Description [Reorders by repeatedly applying a sliding window of width
+  3. Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Uses an event-driven approach to determine convergence.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindowConv3(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+    int x;
+    int res;
+    int nwin;
+    int newevent;
+    int *events;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 2) return(ddWindowConv2(table,low,high));
+
+    nwin = high-low-1;
+    events = ALLOC(int,nwin);
+    if (events == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (x=0; x<nwin; x++) {
+	events[x] = 1;
+    }
+
+    do {
+	newevent = 0;
+	for (x=0; x<nwin; x++) {
+	    if (events[x]) {
+		res = ddPermuteWindow3(table,x+low);
+		switch (res) {
+		case ABC:
+		    break;
+		case BAC:
+		    if (x < nwin-1)	events[x+1] = 1;
+		    if (x > 1)		events[x-2] = 1;
+		    newevent = 1;
+		    break;
+		case BCA:
+		case CBA:
+		case CAB:
+		    if (x < nwin-2)	events[x+2] = 1;
+		    if (x < nwin-1)	events[x+1] = 1;
+		    if (x > 0)		events[x-1] = 1;
+		    if (x > 1)		events[x-2] = 1;
+		    newevent = 1;
+		    break;
+		case ACB:
+		    if (x < nwin-2)	events[x+2] = 1;
+		    if (x > 0)		events[x-1] = 1;
+		    newevent = 1;
+		    break;
+		default:
+		    FREE(events);
+		    return(0);
+		}
+		events[x] = 0;
+#ifdef DD_STATS
+		if (res == ABC) {
+		    (void) fprintf(table->out,"=");
+		} else {
+		    (void) fprintf(table->out,"-");
+		}
+		fflush(table->out);
+#endif
+	    }
+	}
+#ifdef DD_STATS
+	if (newevent) {
+	    (void) fprintf(table->out,"|");
+	    fflush(table->out);
+	}
+#endif
+    } while (newevent);
+
+    FREE(events);
+
+    return(1);
+
+} /* end of ddWindowConv3 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Tries all the permutations of the four variables between w
+  and w+3 and retains the best.]
+
+  Description [Tries all the permutations of the four variables between
+  w and w+3 and retains the best. Assumes that no dead nodes are
+  present.  Returns the index of the best permutation (1-24) in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddPermuteWindow4(
+  DdManager * table,
+  int  w)
+{
+    int x,y,z;
+    int	size,sizeNew;
+    int	best;
+
+#ifdef DD_DEBUG
+    assert(table->dead == 0);
+    assert(w+3 < table->size);
+#endif
+
+    size = table->keys - table->isolated;
+    x = w+1; y = x+1; z = y+1;
+    
+    /* The permutation pattern is:
+     * (w,x)(y,z)(w,x)(x,y)
+     * (y,z)(w,x)(y,z)(x,y)
+     * repeated three times to get all 4! = 24 permutations.
+     * This gives a hamiltonian circuit of Cayley's graph.
+     * The codes to the permutation are assigned in topological order.
+     * The permutations at lower distance from the final permutation are
+     * assigned lower codes. This way we can choose, between
+     * permutations that give the same size, one that requires the minimum
+     * number of swaps from the final permutation of the hamiltonian circuit.
+     * There is an exception to this rule: ABCD is given Code 1, to
+     * avoid oscillation when convergence is sought.
+     */
+#define ABCD 1
+    best = ABCD;
+
+#define	BACD 7
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = BACD;
+	size = sizeNew;
+    }
+#define BADC 13
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = BADC;
+	size = sizeNew;
+    }
+#define ABDC 8
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && ABDC < best)) {
+	if (sizeNew == 0) return(0);
+	best = ABDC;
+	size = sizeNew;
+    }
+#define ADBC 14
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = ADBC;
+	size = sizeNew;
+    }
+#define ADCB 9
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && ADCB < best)) {
+	if (sizeNew == 0) return(0);
+	best = ADCB;
+	size = sizeNew;
+    }
+#define DACB 15
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = DACB;
+	size = sizeNew;
+    }
+#define DABC 20
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = DABC;
+	size = sizeNew;
+    }
+#define DBAC 23
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = DBAC;
+	size = sizeNew;
+    }
+#define BDAC 19
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && BDAC < best)) {
+	if (sizeNew == 0) return(0);
+	best = BDAC;
+	size = sizeNew;
+    }
+#define BDCA 21
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && BDCA < best)) {
+	if (sizeNew == 0) return(0);
+	best = BDCA;
+	size = sizeNew;
+    }
+#define DBCA 24
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size) {
+	if (sizeNew == 0) return(0);
+	best = DBCA;
+	size = sizeNew;
+    }
+#define DCBA 22
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size || (sizeNew == size && DCBA < best)) {
+	if (sizeNew == 0) return(0);
+	best = DCBA;
+	size = sizeNew;
+    }
+#define DCAB 18
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && DCAB < best)) {
+	if (sizeNew == 0) return(0);
+	best = DCAB;
+	size = sizeNew;
+    }
+#define CDAB 12
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && CDAB < best)) {
+	if (sizeNew == 0) return(0);
+	best = CDAB;
+	size = sizeNew;
+    }
+#define CDBA 17
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && CDBA < best)) {
+	if (sizeNew == 0) return(0);
+	best = CDBA;
+	size = sizeNew;
+    }
+#define CBDA 11
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size || (sizeNew == size && CBDA < best)) {
+	if (sizeNew == 0) return(0);
+	best = CBDA;
+	size = sizeNew;
+    }
+#define BCDA 16
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && BCDA < best)) {
+	if (sizeNew == 0) return(0);
+	best = BCDA;
+	size = sizeNew;
+    }
+#define BCAD 10
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && BCAD < best)) {
+	if (sizeNew == 0) return(0);
+	best = BCAD;
+	size = sizeNew;
+    }
+#define CBAD 5
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && CBAD < best)) {
+	if (sizeNew == 0) return(0);
+	best = CBAD;
+	size = sizeNew;
+    }
+#define CABD 3
+    sizeNew = cuddSwapInPlace(table,x,y);
+    if (sizeNew < size || (sizeNew == size && CABD < best)) {
+	if (sizeNew == 0) return(0);
+	best = CABD;
+	size = sizeNew;
+    }
+#define CADB 6
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && CADB < best)) {
+	if (sizeNew == 0) return(0);
+	best = CADB;
+	size = sizeNew;
+    }
+#define ACDB 4
+    sizeNew = cuddSwapInPlace(table,w,x);
+    if (sizeNew < size || (sizeNew == size && ACDB < best)) {
+	if (sizeNew == 0) return(0);
+	best = ACDB;
+	size = sizeNew;
+    }
+#define ACBD 2
+    sizeNew = cuddSwapInPlace(table,y,z);
+    if (sizeNew < size || (sizeNew == size && ACBD < best)) {
+	if (sizeNew == 0) return(0);
+	best = ACBD;
+	size = sizeNew;
+    }
+
+    /* Now take the shortest route to the best permutation.
+    ** The initial permutation is ACBD.
+    */
+    switch(best) {
+    case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0);
+    case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ACBD: break;
+    case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0);
+	       if (!cuddSwapInPlace(table,x,y)) return(0);
+	       if (!cuddSwapInPlace(table,y,z)) return(0);
+	       break;
+    case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0);
+    case DACB: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BACD: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CABD: if (!cuddSwapInPlace(table,w,x)) return(0);
+	       break;
+    case DABC: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case BADC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CADB: if (!cuddSwapInPlace(table,w,x)) return(0);
+	       if (!cuddSwapInPlace(table,y,z)) return(0);
+	       break;
+    case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0);
+    case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0);
+    case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0);
+	       break;
+    case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0);
+    case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0);
+	       if (!cuddSwapInPlace(table,x,y)) return(0);
+	       break;
+    default: return(0);
+    }
+
+#ifdef DD_DEBUG
+    assert(table->keys - table->isolated == (unsigned) size);
+#endif
+
+    return(best);
+
+} /* end of ddPermuteWindow4 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by applying a sliding window of width 4.]
+
+  Description [Reorders by applying a sliding window of width 4.
+  Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindow4(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+
+    int w;
+    int res;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 3) return(ddWindow3(table,low,high));
+
+    for (w = low; w+2 < high; w++) {
+	res = ddPermuteWindow4(table,w);
+	if (res == 0) return(0);
+#ifdef DD_STATS
+	if (res == ABCD) {
+	    (void) fprintf(table->out,"=");
+	} else {
+	    (void) fprintf(table->out,"-");
+	}
+	fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+} /* end of ddWindow4 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders by repeatedly applying a sliding window of width 4.]
+
+  Description [Reorders by repeatedly applying a sliding window of width
+  4. Tries all possible permutations to the variables in a
+  window that slides from low to high.  Assumes that no dead nodes are
+  present.  Uses an event-driven approach to determine convergence.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+ddWindowConv4(
+  DdManager * table,
+  int  low,
+  int  high)
+{
+    int x;
+    int res;
+    int nwin;
+    int newevent;
+    int *events;
+
+#ifdef DD_DEBUG
+    assert(low >= 0 && high < table->size);
+#endif
+
+    if (high-low < 3) return(ddWindowConv3(table,low,high));
+
+    nwin = high-low-2;
+    events = ALLOC(int,nwin);
+    if (events == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (x=0; x<nwin; x++) {
+	events[x] = 1;
+    }
+
+    do {
+	newevent = 0;
+	for (x=0; x<nwin; x++) {
+	    if (events[x]) {
+		res = ddPermuteWindow4(table,x+low);
+		switch (res) {
+		case ABCD:
+		    break;
+		case BACD:
+		    if (x < nwin-1)	events[x+1] = 1;
+		    if (x > 2)		events[x-3] = 1;
+		    newevent = 1;
+		    break;
+		case BADC:
+		    if (x < nwin-3)	events[x+3] = 1;
+		    if (x < nwin-1)	events[x+1] = 1;
+		    if (x > 0)		events[x-1] = 1;
+		    if (x > 2)		events[x-3] = 1;
+		    newevent = 1;
+		    break;
+		case ABDC:
+		    if (x < nwin-3)	events[x+3] = 1;
+		    if (x > 0)		events[x-1] = 1;
+		    newevent = 1;
+		    break;
+		case ADBC:
+		case ADCB:
+		case ACDB:
+		    if (x < nwin-3)	events[x+3] = 1;
+		    if (x < nwin-2)	events[x+2] = 1;
+		    if (x > 0)		events[x-1] = 1;
+		    if (x > 1)		events[x-2] = 1;
+		    newevent = 1;
+		    break;
+		case DACB:
+		case DABC:
+		case DBAC:
+		case BDAC:
+		case BDCA:
+		case DBCA:
+		case DCBA:
+		case DCAB:
+		case CDAB:
+		case CDBA:
+		case CBDA:
+		case BCDA:
+		case CADB:
+		    if (x < nwin-3)	events[x+3] = 1;
+		    if (x < nwin-2)	events[x+2] = 1;
+		    if (x < nwin-1)	events[x+1] = 1;
+		    if (x > 0)		events[x-1] = 1;
+		    if (x > 1)		events[x-2] = 1;
+		    if (x > 2)		events[x-3] = 1;
+		    newevent = 1;
+		    break;
+		case BCAD:
+		case CBAD:
+		case CABD:
+		    if (x < nwin-2)	events[x+2] = 1;
+		    if (x < nwin-1)	events[x+1] = 1;
+		    if (x > 1)		events[x-2] = 1;
+		    if (x > 2)		events[x-3] = 1;
+		    newevent = 1;
+		    break;
+		case ACBD:
+		    if (x < nwin-2)	events[x+2] = 1;
+		    if (x > 1)		events[x-2] = 1;
+		    newevent = 1;
+		    break;
+		default:
+		    FREE(events);
+		    return(0);
+		}
+		events[x] = 0;
+#ifdef DD_STATS
+		if (res == ABCD) {
+		    (void) fprintf(table->out,"=");
+		} else {
+		    (void) fprintf(table->out,"-");
+		}
+		fflush(table->out);
+#endif
+	    }
+	}
+#ifdef DD_STATS
+	if (newevent) {
+	    (void) fprintf(table->out,"|");
+	    fflush(table->out);
+	}
+#endif
+    } while (newevent);
+
+    FREE(events);
+
+    return(1);
+
+} /* end of ddWindowConv4 */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddCount.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddCount.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddCount.c	(revision 8)
@@ -0,0 +1,357 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddCount.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures to count the number of minterms of a ZDD.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddCount();
+		    <li> Cudd_zddCountDouble();
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+       		    <li> cuddZddCountStep();
+		    <li> cuddZddCountDoubleStep();
+		    <li> st_zdd_count_dbl_free()
+		    <li> st_zdd_countfree()
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.14 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddCountStep (DdNode *P, st_table *table, DdNode *base, DdNode *empty);
+static double cuddZddCountDoubleStep (DdNode *P, st_table *table, DdNode *base, DdNode *empty);
+static enum st_retval st_zdd_countfree (char *key, char *value, char *arg);
+static enum st_retval st_zdd_count_dbl_free (char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of minterms in a ZDD.]
+
+  Description [Returns an integer representing the number of minterms
+  in a ZDD.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddCountDouble]
+
+******************************************************************************/
+int
+Cudd_zddCount(
+  DdManager * zdd,
+  DdNode * P)
+{
+    st_table	*table;
+    int		res;
+    DdNode	*base, *empty;
+
+    base  = DD_ONE(zdd);
+    empty = DD_ZERO(zdd);
+    table = st_init_table(st_ptrcmp, st_ptrhash);
+    if (table == NULL) return(CUDD_OUT_OF_MEM);
+    res = cuddZddCountStep(P, table, base, empty);
+    if (res == CUDD_OUT_OF_MEM) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+    }
+    st_foreach(table, st_zdd_countfree, NIL(char));
+    st_free_table(table);
+
+    return(res);
+
+} /* end of Cudd_zddCount */
+
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of minterms of a ZDD.]
+
+  Description [Counts the number of minterms of a ZDD. The result is
+  returned as a double. If the procedure runs out of memory, it
+  returns (double) CUDD_OUT_OF_MEM. This procedure is used in
+  Cudd_zddCountMinterm.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddCountMinterm Cudd_zddCount]
+
+******************************************************************************/
+double
+Cudd_zddCountDouble(
+  DdManager * zdd,
+  DdNode * P)
+{
+    st_table	*table;
+    double	res;
+    DdNode	*base, *empty;
+
+    base  = DD_ONE(zdd);
+    empty = DD_ZERO(zdd);
+    table = st_init_table(st_ptrcmp, st_ptrhash);
+    if (table == NULL) return((double)CUDD_OUT_OF_MEM);
+    res = cuddZddCountDoubleStep(P, table, base, empty);
+    if (res == (double)CUDD_OUT_OF_MEM) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+    }
+    st_foreach(table, st_zdd_count_dbl_free, NIL(char));
+    st_free_table(table);
+
+    return(res);
+
+} /* end of Cudd_zddCountDouble */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddCount.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddCountStep(
+  DdNode * P,
+  st_table * table,
+  DdNode * base,
+  DdNode * empty)
+{
+    int		res;
+    int		*dummy;
+
+    if (P == empty)
+	return(0);
+    if (P == base)
+	return(1);
+
+    /* Check cache. */
+    if (st_lookup(table, P, &dummy)) {
+	res = *dummy;
+	return(res);
+    }
+
+    res = cuddZddCountStep(cuddE(P), table, base, empty) +
+	cuddZddCountStep(cuddT(P), table, base, empty);
+
+    dummy = ALLOC(int, 1);
+    if (dummy == NULL) {
+	return(CUDD_OUT_OF_MEM);
+    }
+    *dummy = res;
+    if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) {
+	FREE(dummy);
+	return(CUDD_OUT_OF_MEM);
+    }
+
+    return(res);
+
+} /* end of cuddZddCountStep */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddCountDouble.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static double
+cuddZddCountDoubleStep(
+  DdNode * P,
+  st_table * table,
+  DdNode * base,
+  DdNode * empty)
+{
+    double	res;
+    double	*dummy;
+
+    if (P == empty)
+	return((double)0.0);
+    if (P == base)
+	return((double)1.0);
+
+    /* Check cache */
+    if (st_lookup(table, P, &dummy)) {
+	res = *dummy;
+	return(res);
+    }
+
+    res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) +
+	cuddZddCountDoubleStep(cuddT(P), table, base, empty);
+
+    dummy = ALLOC(double, 1);
+    if (dummy == NULL) {
+	return((double)CUDD_OUT_OF_MEM);
+    }
+    *dummy = res;
+    if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) {
+	FREE(dummy);
+	return((double)CUDD_OUT_OF_MEM);
+    }
+
+    return(res);
+
+} /* end of cuddZddCountDoubleStep */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory associated with the computed table of
+  Cudd_zddCount.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static enum st_retval
+st_zdd_countfree(
+  char * key,
+  char * value,
+  char * arg)
+{
+    int	*d;
+
+    d = (int *)value;
+    FREE(d);
+    return(ST_CONTINUE);
+
+} /* end of st_zdd_countfree */
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees the memory associated with the computed table of
+  Cudd_zddCountDouble.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static enum st_retval
+st_zdd_count_dbl_free(
+  char * key,
+  char * value,
+  char * arg)
+{
+    double	*d;
+
+    d = (double *)value;
+    FREE(d);
+    return(ST_CONTINUE);
+
+} /* end of st_zdd_count_dbl_free */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddFuncs.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddFuncs.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddFuncs.c	(revision 8)
@@ -0,0 +1,1630 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddFuncs.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to manipulate covers represented as ZDDs.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddProduct();
+		    <li> Cudd_zddUnateProduct();
+		    <li> Cudd_zddWeakDiv();
+		    <li> Cudd_zddWeakDivF();
+		    <li> Cudd_zddDivide();
+		    <li> Cudd_zddDivideF();
+		    <li> Cudd_zddComplement();
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    <li> cuddZddProduct();
+		    <li> cuddZddUnateProduct();
+		    <li> cuddZddWeakDiv();
+		    <li> cuddZddWeakDivF();
+		    <li> cuddZddDivide();
+		    <li> cuddZddDivideF();
+		    <li> cuddZddGetCofactors3()
+		    <li> cuddZddGetCofactors2()
+		    <li> cuddZddComplement();
+		    <li> cuddZddGetPosVarIndex();
+		    <li> cuddZddGetNegVarIndex();
+		    <li> cuddZddGetPosVarLevel();
+		    <li> cuddZddGetNegVarLevel();
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.14 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the product of two covers represented by ZDDs.]
+
+  Description [Computes the product of two covers represented by
+  ZDDs. The result is also a ZDD. Returns a pointer to the result if
+  successful; NULL otherwise.  The covers on which Cudd_zddProduct
+  operates use two ZDD variables for each function variable (one ZDD
+  variable for each literal of the variable). Those two ZDD variables
+  should be adjacent in the order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddUnateProduct]
+
+******************************************************************************/
+DdNode	*
+Cudd_zddProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddProduct(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the product of two unate covers.]
+
+  Description [Computes the product of two unate covers represented as
+  ZDDs. Unate covers use one ZDD variable for each BDD
+  variable. Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddProduct]
+
+******************************************************************************/
+DdNode	*
+Cudd_zddUnateProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddUnateProduct(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddUnateProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies weak division to two covers.]
+
+  Description [Applies weak division to two ZDDs representing two
+  covers. Returns a pointer to the ZDD representing the result if
+  successful; NULL otherwise. The result of weak division depends on
+  the variable order. The covers on which Cudd_zddWeakDiv operates use
+  two ZDD variables for each function variable (one ZDD variable for
+  each literal of the variable). Those two ZDD variables should be
+  adjacent in the order.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDivide]
+
+******************************************************************************/
+DdNode	*
+Cudd_zddWeakDiv(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddWeakDiv(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddWeakDiv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the quotient of two unate covers.]
+
+  Description [Computes the quotient of two unate covers represented
+  by ZDDs.  Unate covers use one ZDD variable for each BDD
+  variable. Returns a pointer to the resulting ZDD if successful; NULL
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDiv]
+
+******************************************************************************/
+DdNode	*
+Cudd_zddDivide(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddDivide(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddDivide */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Modified version of Cudd_zddWeakDiv.]
+
+  Description [Modified version of Cudd_zddWeakDiv. This function may
+  disappear in future releases.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDiv]
+
+******************************************************************************/
+DdNode	*
+Cudd_zddWeakDivF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddWeakDivF(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddWeakDivF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Modified version of Cudd_zddDivide.]
+
+  Description [Modified version of Cudd_zddDivide. This function may
+  disappear in future releases.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode	*
+Cudd_zddDivideF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddDivideF(dd, f, g);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddDivideF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a complement cover for a ZDD node.]
+
+  Description [Computes a complement cover for a ZDD node. For lack of a
+  better method, we first extract the function BDD from the ZDD cover,
+  then make the complement of the ZDD cover from the complement of the
+  BDD node by using ISOP. Returns a pointer to the resulting cover if
+  successful; NULL otherwise. The result depends on current variable
+  order.]
+
+  SideEffects [The result depends on current variable order.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode	*
+Cudd_zddComplement(
+  DdManager *dd,
+  DdNode *node)
+{
+    DdNode	*b, *isop, *zdd_I;
+
+    /* Check cache */
+    zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node);
+    if (zdd_I)
+	return(zdd_I);
+
+    b = Cudd_MakeBddFromZddCover(dd, node);
+    if (!b)
+	return(NULL);
+    Cudd_Ref(b);
+    isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I);
+    if (!isop) {
+	Cudd_RecursiveDeref(dd, b);
+	return(NULL);
+    }
+    Cudd_Ref(isop);
+    Cudd_Ref(zdd_I);
+    Cudd_RecursiveDeref(dd, b);
+    Cudd_RecursiveDeref(dd, isop);
+
+    cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I);
+    Cudd_Deref(zdd_I);
+    return(zdd_I);
+} /* end of Cudd_zddComplement */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddProduct.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddProduct]
+
+******************************************************************************/
+DdNode	*
+cuddZddProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int		v, top_f, top_g;
+    DdNode	*tmp, *term1, *term2, *term3;
+    DdNode	*f0, *f1, *fd, *g0, *g1, *gd;
+    DdNode	*R0, *R1, *Rd, *N0, *N1;
+    DdNode	*r;
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = DD_ZERO(dd);
+    int		flag;
+    int		pv, nv;
+
+    statLine(dd);
+    if (f == zero || g == zero)
+        return(zero);
+    if (f == one)
+        return(g);
+    if (g == one)
+        return(f);
+
+    top_f = dd->permZ[f->index];
+    top_g = dd->permZ[g->index];
+
+    if (top_f > top_g)
+	return(cuddZddProduct(dd, g, f));
+
+    /* Check cache */
+    r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g);
+    if (r)
+	return(r);
+
+    v = f->index;	/* either yi or zi */
+    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+    if (flag == 1)
+	return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
+    if (flag == 1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+    Cudd_Ref(gd);
+    pv = cuddZddGetPosVarIndex(dd, v);
+    nv = cuddZddGetNegVarIndex(dd, v);
+
+    Rd = cuddZddProduct(dd, fd, gd);
+    if (Rd == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	return(NULL);
+    }
+    Cudd_Ref(Rd);
+
+    term1 = cuddZddProduct(dd, f0, g0);
+    if (term1 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, Rd);
+	return(NULL);
+    }
+    Cudd_Ref(term1);
+    term2 = cuddZddProduct(dd, f0, gd);
+    if (term2 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, Rd);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	return(NULL);
+    }
+    Cudd_Ref(term2);
+    term3 = cuddZddProduct(dd, fd, g0);
+    if (term3 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, Rd);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, term2);
+	return(NULL);
+    }
+    Cudd_Ref(term3);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    tmp = cuddZddUnion(dd, term1, term2);
+    if (tmp == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, Rd);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, term2);
+	Cudd_RecursiveDerefZdd(dd, term3);
+	return(NULL);
+    }
+    Cudd_Ref(tmp);
+    Cudd_RecursiveDerefZdd(dd, term1);
+    Cudd_RecursiveDerefZdd(dd, term2);
+    R0 = cuddZddUnion(dd, tmp, term3);
+    if (R0 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, Rd);
+	Cudd_RecursiveDerefZdd(dd, term3);
+	Cudd_RecursiveDerefZdd(dd, tmp);
+	return(NULL);
+    }
+    Cudd_Ref(R0);
+    Cudd_RecursiveDerefZdd(dd, tmp);
+    Cudd_RecursiveDerefZdd(dd, term3);
+    N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */
+    if (N0 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, Rd);
+	Cudd_RecursiveDerefZdd(dd, R0);
+	return(NULL);
+    }
+    Cudd_Ref(N0);
+    Cudd_RecursiveDerefZdd(dd, R0);
+    Cudd_RecursiveDerefZdd(dd, Rd);
+
+    term1 = cuddZddProduct(dd, f1, g1);
+    if (term1 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, N0);
+	return(NULL);
+    }
+    Cudd_Ref(term1);
+    term2 = cuddZddProduct(dd, f1, gd);
+    if (term2 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, N0);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	return(NULL);
+    }
+    Cudd_Ref(term2);
+    term3 = cuddZddProduct(dd, fd, g1);
+    if (term3 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	Cudd_RecursiveDerefZdd(dd, N0);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, term2);
+	return(NULL);
+    }
+    Cudd_Ref(term3);
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, fd);
+    Cudd_RecursiveDerefZdd(dd, gd);
+    tmp = cuddZddUnion(dd, term1, term2);
+    if (tmp == NULL) {
+	Cudd_RecursiveDerefZdd(dd, N0);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, term2);
+	Cudd_RecursiveDerefZdd(dd, term3);
+	return(NULL);
+    }
+    Cudd_Ref(tmp);
+    Cudd_RecursiveDerefZdd(dd, term1);
+    Cudd_RecursiveDerefZdd(dd, term2);
+    R1 = cuddZddUnion(dd, tmp, term3);
+    if (R1 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, N0);
+	Cudd_RecursiveDerefZdd(dd, term3);
+	Cudd_RecursiveDerefZdd(dd, tmp);
+	return(NULL);
+    }
+    Cudd_Ref(R1);
+    Cudd_RecursiveDerefZdd(dd, tmp);
+    Cudd_RecursiveDerefZdd(dd, term3);
+    N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */
+    if (N1 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, N0);
+	Cudd_RecursiveDerefZdd(dd, R1);
+	return(NULL);
+    }
+    Cudd_Ref(N1);
+    Cudd_RecursiveDerefZdd(dd, R1);
+    Cudd_RecursiveDerefZdd(dd, N0);
+
+    cuddCacheInsert2(dd, cuddZddProduct, f, g, N1);
+    Cudd_Deref(N1);
+    return(N1);
+
+} /* end of cuddZddProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddUnateProduct.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddUnateProduct]
+
+******************************************************************************/
+DdNode	*
+cuddZddUnateProduct(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int		v, top_f, top_g;
+    DdNode	*term1, *term2, *term3, *term4;
+    DdNode	*sum1, *sum2;
+    DdNode	*f0, *f1, *g0, *g1;
+    DdNode	*r;
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = DD_ZERO(dd);
+    int		flag;
+
+    statLine(dd);
+    if (f == zero || g == zero)
+        return(zero);
+    if (f == one)
+        return(g);
+    if (g == one)
+        return(f);
+
+    top_f = dd->permZ[f->index];
+    top_g = dd->permZ[g->index];
+
+    if (top_f > top_g)
+	return(cuddZddUnateProduct(dd, g, f));
+
+    /* Check cache */
+    r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g);
+    if (r)
+	return(r);
+
+    v = f->index;	/* either yi or zi */
+    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
+    if (flag == 1)
+	return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);
+    if (flag == 1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+
+    term1 = cuddZddUnateProduct(dd, f1, g1);
+    if (term1 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	return(NULL);
+    }
+    Cudd_Ref(term1);
+    term2 = cuddZddUnateProduct(dd, f1, g0);
+    if (term2 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	return(NULL);
+    }
+    Cudd_Ref(term2);
+    term3 = cuddZddUnateProduct(dd, f0, g1);
+    if (term3 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, term2);
+	return(NULL);
+    }
+    Cudd_Ref(term3);
+    term4 = cuddZddUnateProduct(dd, f0, g0);
+    if (term4 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, term2);
+	Cudd_RecursiveDerefZdd(dd, term3);
+	return(NULL);
+    }
+    Cudd_Ref(term4);
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    sum1 = cuddZddUnion(dd, term1, term2);
+    if (sum1 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, term2);
+	Cudd_RecursiveDerefZdd(dd, term3);
+	Cudd_RecursiveDerefZdd(dd, term4);
+	return(NULL);
+    }
+    Cudd_Ref(sum1);
+    Cudd_RecursiveDerefZdd(dd, term1);
+    Cudd_RecursiveDerefZdd(dd, term2);
+    sum2 = cuddZddUnion(dd, sum1, term3);
+    if (sum2 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, term3);
+	Cudd_RecursiveDerefZdd(dd, term4);
+	Cudd_RecursiveDerefZdd(dd, sum1);
+	return(NULL);
+    }
+    Cudd_Ref(sum2);
+    Cudd_RecursiveDerefZdd(dd, sum1);
+    Cudd_RecursiveDerefZdd(dd, term3);
+    r = cuddZddGetNode(dd, v, sum2, term4);
+    if (r == NULL) {
+	Cudd_RecursiveDerefZdd(dd, term4);
+	Cudd_RecursiveDerefZdd(dd, sum2);
+	return(NULL);
+    }
+    Cudd_Ref(r);
+    Cudd_RecursiveDerefZdd(dd, sum2);
+    Cudd_RecursiveDerefZdd(dd, term4);
+
+    cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r);
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddZddUnateProduct */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddWeakDiv.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDiv]
+
+******************************************************************************/
+DdNode	*
+cuddZddWeakDiv(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int		v;
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = DD_ZERO(dd);
+    DdNode	*f0, *f1, *fd, *g0, *g1, *gd;
+    DdNode	*q, *tmp;
+    DdNode	*r;
+    int		flag;
+
+    statLine(dd);
+    if (g == one)
+	return(f);
+    if (f == zero || f == one)
+	return(zero);
+    if (f == g)
+	return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g);
+    if (r)
+	return(r);
+
+    v = g->index;
+
+    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+    if (flag == 1)
+	return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
+    if (flag == 1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+    Cudd_Ref(gd);
+
+    q = g;
+
+    if (g0 != zero) {
+	q = cuddZddWeakDiv(dd, f0, g0);
+	if (q == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, g0);
+	    Cudd_RecursiveDerefZdd(dd, gd);
+	    return(NULL);
+	}
+	Cudd_Ref(q);
+    }
+    else
+	Cudd_Ref(q);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g0);
+
+    if (q == zero) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
+	Cudd_Deref(q);
+	return(zero);
+    }
+
+    if (g1 != zero) {
+	Cudd_RecursiveDerefZdd(dd, q);
+	tmp = cuddZddWeakDiv(dd, f1, g1);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, gd);
+	    return(NULL);
+	}
+	Cudd_Ref(tmp);
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	if (q == g)
+	    q = tmp;
+	else {
+	    q = cuddZddIntersect(dd, q, tmp);
+	    if (q == NULL) {
+		Cudd_RecursiveDerefZdd(dd, fd);
+		Cudd_RecursiveDerefZdd(dd, gd);
+		return(NULL);
+	    }
+	    Cudd_Ref(q);
+	    Cudd_RecursiveDerefZdd(dd, tmp);
+	}
+    }
+    else {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, g1);
+    }
+
+    if (q == zero) {
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
+	Cudd_Deref(q);
+	return(zero);
+    }
+
+    if (gd != zero) {
+	Cudd_RecursiveDerefZdd(dd, q);
+	tmp = cuddZddWeakDiv(dd, fd, gd);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, gd);
+	    return(NULL);
+	}
+	Cudd_Ref(tmp);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	if (q == g)
+	    q = tmp;
+	else {
+	    q = cuddZddIntersect(dd, q, tmp);
+	    if (q == NULL) {
+		Cudd_RecursiveDerefZdd(dd, tmp);
+		return(NULL);
+	    }
+	    Cudd_Ref(q);
+	    Cudd_RecursiveDerefZdd(dd, tmp);
+	}
+    }
+    else {
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+    }
+
+    cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q);
+    Cudd_Deref(q);
+    return(q);
+
+} /* end of cuddZddWeakDiv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddWeakDivF.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddWeakDivF]
+
+******************************************************************************/
+DdNode	*
+cuddZddWeakDivF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int		v, top_f, top_g, vf, vg;
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = DD_ZERO(dd);
+    DdNode	*f0, *f1, *fd, *g0, *g1, *gd;
+    DdNode	*q, *tmp;
+    DdNode	*r;
+    DdNode	*term1, *term0, *termd;
+    int		flag;
+    int		pv, nv;
+
+    statLine(dd);
+    if (g == one)
+	return(f);
+    if (f == zero || f == one)
+	return(zero);
+    if (f == g)
+	return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g);
+    if (r)
+	return(r);
+
+    top_f = dd->permZ[f->index];
+    top_g = dd->permZ[g->index];
+    vf = top_f >> 1;
+    vg = top_g >> 1;
+    v = ddMin(top_f, top_g);
+
+    if (v == top_f && vf < vg) {
+	v = f->index;
+	flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+	if (flag == 1)
+	    return(NULL);
+	Cudd_Ref(f1);
+	Cudd_Ref(f0);
+	Cudd_Ref(fd);
+
+	pv = cuddZddGetPosVarIndex(dd, v);
+	nv = cuddZddGetNegVarIndex(dd, v);
+
+	term1 = cuddZddWeakDivF(dd, f1, g);
+	if (term1 == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    return(NULL);
+	}
+	Cudd_Ref(term1);
+	Cudd_RecursiveDerefZdd(dd, f1);
+	term0 = cuddZddWeakDivF(dd, f0, g);
+	if (term0 == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, term1);
+	    return(NULL);
+	}
+	Cudd_Ref(term0);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	termd = cuddZddWeakDivF(dd, fd, g);
+	if (termd == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, term1);
+	    Cudd_RecursiveDerefZdd(dd, term0);
+	    return(NULL);
+	}
+	Cudd_Ref(termd);
+	Cudd_RecursiveDerefZdd(dd, fd);
+
+	tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */
+	if (tmp == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, term1);
+	    Cudd_RecursiveDerefZdd(dd, term0);
+	    Cudd_RecursiveDerefZdd(dd, termd);
+	    return(NULL);
+	}
+	Cudd_Ref(tmp);
+	Cudd_RecursiveDerefZdd(dd, term0);
+	Cudd_RecursiveDerefZdd(dd, termd);
+	q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */
+	if (q == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, term1);
+	    Cudd_RecursiveDerefZdd(dd, tmp);
+	    return(NULL);
+	}
+	Cudd_Ref(q);
+	Cudd_RecursiveDerefZdd(dd, term1);
+	Cudd_RecursiveDerefZdd(dd, tmp);
+
+	cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
+	Cudd_Deref(q);
+	return(q);
+    }
+
+    if (v == top_f)
+	v = f->index;
+    else
+	v = g->index;
+
+    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
+    if (flag == 1)
+	return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
+    if (flag == 1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+    Cudd_Ref(gd);
+
+    q = g;
+
+    if (g0 != zero) {
+	q = cuddZddWeakDivF(dd, f0, g0);
+	if (q == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, g0);
+	    Cudd_RecursiveDerefZdd(dd, gd);
+	    return(NULL);
+	}
+	Cudd_Ref(q);
+    }
+    else
+	Cudd_Ref(q);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g0);
+
+    if (q == zero) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
+	Cudd_Deref(q);
+	return(zero);
+    }
+
+    if (g1 != zero) {
+	Cudd_RecursiveDerefZdd(dd, q);
+	tmp = cuddZddWeakDivF(dd, f1, g1);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, gd);
+	    return(NULL);
+	}
+	Cudd_Ref(tmp);
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	if (q == g)
+	    q = tmp;
+	else {
+	    q = cuddZddIntersect(dd, q, tmp);
+	    if (q == NULL) {
+		Cudd_RecursiveDerefZdd(dd, fd);
+		Cudd_RecursiveDerefZdd(dd, gd);
+		return(NULL);
+	    }
+	    Cudd_Ref(q);
+	    Cudd_RecursiveDerefZdd(dd, tmp);
+	}
+    }
+    else {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, g1);
+    }
+
+    if (q == zero) {
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
+	Cudd_Deref(q);
+	return(zero);
+    }
+
+    if (gd != zero) {
+	Cudd_RecursiveDerefZdd(dd, q);
+	tmp = cuddZddWeakDivF(dd, fd, gd);
+	if (tmp == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDerefZdd(dd, gd);
+	    return(NULL);
+	}
+	Cudd_Ref(tmp);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+	if (q == g)
+	    q = tmp;
+	else {
+	    q = cuddZddIntersect(dd, q, tmp);
+	    if (q == NULL) {
+		Cudd_RecursiveDerefZdd(dd, tmp);
+		return(NULL);
+	    }
+	    Cudd_Ref(q);
+	    Cudd_RecursiveDerefZdd(dd, tmp);
+	}
+    }
+    else {
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDerefZdd(dd, gd);
+    }
+
+    cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
+    Cudd_Deref(q);
+    return(q);
+
+} /* end of cuddZddWeakDivF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddDivide.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDivide]
+
+******************************************************************************/
+DdNode	*
+cuddZddDivide(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int		v;
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = DD_ZERO(dd);
+    DdNode	*f0, *f1, *g0, *g1;
+    DdNode	*q, *r, *tmp;
+    int		flag;
+
+    statLine(dd);
+    if (g == one)
+	return(f);
+    if (f == zero || f == one)
+	return(zero);
+    if (f == g)
+	return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g);
+    if (r)
+	return(r);
+
+    v = g->index;
+
+    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
+    if (flag == 1)
+	return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);	/* g1 != zero */
+    if (flag == 1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+
+    r = cuddZddDivide(dd, f1, g1);
+    if (r == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	return(NULL);
+    }
+    Cudd_Ref(r);
+
+    if (r != zero && g0 != zero) {
+	tmp = r;
+	q = cuddZddDivide(dd, f0, g0);
+	if (q == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, g0);
+	    return(NULL);
+	}
+	Cudd_Ref(q);
+	r = cuddZddIntersect(dd, r, q);
+	if (r == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, g0);
+	    Cudd_RecursiveDerefZdd(dd, q);
+	    return(NULL);
+	}
+	Cudd_Ref(r);
+	Cudd_RecursiveDerefZdd(dd, q);
+	Cudd_RecursiveDerefZdd(dd, tmp);
+    }
+
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    
+    cuddCacheInsert2(dd, cuddZddDivide, f, g, r);
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddZddDivide */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddDivideF.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDivideF]
+
+******************************************************************************/
+DdNode	*
+cuddZddDivideF(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g)
+{
+    int		v;
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = DD_ZERO(dd);
+    DdNode	*f0, *f1, *g0, *g1;
+    DdNode	*q, *r, *tmp;
+    int		flag;
+
+    statLine(dd);
+    if (g == one)
+	return(f);
+    if (f == zero || f == one)
+	return(zero);
+    if (f == g)
+	return(one);
+
+    /* Check cache. */
+    r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g);
+    if (r)
+	return(r);
+
+    v = g->index;
+
+    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
+    if (flag == 1)
+	return(NULL);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);	/* g1 != zero */
+    if (flag == 1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	return(NULL);
+    }
+    Cudd_Ref(g1);
+    Cudd_Ref(g0);
+
+    r = cuddZddDivideF(dd, f1, g1);
+    if (r == NULL) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, g1);
+	Cudd_RecursiveDerefZdd(dd, g0);
+	return(NULL);
+    }
+    Cudd_Ref(r);
+
+    if (r != zero && g0 != zero) {
+	tmp = r;
+	q = cuddZddDivideF(dd, f0, g0);
+	if (q == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, g0);
+	    return(NULL);
+	}
+	Cudd_Ref(q);
+	r = cuddZddIntersect(dd, r, q);
+	if (r == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, f1);
+	    Cudd_RecursiveDerefZdd(dd, f0);
+	    Cudd_RecursiveDerefZdd(dd, g1);
+	    Cudd_RecursiveDerefZdd(dd, g0);
+	    Cudd_RecursiveDerefZdd(dd, q);
+	    return(NULL);
+	}
+	Cudd_Ref(r);
+	Cudd_RecursiveDerefZdd(dd, q);
+	Cudd_RecursiveDerefZdd(dd, tmp);
+    }
+
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    Cudd_RecursiveDerefZdd(dd, g1);
+    Cudd_RecursiveDerefZdd(dd, g0);
+    
+    cuddCacheInsert2(dd, cuddZddDivideF, f, g, r);
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddZddDivideF */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the three-way decomposition of f w.r.t. v.]
+
+  Description [Computes the three-way decomposition of function f (represented
+  by a ZDD) wit respect to variable v.]
+
+  SideEffects [The results are returned in f1, f0, and fd.]
+
+  SeeAlso     [cuddZddGetCofactors2]
+
+******************************************************************************/
+int
+cuddZddGetCofactors3(
+  DdManager * dd,
+  DdNode * f,
+  int  v,
+  DdNode ** f1,
+  DdNode ** f0,
+  DdNode ** fd)
+{
+    DdNode	*pc, *nc;
+    DdNode	*zero = DD_ZERO(dd);
+    int		top, hv, ht, pv, nv;
+    int		level;
+
+    top = dd->permZ[f->index];
+    level = dd->permZ[v];
+    hv = level >> 1;
+    ht = top >> 1;
+
+    if (hv < ht) {
+	*f1 = zero;
+	*f0 = zero;
+	*fd = f;
+    }
+    else {
+	pv = cuddZddGetPosVarIndex(dd, v);
+	nv = cuddZddGetNegVarIndex(dd, v);
+
+	/* not to create intermediate ZDD node */
+	if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) {
+	    pc = cuddZddSubset1(dd, f, pv);
+	    if (pc == NULL)
+		return(1);
+	    Cudd_Ref(pc);
+	    nc = cuddZddSubset0(dd, f, pv);
+	    if (nc == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		return(1);
+	    }
+	    Cudd_Ref(nc);
+
+	    *f1 = cuddZddSubset0(dd, pc, nv);
+	    if (*f1 == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		Cudd_RecursiveDerefZdd(dd, nc);
+		return(1);
+	    }
+	    Cudd_Ref(*f1);
+	    *f0 = cuddZddSubset1(dd, nc, nv);
+	    if (*f0 == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		Cudd_RecursiveDerefZdd(dd, nc);
+		Cudd_RecursiveDerefZdd(dd, *f1);
+		return(1);
+	    }
+	    Cudd_Ref(*f0);
+
+	    *fd = cuddZddSubset0(dd, nc, nv);
+	    if (*fd == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		Cudd_RecursiveDerefZdd(dd, nc);
+		Cudd_RecursiveDerefZdd(dd, *f1);
+		Cudd_RecursiveDerefZdd(dd, *f0);
+		return(1);
+	    }
+	    Cudd_Ref(*fd);
+	} else {
+	    pc = cuddZddSubset1(dd, f, nv);
+	    if (pc == NULL)
+		return(1);
+	    Cudd_Ref(pc);
+	    nc = cuddZddSubset0(dd, f, nv);
+	    if (nc == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		return(1);
+	    }
+	    Cudd_Ref(nc);
+
+	    *f0 = cuddZddSubset0(dd, pc, pv);
+	    if (*f0 == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		Cudd_RecursiveDerefZdd(dd, nc);
+		return(1);
+	    }
+	    Cudd_Ref(*f0);
+	    *f1 = cuddZddSubset1(dd, nc, pv);
+	    if (*f1 == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		Cudd_RecursiveDerefZdd(dd, nc);
+		Cudd_RecursiveDerefZdd(dd, *f1);
+		return(1);
+	    }
+	    Cudd_Ref(*f1);
+
+	    *fd = cuddZddSubset0(dd, nc, pv);
+	    if (*fd == NULL) {
+		Cudd_RecursiveDerefZdd(dd, pc);
+		Cudd_RecursiveDerefZdd(dd, nc);
+		Cudd_RecursiveDerefZdd(dd, *f1);
+		Cudd_RecursiveDerefZdd(dd, *f0);
+		return(1);
+	    }
+	    Cudd_Ref(*fd);
+	}
+
+	Cudd_RecursiveDerefZdd(dd, pc);
+	Cudd_RecursiveDerefZdd(dd, nc);
+	Cudd_Deref(*f1);
+	Cudd_Deref(*f0);
+	Cudd_Deref(*fd);
+    }
+    return(0);
+
+} /* end of cuddZddGetCofactors3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the two-way decomposition of f w.r.t. v.]
+
+  Description []
+
+  SideEffects [The results are returned in f1 and f0.]
+
+  SeeAlso     [cuddZddGetCofactors3]
+
+******************************************************************************/
+int
+cuddZddGetCofactors2(
+  DdManager * dd,
+  DdNode * f,
+  int  v,
+  DdNode ** f1,
+  DdNode ** f0)
+{
+    *f1 = cuddZddSubset1(dd, f, v);
+    if (*f1 == NULL)
+	return(1);
+    *f0 = cuddZddSubset0(dd, f, v);
+    if (*f0 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, *f1);
+	return(1);
+    }
+    return(0);
+
+} /* end of cuddZddGetCofactors2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a complement of a ZDD node.]
+
+  Description [Computes the complement of a ZDD node. So far, since we
+  couldn't find a direct way to get the complement of a ZDD cover, we first
+  convert a ZDD cover to a BDD, then make the complement of the ZDD cover
+  from the complement of the BDD node by using ISOP.]
+
+  SideEffects [The result depends on current variable order.]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode	*
+cuddZddComplement(
+  DdManager * dd,
+  DdNode *node)
+{
+    DdNode	*b, *isop, *zdd_I;
+
+    /* Check cache */
+    zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node);
+    if (zdd_I)
+	return(zdd_I);
+
+    b = cuddMakeBddFromZddCover(dd, node);
+    if (!b)
+	return(NULL);
+    cuddRef(b);
+    isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I);
+    if (!isop) {
+	Cudd_RecursiveDeref(dd, b);
+	return(NULL);
+    }
+    cuddRef(isop);
+    cuddRef(zdd_I);
+    Cudd_RecursiveDeref(dd, b);
+    Cudd_RecursiveDeref(dd, isop);
+
+    cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I);
+    cuddDeref(zdd_I);
+    return(zdd_I);
+} /* end of cuddZddComplement */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of positive ZDD variable.]
+
+  Description [Returns the index of positive ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetPosVarIndex(
+  DdManager * dd,
+  int index)
+{
+    int	pv = (index >> 1) << 1;
+    return(pv);
+} /* end of cuddZddGetPosVarIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of negative ZDD variable.]
+
+  Description [Returns the index of negative ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetNegVarIndex(
+  DdManager * dd,
+  int index)
+{
+    int	nv = index | 0x1;
+    return(nv);
+} /* end of cuddZddGetPosVarIndex */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the level of positive ZDD variable.]
+
+  Description [Returns the level of positive ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetPosVarLevel(
+  DdManager * dd,
+  int index)
+{
+    int	pv = cuddZddGetPosVarIndex(dd, index);
+    return(dd->permZ[pv]);
+} /* end of cuddZddGetPosVarLevel */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the level of negative ZDD variable.]
+
+  Description [Returns the level of negative ZDD variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddGetNegVarLevel(
+  DdManager * dd,
+  int index)
+{
+    int	nv = cuddZddGetNegVarIndex(dd, index);
+    return(dd->permZ[nv]);
+} /* end of cuddZddGetNegVarLevel */
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddGroup.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddGroup.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddGroup.c	(revision 8)
@@ -0,0 +1,1337 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddGroup.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for ZDD group sifting.]
+
+  Description [External procedures included in this file:
+		<ul>
+		<li> Cudd_MakeZddTreeNode()
+		</ul>
+	Internal procedures included in this file:
+		<ul>
+		<li> cuddZddTreeSifting()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> zddTreeSiftingAux()
+		<li> zddCountInternalMtrNodes()
+		<li> zddReorderChildren()
+		<li> zddFindNodeHiLo()
+		<li> zddUniqueCompareGroup()
+		<li> zddGroupSifting()
+		<li> zddGroupSiftingAux()
+		<li> zddGroupSiftingUp()
+		<li> zddGroupSiftingDown()
+		<li> zddGroupMove()
+		<li> zddGroupMoveBackward()
+		<li> zddGroupSiftingBackward()
+		<li> zddMergeGroups()
+		</ul>]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.19 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+static	int	*entry;
+extern	int	zddTotalNumberSwapping;
+#ifdef DD_STATS
+static  int     extsymmcalls;
+static  int     extsymm;
+static  int     secdiffcalls;
+static  int     secdiff;
+static  int     secdiffmisfire;
+#endif
+#ifdef DD_DEBUG
+static	int	pr = 0;	/* flag to enable printing while debugging */
+			/* by depositing a 1 into it */
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int zddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+#ifdef DD_STATS
+static int zddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
+#endif
+static int zddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
+static void zddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
+static int zddUniqueCompareGroup (int *ptrX, int *ptrY);
+static int zddGroupSifting (DdManager *table, int lower, int upper);
+static int zddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh);
+static int zddGroupSiftingUp (DdManager *table, int y, int xLow, Move **moves);
+static int zddGroupSiftingDown (DdManager *table, int x, int xHigh, Move **moves);
+static int zddGroupMove (DdManager *table, int x, int y, Move **moves);
+static int zddGroupMoveBackward (DdManager *table, int x, int y);
+static int zddGroupSiftingBackward (DdManager *table, Move *moves, int size);
+static void zddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new ZDD variable group.]
+
+  Description [Creates a new ZDD variable group. The group starts at
+  variable and contains size variables. The parameter low is the index
+  of the first variable. If the variable already exists, its current
+  position in the order is known to the manager. If the variable does
+  not exist yet, the position is assumed to be the same as the index.
+  The group tree is created if it does not exist yet.
+  Returns a pointer to the group if successful; NULL otherwise.]
+
+  SideEffects [The ZDD variable tree is changed.]
+
+  SeeAlso     [Cudd_MakeTreeNode]
+
+******************************************************************************/
+MtrNode *
+Cudd_MakeZddTreeNode(
+  DdManager * dd /* manager */,
+  unsigned int  low /* index of the first group variable */,
+  unsigned int  size /* number of variables in the group */,
+  unsigned int  type /* MTR_DEFAULT or MTR_FIXED */)
+{
+    MtrNode *group;
+    MtrNode *tree;
+    unsigned int level;
+
+    /* If the variable does not exist yet, the position is assumed to be
+    ** the same as the index. Therefore, applications that rely on
+    ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
+    ** variables have to create the variables before they group them.
+    */
+    level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low;
+
+    if (level + size - 1> (int) MTR_MAXHIGH)
+	return(NULL);
+
+    /* If the tree does not exist yet, create it. */
+    tree = dd->treeZ;
+    if (tree == NULL) {
+	dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ);
+	if (tree == NULL)
+	    return(NULL);
+	tree->index = dd->invpermZ[0];
+    }
+
+    /* Extend the upper bound of the tree if necessary. This allows the
+    ** application to create groups even before the variables are created.
+    */
+    tree->size = ddMax(tree->size, level + size);
+
+    /* Create the group. */
+    group = Mtr_MakeGroup(tree, level, size, type);
+    if (group == NULL)
+	return(NULL);
+
+    /* Initialize the index field to the index of the variable currently
+    ** in position low. This field will be updated by the reordering
+    ** procedure to provide a handle to the group once it has been moved.
+    */
+    group->index = (MtrHalfWord) low;
+
+    return(group);
+
+} /* end of Cudd_MakeZddTreeNode */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tree sifting algorithm for ZDDs.]
+
+  Description [Tree sifting algorithm for ZDDs. Assumes that a tree
+  representing a group hierarchy is passed as a parameter. It then
+  reorders each group in postorder fashion by calling
+  zddTreeSiftingAux.  Assumes that no dead nodes are present.  Returns
+  1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+cuddZddTreeSifting(
+  DdManager * table /* DD table */,
+  Cudd_ReorderingType method /* reordering method for the groups of leaves */)
+{
+    int i;
+    int nvars;
+    int result;
+    int tempTree;
+
+    /* If no tree is provided we create a temporary one in which all
+    ** variables are in a single group. After reordering this tree is
+    ** destroyed.
+    */
+    tempTree = table->treeZ == NULL;
+    if (tempTree) {
+	table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
+	table->treeZ->index = table->invpermZ[0];
+    }
+    nvars = table->sizeZ;
+
+#ifdef DD_DEBUG
+    if (pr > 0 && !tempTree)
+	(void) fprintf(table->out,"cuddZddTreeSifting:");
+    Mtr_PrintGroups(table->treeZ,pr <= 0);
+#endif
+#if 0
+    /* Debugging code. */
+    if (table->tree && table->treeZ) {
+	(void) fprintf(table->out,"\n");
+	Mtr_PrintGroups(table->tree, 0);
+	cuddPrintVarGroups(table,table->tree,0,0);
+	for (i = 0; i < table->size; i++) {
+	    (void) fprintf(table->out,"%s%d",
+			   (i == 0) ? "" : ",", table->invperm[i]);
+	}
+	(void) fprintf(table->out,"\n");
+	for (i = 0; i < table->size; i++) {
+	    (void) fprintf(table->out,"%s%d",
+			   (i == 0) ? "" : ",", table->perm[i]);
+	}
+	(void) fprintf(table->out,"\n\n");
+	Mtr_PrintGroups(table->treeZ,0);
+	cuddPrintVarGroups(table,table->treeZ,1,0);
+	for (i = 0; i < table->sizeZ; i++) {
+	    (void) fprintf(table->out,"%s%d",
+			   (i == 0) ? "" : ",", table->invpermZ[i]);
+	}
+	(void) fprintf(table->out,"\n");
+	for (i = 0; i < table->sizeZ; i++) {
+	    (void) fprintf(table->out,"%s%d",
+			   (i == 0) ? "" : ",", table->permZ[i]);
+	}
+	(void) fprintf(table->out,"\n");
+    }
+    /* End of debugging code. */
+#endif
+#ifdef DD_STATS
+    extsymmcalls = 0;
+    extsymm = 0;
+    secdiffcalls = 0;
+    secdiff = 0;
+    secdiffmisfire = 0;
+
+    (void) fprintf(table->out,"\n");
+    if (!tempTree)
+	(void) fprintf(table->out,"#:IM_NODES  %8d: group tree nodes\n",
+		       zddCountInternalMtrNodes(table,table->treeZ));
+#endif
+
+    /* Initialize the group of each subtable to itself. Initially
+    ** there are no groups. Groups are created according to the tree
+    ** structure in postorder fashion.
+    */
+    for (i = 0; i < nvars; i++)
+        table->subtableZ[i].next = i;
+
+    /* Reorder. */
+    result = zddTreeSiftingAux(table, table->treeZ, method);
+
+#ifdef DD_STATS		/* print stats */
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+	(table->groupcheck == CUDD_GROUP_CHECK7 ||
+	 table->groupcheck == CUDD_GROUP_CHECK5)) {
+	(void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
+	(void) fprintf(table->out,"extsymm = %d",extsymm);
+    }
+    if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
+	table->groupcheck == CUDD_GROUP_CHECK7) {
+	(void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
+	(void) fprintf(table->out,"secdiff = %d\n",secdiff);
+	(void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
+    }
+#endif
+
+    if (tempTree)
+	Cudd_FreeZddTree(table);
+    return(result);
+
+} /* end of cuddZddTreeSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Visits the group tree and reorders each group.]
+
+  Description [Recursively visits the group tree and reorders each
+  group in postorder fashion.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddTreeSiftingAux(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    MtrNode  *auxnode;
+    int res;
+
+#ifdef DD_DEBUG
+    Mtr_PrintGroups(treenode,1);
+#endif
+
+    auxnode = treenode;
+    while (auxnode != NULL) {
+	if (auxnode->child != NULL) {
+	    if (!zddTreeSiftingAux(table, auxnode->child, method))
+		return(0);
+	    res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
+	    if (res == 0)
+		return(0);
+	} else if (auxnode->size > 1) {
+	    if (!zddReorderChildren(table, auxnode, method))
+		return(0);
+	}
+	auxnode = auxnode->younger;
+    }
+
+    return(1);
+
+} /* end of zddTreeSiftingAux */
+
+
+#ifdef DD_STATS
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of internal nodes of the group tree.]
+
+  Description [Counts the number of internal nodes of the group tree.
+  Returns the count.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddCountInternalMtrNodes(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    MtrNode *auxnode;
+    int     count,nodeCount;
+
+
+    nodeCount = 0;
+    auxnode = treenode;
+    while (auxnode != NULL) {
+	if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
+	    nodeCount++;
+	    count = zddCountInternalMtrNodes(table,auxnode->child);
+	    nodeCount += count;
+	}
+	auxnode = auxnode->younger;
+    }
+
+    return(nodeCount);
+
+} /* end of zddCountInternalMtrNodes */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders the children of a group tree node according to
+  the options.]
+
+  Description [Reorders the children of a group tree node according to
+  the options. After reordering puts all the variables in the group
+  and/or its descendents in a single group. This allows hierarchical
+  reordering.  If the variables in the group do not exist yet, simply
+  does nothing. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddReorderChildren(
+  DdManager * table,
+  MtrNode * treenode,
+  Cudd_ReorderingType method)
+{
+    int lower;
+    int upper;
+    int result;
+    unsigned int initialSize;
+
+    zddFindNodeHiLo(table,treenode,&lower,&upper);
+    /* If upper == -1 these variables do not exist yet. */
+    if (upper == -1)
+	return(1);
+
+    if (treenode->flags == MTR_FIXED) {
+	result = 1;
+    } else {
+#ifdef DD_STATS
+	(void) fprintf(table->out," ");
+#endif
+	switch (method) {
+	case CUDD_REORDER_RANDOM:
+	case CUDD_REORDER_RANDOM_PIVOT:
+	    result = cuddZddSwapping(table,lower,upper,method);
+	    break;
+	case CUDD_REORDER_SIFT:
+	    result = cuddZddSifting(table,lower,upper);
+	    break;
+	case CUDD_REORDER_SIFT_CONVERGE:
+	    do {
+		initialSize = table->keysZ;
+		result = cuddZddSifting(table,lower,upper);
+		if (initialSize <= table->keysZ)
+		    break;
+#ifdef DD_STATS
+		else
+		    (void) fprintf(table->out,"\n");
+#endif
+	    } while (result != 0);
+	    break;
+	case CUDD_REORDER_SYMM_SIFT:
+	    result = cuddZddSymmSifting(table,lower,upper);
+	    break;
+	case CUDD_REORDER_SYMM_SIFT_CONV:
+	    result = cuddZddSymmSiftingConv(table,lower,upper);
+	    break;
+	case CUDD_REORDER_GROUP_SIFT:
+	    result = zddGroupSifting(table,lower,upper);
+	    break;
+	case CUDD_REORDER_LINEAR:
+	    result = cuddZddLinearSifting(table,lower,upper);
+	    break;
+	case CUDD_REORDER_LINEAR_CONVERGE:
+	    do {
+		initialSize = table->keysZ;
+		result = cuddZddLinearSifting(table,lower,upper);
+		if (initialSize <= table->keysZ)
+		    break;
+#ifdef DD_STATS
+		else
+		    (void) fprintf(table->out,"\n");
+#endif
+	    } while (result != 0);
+	    break;
+	default:
+	    return(0);
+	}
+    }
+
+    /* Create a single group for all the variables that were sifted,
+    ** so that they will be treated as a single block by successive
+    ** invocations of zddGroupSifting.
+    */
+    zddMergeGroups(table,treenode,lower,upper);
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
+#endif
+
+    return(result);
+
+} /* end of zddReorderChildren */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the lower and upper bounds of the group represented
+  by treenode.]
+
+  Description [Finds the lower and upper bounds of the group represented
+  by treenode.  The high and low fields of treenode are indices.  From
+  those we need to derive the current positions, and find maximum and
+  minimum.]
+
+  SideEffects [The bounds are returned as side effects.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddFindNodeHiLo(
+  DdManager * table,
+  MtrNode * treenode,
+  int * lower,
+  int * upper)
+{
+    int low;
+    int high;
+
+    /* Check whether no variables in this group already exist.
+    ** If so, return immediately. The calling procedure will know from
+    ** the values of upper that no reordering is needed.
+    */
+    if ((int) treenode->low >= table->sizeZ) {
+	*lower = table->sizeZ;
+	*upper = -1;
+	return;
+    }
+
+    *lower = low = (unsigned int) table->permZ[treenode->index];
+    high = (int) (low + treenode->size - 1);
+
+    if (high >= table->sizeZ) {
+	/* This is the case of a partially existing group. The aim is to
+	** reorder as many variables as safely possible.  If the tree
+	** node is terminal, we just reorder the subset of the group
+	** that is currently in existence.  If the group has
+	** subgroups, then we only reorder those subgroups that are
+	** fully instantiated.  This way we avoid breaking up a group.
+	*/
+	MtrNode *auxnode = treenode->child;
+	if (auxnode == NULL) {
+	    *upper = (unsigned int) table->sizeZ - 1;
+	} else {
+	    /* Search the subgroup that strands the table->sizeZ line.
+	    ** If the first group starts at 0 and goes past table->sizeZ
+	    ** upper will get -1, thus correctly signaling that no reordering
+	    ** should take place.
+	    */
+	    while (auxnode != NULL) {
+		int thisLower = table->permZ[auxnode->low];
+		int thisUpper = thisLower + auxnode->size - 1;
+		if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
+		    *upper = (unsigned int) thisLower - 1;
+		auxnode = auxnode->younger;
+	    }
+	}
+    } else {
+	/* Normal case: All the variables of the group exist. */
+	*upper = (unsigned int) high;
+    }
+
+#ifdef DD_DEBUG
+    /* Make sure that all variables in group are contiguous. */
+    assert(treenode->size >= *upper - *lower + 1);
+#endif
+
+    return;
+
+} /* end of zddFindNodeHiLo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the variables
+  according to the number of keys in the subtables.  Returns the
+  difference in number of keys between the two variables being
+  compared.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddUniqueCompareGroup(
+  int * ptrX,
+  int * ptrY)
+{
+#if 0
+    if (entry[*ptrY] == entry[*ptrX]) {
+	return((*ptrX) - (*ptrY));
+    }
+#endif
+    return(entry[*ptrY] - entry[*ptrX]);
+
+} /* end of zddUniqueCompareGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts from treenode->low to treenode->high.]
+
+  Description [Sifts from treenode->low to treenode->high. If
+  croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the
+  end of the initial sifting. If a group is created, it is then sifted
+  again. After sifting one variable, the group that contains it is
+  dissolved.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int		*var;
+    int		i,j,x,xInit;
+    int		nvars;
+    int		classes;
+    int		result;
+    int		*sifted;
+#ifdef DD_STATS
+    unsigned	previousSize;
+#endif
+    int		xindex;
+
+    nvars = table->sizeZ;
+
+    /* Order variables to sift. */
+    entry = NULL;
+    sifted = NULL;
+    var = ALLOC(int,nvars);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto zddGroupSiftingOutOfMem;
+    }
+    entry = ALLOC(int,nvars);
+    if (entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto zddGroupSiftingOutOfMem;
+    }
+    sifted = ALLOC(int,nvars);
+    if (sifted == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto zddGroupSiftingOutOfMem;
+    }
+
+    /* Here we consider only one representative for each group. */
+    for (i = 0, classes = 0; i < nvars; i++) {
+	sifted[i] = 0;
+	x = table->permZ[i];
+	if ((unsigned) x >= table->subtableZ[x].next) {
+	    entry[i] = table->subtableZ[x].keys;
+	    var[classes] = i;
+	    classes++;
+	}
+    }
+
+    qsort((void *)var,classes,sizeof(int),(DD_QSFP)zddUniqueCompareGroup);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
+	if (zddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	xindex = var[i];
+	if (sifted[xindex] == 1) /* variable already sifted as part of group */
+	    continue;
+        x = table->permZ[xindex]; /* find current level of this variable */
+	if (x < lower || x > upper)
+	    continue;
+#ifdef DD_STATS
+	previousSize = table->keysZ;
+#endif
+#ifdef DD_DEBUG
+	/* x is bottom of group */
+        assert((unsigned) x >= table->subtableZ[x].next);
+#endif
+	result = zddGroupSiftingAux(table,x,lower,upper);
+	if (!result) goto zddGroupSiftingOutOfMem;
+
+#ifdef DD_STATS
+	if (table->keysZ < previousSize) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keysZ > previousSize) {
+	    (void) fprintf(table->out,"+");
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+
+	/* Mark variables in the group just sifted. */
+	x = table->permZ[xindex];
+	if ((unsigned) x != table->subtableZ[x].next) {
+	    xInit = x;
+	    do {
+		j = table->invpermZ[x];
+		sifted[j] = 1;
+		x = table->subtableZ[x].next;
+	    } while (x != xInit);
+	}
+
+#ifdef DD_DEBUG
+	if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
+#endif
+    } /* for */
+
+    FREE(sifted);
+    FREE(var);
+    FREE(entry);
+
+    return(1);
+
+zddGroupSiftingOutOfMem:
+    if (entry != NULL)	FREE(entry);
+    if (var != NULL)	FREE(var);
+    if (sifted != NULL)	FREE(sifted);
+
+    return(0);
+
+} /* end of zddGroupSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation.]
+
+  Description [Sifts one variable up and down until it has taken all
+  positions. Checks for aggregation. There may be at most two sweeps,
+  even if the group grows.  Assumes that x is either an isolated
+  variable, or it is the bottom of a group. All groups may not have
+  been found. The variable being moved is returned to the best position
+  seen during sifting.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move *move;
+    Move *moves;	/* list of moves */
+    int  initialSize;
+    int  result;
+
+
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
+    assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */
+#endif
+
+    initialSize = table->keysZ;
+    moves = NULL;
+
+    if (x == xLow) { /* Sift down */
+#ifdef DD_DEBUG
+	/* x must be a singleton */
+	assert((unsigned) x == table->subtableZ[x].next);
+#endif
+	if (x == xHigh) return(1);	/* just one variable */
+
+        if (!zddGroupSiftingDown(table,x,xHigh,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+	/* at this point x == xHigh, unless early term */
+
+	/* move backward and stop at best position */
+	result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+	assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+
+    } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */
+#ifdef DD_DEBUG
+	/* x is bottom of group */
+        assert((unsigned) x >= table->subtableZ[x].next);
+#endif
+        /* Find top of x's group */
+        x = table->subtableZ[x].next;
+
+        if (!zddGroupSiftingUp(table,x,xLow,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+	/* at this point x == xLow, unless early term */
+
+	/* move backward and stop at best position */
+	result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+	assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+
+    } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
+        if (!zddGroupSiftingDown(table,x,xHigh,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+	/* at this point x == xHigh, unless early term */
+
+        /* Find top of group */
+	if (moves) {
+	    x = moves->y;
+	}
+	while ((unsigned) x < table->subtableZ[x].next)
+	    x = table->subtableZ[x].next;
+	x = table->subtableZ[x].next;
+#ifdef DD_DEBUG
+        /* x should be the top of a group */
+        assert((unsigned) x <= table->subtableZ[x].next);
+#endif
+
+        if (!zddGroupSiftingUp(table,x,xLow,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+
+	/* move backward and stop at best position */
+	result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+	assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+
+    } else { /* moving up first: shorter */
+        /* Find top of x's group */
+        x = table->subtableZ[x].next;
+
+        if (!zddGroupSiftingUp(table,x,xLow,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+	/* at this point x == xHigh, unless early term */
+
+        if (moves) {
+	    x = moves->x;
+	}
+	while ((unsigned) x < table->subtableZ[x].next)
+	    x = table->subtableZ[x].next;
+#ifdef DD_DEBUG
+        /* x is bottom of a group */
+        assert((unsigned) x >= table->subtableZ[x].next);
+#endif
+
+        if (!zddGroupSiftingDown(table,x,xHigh,&moves))
+            goto zddGroupSiftingAuxOutOfMem;
+
+	/* move backward and stop at best position */
+	result = zddGroupSiftingBackward(table,moves,initialSize);
+#ifdef DD_DEBUG
+	assert(table->keysZ <= (unsigned) initialSize);
+#endif
+        if (!result) goto zddGroupSiftingAuxOutOfMem;
+    }
+
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(1);
+
+zddGroupSiftingAuxOutOfMem:
+    while (moves != NULL) {
+        move = moves->next;
+        cuddDeallocMove(table, moves);
+        moves = move;
+    }
+
+    return(0);
+
+} /* end of zddGroupSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts up a variable until either it reaches position xLow
+  or the size of the DD heap increases too much.]
+
+  Description [Sifts up a variable until either it reaches position
+  xLow or the size of the DD heap increases too much. Assumes that y is
+  the top of a group (or a singleton).  Checks y for aggregation to the
+  adjacent variables. Records all the moves that are appended to the
+  list of moves received as input and returned as a side effect.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  Move ** moves)
+{
+    Move *move;
+    int  x;
+    int  size;
+    int  gxtop;
+    int  limitSize;
+
+    limitSize = table->keysZ;
+
+    x = cuddZddNextLow(table,y);
+    while (x >= xLow) {
+        gxtop = table->subtableZ[x].next;
+        if (table->subtableZ[x].next == (unsigned) x &&
+	    table->subtableZ[y].next == (unsigned) y) {
+            /* x and y are self groups */
+            size = cuddZddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtableZ[x].next == (unsigned) x);
+            assert(table->subtableZ[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto zddGroupSiftingUpOutOfMem;
+            move = (Move *)cuddDynamicAllocNode(table);
+            if (move == NULL) goto zddGroupSiftingUpOutOfMem;
+            move->x = x;
+            move->y = y;
+	    move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+	    if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+		return(1);
+            if (size < limitSize) limitSize = size;
+        } else { /* group move */
+            size = zddGroupMove(table,x,y,moves);
+	    if (size == 0) goto zddGroupSiftingUpOutOfMem;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+		return(1);
+            if (size < limitSize) limitSize = size;
+        }
+        y = gxtop;
+        x = cuddZddNextLow(table,y);
+    }
+
+    return(1);
+
+zddGroupSiftingUpOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of zddGroupSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts down a variable until it reaches position xHigh.]
+
+  Description [Sifts down a variable until it reaches position xHigh.
+  Assumes that x is the bottom of a group (or a singleton).  Records
+  all the moves.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  Move ** moves)
+{
+    Move *move;
+    int  y;
+    int  size;
+    int  limitSize;
+    int  gybot;
+
+
+    /* Initialize R */
+    limitSize = size = table->keysZ;
+    y = cuddZddNextHigh(table,x);
+    while (y <= xHigh) {
+	/* Find bottom of y group. */
+        gybot = table->subtableZ[y].next;
+        while (table->subtableZ[gybot].next != (unsigned) y)
+            gybot = table->subtableZ[gybot].next;
+
+        if (table->subtableZ[x].next == (unsigned) x &&
+	    table->subtableZ[y].next == (unsigned) y) {
+            /* x and y are self groups */
+            size = cuddZddSwapInPlace(table,x,y);
+#ifdef DD_DEBUG
+            assert(table->subtableZ[x].next == (unsigned) x);
+            assert(table->subtableZ[y].next == (unsigned) y);
+#endif
+            if (size == 0) goto zddGroupSiftingDownOutOfMem;
+
+	    /* Record move. */
+            move = (Move *) cuddDynamicAllocNode(table);
+            if (move == NULL) goto zddGroupSiftingDownOutOfMem;
+            move->x = x;
+            move->y = y;
+	    move->flags = MTR_DEFAULT;
+            move->size = size;
+            move->next = *moves;
+            *moves = move;
+
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
+#endif
+            if ((double) size > (double) limitSize * table->maxGrowth)
+                return(1);
+            if (size < limitSize) limitSize = size;
+            x = y;
+            y = cuddZddNextHigh(table,x);
+        } else { /* Group move */
+            size = zddGroupMove(table,x,y,moves);
+            if (size == 0) goto zddGroupSiftingDownOutOfMem;
+            if ((double) size > (double) limitSize * table->maxGrowth)
+		return(1);
+            if (size < limitSize) limitSize = size;
+        }
+        x = gybot;
+        y = cuddZddNextHigh(table,x);
+    }
+
+    return(1);
+
+zddGroupSiftingDownOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+
+    return(0);
+
+} /* end of zddGroupSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two groups and records the move.]
+
+  Description [Swaps two groups and records the move. Returns the
+  number of keys in the DD table in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupMove(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move *move;
+    int  size;
+    int  i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+    int  swapx,swapy;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    int  initialSize,bestSize;
+#endif
+
+#if DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtableZ[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtableZ[ybot].next)
+        ybot = table->subtableZ[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    initialSize = bestSize = table->keysZ;
+#endif
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddZddSwapInPlace(table,x,y);
+            if (size == 0) goto zddGroupMoveOutOfMem;
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+	    if (size < bestSize)
+		bestSize = size;
+#endif
+            swapx = x; swapy = y;
+            y = x;
+            x = cuddZddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddZddNextLow(table,y);
+    }
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if ((bestSize < initialSize) && (bestSize < size))
+	(void) fprintf(table->out,"Missed local minimum: initialSize:%d  bestSize:%d  finalSize:%d\n",initialSize,bestSize,size);
+#endif
+
+    /* fix groups */
+    y = xtop; /* ytop is now where xtop used to be */
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtableZ[y].next = cuddZddNextHigh(table,y);
+        y = cuddZddNextHigh(table,y);
+    }
+    table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
+                                    /* it to top of its group */
+    x = cuddZddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtableZ[x].next = cuddZddNextHigh(table,x);
+        x = cuddZddNextHigh(table,x);
+    }
+    table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* it to top of its group */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
+#endif
+
+    /* Store group move */
+    move = (Move *) cuddDynamicAllocNode(table);
+    if (move == NULL) goto zddGroupMoveOutOfMem;
+    move->x = swapx;
+    move->y = swapy;
+    move->flags = MTR_DEFAULT;
+    move->size = table->keysZ;
+    move->next = *moves;
+    *moves = move;
+
+    return(table->keysZ);
+
+zddGroupMoveOutOfMem:
+    while (*moves != NULL) {
+        move = (*moves)->next;
+        cuddDeallocMove(table, *moves);
+        *moves = move;
+    }
+    return(0);
+
+} /* end of zddGroupMove */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Undoes the swap two groups.]
+
+  Description [Undoes the swap two groups.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupMoveBackward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int size;
+    int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
+
+
+#if DD_DEBUG
+    /* We assume that x < y */
+    assert(x < y);
+#endif
+
+    /* Find top, bottom, and size for the two groups. */
+    xbot = x;
+    xtop = table->subtableZ[x].next;
+    xsize = xbot - xtop + 1;
+    ybot = y;
+    while ((unsigned) ybot < table->subtableZ[ybot].next)
+        ybot = table->subtableZ[ybot].next;
+    ytop = y;
+    ysize = ybot - ytop + 1;
+
+    /* Sift the variables of the second group up through the first group */
+    for (i = 1; i <= ysize; i++) {
+        for (j = 1; j <= xsize; j++) {
+            size = cuddZddSwapInPlace(table,x,y);
+            if (size == 0)
+                return(0);
+            y = x;
+            x = cuddZddNextLow(table,y);
+        }
+        y = ytop + i;
+        x = cuddZddNextLow(table,y);
+    }
+
+    /* fix groups */
+    y = xtop;
+    for (i = 0; i < ysize - 1; i++) {
+        table->subtableZ[y].next = cuddZddNextHigh(table,y);
+        y = cuddZddNextHigh(table,y);
+    }
+    table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
+                                    /* to its top */
+    x = cuddZddNextHigh(table,y);
+    newxtop = x;
+    for (i = 0; i < xsize - 1; i++) {
+        table->subtableZ[x].next = cuddZddNextHigh(table,x);
+        x = cuddZddNextHigh(table,x);
+    }
+    table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
+                                    /* to its top */
+#ifdef DD_DEBUG
+    if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
+#endif
+
+    return(1);
+
+} /* end of zddGroupMoveBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines the best position for a variables and returns
+  it there.]
+
+  Description [Determines the best position for a variables and returns
+  it there.  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddGroupSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    Move *move;
+    int  res;
+
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size < size) {
+            size = move->size;
+        }
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+        if (move->size == size) return(1);
+        if ((table->subtableZ[move->x].next == move->x) &&
+	(table->subtableZ[move->y].next == move->y)) {
+            res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+            if (!res) return(0);
+#ifdef DD_DEBUG
+            if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
+            assert(table->subtableZ[move->x].next == move->x);
+            assert(table->subtableZ[move->y].next == move->y);
+#endif
+        } else { /* Group move necessary */
+	    res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
+	    if (!res) return(0);
+        }
+    }
+
+    return(1);
+
+} /* end of zddGroupSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges groups in the DD table.]
+
+  Description [Creates a single group from low to high and adjusts the
+  idex field of the tree node.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+zddMergeGroups(
+  DdManager * table,
+  MtrNode * treenode,
+  int  low,
+  int  high)
+{
+    int i;
+    MtrNode *auxnode;
+    int saveindex;
+    int newindex;
+
+    /* Merge all variables from low to high in one group, unless
+    ** this is the topmost group. In such a case we do not merge lest
+    ** we lose the symmetry information. */
+    if (treenode != table->treeZ) {
+	for (i = low; i < high; i++)
+	    table->subtableZ[i].next = i+1;
+	table->subtableZ[high].next = low;
+    }
+
+    /* Adjust the index fields of the tree nodes. If a node is the
+    ** first child of its parent, then the parent may also need adjustment. */
+    saveindex = treenode->index;
+    newindex = table->invpermZ[low];
+    auxnode = treenode;
+    do {
+	auxnode->index = newindex;
+	if (auxnode->parent == NULL ||
+		(int) auxnode->parent->index != saveindex)
+	    break;
+	auxnode = auxnode->parent;
+    } while (1);
+    return;
+
+} /* end of zddMergeGroups */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddIsop.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddIsop.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddIsop.c	(revision 8)
@@ -0,0 +1,912 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddIsop.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions to find irredundant SOP covers as ZDDs from BDDs.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_bddIsop()
+		    <li> Cudd_zddIsop()
+		    <li> Cudd_MakeBddFromZddCover()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    <li> cuddBddIsop()
+		    <li> cuddZddIsop()
+		    <li> cuddMakeBddFromZddCover()
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.17 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an ISOP in ZDD form from BDDs.]
+
+  Description [Computes an irredundant sum of products (ISOP) in ZDD
+  form from BDDs. The two BDDs L and U represent the lower bound and
+  the upper bound, respectively, of the function. The ISOP uses two
+  ZDD variables for each BDD variable: One for the positive literal,
+  and one for the negative literal. These two variables should be
+  adjacent in the ZDD order. The two ZDD variables corresponding to
+  BDD variable <code>i</code> should have indices <code>2i</code> and
+  <code>2i+1</code>.  The result of this procedure depends on the
+  variable order. If successful, Cudd_zddIsop returns the BDD for
+  the function chosen from the interval. The ZDD representing the
+  irredundant cover is returned as a side effect in zdd_I. In case of
+  failure, NULL is returned.]
+
+  SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on
+  successful return.]
+
+  SeeAlso     [Cudd_bddIsop Cudd_zddVarsFromBddVars]
+
+******************************************************************************/
+DdNode	*
+Cudd_zddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U,
+  DdNode ** zdd_I)
+{
+    DdNode	*res;
+    int		autoDynZ;
+
+    autoDynZ = dd->autoDynZ;
+    dd->autoDynZ = 0;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddIsop(dd, L, U, zdd_I);
+    } while (dd->reordered == 1);
+    dd->autoDynZ = autoDynZ;
+    return(res);
+
+} /* end of Cudd_zddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a BDD in the interval between L and U with a
+  simple sum-of-produuct cover.]
+
+  Description [Computes a BDD in the interval between L and U with a
+  simple sum-of-produuct cover. This procedure is similar to
+  Cudd_zddIsop, but it does not return the ZDD for the cover. Returns
+  a pointer to the BDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddIsop]
+
+******************************************************************************/
+DdNode	*
+Cudd_bddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddBddIsop(dd, L, U);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_bddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a ZDD cover to a BDD graph.]
+
+  Description [Converts a ZDD cover to a BDD graph. If successful, it
+  returns a BDD node, otherwise it returns NULL.]
+
+  SideEffects []
+
+  SeeAlso     [cuddMakeBddFromZddCover]
+
+******************************************************************************/
+DdNode	*
+Cudd_MakeBddFromZddCover(
+  DdManager * dd,
+  DdNode * node)
+{
+    DdNode	*res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddMakeBddFromZddCover(dd, node);
+    } while (dd->reordered == 1);
+    return(res);
+} /* end of Cudd_MakeBddFromZddCover */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddIsop.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddIsop]
+
+******************************************************************************/
+DdNode	*
+cuddZddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U,
+  DdNode ** zdd_I)
+{
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = Cudd_Not(one);
+    DdNode	*zdd_one = DD_ONE(dd);
+    DdNode	*zdd_zero = DD_ZERO(dd);
+    int		v, top_l, top_u;
+    DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
+    DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
+    DdNode	*Isub0, *Isub1, *Id;
+    DdNode	*zdd_Isub0, *zdd_Isub1, *zdd_Id;
+    DdNode	*x;
+    DdNode	*term0, *term1, *sum;
+    DdNode	*Lv, *Uv, *Lnv, *Unv;
+    DdNode	*r, *y, *z;
+    int		index;
+    DD_CTFP	cacheOp;
+
+    statLine(dd);
+    if (L == zero) {
+	*zdd_I = zdd_zero;
+    	return(zero);
+    }
+    if (U == one) {
+	*zdd_I = zdd_one;
+    	return(one);
+    }
+
+    if (U == zero || L == one) {
+	printf("*** ERROR : illegal condition for ISOP (U < L).\n");
+	exit(1);
+    }
+
+    /* Check the cache. We store two results for each recursive call.
+    ** One is the BDD, and the other is the ZDD. Both are needed.
+    ** Hence we need a double hit in the cache to terminate the
+    ** recursion. Clearly, collisions may evict only one of the two
+    ** results. */
+    cacheOp = (DD_CTFP) cuddZddIsop;
+    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
+    if (r) {
+	*zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
+	if (*zdd_I)
+	    return(r);
+	else {
+	    /* The BDD result may have been dead. In that case
+	    ** cuddCacheLookup2 would have called cuddReclaim,
+	    ** whose effects we now have to undo. */
+	    cuddRef(r);
+	    Cudd_RecursiveDeref(dd, r);
+	}
+    }
+
+    top_l = dd->perm[Cudd_Regular(L)->index];
+    top_u = dd->perm[Cudd_Regular(U)->index];
+    v = ddMin(top_l, top_u);
+
+    /* Compute cofactors. */
+    if (top_l == v) {
+	index = Cudd_Regular(L)->index;
+    	Lv = Cudd_T(L);
+    	Lnv = Cudd_E(L);
+    	if (Cudd_IsComplement(L)) {
+    	    Lv = Cudd_Not(Lv);
+    	    Lnv = Cudd_Not(Lnv);
+    	}
+    }
+    else {
+	index = Cudd_Regular(U)->index;
+        Lv = Lnv = L;
+    }
+
+    if (top_u == v) {
+    	Uv = Cudd_T(U);
+    	Unv = Cudd_E(U);
+    	if (Cudd_IsComplement(U)) {
+    	    Uv = Cudd_Not(Uv);
+    	    Unv = Cudd_Not(Unv);
+    	}
+    }
+    else {
+        Uv = Unv = U;
+    }
+
+    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
+    if (Lsub0 == NULL)
+	return(NULL);
+    Cudd_Ref(Lsub0);
+    Usub0 = Unv;
+    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
+    if (Lsub1 == NULL) {
+	Cudd_RecursiveDeref(dd, Lsub0);
+	return(NULL);
+    }
+    Cudd_Ref(Lsub1);
+    Usub1 = Uv;
+
+    Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
+    if (Isub0 == NULL) {
+	Cudd_RecursiveDeref(dd, Lsub0);
+	Cudd_RecursiveDeref(dd, Lsub1);
+	return(NULL);
+    }
+    /*
+    if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
+	(Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
+	dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
+	printf("*** ERROR : illegal permutation in ZDD. ***\n");
+    }
+    */
+    Cudd_Ref(Isub0);
+    Cudd_Ref(zdd_Isub0);
+    Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
+    if (Isub1 == NULL) {
+	Cudd_RecursiveDeref(dd, Lsub0);
+	Cudd_RecursiveDeref(dd, Lsub1);
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	return(NULL);
+    }
+    /*
+    if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
+	(Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
+	dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
+	printf("*** ERROR : illegal permutation in ZDD. ***\n");
+    }
+    */
+    Cudd_Ref(Isub1);
+    Cudd_Ref(zdd_Isub1);
+    Cudd_RecursiveDeref(dd, Lsub0);
+    Cudd_RecursiveDeref(dd, Lsub1);
+
+    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
+    if (Lsuper0 == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	return(NULL);
+    }
+    Cudd_Ref(Lsuper0);
+    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
+    if (Lsuper1 == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Lsuper0);
+	return(NULL);
+    }
+    Cudd_Ref(Lsuper1);
+    Usuper0 = Unv;
+    Usuper1 = Uv;
+
+    /* Ld = Lsuper0 + Lsuper1 */
+    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
+    if (Ld == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Lsuper0);
+	Cudd_RecursiveDeref(dd, Lsuper1);
+	return(NULL);
+    }
+    Ld = Cudd_Not(Ld);
+    Cudd_Ref(Ld);
+    /* Ud = Usuper0 * Usuper1 */
+    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
+    if (Ud == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Lsuper0);
+	Cudd_RecursiveDeref(dd, Lsuper1);
+	Cudd_RecursiveDeref(dd, Ld);
+	return(NULL);
+    }
+    Cudd_Ref(Ud);
+    Cudd_RecursiveDeref(dd, Lsuper0);
+    Cudd_RecursiveDeref(dd, Lsuper1);
+
+    Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
+    if (Id == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Ld);
+	Cudd_RecursiveDeref(dd, Ud);
+	return(NULL);
+    }
+    /*
+    if ((!cuddIsConstant(Cudd_Regular(Id))) &&
+	(Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
+	dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
+	printf("*** ERROR : illegal permutation in ZDD. ***\n");
+    }
+    */
+    Cudd_Ref(Id);
+    Cudd_Ref(zdd_Id);
+    Cudd_RecursiveDeref(dd, Ld);
+    Cudd_RecursiveDeref(dd, Ud);
+
+    x = cuddUniqueInter(dd, index, one, zero);
+    if (x == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDerefZdd(dd, zdd_Id);
+	return(NULL);
+    }
+    Cudd_Ref(x);
+    /* term0 = x * Isub0 */
+    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
+    if (term0 == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDerefZdd(dd, zdd_Id);
+	Cudd_RecursiveDeref(dd, x);
+	return(NULL);
+    }
+    Cudd_Ref(term0);
+    Cudd_RecursiveDeref(dd, Isub0);
+    /* term1 = x * Isub1 */
+    term1 = cuddBddAndRecur(dd, x, Isub1);
+    if (term1 == NULL) {
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDerefZdd(dd, zdd_Id);
+	Cudd_RecursiveDeref(dd, x);
+	Cudd_RecursiveDeref(dd, term0);
+	return(NULL);
+    }
+    Cudd_Ref(term1);
+    Cudd_RecursiveDeref(dd, x);
+    Cudd_RecursiveDeref(dd, Isub1);
+    /* sum = term0 + term1 */
+    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
+    if (sum == NULL) {
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDerefZdd(dd, zdd_Id);
+	Cudd_RecursiveDeref(dd, term0);
+	Cudd_RecursiveDeref(dd, term1);
+	return(NULL);
+    }
+    sum = Cudd_Not(sum);
+    Cudd_Ref(sum);
+    Cudd_RecursiveDeref(dd, term0);
+    Cudd_RecursiveDeref(dd, term1);
+    /* r = sum + Id */
+    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
+    r = Cudd_NotCond(r, r != NULL);
+    if (r == NULL) {
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDerefZdd(dd, zdd_Id);
+	Cudd_RecursiveDeref(dd, sum);
+	return(NULL);
+    }
+    Cudd_Ref(r);
+    Cudd_RecursiveDeref(dd, sum);
+    Cudd_RecursiveDeref(dd, Id);
+
+    if (zdd_Isub0 != zdd_zero) {
+	z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
+	if (z == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
+	    Cudd_RecursiveDeref(dd, r);
+	    return(NULL);
+	}
+    }
+    else {
+	z = zdd_Id;
+    }
+    Cudd_Ref(z);
+    if (zdd_Isub1 != zdd_zero) {
+	y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
+	if (y == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
+	    Cudd_RecursiveDeref(dd, r);
+	    Cudd_RecursiveDerefZdd(dd, z);
+	    return(NULL);
+	}
+    }
+    else
+	y = z;
+    Cudd_Ref(y);
+
+    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
+    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
+    Cudd_RecursiveDerefZdd(dd, zdd_Id);
+    Cudd_RecursiveDerefZdd(dd, z);
+
+    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
+    cuddCacheInsert2(dd, cacheOp, L, U, y);
+
+    Cudd_Deref(r);
+    Cudd_Deref(y);
+    *zdd_I = y;
+    /*
+    if (Cudd_Regular(r)->index != y->index / 2) {
+	printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
+    }
+    */
+    return(r);
+
+} /* end of cuddZddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_bddIsop.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_bddIsop]
+
+******************************************************************************/
+DdNode	*
+cuddBddIsop(
+  DdManager * dd,
+  DdNode * L,
+  DdNode * U)
+{
+    DdNode	*one = DD_ONE(dd);
+    DdNode	*zero = Cudd_Not(one);
+    int		v, top_l, top_u;
+    DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
+    DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
+    DdNode	*Isub0, *Isub1, *Id;
+    DdNode	*x;
+    DdNode	*term0, *term1, *sum;
+    DdNode	*Lv, *Uv, *Lnv, *Unv;
+    DdNode	*r;
+    int		index;
+
+    statLine(dd);
+    if (L == zero)
+    	return(zero);
+    if (U == one)
+    	return(one);
+
+    /* Check cache */
+    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
+    if (r)
+    	return(r);
+
+    top_l = dd->perm[Cudd_Regular(L)->index];
+    top_u = dd->perm[Cudd_Regular(U)->index];
+    v = ddMin(top_l, top_u);
+
+    /* Compute cofactors */
+    if (top_l == v) {
+	index = Cudd_Regular(L)->index;
+    	Lv = Cudd_T(L);
+    	Lnv = Cudd_E(L);
+    	if (Cudd_IsComplement(L)) {
+    	    Lv = Cudd_Not(Lv);
+    	    Lnv = Cudd_Not(Lnv);
+    	}
+    }
+    else {
+	index = Cudd_Regular(U)->index;
+        Lv = Lnv = L;
+    }
+
+    if (top_u == v) {
+    	Uv = Cudd_T(U);
+    	Unv = Cudd_E(U);
+    	if (Cudd_IsComplement(U)) {
+    	    Uv = Cudd_Not(Uv);
+    	    Unv = Cudd_Not(Unv);
+    	}
+    }
+    else {
+        Uv = Unv = U;
+    }
+
+    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
+    if (Lsub0 == NULL)
+	return(NULL);
+    Cudd_Ref(Lsub0);
+    Usub0 = Unv;
+    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
+    if (Lsub1 == NULL) {
+	Cudd_RecursiveDeref(dd, Lsub0);
+	return(NULL);
+    }
+    Cudd_Ref(Lsub1);
+    Usub1 = Uv;
+
+    Isub0 = cuddBddIsop(dd, Lsub0, Usub0);
+    if (Isub0 == NULL) {
+	Cudd_RecursiveDeref(dd, Lsub0);
+	Cudd_RecursiveDeref(dd, Lsub1);
+	return(NULL);
+    }
+    Cudd_Ref(Isub0);
+    Isub1 = cuddBddIsop(dd, Lsub1, Usub1);
+    if (Isub1 == NULL) {
+	Cudd_RecursiveDeref(dd, Lsub0);
+	Cudd_RecursiveDeref(dd, Lsub1);
+	Cudd_RecursiveDeref(dd, Isub0);
+	return(NULL);
+    }
+    Cudd_Ref(Isub1);
+    Cudd_RecursiveDeref(dd, Lsub0);
+    Cudd_RecursiveDeref(dd, Lsub1);
+
+    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
+    if (Lsuper0 == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	return(NULL);
+    }
+    Cudd_Ref(Lsuper0);
+    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
+    if (Lsuper1 == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDeref(dd, Lsuper0);
+	return(NULL);
+    }
+    Cudd_Ref(Lsuper1);
+    Usuper0 = Unv;
+    Usuper1 = Uv;
+
+    /* Ld = Lsuper0 + Lsuper1 */
+    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
+    Ld = Cudd_NotCond(Ld, Ld != NULL);
+    if (Ld == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDeref(dd, Lsuper0);
+	Cudd_RecursiveDeref(dd, Lsuper1);
+	return(NULL);
+    }
+    Cudd_Ref(Ld);
+    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
+    if (Ud == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDeref(dd, Lsuper0);
+	Cudd_RecursiveDeref(dd, Lsuper1);
+	Cudd_RecursiveDeref(dd, Ld);
+	return(NULL);
+    }
+    Cudd_Ref(Ud);
+    Cudd_RecursiveDeref(dd, Lsuper0);
+    Cudd_RecursiveDeref(dd, Lsuper1);
+
+    Id = cuddBddIsop(dd, Ld, Ud);
+    if (Id == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDeref(dd, Ld);
+	Cudd_RecursiveDeref(dd, Ud);
+	return(NULL);
+    }
+    Cudd_Ref(Id);
+    Cudd_RecursiveDeref(dd, Ld);
+    Cudd_RecursiveDeref(dd, Ud);
+
+    x = cuddUniqueInter(dd, index, one, zero);
+    if (x == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	return(NULL);
+    }
+    Cudd_Ref(x);
+    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
+    if (term0 == NULL) {
+	Cudd_RecursiveDeref(dd, Isub0);
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDeref(dd, x);
+	return(NULL);
+    }
+    Cudd_Ref(term0);
+    Cudd_RecursiveDeref(dd, Isub0);
+    term1 = cuddBddAndRecur(dd, x, Isub1);
+    if (term1 == NULL) {
+	Cudd_RecursiveDeref(dd, Isub1);
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDeref(dd, x);
+	Cudd_RecursiveDeref(dd, term0);
+	return(NULL);
+    }
+    Cudd_Ref(term1);
+    Cudd_RecursiveDeref(dd, x);
+    Cudd_RecursiveDeref(dd, Isub1);
+    /* sum = term0 + term1 */
+    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
+    sum = Cudd_NotCond(sum, sum != NULL);
+    if (sum == NULL) {
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDeref(dd, term0);
+	Cudd_RecursiveDeref(dd, term1);
+	return(NULL);
+    }
+    Cudd_Ref(sum);
+    Cudd_RecursiveDeref(dd, term0);
+    Cudd_RecursiveDeref(dd, term1);
+    /* r = sum + Id */
+    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
+    r = Cudd_NotCond(r, r != NULL);
+    if (r == NULL) {
+	Cudd_RecursiveDeref(dd, Id);
+	Cudd_RecursiveDeref(dd, sum);
+	return(NULL);
+    }
+    Cudd_Ref(r);
+    Cudd_RecursiveDeref(dd, sum);
+    Cudd_RecursiveDeref(dd, Id);
+
+    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
+
+    Cudd_Deref(r);
+    return(r);
+
+} /* end of cuddBddIsop */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a ZDD cover to a BDD graph.]
+
+  Description [Converts a ZDD cover to a BDD graph. If successful, it
+  returns a BDD node, otherwise it returns NULL. It is a recursive
+  algorithm as the following. First computes 3 cofactors of a ZDD cover;
+  f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd.
+  Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v
+  is the variable which has the index of the top node of the ZDD cover.
+  In this case, since the index of v can be larger than either one of T or
+  one of E, cuddUniqueInterIVO is called, here IVO stands for
+  independent variable ordering.]
+
+  SideEffects []
+
+  SeeAlso     [Cudd_MakeBddFromZddCover]
+
+******************************************************************************/
+DdNode	*
+cuddMakeBddFromZddCover(
+  DdManager * dd,
+  DdNode * node)
+{
+    DdNode	*neW;
+    int		v;
+    DdNode	*f1, *f0, *fd;
+    DdNode	*b1, *b0, *bd;
+    DdNode	*T, *E;
+
+    statLine(dd);
+    if (node == dd->one)
+	return(dd->one);
+    if (node == dd->zero)
+	return(Cudd_Not(dd->one));
+
+    /* Check cache */
+    neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node);
+    if (neW)
+	return(neW);
+
+    v = Cudd_Regular(node)->index;	/* either yi or zi */
+    cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd);
+    Cudd_Ref(f1);
+    Cudd_Ref(f0);
+    Cudd_Ref(fd);
+
+    b1 = cuddMakeBddFromZddCover(dd, f1);
+    if (!b1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	return(NULL);
+    }
+    Cudd_Ref(b1);
+    b0 = cuddMakeBddFromZddCover(dd, f0);
+    if (!b1) {
+	Cudd_RecursiveDerefZdd(dd, f1);
+	Cudd_RecursiveDerefZdd(dd, f0);
+	Cudd_RecursiveDerefZdd(dd, fd);
+	Cudd_RecursiveDeref(dd, b1);
+	return(NULL);
+    }
+    Cudd_Ref(b0);
+    Cudd_RecursiveDerefZdd(dd, f1);
+    Cudd_RecursiveDerefZdd(dd, f0);
+    if (fd != dd->zero) {
+	bd = cuddMakeBddFromZddCover(dd, fd);
+	if (!bd) {
+	    Cudd_RecursiveDerefZdd(dd, fd);
+	    Cudd_RecursiveDeref(dd, b1);
+	    Cudd_RecursiveDeref(dd, b0);
+	    return(NULL);
+	}
+	Cudd_Ref(bd);
+	Cudd_RecursiveDerefZdd(dd, fd);
+
+	T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd));
+	if (!T) {
+	    Cudd_RecursiveDeref(dd, b1);
+	    Cudd_RecursiveDeref(dd, b0);
+	    Cudd_RecursiveDeref(dd, bd);
+	    return(NULL);
+	}
+	T = Cudd_NotCond(T, T != NULL);
+	Cudd_Ref(T);
+	Cudd_RecursiveDeref(dd, b1);
+	E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd));
+	if (!E) {
+	    Cudd_RecursiveDeref(dd, b0);
+	    Cudd_RecursiveDeref(dd, bd);
+	    Cudd_RecursiveDeref(dd, T);
+	    return(NULL);
+	}
+	E = Cudd_NotCond(E, E != NULL);
+	Cudd_Ref(E);
+	Cudd_RecursiveDeref(dd, b0);
+	Cudd_RecursiveDeref(dd, bd);
+    }
+    else {
+	Cudd_RecursiveDerefZdd(dd, fd);
+	T = b1;
+	E = b0;
+    }
+
+    if (Cudd_IsComplement(T)) {
+	neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E));
+	if (!neW) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+	neW = Cudd_Not(neW);
+    }
+    else {
+	neW = cuddUniqueInterIVO(dd, v / 2, T, E);
+	if (!neW) {
+	    Cudd_RecursiveDeref(dd, T);
+	    Cudd_RecursiveDeref(dd, E);
+	    return(NULL);
+	}
+    }
+    Cudd_Ref(neW);
+    Cudd_RecursiveDeref(dd, T);
+    Cudd_RecursiveDeref(dd, E);
+
+    cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW);
+    Cudd_Deref(neW);
+    return(neW);
+
+} /* end of cuddMakeBddFromZddCover */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddLin.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddLin.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddLin.c	(revision 8)
@@ -0,0 +1,967 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddLin.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures for dynamic variable ordering of ZDDs.]
+
+  Description [Internal procedures included in this module:
+		    <ul>
+		    <li> cuddZddLinearSifting()
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    <li> cuddZddLinearInPlace()
+		    <li> cuddZddLinerAux()
+		    <li> cuddZddLinearUp()
+		    <li> cuddZddLinearDown()
+		    <li> cuddZddLinearBackward()
+		    <li> cuddZddUndoMoves()
+		    </ul>
+	      ]
+
+  SeeAlso     [cuddLinear.c cuddZddReord.c]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CUDD_SWAP_MOVE 0
+#define CUDD_LINEAR_TRANSFORM_MOVE 1
+#define CUDD_INVERSE_TRANSFORM_MOVE 2
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.14 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+extern  int	*zdd_entry;
+extern	int	zddTotalNumberSwapping;
+static	int	zddTotalNumberLinearTr;
+static  DdNode	*empty;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddLinearInPlace (DdManager * table, int x, int y);
+static int cuddZddLinearAux (DdManager *table, int x, int xLow, int xHigh);
+static Move * cuddZddLinearUp (DdManager *table, int y, int xLow, Move *prevMoves);
+static Move * cuddZddLinearDown (DdManager *table, int x, int xHigh, Move *prevMoves);
+static int cuddZddLinearBackward (DdManager *table, int size, Move *moves);
+static Move* cuddZddUndoMoves (DdManager *table, Move *moves);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implementation of the linear sifting algorithm for ZDDs.]
+
+  Description [Implementation of the linear sifting algorithm for ZDDs.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down and applies the XOR transformation,
+    remembering each time the total size of the DD heap.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddLinearSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int	i;
+    int	*var;
+    int	size;
+    int	x;
+    int	result;
+#ifdef DD_STATS
+    int	previousSize;
+#endif
+
+    size = table->sizeZ;
+    empty = table->zero;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ALLOC(int, size);
+    if (zdd_entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSiftingOutOfMem;
+    }
+    var = ALLOC(int, size);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+	x = table->permZ[i];
+	zdd_entry[i] = table->subtableZ[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
+	if (zddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	x = table->permZ[var[i]];
+	if (x < lower || x > upper) continue;
+#ifdef DD_STATS
+	previousSize = table->keysZ;
+#endif
+	result = cuddZddLinearAux(table, x, lower, upper);
+	if (!result)
+	    goto cuddZddSiftingOutOfMem;
+#ifdef DD_STATS
+	if (table->keysZ < (unsigned) previousSize) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keysZ > (unsigned) previousSize) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	    (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+    }
+
+    FREE(var);
+    FREE(zdd_entry);
+
+    return(1);
+
+cuddZddSiftingOutOfMem:
+
+    if (zdd_entry != NULL) FREE(zdd_entry);
+    if (var != NULL) FREE(var);
+
+    return(0);
+
+} /* end of cuddZddLinearSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Linearly combines two adjacent variables.]
+
+  Description [Linearly combines two adjacent variables. It assumes
+  that no dead nodes are present on entry to this procedure.  The
+  procedure then guarantees that no dead nodes will be present when it
+  terminates.  cuddZddLinearInPlace assumes that x &lt; y.  Returns the
+  number of keys in the table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSwapInPlace cuddLinearInPlace]
+
+******************************************************************************/
+static int
+cuddZddLinearInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr *xlist, *ylist;
+    int		xindex, yindex;
+    int		xslots, yslots;
+    int		xshift, yshift;
+    int         oldxkeys, oldykeys;
+    int         newxkeys, newykeys;
+    int		i;
+    int		posn;
+    DdNode	*f, *f1, *f0, *f11, *f10, *f01, *f00;
+    DdNode	*newf1, *newf0, *g, *next, *previous;
+    DdNode	*special;
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddZddNextHigh(table,x) == y);
+    assert(table->subtableZ[x].keys != 0);
+    assert(table->subtableZ[y].keys != 0);
+    assert(table->subtableZ[x].dead == 0);
+    assert(table->subtableZ[y].dead == 0);
+#endif
+
+    zddTotalNumberLinearTr++;
+
+    /* Get parameters of x subtable. */
+    xindex   = table->invpermZ[x];
+    xlist    = table->subtableZ[x].nodelist;
+    oldxkeys = table->subtableZ[x].keys;
+    xslots   = table->subtableZ[x].slots;
+    xshift   = table->subtableZ[x].shift;
+    newxkeys = 0;
+
+    /* Get parameters of y subtable. */
+    yindex   = table->invpermZ[y];
+    ylist    = table->subtableZ[y].nodelist;
+    oldykeys = table->subtableZ[y].keys;
+    yslots   = table->subtableZ[y].slots;
+    yshift   = table->subtableZ[y].shift;
+    newykeys = oldykeys;
+
+    /* The nodes in the x layer are put in two chains.  The chain
+    ** pointed by g holds the normal nodes. When re-expressed they stay
+    ** in the x list. The chain pointed by special holds the elements
+    ** that will move to the y list.
+    */
+    g = special = NULL;
+    for (i = 0; i < xslots; i++) {
+	f = xlist[i];
+	if (f == NULL) continue;
+	xlist[i] = NULL;
+	while (f != NULL) {
+	    next = f->next;
+	    f1 = cuddT(f);
+	    /* if (f1->index == yindex) */ cuddSatDec(f1->ref);
+	    f0 = cuddE(f);
+	    /* if (f0->index == yindex) */ cuddSatDec(f0->ref);
+	    if ((int) f1->index == yindex && cuddE(f1) == empty &&
+		(int) f0->index != yindex) {
+		f->next = special;
+		special = f;
+	    } else {
+		f->next = g;
+		g = f;
+	    }
+	    f = next;
+	} /* while there are elements in the collision chain */
+    } /* for each slot of the x subtable */
+
+    /* Mark y nodes with pointers from above x. We mark them by
+    **  changing their index to x.
+    */
+    for (i = 0; i < yslots; i++) {
+	f = ylist[i];
+	while (f != NULL) {
+	    if (f->ref != 0) {
+		f->index = xindex;
+	    }
+	    f = f->next;
+	} /* while there are elements in the collision chain */
+    } /* for each slot of the y subtable */
+
+    /* Move special nodes to the y list. */
+    f = special;
+    while (f != NULL) {
+	next = f->next;
+	f1 = cuddT(f);
+	f11 = cuddT(f1);
+	cuddT(f) = f11;
+	cuddSatInc(f11->ref);
+	f0 = cuddE(f);
+	cuddSatInc(f0->ref);
+	f->index = yindex;
+	/* Insert at the beginning of the list so that it will be
+	** found first if there is a duplicate. The duplicate will
+	** eventually be moved or garbage collected. No node
+	** re-expression will add a pointer to it.
+	*/
+	posn = ddHash(f11, f0, yshift);
+	f->next = ylist[posn];
+	ylist[posn] = f;
+	newykeys++;
+	f = next;
+    }
+
+    /* Take care of the remaining x nodes that must be re-expressed.
+    ** They form a linked list pointed by g.
+    */
+    f = g;
+    while (f != NULL) {
+#ifdef DD_COUNT
+	table->swapSteps++;
+#endif
+	next = f->next;
+	/* Find f1, f0, f11, f10, f01, f00. */
+	f1 = cuddT(f);
+	if ((int) f1->index == yindex || (int) f1->index == xindex) {
+	    f11 = cuddT(f1); f10 = cuddE(f1);
+	} else {
+	    f11 = empty; f10 = f1;
+	}
+	f0 = cuddE(f);
+	if ((int) f0->index == yindex || (int) f0->index == xindex) {
+	    f01 = cuddT(f0); f00 = cuddE(f0);
+	} else {
+	    f01 = empty; f00 = f0;
+	}
+	/* Create the new T child. */
+	if (f01 == empty) {
+	    newf1 = f10;
+	    cuddSatInc(newf1->ref);
+	} else {
+	    /* Check ylist for triple (yindex, f01, f10). */
+	    posn = ddHash(f01, f10, yshift);
+	    /* For each element newf1 in collision list ylist[posn]. */
+	    newf1 = ylist[posn];
+	    /* Search the collision chain skipping the marked nodes. */
+	    while (newf1 != NULL) {
+		if (cuddT(newf1) == f01 && cuddE(newf1) == f10 &&
+		    (int) newf1->index == yindex) {
+		    cuddSatInc(newf1->ref);
+		    break; /* match */
+		}
+		newf1 = newf1->next;
+	    } /* while newf1 */
+	    if (newf1 == NULL) {	/* no match */
+		newf1 = cuddDynamicAllocNode(table);
+		if (newf1 == NULL)
+		    goto zddSwapOutOfMem;
+		newf1->index = yindex; newf1->ref = 1;
+		cuddT(newf1) = f01;
+		cuddE(newf1) = f10;
+		/* Insert newf1 in the collision list ylist[pos];
+		** increase the ref counts of f01 and f10
+		*/
+		newykeys++;
+		newf1->next = ylist[posn];
+		ylist[posn] = newf1;
+		cuddSatInc(f01->ref);
+		cuddSatInc(f10->ref);
+	    }
+	}
+	cuddT(f) = newf1;
+
+	/* Do the same for f0. */
+	/* Create the new E child. */
+	if (f11 == empty) {
+	    newf0 = f00;
+	    cuddSatInc(newf0->ref);
+	} else {
+	    /* Check ylist for triple (yindex, f11, f00). */
+	    posn = ddHash(f11, f00, yshift);
+	    /* For each element newf0 in collision list ylist[posn]. */
+	    newf0 = ylist[posn];
+	    while (newf0 != NULL) {
+		if (cuddT(newf0) == f11 && cuddE(newf0) == f00 &&
+		    (int) newf0->index == yindex) {
+		    cuddSatInc(newf0->ref);
+		    break; /* match */
+		}
+		newf0 = newf0->next;
+	    } /* while newf0 */
+	    if (newf0 == NULL) {	/* no match */
+		newf0 = cuddDynamicAllocNode(table);
+		if (newf0 == NULL)
+		    goto zddSwapOutOfMem;
+		newf0->index = yindex; newf0->ref = 1;
+		cuddT(newf0) = f11; cuddE(newf0) = f00;
+		/* Insert newf0 in the collision list ylist[posn];
+		** increase the ref counts of f11 and f00.
+		*/
+		newykeys++;
+		newf0->next = ylist[posn];
+		ylist[posn] = newf0;
+		cuddSatInc(f11->ref);
+		cuddSatInc(f00->ref);
+	    }
+	}
+	cuddE(f) = newf0;
+
+	/* Re-insert the modified f in xlist.
+	** The modified f does not already exists in xlist.
+	** (Because of the uniqueness of the cofactors.)
+	*/
+	posn = ddHash(newf1, newf0, xshift);
+	newxkeys++;
+	f->next = xlist[posn];
+	xlist[posn] = f;
+	f = next;
+    } /* while f != NULL */
+
+    /* GC the y layer and move the marked nodes to the x list. */
+
+    /* For each node f in ylist. */
+    for (i = 0; i < yslots; i++) {
+	previous = NULL;
+	f = ylist[i];
+	while (f != NULL) {
+	    next = f->next;
+	    if (f->ref == 0) {
+		cuddSatDec(cuddT(f)->ref);
+		cuddSatDec(cuddE(f)->ref);
+		cuddDeallocNode(table, f);
+		newykeys--;
+		if (previous == NULL)
+		    ylist[i] = next;
+		else
+		    previous->next = next;
+	    } else if ((int) f->index == xindex) { /* move marked node */
+		if (previous == NULL)
+		    ylist[i] = next;
+		else
+		    previous->next = next;
+		f1 = cuddT(f);
+		cuddSatDec(f1->ref);
+		/* Check ylist for triple (yindex, f1, empty). */
+		posn = ddHash(f1, empty, yshift);
+		/* For each element newf1 in collision list ylist[posn]. */
+		newf1 = ylist[posn];
+		while (newf1 != NULL) {
+		    if (cuddT(newf1) == f1 && cuddE(newf1) == empty &&
+			(int) newf1->index == yindex) {
+			cuddSatInc(newf1->ref);
+			break; /* match */
+		    }
+		    newf1 = newf1->next;
+		} /* while newf1 */
+		if (newf1 == NULL) {	/* no match */
+		    newf1 = cuddDynamicAllocNode(table);
+		    if (newf1 == NULL)
+			goto zddSwapOutOfMem;
+		    newf1->index = yindex; newf1->ref = 1;
+		    cuddT(newf1) = f1; cuddE(newf1) = empty;
+		    /* Insert newf1 in the collision list ylist[posn];
+		    ** increase the ref counts of f1 and empty.
+		    */
+		    newykeys++;
+		    newf1->next = ylist[posn];
+		    ylist[posn] = newf1;
+		    if (posn == i && previous == NULL)
+			previous = newf1;
+		    cuddSatInc(f1->ref);
+		    cuddSatInc(empty->ref);
+		}
+		cuddT(f) = newf1;
+		f0 = cuddE(f);
+		/* Insert f in x list. */
+		posn = ddHash(newf1, f0, xshift);
+		newxkeys++;
+		newykeys--;
+		f->next = xlist[posn];
+		xlist[posn] = f;
+	    } else {
+		previous = f;
+	    }
+	    f = next;
+	} /* while f */
+    } /* for i */
+
+    /* Set the appropriate fields in table. */
+    table->subtableZ[x].keys     = newxkeys;
+    table->subtableZ[y].keys     = newykeys;
+
+    table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
+
+    /* Update univ section; univ[x] remains the same. */
+    table->univ[y] = cuddT(table->univ[x]);
+
+#if 0
+    (void) fprintf(table->out,"x = %d  y = %d\n", x, y);
+    (void) Cudd_DebugCheck(table);
+    (void) Cudd_CheckKeys(table);
+#endif
+
+    return (table->keysZ);
+
+zddSwapOutOfMem:
+    (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddZddLinearInPlace */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddLinearAux(
+  DdManager * table,
+  int  x,
+  int  xLow,
+  int  xHigh)
+{
+    Move	*move;
+    Move	*moveUp;	/* list of up move */
+    Move	*moveDown;	/* list of down move */
+
+    int		initial_size;
+    int		result;
+
+    initial_size = table->keysZ;
+
+#ifdef DD_DEBUG
+    assert(table->subtableZ[x].keys > 0);
+#endif
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == xLow) {
+	moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
+	/* At this point x --> xHigh. */
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM)
+	    goto cuddZddLinearAuxOutOfMem;
+	/* Move backward and stop at best position. */
+	result = cuddZddLinearBackward(table, initial_size, moveDown);
+	if (!result)
+	    goto cuddZddLinearAuxOutOfMem;
+
+    } else if (x == xHigh) {
+	moveUp = cuddZddLinearUp(table, x, xLow, NULL);
+	/* At this point x --> xLow. */
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM)
+	    goto cuddZddLinearAuxOutOfMem;
+	/* Move backward and stop at best position. */
+	result = cuddZddLinearBackward(table, initial_size, moveUp);
+	if (!result)
+	    goto cuddZddLinearAuxOutOfMem;
+
+    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
+	moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
+	/* At this point x --> xHigh. */
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM)
+	    goto cuddZddLinearAuxOutOfMem;
+	moveUp = cuddZddUndoMoves(table,moveDown);
+#ifdef DD_DEBUG
+	assert(moveUp == NULL || moveUp->x == x);
+#endif
+	moveUp = cuddZddLinearUp(table, x, xLow, moveUp);
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM)
+	    goto cuddZddLinearAuxOutOfMem;
+	/* Move backward and stop at best position. */
+	result = cuddZddLinearBackward(table, initial_size, moveUp);
+	if (!result)
+	    goto cuddZddLinearAuxOutOfMem;
+
+    } else {
+	moveUp = cuddZddLinearUp(table, x, xLow, NULL);
+	/* At this point x --> xHigh. */
+	if (moveUp == (Move *) CUDD_OUT_OF_MEM)
+	    goto cuddZddLinearAuxOutOfMem;
+	/* Then move up. */
+	moveDown = cuddZddUndoMoves(table,moveUp);
+#ifdef DD_DEBUG
+	assert(moveDown == NULL || moveDown->y == x);
+#endif
+	moveDown = cuddZddLinearDown(table, x, xHigh, moveDown);
+	if (moveDown == (Move *) CUDD_OUT_OF_MEM)
+	    goto cuddZddLinearAuxOutOfMem;
+	/* Move backward and stop at best position. */
+	result = cuddZddLinearBackward(table, initial_size, moveDown);
+	if (!result)
+	    goto cuddZddLinearAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(1);
+
+cuddZddLinearAuxOutOfMem:
+    if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
+	while (moveDown != NULL) {
+	    move = moveDown->next;
+	    cuddDeallocMove(table, moveDown);
+	    moveDown = move;
+	}
+    }
+    if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
+	while (moveUp != NULL) {
+	    move = moveUp->next;
+	    cuddDeallocMove(table, moveUp);
+	    moveUp = move;
+	}
+    }
+
+    return(0);
+
+} /* end of cuddZddLinearAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up applying the XOR transformation.]
+
+  Description [Sifts a variable up applying the XOR
+  transformation. Moves y up until either it reaches the bound (xLow)
+  or the size of the ZDD heap increases too much.  Returns the set of
+  moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddLinearUp(
+  DdManager * table,
+  int  y,
+  int  xLow,
+  Move * prevMoves)
+{
+    Move	*moves;
+    Move	*move;
+    int		x;
+    int		size, newsize;
+    int		limitSize;
+
+    moves = prevMoves;
+    limitSize = table->keysZ;
+
+    x = cuddZddNextLow(table, y);
+    while (x >= xLow) {
+	size = cuddZddSwapInPlace(table, x, y);
+	if (size == 0)
+	    goto cuddZddLinearUpOutOfMem;
+	newsize = cuddZddLinearInPlace(table, x, y);
+	if (newsize == 0)
+	    goto cuddZddLinearUpOutOfMem;
+	move = (Move *) cuddDynamicAllocNode(table);
+	if (move == NULL)
+	    goto cuddZddLinearUpOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->next = moves;
+	moves = move;
+	move->flags = CUDD_SWAP_MOVE;
+	if (newsize > size) {
+	    /* Undo transformation. The transformation we apply is
+	    ** its own inverse. Hence, we just apply the transformation
+	    ** again.
+	    */
+	    newsize = cuddZddLinearInPlace(table,x,y);
+	    if (newsize == 0) goto cuddZddLinearUpOutOfMem;
+#ifdef DD_DEBUG
+	    if (newsize != size) {
+		(void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+	    }
+#endif
+	} else {
+	    size = newsize;
+	    move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+	}
+	move->size = size;
+
+	if ((double)size > (double)limitSize * table->maxGrowth)
+	    break;
+        if (size < limitSize)
+	    limitSize = size;
+
+	y = x;
+	x = cuddZddNextLow(table, y);
+    }
+    return(moves);
+
+cuddZddLinearUpOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of cuddZddLinearUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down and applies the XOR transformation.]
+
+  Description [Sifts a variable down. Moves x down until either it
+  reaches the bound (xHigh) or the size of the ZDD heap increases too
+  much. Returns the set of moves in case of success; NULL if memory is
+  full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddLinearDown(
+  DdManager * table,
+  int  x,
+  int  xHigh,
+  Move * prevMoves)
+{
+    Move	*moves;
+    Move	*move;
+    int		y;
+    int		size, newsize;
+    int		limitSize;
+
+    moves = prevMoves;
+    limitSize = table->keysZ;
+
+    y = cuddZddNextHigh(table, x);
+    while (y <= xHigh) {
+	size = cuddZddSwapInPlace(table, x, y);
+	if (size == 0)
+	    goto cuddZddLinearDownOutOfMem;
+	newsize = cuddZddLinearInPlace(table, x, y);
+	if (newsize == 0)
+	    goto cuddZddLinearDownOutOfMem;
+	move = (Move *) cuddDynamicAllocNode(table);
+	if (move == NULL)
+	    goto cuddZddLinearDownOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->next = moves;
+	moves = move;
+	move->flags = CUDD_SWAP_MOVE;
+	if (newsize > size) {
+	    /* Undo transformation. The transformation we apply is
+	    ** its own inverse. Hence, we just apply the transformation
+	    ** again.
+	    */
+	    newsize = cuddZddLinearInPlace(table,x,y);
+	    if (newsize == 0) goto cuddZddLinearDownOutOfMem;
+	    if (newsize != size) {
+		(void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
+	    }
+	} else {
+	    size = newsize;
+	    move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+	}
+	move->size = size;
+
+	if ((double)size > (double)limitSize * table->maxGrowth)
+	    break;
+        if (size < limitSize)
+	    limitSize = size;
+
+	x = y;
+	y = cuddZddNextHigh(table, x);
+    }
+    return(moves);
+
+cuddZddLinearDownOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of cuddZddLinearDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the ZDD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddLinearBackward(
+  DdManager * table,
+  int  size,
+  Move * moves)
+{
+    Move	*move;
+    int		res;
+
+    /* Find the minimum size among moves. */
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size < size) {
+	    size = move->size;
+	}
+    }
+
+    for (move = moves; move != NULL; move = move->next) {
+	if (move->size == size) return(1);
+	if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+	    res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!res) return(0);
+	}
+	res = cuddZddSwapInPlace(table, move->x, move->y);
+	if (!res)
+	    return(0);
+	if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
+	    res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!res) return(0);
+	}
+    }
+
+    return(1);
+
+} /* end of cuddZddLinearBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the ZDD heap to the order
+  in effect before the moves.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  order in effect before the moves.  Returns 1 in case of success;
+  0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static Move*
+cuddZddUndoMoves(
+  DdManager * table,
+  Move * moves)
+{
+    Move *invmoves = NULL;
+    Move *move;
+    Move *invmove;
+    int	size;
+
+    for (move = moves; move != NULL; move = move->next) {
+	invmove = (Move *) cuddDynamicAllocNode(table);
+	if (invmove == NULL) goto cuddZddUndoMovesOutOfMem;
+	invmove->x = move->x;
+	invmove->y = move->y;
+	invmove->next = invmoves;
+	invmoves = invmove;
+	if (move->flags == CUDD_SWAP_MOVE) {
+	    invmove->flags = CUDD_SWAP_MOVE;
+	    size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto cuddZddUndoMovesOutOfMem;
+	} else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
+	    invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
+	    size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto cuddZddUndoMovesOutOfMem;
+	    size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto cuddZddUndoMovesOutOfMem;
+	} else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
+#ifdef DD_DEBUG
+	    (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
+#endif
+	    invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
+	    size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto cuddZddUndoMovesOutOfMem;
+	    size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
+	    if (!size) goto cuddZddUndoMovesOutOfMem;
+	}
+	invmove->size = size;
+    }
+
+    return(invmoves);
+
+cuddZddUndoMovesOutOfMem:
+    while (invmoves != NULL) {
+	move = invmoves->next;
+	cuddDeallocMove(table, invmoves);
+	invmoves = move;
+    }
+    return((Move *) CUDD_OUT_OF_MEM);
+
+} /* end of cuddZddUndoMoves */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddMisc.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddMisc.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddMisc.c	(revision 8)
@@ -0,0 +1,279 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddMisc.c]
+
+  PackageName [cudd]
+
+  Synopsis    [.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddDagSize()
+		    <li> Cudd_zddCountMinterm()
+		    <li> Cudd_zddPrintSubtable()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    <li> cuddZddDagInt()
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include <math.h>
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.14 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddDagInt (DdNode *n, st_table *tab);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of nodes in a ZDD.]
+
+  Description [Counts the number of nodes in a ZDD. This function
+  duplicates Cudd_DagSize and is only retained for compatibility.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DagSize]
+
+******************************************************************************/
+int
+Cudd_zddDagSize(
+  DdNode * p_node)
+{
+
+    int		i;	
+    st_table	*table;
+
+    table = st_init_table(st_ptrcmp, st_ptrhash);
+    i = cuddZddDagInt(p_node, table);
+    st_free_table(table);
+    return(i);
+
+} /* end of Cudd_zddDagSize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms of a ZDD.]
+
+  Description [Counts the number of minterms of the ZDD rooted at
+  <code>node</code>. This procedure takes a parameter
+  <code>path</code> that specifies how many variables are in the
+  support of the function. If the procedure runs out of memory, it
+  returns (double) CUDD_OUT_OF_MEM.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddCountDouble]
+
+******************************************************************************/
+double
+Cudd_zddCountMinterm(
+  DdManager * zdd,
+  DdNode * node,
+  int  path)
+{
+    double	dc_var, minterms;	
+
+    dc_var = (double)((double)(zdd->sizeZ) - (double)path);
+    minterms = Cudd_zddCountDouble(zdd, node) / pow(2.0, dc_var);
+    return(minterms);
+
+} /* end of Cudd_zddCountMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the ZDD table.]
+
+  Description [Prints the ZDD table for debugging purposes.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_zddPrintSubtable(
+  DdManager * table)
+{
+    int		i, j;
+    DdNode 	*z1, *z1_next, *base;
+    DdSubtable	*ZSubTable;
+
+    base = table->one;
+    for (i = table->sizeZ - 1; i >= 0; i--) {
+	ZSubTable = &(table->subtableZ[i]);
+	printf("subtable[%d]:\n", i);
+	for (j = ZSubTable->slots - 1; j >= 0; j--) {
+	    z1 = ZSubTable->nodelist[j];
+	    while (z1 != NIL(DdNode)) {
+		(void) fprintf(table->out,
+#if SIZEOF_VOID_P == 8
+		    "ID = 0x%lx\tindex = %d\tr = %d\t",
+		    (unsigned long) z1 / (unsigned long) sizeof(DdNode),
+		    z1->index, z1->ref);
+#else
+		    "ID = 0x%x\tindex = %d\tr = %d\t",
+		    (unsigned) z1 / (unsigned) sizeof(DdNode),
+		    z1->index, z1->ref);
+#endif
+		z1_next = cuddT(z1);
+		if (Cudd_IsConstant(z1_next)) {
+		    (void) fprintf(table->out, "T = %d\t\t",
+			(z1_next == base));
+		}
+		else {
+#if SIZEOF_VOID_P == 8
+		    (void) fprintf(table->out, "T = 0x%lx\t",
+			(unsigned long) z1_next / (unsigned long) sizeof(DdNode));
+#else
+		    (void) fprintf(table->out, "T = 0x%x\t",
+			(unsigned) z1_next / (unsigned) sizeof(DdNode));
+#endif
+		}
+		z1_next = cuddE(z1);
+		if (Cudd_IsConstant(z1_next)) {
+		    (void) fprintf(table->out, "E = %d\n",
+			(z1_next == base));
+		}
+		else {
+#if SIZEOF_VOID_P == 8
+		    (void) fprintf(table->out, "E = 0x%lx\n",
+			(unsigned long) z1_next / (unsigned long) sizeof(DdNode));
+#else
+		    (void) fprintf(table->out, "E = 0x%x\n",
+			(unsigned) z1_next / (unsigned) sizeof(DdNode));
+#endif
+		}
+
+		z1_next = z1->next;
+		z1 = z1_next;
+	    }
+	}
+    }
+    putchar('\n');
+
+} /* Cudd_zddPrintSubtable */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddDagSize.]
+
+  Description [Performs the recursive step of Cudd_zddDagSize. Does
+  not check for out-of-memory conditions.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddDagInt(
+  DdNode * n,
+  st_table * tab)
+{
+    if (n == NIL(DdNode))
+	return(0);
+
+    if (st_is_member(tab, (char *)n) == 1)
+	return(0);
+
+    if (Cudd_IsConstant(n))
+	return(0);
+
+    (void)st_insert(tab, (char *)n, NIL(char));
+    return(1 + cuddZddDagInt(cuddT(n), tab) +
+	cuddZddDagInt(cuddE(n), tab));
+
+} /* cuddZddDagInt */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddPort.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddPort.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddPort.c	(revision 8)
@@ -0,0 +1,381 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddPort.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions that translate BDDs to ZDDs.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddPortFromBdd()
+		    <li> Cudd_zddPortToBdd()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    <li> zddPortFromBddStep()
+		    <li> zddPortToBddStep()
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Hyong-kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.13 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * zddPortFromBddStep (DdManager *dd, DdNode *B, int expected);
+static DdNode * zddPortToBddStep (DdManager *dd, DdNode *f, int depth);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a BDD into a ZDD.]
+
+  Description [Converts a BDD into a ZDD. This function assumes that
+  there is a one-to-one correspondence between the BDD variables and the
+  ZDD variables, and that the variable order is the same for both types
+  of variables. These conditions are established if the ZDD variables
+  are created by one call to Cudd_zddVarsFromBddVars with multiplicity =
+  1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddVarsFromBddVars]
+
+******************************************************************************/
+DdNode *
+Cudd_zddPortFromBdd(
+  DdManager * dd,
+  DdNode * B)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = zddPortFromBddStep(dd,B,0);
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_zddPortFromBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a ZDD into a BDD.]
+
+  Description [Converts a ZDD into a BDD. Returns a pointer to the resulting
+  ZDD if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPortFromBdd]
+
+******************************************************************************/
+DdNode *
+Cudd_zddPortToBdd(
+  DdManager * dd,
+  DdNode * f)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = zddPortToBddStep(dd,f,0);
+    } while (dd->reordered == 1);
+
+    return(res);
+
+} /* end of Cudd_zddPortToBdd */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zddPortFromBddStep(
+  DdManager * dd,
+  DdNode * B,
+  int  expected)
+{
+    DdNode	*res, *prevZdd, *t, *e;
+    DdNode	*Breg, *Bt, *Be;
+    int		id, level;
+
+    statLine(dd);
+    /* Terminal cases. */
+    if (B == Cudd_Not(DD_ONE(dd)))
+	return(DD_ZERO(dd));
+    if (B == DD_ONE(dd)) {
+	if (expected >= dd->sizeZ) {
+	    return(DD_ONE(dd));
+	} else {
+	    return(dd->univ[expected]);
+	}
+    }
+
+    Breg = Cudd_Regular(B);
+
+    /* Computed table look-up. */
+    res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B);
+    if (res != NULL) {
+	level = cuddI(dd,Breg->index);
+	/* Adding DC vars. */
+	if (expected < level) {
+	    /* Add suppressed variables. */
+	    cuddRef(res);
+	    for (level--; level >= expected; level--) {
+		prevZdd = res;
+		id = dd->invperm[level];
+		res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
+		if (res == NULL) {
+		    Cudd_RecursiveDerefZdd(dd, prevZdd);
+		    return(NULL);
+		}
+		cuddRef(res);
+		Cudd_RecursiveDerefZdd(dd, prevZdd);
+	    }
+	    cuddDeref(res);
+	}
+	return(res);
+    }	/* end of cache look-up */
+
+    if (Cudd_IsComplement(B)) {
+	Bt = Cudd_Not(cuddT(Breg));
+	Be = Cudd_Not(cuddE(Breg));
+    } else {
+	Bt = cuddT(Breg);
+	Be = cuddE(Breg);
+    }
+
+    id = Breg->index;
+    level = cuddI(dd,id);
+    t = zddPortFromBddStep(dd, Bt, level+1);
+    if (t == NULL) return(NULL);
+    cuddRef(t);
+    e = zddPortFromBddStep(dd, Be, level+1);
+    if (e == NULL) {
+	Cudd_RecursiveDerefZdd(dd, t);
+	return(NULL);
+    }
+    cuddRef(e);
+    res = cuddZddGetNode(dd, id, t, e);
+    if (res == NULL) {
+	Cudd_RecursiveDerefZdd(dd, t);
+	Cudd_RecursiveDerefZdd(dd, e);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDerefZdd(dd, t);
+    Cudd_RecursiveDerefZdd(dd, e);
+
+    cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res);
+
+    for (level--; level >= expected; level--) {
+	prevZdd = res;
+	id = dd->invperm[level];
+	res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, prevZdd);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDerefZdd(dd, prevZdd);
+    }
+
+    cuddDeref(res);
+    return(res);
+
+} /* end of zddPortFromBddStep */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddPortToBdd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zddPortToBddStep(
+  DdManager * dd /* manager */,
+  DdNode * f /* ZDD to be converted */,
+  int  depth /* recursion depth */)
+{
+    DdNode *one, *zero, *T, *E, *res, *var;
+    unsigned int index;
+    unsigned int level;
+
+    statLine(dd);
+    one = DD_ONE(dd);
+    zero = DD_ZERO(dd);
+    if (f == zero) return(Cudd_Not(one));
+
+    if (depth == dd->sizeZ) return(one);
+
+    index = dd->invpermZ[depth];
+    level = cuddIZ(dd,f->index);
+    var = cuddUniqueInter(dd,index,one,Cudd_Not(one));
+    if (var == NULL) return(NULL);
+    cuddRef(var);
+
+    if (level > (unsigned) depth) {
+	E = zddPortToBddStep(dd,f,depth+1);
+	if (E == NULL) {
+	    Cudd_RecursiveDeref(dd,var);
+	    return(NULL);
+	}
+	cuddRef(E);
+	res = cuddBddIteRecur(dd,var,Cudd_Not(one),E);
+	if (res == NULL) {
+	    Cudd_RecursiveDeref(dd,var);
+	    Cudd_RecursiveDeref(dd,E);
+	    return(NULL);
+	}
+	cuddRef(res);
+	Cudd_RecursiveDeref(dd,var);
+	Cudd_RecursiveDeref(dd,E);
+	cuddDeref(res);
+	return(res);
+    }
+
+    res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f);
+    if (res != NULL) {
+	Cudd_RecursiveDeref(dd,var);
+	return(res);
+    }
+
+    T = zddPortToBddStep(dd,cuddT(f),depth+1);
+    if (T == NULL) {
+	Cudd_RecursiveDeref(dd,var);
+	return(NULL);
+    }
+    cuddRef(T);
+    E = zddPortToBddStep(dd,cuddE(f),depth+1);
+    if (E == NULL) {
+	Cudd_RecursiveDeref(dd,var);
+	Cudd_RecursiveDeref(dd,T);
+	return(NULL);
+    }
+    cuddRef(E);
+
+    res = cuddBddIteRecur(dd,var,T,E);
+    if (res == NULL) {
+	Cudd_RecursiveDeref(dd,var);
+	Cudd_RecursiveDeref(dd,T);
+	Cudd_RecursiveDeref(dd,E);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDeref(dd,var);
+    Cudd_RecursiveDeref(dd,T);
+    Cudd_RecursiveDeref(dd,E);
+    cuddDeref(res);
+
+    cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res);
+
+    return(res);
+
+} /* end of zddPortToBddStep */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddReord.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddReord.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddReord.c	(revision 8)
@@ -0,0 +1,1660 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddReord.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Procedures for dynamic variable ordering of ZDDs.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddReduceHeap()
+		    <li> Cudd_zddShuffleHeap()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    <li> cuddZddAlignToBdd()
+		    <li> cuddZddNextHigh()
+		    <li> cuddZddNextLow()
+		    <li> cuddZddUniqueCompare()
+		    <li> cuddZddSwapInPlace()
+		    <li> cuddZddSwapping()
+		    <li> cuddZddSifting()
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    <li> zddSwapAny()
+		    <li> cuddZddSiftingAux()
+		    <li> cuddZddSiftingUp()
+		    <li> cuddZddSiftingDown()
+		    <li> cuddZddSiftingBackward()
+		    <li> zddReorderPreprocess()
+		    <li> zddReorderPostprocess()
+		    <li> zddShuffle()
+		    <li> zddSiftUp()
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DD_MAX_SUBTABLE_SPARSITY 8
+#define DD_SHRINK_FACTOR 2
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $";
+#endif
+
+int	*zdd_entry;
+
+int	zddTotalNumberSwapping;
+
+static  DdNode	*empty;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Move * zddSwapAny (DdManager *table, int x, int y);
+static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high);
+static Move * cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size);
+static Move * cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size);
+static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size);
+static void zddReorderPreprocess (DdManager *table);
+static int zddReorderPostprocess (DdManager *table);
+static int zddShuffle (DdManager *table, int *permutation);
+static int zddSiftUp (DdManager *table, int x, int xLow);
+static void zddFixTree (DdManager *table, MtrNode *treenode);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main dynamic reordering routine for ZDDs.]
+
+  Description [Main dynamic reordering routine for ZDDs.
+  Calls one of the possible reordering procedures:
+  <ul>
+  <li>Swapping
+  <li>Sifting
+  <li>Symmetric Sifting
+  </ul>
+
+  For sifting and symmetric sifting it is possible to request reordering
+  to convergence.<p>
+
+  The core of all methods is the reordering procedure
+  cuddZddSwapInPlace() which swaps two adjacent variables.
+  Returns 1 in case of success; 0 otherwise. In the case of symmetric
+  sifting (with and without convergence) returns 1 plus the number of
+  symmetric variables, in case of success.]
+
+  SideEffects [Changes the variable order for all ZDDs and clears
+  the cache.]
+
+******************************************************************************/
+int
+Cudd_zddReduceHeap(
+  DdManager * table /* DD manager */,
+  Cudd_ReorderingType heuristic /* method used for reordering */,
+  int minsize /* bound below which no reordering occurs */)
+{
+    DdHook	 *hook;
+    int		 result;
+    unsigned int nextDyn;
+#ifdef DD_STATS
+    unsigned int initialSize;
+    unsigned int finalSize;
+#endif
+    long	 localTime;
+
+    /* Don't reorder if there are too many dead nodes. */
+    if (table->keysZ - table->deadZ < (unsigned) minsize)
+	return(1);
+
+    if (heuristic == CUDD_REORDER_SAME) {
+	heuristic = table->autoMethodZ;
+    }
+    if (heuristic == CUDD_REORDER_NONE) {
+	return(1);
+    }
+
+    /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore
+    ** we count it.
+    */
+    table->reorderings++;
+    empty = table->zero;
+
+    localTime = util_cpu_time();
+
+    /* Run the hook functions. */
+    hook = table->preReorderingHook;
+    while (hook != NULL) {
+	int res = (hook->f)(table, "ZDD", (void *)heuristic);
+	if (res == 0) return(0);
+	hook = hook->next;
+    }
+
+    /* Clear the cache and collect garbage. */
+    zddReorderPreprocess(table);
+    zddTotalNumberSwapping = 0;
+
+#ifdef DD_STATS
+    initialSize = table->keysZ;
+
+    switch(heuristic) {
+    case CUDD_REORDER_RANDOM:
+    case CUDD_REORDER_RANDOM_PIVOT:
+	(void) fprintf(table->out,"#:I_RANDOM  ");
+	break;
+    case CUDD_REORDER_SIFT:
+    case CUDD_REORDER_SIFT_CONVERGE:
+    case CUDD_REORDER_SYMM_SIFT:
+    case CUDD_REORDER_SYMM_SIFT_CONV:
+	(void) fprintf(table->out,"#:I_SIFTING ");
+	break;
+    case CUDD_REORDER_LINEAR:
+    case CUDD_REORDER_LINEAR_CONVERGE:
+	(void) fprintf(table->out,"#:I_LINSIFT ");
+	break;
+    default:
+	(void) fprintf(table->err,"Unsupported ZDD reordering method\n");
+	return(0);
+    }
+    (void) fprintf(table->out,"%8d: initial size",initialSize); 
+#endif
+
+    result = cuddZddTreeSifting(table,heuristic);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keysZ;
+    (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); 
+    (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
+		   ((double)(util_cpu_time() - localTime)/1000.0)); 
+    (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
+		   zddTotalNumberSwapping);
+#endif
+
+    if (result == 0)
+	return(0);
+
+    if (!zddReorderPostprocess(table))
+	return(0);
+
+    if (table->realignZ) {
+	if (!cuddBddAlignToZdd(table))
+	    return(0);
+    }
+
+    nextDyn = table->keysZ * DD_DYN_RATIO;
+    if (table->reorderings < 20 || nextDyn > table->nextDyn)
+	table->nextDyn = nextDyn;
+    else
+	table->nextDyn += 20;
+
+    table->reordered = 1;
+
+    /* Run hook functions. */
+    hook = table->postReorderingHook;
+    while (hook != NULL) {
+	int res = (hook->f)(table, "ZDD", (void *)localTime);
+	if (res == 0) return(0);
+	hook = hook->next;
+    }
+    /* Update cumulative reordering time. */
+    table->reordTime += util_cpu_time() - localTime;
+
+    return(result);
+
+} /* end of Cudd_zddReduceHeap */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders ZDD variables according to given permutation.]
+
+  Description [Reorders ZDD variables according to given permutation.
+  The i-th entry of the permutation array contains the index of the variable
+  that should be brought to the i-th level.  The size of the array should be
+  equal or greater to the number of variables currently in use.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [Changes the ZDD variable order for all diagrams and clears
+  the cache.]
+
+  SeeAlso [Cudd_zddReduceHeap]
+
+******************************************************************************/
+int
+Cudd_zddShuffleHeap(
+  DdManager * table /* DD manager */,
+  int * permutation /* required variable permutation */)
+{
+
+    int	result;
+
+    empty = table->zero;
+    zddReorderPreprocess(table);
+
+    result = zddShuffle(table,permutation);
+
+    if (!zddReorderPostprocess(table)) return(0);
+
+    return(result);
+
+} /* end of Cudd_zddShuffleHeap */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders ZDD variables according to the order of the BDD
+  variables.]
+
+  Description [Reorders ZDD variables according to the order of the
+  BDD variables. This function can be called at the end of BDD
+  reordering to insure that the order of the ZDD variables is
+  consistent with the order of the BDD variables. The number of ZDD
+  variables must be a multiple of the number of BDD variables. Let
+  <code>M</code> be the ratio of the two numbers. cuddZddAlignToBdd
+  then considers the ZDD variables from <code>M*i</code> to
+  <code>(M+1)*i-1</code> as corresponding to BDD variable
+  <code>i</code>.  This function should be normally called from
+  Cudd_ReduceHeap, which clears the cache.  Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [Changes the ZDD variable order for all diagrams and performs
+  garbage collection of the ZDD unique table.]
+
+  SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap]
+
+******************************************************************************/
+int
+cuddZddAlignToBdd(
+  DdManager * table /* DD manager */)
+{
+    int *invpermZ;		/* permutation array */
+    int M;			/* ratio of ZDD variables to BDD variables */
+    int i,j;			/* loop indices */
+    int result;			/* return value */
+
+    /* We assume that a ratio of 0 is OK. */
+    if (table->sizeZ == 0)
+	return(1);
+
+    empty = table->zero;
+    M = table->sizeZ / table->size;
+    /* Check whether the number of ZDD variables is a multiple of the
+    ** number of BDD variables.
+    */
+    if (M * table->size != table->sizeZ)
+	return(0);
+    /* Create and initialize the inverse permutation array. */
+    invpermZ = ALLOC(int,table->sizeZ);
+    if (invpermZ == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < table->size; i++) {
+	int index = table->invperm[i];
+	int indexZ = index * M;
+	int levelZ = table->permZ[indexZ];
+	levelZ = (levelZ / M) * M;
+	for (j = 0; j < M; j++) {
+	    invpermZ[M * i + j] = table->invpermZ[levelZ + j];
+	}
+    }
+    /* Eliminate dead nodes. Do not scan the cache again, because we
+    ** assume that Cudd_ReduceHeap has already cleared it.
+    */
+    cuddGarbageCollect(table,0);
+
+    result = zddShuffle(table, invpermZ);
+    FREE(invpermZ);
+    /* Fix the ZDD variable group tree. */
+    zddFixTree(table,table->treeZ);
+    return(result);
+    
+} /* end of cuddZddAlignToBdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a larger index.]
+
+  Description [Finds the next subtable with a larger index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddNextHigh(
+  DdManager * table,
+  int  x)
+{
+    return(x + 1);
+
+} /* end of cuddZddNextHigh */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the next subtable with a smaller index.]
+
+  Description [Finds the next subtable with a smaller index. Returns the
+  index.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddNextLow(
+  DdManager * table,
+  int  x)
+{
+    return(x - 1);
+
+} /* end of cuddZddNextLow */
+
+
+/**Function********************************************************************
+
+  Synopsis [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to the number of keys in the subtables.
+  Returns the difference in number of keys between the two
+  variables being compared.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddUniqueCompare(
+  int * ptr_x,
+  int * ptr_y)
+{
+    return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
+
+} /* end of cuddZddUniqueCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two adjacent variables.]
+
+  Description [Swaps two adjacent variables. It assumes that no dead
+  nodes are present on entry to this procedure.  The procedure then
+  guarantees that no dead nodes will be present when it terminates.
+  cuddZddSwapInPlace assumes that x &lt; y.  Returns the number of keys in
+  the table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSwapInPlace(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    DdNodePtr	*xlist, *ylist;
+    int		xindex, yindex;
+    int		xslots, yslots;
+    int		xshift, yshift;
+    int         oldxkeys, oldykeys;
+    int         newxkeys, newykeys;
+    int		i;
+    int		posn;
+    DdNode	*f, *f1, *f0, *f11, *f10, *f01, *f00;
+    DdNode	*newf1, *newf0, *next;
+    DdNodePtr	g, *lastP, *previousP;
+
+#ifdef DD_DEBUG
+    assert(x < y);
+    assert(cuddZddNextHigh(table,x) == y);
+    assert(table->subtableZ[x].keys != 0);
+    assert(table->subtableZ[y].keys != 0);
+    assert(table->subtableZ[x].dead == 0);
+    assert(table->subtableZ[y].dead == 0);
+#endif
+
+    zddTotalNumberSwapping++;
+
+    /* Get parameters of x subtable. */
+    xindex   = table->invpermZ[x];
+    xlist    = table->subtableZ[x].nodelist;
+    oldxkeys = table->subtableZ[x].keys;
+    xslots   = table->subtableZ[x].slots;
+    xshift   = table->subtableZ[x].shift;
+    newxkeys = 0;
+
+    yindex   = table->invpermZ[y];
+    ylist    = table->subtableZ[y].nodelist;
+    oldykeys = table->subtableZ[y].keys;
+    yslots   = table->subtableZ[y].slots;
+    yshift   = table->subtableZ[y].shift;
+    newykeys = oldykeys;
+
+    /* The nodes in the x layer that don't depend on y directly
+    ** will stay there; the others are put in a chain.
+    ** The chain is handled as a FIFO; g points to the beginning and
+    ** last points to the end.
+    */
+
+    g = NULL;
+    lastP = &g;
+    for (i = 0; i < xslots; i++) {
+	previousP = &(xlist[i]);
+	f = *previousP;
+	while (f != NULL) {
+	    next = f->next;
+	    f1 = cuddT(f); f0 = cuddE(f);
+	    if ((f1->index != (DdHalfWord) yindex) &&
+		(f0->index != (DdHalfWord) yindex)) { /* stays */
+	        newxkeys++;
+		*previousP = f;
+		previousP = &(f->next);
+	    } else {
+		f->index = yindex;
+		*lastP = f;
+		lastP = &(f->next);
+	    }
+	    f = next;
+	} /* while there are elements in the collision chain */
+	*previousP = NULL;
+    } /* for each slot of the x subtable */
+    *lastP = NULL;
+
+
+#ifdef DD_COUNT
+    table->swapSteps += oldxkeys - newxkeys;
+#endif
+    /* Take care of the x nodes that must be re-expressed.
+    ** They form a linked list pointed by g. Their index has been
+    ** changed to yindex already.
+    */
+    f = g;
+    while (f != NULL) {
+	next = f->next;
+	/* Find f1, f0, f11, f10, f01, f00. */
+	f1 = cuddT(f);
+	if ((int) f1->index == yindex) {
+	    f11 = cuddT(f1); f10 = cuddE(f1);
+	} else {
+	    f11 = empty; f10 = f1;
+	}
+	f0 = cuddE(f);
+	if ((int) f0->index == yindex) {
+	    f01 = cuddT(f0); f00 = cuddE(f0);
+	} else {
+	    f01 = empty; f00 = f0;
+	}
+
+	/* Decrease ref count of f1. */
+	cuddSatDec(f1->ref);
+	/* Create the new T child. */
+	if (f11 == empty) {
+	    if (f01 != empty) {
+		newf1 = f01;
+		cuddSatInc(newf1->ref);
+	    }
+	    /* else case was already handled when finding nodes
+	    ** with both children below level y
+	    */
+	} else {
+	    /* Check xlist for triple (xindex, f11, f01). */
+	    posn = ddHash(f11, f01, xshift);
+	    /* For each element newf1 in collision list xlist[posn]. */
+	    newf1 = xlist[posn];
+	    while (newf1 != NULL) {
+		if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
+		    cuddSatInc(newf1->ref);
+		    break; /* match */
+		}
+		newf1 = newf1->next;
+	    } /* while newf1 */
+	    if (newf1 == NULL) {	/* no match */
+		newf1 = cuddDynamicAllocNode(table);
+		if (newf1 == NULL)
+		    goto zddSwapOutOfMem;
+		newf1->index = xindex; newf1->ref = 1;
+		cuddT(newf1) = f11;
+		cuddE(newf1) = f01;
+		/* Insert newf1 in the collision list xlist[pos];
+		** increase the ref counts of f11 and f01
+		*/
+		newxkeys++;
+		newf1->next = xlist[posn];
+		xlist[posn] = newf1;
+		cuddSatInc(f11->ref);
+		cuddSatInc(f01->ref);
+	    }
+	}
+	cuddT(f) = newf1;
+
+	/* Do the same for f0. */
+	/* Decrease ref count of f0. */
+	cuddSatDec(f0->ref);
+	/* Create the new E child. */
+	if (f10 == empty) {
+	    newf0 = f00;
+	    cuddSatInc(newf0->ref);
+	} else {
+	    /* Check xlist for triple (xindex, f10, f00). */
+	    posn = ddHash(f10, f00, xshift);
+	    /* For each element newf0 in collision list xlist[posn]. */
+	    newf0 = xlist[posn];
+	    while (newf0 != NULL) {
+		if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
+		    cuddSatInc(newf0->ref);
+		    break; /* match */
+		}
+		newf0 = newf0->next;
+	    } /* while newf0 */
+	    if (newf0 == NULL) {	/* no match */
+		newf0 = cuddDynamicAllocNode(table);
+		if (newf0 == NULL)
+		    goto zddSwapOutOfMem;
+		newf0->index = xindex; newf0->ref = 1;
+		cuddT(newf0) = f10; cuddE(newf0) = f00;
+		/* Insert newf0 in the collision list xlist[posn];
+		** increase the ref counts of f10 and f00.
+		*/
+		newxkeys++;
+		newf0->next = xlist[posn];
+		xlist[posn] = newf0;
+		cuddSatInc(f10->ref);
+		cuddSatInc(f00->ref);
+	    }
+	}
+	cuddE(f) = newf0;
+
+	/* Insert the modified f in ylist.
+	** The modified f does not already exists in ylist.
+	** (Because of the uniqueness of the cofactors.)
+	*/
+	posn = ddHash(newf1, newf0, yshift);
+	newykeys++;
+	f->next = ylist[posn];
+	ylist[posn] = f;
+	f = next;
+    } /* while f != NULL */
+
+    /* GC the y layer. */
+
+    /* For each node f in ylist. */
+    for (i = 0; i < yslots; i++) {
+	previousP = &(ylist[i]);
+	f = *previousP;
+	while (f != NULL) {
+	    next = f->next;
+	    if (f->ref == 0) {
+		cuddSatDec(cuddT(f)->ref);
+		cuddSatDec(cuddE(f)->ref);
+		cuddDeallocNode(table, f);
+		newykeys--;
+	    } else {
+		*previousP = f;
+		previousP = &(f->next);
+	    }
+	    f = next;
+	} /* while f */
+	*previousP = NULL;
+    } /* for i */
+
+    /* Set the appropriate fields in table. */
+    table->subtableZ[x].nodelist = ylist;
+    table->subtableZ[x].slots    = yslots;
+    table->subtableZ[x].shift    = yshift;
+    table->subtableZ[x].keys     = newykeys;
+    table->subtableZ[x].maxKeys  = yslots * DD_MAX_SUBTABLE_DENSITY;
+
+    table->subtableZ[y].nodelist = xlist;
+    table->subtableZ[y].slots    = xslots;
+    table->subtableZ[y].shift    = xshift;
+    table->subtableZ[y].keys     = newxkeys;
+    table->subtableZ[y].maxKeys  = xslots * DD_MAX_SUBTABLE_DENSITY;
+
+    table->permZ[xindex] = y; table->permZ[yindex] = x;
+    table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
+
+    table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
+
+    /* Update univ section; univ[x] remains the same. */
+    table->univ[y] = cuddT(table->univ[x]);
+
+    return (table->keysZ);
+
+zddSwapOutOfMem:
+    (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
+
+    return (0);
+
+} /* end of cuddZddSwapInPlace */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders variables by a sequence of (non-adjacent) swaps.]
+
+  Description [Implementation of Plessier's algorithm that reorders
+  variables by a sequence of (non-adjacent) swaps.
+    <ol>
+    <li> Select two variables (RANDOM or HEURISTIC).
+    <li> Permute these variables.
+    <li> If the nodes have decreased accept the permutation.
+    <li> Otherwise reconstruct the original heap.
+    <li> Loop.
+    </ol>
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSwapping(
+  DdManager * table,
+  int lower,
+  int upper,
+  Cudd_ReorderingType heuristic)
+{
+    int	i, j;
+    int max, keys;
+    int nvars;
+    int	x, y;
+    int iterate;
+    int previousSize;
+    Move *moves, *move;
+    int	pivot;
+    int modulo;
+    int result;
+
+#ifdef DD_DEBUG
+    /* Sanity check */
+    assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
+#endif
+
+    nvars = upper - lower + 1;
+    iterate = nvars;
+
+    for (i = 0; i < iterate; i++) {
+	if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
+	    /* Find pivot <= id with maximum keys. */
+	    for (max = -1, j = lower; j <= upper; j++) {
+		if ((keys = table->subtableZ[j].keys) > max) {
+		    max = keys;
+		    pivot = j;
+		}
+	    }
+
+	    modulo = upper - pivot;
+	    if (modulo == 0) {
+		y = pivot;	/* y = nvars-1 */
+	    } else {
+		/* y = random # from {pivot+1 .. nvars-1} */
+		y = pivot + 1 + (int) (Cudd_Random() % modulo);
+	    }
+
+	    modulo = pivot - lower - 1;
+	    if (modulo < 1) {	/* if pivot = 1 or 0 */
+		x = lower;
+	    } else {
+		do { /* x = random # from {0 .. pivot-2} */
+		    x = (int) Cudd_Random() % modulo;
+		} while (x == y);
+		  /* Is this condition really needed, since x and y
+		     are in regions separated by pivot? */
+	    }
+	} else {
+	    x = (int) (Cudd_Random() % nvars) + lower;
+	    do {
+		y = (int) (Cudd_Random() % nvars) + lower;
+	    } while (x == y);
+	}
+
+	previousSize = table->keysZ;
+	moves = zddSwapAny(table, x, y);
+	if (moves == NULL)
+	    goto cuddZddSwappingOutOfMem;
+
+	result = cuddZddSiftingBackward(table, moves, previousSize);
+	if (!result)
+	    goto cuddZddSwappingOutOfMem;
+
+	while (moves != NULL) {
+	    move = moves->next;
+	    cuddDeallocMove(table, moves);
+	    moves = move;
+	}
+#ifdef DD_STATS
+	if (table->keysZ < (unsigned) previousSize) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keysZ > (unsigned) previousSize) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+    }
+
+    return(1);
+
+cuddZddSwappingOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(0);
+
+} /* end of cuddZddSwapping */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implementation of Rudell's sifting algorithm.]
+
+  Description [Implementation of Rudell's sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries
+    in each unique table.
+    <li> Sift the variable up and down, remembering each time the
+    total size of the DD heap.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int	i;
+    int	*var;
+    int	size;
+    int	x;
+    int	result;
+#ifdef DD_STATS
+    int	previousSize;
+#endif
+
+    size = table->sizeZ;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ALLOC(int, size);
+    if (zdd_entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSiftingOutOfMem;
+    }
+    var = ALLOC(int, size);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSiftingOutOfMem;
+    }
+
+    for (i = 0; i < size; i++) {
+	x = table->permZ[i];
+	zdd_entry[i] = table->subtableZ[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Now sift. */
+    for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
+	if (zddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	x = table->permZ[var[i]];
+	if (x < lower || x > upper) continue;
+#ifdef DD_STATS
+	previousSize = table->keysZ;
+#endif
+	result = cuddZddSiftingAux(table, x, lower, upper);
+	if (!result)
+	    goto cuddZddSiftingOutOfMem;
+#ifdef DD_STATS
+	if (table->keysZ < (unsigned) previousSize) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keysZ > (unsigned) previousSize) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	    (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+    }
+
+    FREE(var);
+    FREE(zdd_entry);
+
+    return(1);
+
+cuddZddSiftingOutOfMem:
+
+    if (zdd_entry != NULL) FREE(zdd_entry);
+    if (var != NULL) FREE(var);
+
+    return(0);
+
+} /* end of cuddZddSifting */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps any two variables.]
+
+  Description [Swaps any two variables. Returns the set of moves.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+zddSwapAny(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    Move	*move, *moves;
+    int		tmp, size;
+    int		x_ref, y_ref;
+    int		x_next, y_next;
+    int		limit_size;
+
+    if (x > y) {	/* make x precede y */
+	tmp = x; x = y;	y = tmp;
+    }
+
+    x_ref = x; y_ref = y;
+
+    x_next = cuddZddNextHigh(table, x);
+    y_next = cuddZddNextLow(table, y);
+    moves = NULL;
+    limit_size = table->keysZ;
+
+    for (;;) {
+	if (x_next == y_next) {	/* x < x_next = y_next < y */
+	    size = cuddZddSwapInPlace(table, x, x_next);
+	    if (size == 0)
+		goto zddSwapAnyOutOfMem;
+	    move = (Move *) cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto zddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    size = cuddZddSwapInPlace(table, y_next, y);
+	    if (size == 0)
+		goto zddSwapAnyOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto zddSwapAnyOutOfMem;
+	    move->x = y_next;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    size = cuddZddSwapInPlace(table, x, x_next);
+	    if (size == 0)
+		goto zddSwapAnyOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto zddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    tmp = x; x = y; y = tmp;
+
+	} else if (x == y_next) { /* x = y_next < y = x_next */
+	    size = cuddZddSwapInPlace(table, x, x_next);
+	    if (size == 0)
+		goto zddSwapAnyOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto zddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    tmp = x; x = y;  y = tmp;
+	} else {
+	    size = cuddZddSwapInPlace(table, x, x_next);
+	    if (size == 0)
+		goto zddSwapAnyOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto zddSwapAnyOutOfMem;
+	    move->x = x;
+	    move->y = x_next;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    size = cuddZddSwapInPlace(table, y_next, y);
+	    if (size == 0)
+		goto zddSwapAnyOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto zddSwapAnyOutOfMem;
+	    move->x = y_next;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+
+	    x = x_next; y = y_next;
+	}
+
+	x_next = cuddZddNextHigh(table, x);
+	y_next = cuddZddNextLow(table, y);
+	if (x_next > y_ref)
+	    break;	/* if x == y_ref */
+
+	if ((double) size > table->maxGrowth * (double) limit_size)
+	    break;
+	if (size < limit_size)
+	    limit_size = size;
+    }
+    if (y_next >= x_ref) {
+	size = cuddZddSwapInPlace(table, y_next, y);
+	if (size == 0)
+	    goto zddSwapAnyOutOfMem;
+	move = (Move *)cuddDynamicAllocNode(table);
+	if (move == NULL)
+	    goto zddSwapAnyOutOfMem;
+	move->x = y_next;
+	move->y = y;
+	move->size = size;
+	move->next = moves;
+	moves = move;
+    }
+
+    return(moves);
+
+zddSwapAnyOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(NULL);
+
+} /* end of zddSwapAny */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries.]
+
+  Description [Given xLow <= x <= xHigh moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSiftingAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high)
+{
+    Move	*move;
+    Move	*moveUp;	/* list of up move */
+    Move	*moveDown;	/* list of down move */
+
+    int		initial_size;
+    int		result;
+
+    initial_size = table->keysZ;
+
+#ifdef DD_DEBUG
+    assert(table->subtableZ[x].keys > 0);
+#endif
+
+    moveDown = NULL;
+    moveUp = NULL;
+
+    if (x == x_low) {
+	moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
+	/* after that point x --> x_high */
+	if (moveDown == NULL)
+	    goto cuddZddSiftingAuxOutOfMem;
+	result = cuddZddSiftingBackward(table, moveDown,
+	    initial_size);
+	/* move backward and stop at best position */
+	if (!result)
+	    goto cuddZddSiftingAuxOutOfMem;
+
+    }
+    else if (x == x_high) {
+	moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
+	/* after that point x --> x_low */
+	if (moveUp == NULL)
+	    goto cuddZddSiftingAuxOutOfMem;
+	result = cuddZddSiftingBackward(table, moveUp, initial_size);
+	/* move backward and stop at best position */
+	if (!result)
+	    goto cuddZddSiftingAuxOutOfMem;
+    }
+    else if ((x - x_low) > (x_high - x)) {
+	/* must go down first:shorter */
+	moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
+	/* after that point x --> x_high */
+	if (moveDown == NULL)
+	    goto cuddZddSiftingAuxOutOfMem;
+	moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
+	    initial_size);
+	if (moveUp == NULL)
+	    goto cuddZddSiftingAuxOutOfMem;
+	result = cuddZddSiftingBackward(table, moveUp, initial_size);
+	/* move backward and stop at best position */
+	if (!result)
+	    goto cuddZddSiftingAuxOutOfMem;
+    }
+    else {
+	moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
+	/* after that point x --> x_high */
+	if (moveUp == NULL)
+	    goto cuddZddSiftingAuxOutOfMem;
+	moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
+	    initial_size);
+	/* then move up */
+	if (moveDown == NULL)
+	    goto cuddZddSiftingAuxOutOfMem;
+	result = cuddZddSiftingBackward(table, moveDown,
+	    initial_size);
+	/* move backward and stop at best position */
+	if (!result)
+	    goto cuddZddSiftingAuxOutOfMem;
+    }
+
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(1);
+
+cuddZddSiftingAuxOutOfMem:
+    while (moveDown != NULL) {
+	move = moveDown->next;
+	cuddDeallocMove(table, moveDown);
+	moveDown = move;
+    }
+    while (moveUp != NULL) {
+	move = moveUp->next;
+	cuddDeallocMove(table, moveUp);
+	moveUp = move;
+    }
+
+    return(0);
+
+} /* end of cuddZddSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable up.]
+
+  Description [Sifts a variable up. Moves y up until either it reaches
+  the bound (x_low) or the size of the ZDD heap increases too much.
+  Returns the set of moves in case of success; NULL if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSiftingUp(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  initial_size)
+{
+    Move	*moves;
+    Move	*move;
+    int		y;
+    int		size;
+    int		limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddZddNextLow(table, x);
+    while (y >= x_low) {
+	size = cuddZddSwapInPlace(table, y, x);
+	if (size == 0)
+	    goto cuddZddSiftingUpOutOfMem;
+	move = (Move *)cuddDynamicAllocNode(table);
+	if (move == NULL)
+	    goto cuddZddSiftingUpOutOfMem;
+	move->x = y;
+	move->y = x;
+	move->size = size;
+	move->next = moves;
+	moves = move;
+
+	if ((double)size > (double)limit_size * table->maxGrowth)
+	    break;
+        if (size < limit_size)
+	    limit_size = size;
+
+	x = y;
+	y = cuddZddNextLow(table, x);
+    }
+    return(moves);
+
+cuddZddSiftingUpOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(NULL);
+
+} /* end of cuddZddSiftingUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sifts a variable down.]
+
+  Description [Sifts a variable down. Moves x down until either it
+  reaches the bound (x_high) or the size of the ZDD heap increases too
+  much. Returns the set of moves in case of success; NULL if memory is
+  full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSiftingDown(
+  DdManager * table,
+  int  x,
+  int  x_high,
+  int  initial_size)
+{
+    Move	*moves;
+    Move	*move;
+    int		y;
+    int		size;
+    int		limit_size = initial_size;
+
+    moves = NULL;
+    y = cuddZddNextHigh(table, x);
+    while (y <= x_high) {
+	size = cuddZddSwapInPlace(table, x, y);
+	if (size == 0)
+	    goto cuddZddSiftingDownOutOfMem;
+	move = (Move *)cuddDynamicAllocNode(table);
+	if (move == NULL)
+	    goto cuddZddSiftingDownOutOfMem;
+	move->x = x;
+	move->y = y;
+	move->size = size;
+	move->next = moves;
+	moves = move;
+
+	if ((double)size > (double)limit_size * table->maxGrowth)
+	    break;
+        if (size < limit_size)
+	    limit_size = size;
+
+	x = y;
+	y = cuddZddNextHigh(table, x);
+    }
+    return(moves);
+
+cuddZddSiftingDownOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(NULL);
+
+} /* end of cuddZddSiftingDown */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a set of moves, returns the ZDD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    int	    	i;
+    int		i_best;
+    Move	*move;
+    int		res;
+
+    /* Find the minimum size among moves. */
+    i_best = -1;
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+	if (move->size < size) {
+	    i_best = i;
+	    size = move->size;
+	}
+    }
+
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+	if (i == i_best)
+	    break;
+	res = cuddZddSwapInPlace(table, move->x, move->y);
+	if (!res)
+	    return(0);
+	if (i_best == -1 && res == size)
+	    break;
+    }
+
+    return(1);
+
+} /* end of cuddZddSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prepares the ZDD heap for dynamic reordering.]
+
+  Description [Prepares the ZDD heap for dynamic reordering. Does
+  garbage collection, to guarantee that there are no dead nodes;
+  and clears the cache, which is invalidated by dynamic reordering.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+zddReorderPreprocess(
+  DdManager * table)
+{
+
+    /* Clear the cache. */
+    cuddCacheFlush(table);
+
+    /* Eliminate dead nodes. Do not scan the cache again. */
+    cuddGarbageCollect(table,0);
+
+    return;
+
+} /* end of ddReorderPreprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Shrinks almost empty ZDD subtables at the end of reordering
+  to guarantee that they have a reasonable load factor.]
+
+  Description [Shrinks almost empty subtables at the end of reordering to
+  guarantee that they have a reasonable load factor. However, if there many
+  nodes are being reclaimed, then no resizing occurs. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+zddReorderPostprocess(
+  DdManager * table)
+{
+    int i, j, posn;
+    DdNodePtr *nodelist, *oldnodelist;
+    DdNode *node, *next;
+    unsigned int slots, oldslots;
+    extern DD_OOMFP MMoutOfMemory;
+    DD_OOMFP saveHandler;
+
+#ifdef DD_VERBOSE
+    (void) fflush(table->out);
+#endif
+
+    /* If we have very many reclaimed nodes, we do not want to shrink
+    ** the subtables, because this will lead to more garbage
+    ** collections. More garbage collections mean shorter mean life for
+    ** nodes with zero reference count; hence lower probability of finding
+    ** a result in the cache.
+    */
+    if (table->reclaimed > table->allocated * 0.5) return(1);
+
+    /* Resize subtables. */
+    for (i = 0; i < table->sizeZ; i++) {
+	int shift;
+	oldslots = table->subtableZ[i].slots;
+	if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
+	    oldslots <= table->initSlots) continue;
+	oldnodelist = table->subtableZ[i].nodelist;
+	slots = oldslots >> 1;
+	saveHandler = MMoutOfMemory;
+	MMoutOfMemory = Cudd_OutOfMem;
+	nodelist = ALLOC(DdNodePtr, slots);
+	MMoutOfMemory = saveHandler;
+	if (nodelist == NULL) {
+	    return(1);
+	}
+	table->subtableZ[i].nodelist = nodelist;
+	table->subtableZ[i].slots = slots;
+	table->subtableZ[i].shift++;
+	table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
+#ifdef DD_VERBOSE
+	(void) fprintf(table->err,
+		       "shrunk layer %d (%d keys) from %d to %d slots\n",
+		       i, table->subtableZ[i].keys, oldslots, slots);
+#endif
+
+	for (j = 0; (unsigned) j < slots; j++) {
+	    nodelist[j] = NULL;
+	}
+	shift = table->subtableZ[i].shift;
+	for (j = 0; (unsigned) j < oldslots; j++) {
+	    node = oldnodelist[j];
+	    while (node != NULL) {
+		next = node->next;
+		posn = ddHash(cuddT(node), cuddE(node), shift);
+		node->next = nodelist[posn];
+		nodelist[posn] = node;
+		node = next;
+	    }
+	}
+	FREE(oldnodelist);
+
+	table->memused += (slots - oldslots) * sizeof(DdNode *);
+	table->slots += slots - oldslots;
+	table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
+	table->cacheSlack = (int) ddMin(table->maxCacheHard,
+	    DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) -
+	    2 * (int) table->cacheSlots;
+    }
+    /* We don't look at the constant subtable, because it is not
+    ** affected by reordering.
+    */
+
+    return(1);
+
+} /* end of zddReorderPostprocess */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders ZDD variables according to a given permutation.]
+
+  Description [Reorders ZDD variables according to a given permutation.
+  The i-th permutation array contains the index of the variable that
+  should be brought to the i-th level. zddShuffle assumes that no
+  dead nodes are present.  The reordering is achieved by a series of
+  upward sifts.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+zddShuffle(
+  DdManager * table,
+  int * permutation)
+{
+    int		index;
+    int		level;
+    int		position;
+    int		numvars;
+    int		result;
+#ifdef DD_STATS
+    long	localTime;
+    int		initialSize;
+    int		finalSize;
+    int		previousSize;
+#endif
+
+    zddTotalNumberSwapping = 0;
+#ifdef DD_STATS
+    localTime = util_cpu_time();
+    initialSize = table->keysZ;
+    (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
+		   initialSize); 
+#endif
+
+    numvars = table->sizeZ;
+
+    for (level = 0; level < numvars; level++) {
+	index = permutation[level];
+	position = table->permZ[index];
+#ifdef DD_STATS
+	previousSize = table->keysZ;
+#endif
+	result = zddSiftUp(table,position,level);
+	if (!result) return(0);
+#ifdef DD_STATS
+	if (table->keysZ < (unsigned) previousSize) {
+	    (void) fprintf(table->out,"-");
+	} else if (table->keysZ > (unsigned) previousSize) {
+	    (void) fprintf(table->out,"+");	/* should never happen */
+	} else {
+	    (void) fprintf(table->out,"=");
+	}
+	fflush(table->out);
+#endif
+    }
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n");
+    finalSize = table->keysZ;
+    (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); 
+    (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
+	((double)(util_cpu_time() - localTime)/1000.0)); 
+    (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
+		   zddTotalNumberSwapping);
+#endif
+
+    return(1);
+
+} /* end of zddShuffle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves one ZDD variable up.]
+
+  Description [Takes a ZDD variable from position x and sifts it up to
+  position xLow;  xLow should be less than or equal to x.
+  Returns 1 if successful; 0 otherwise]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zddSiftUp(
+  DdManager * table,
+  int  x,
+  int  xLow)
+{
+    int        y;
+    int        size;
+
+    y = cuddZddNextLow(table,x);
+    while (y >= xLow) {
+	size = cuddZddSwapInPlace(table,y,x);
+	if (size == 0) {
+	    return(0);
+	}
+	x = y;
+	y = cuddZddNextLow(table,x);
+    }
+    return(1);
+
+} /* end of zddSiftUp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fixes the ZDD variable group tree after a shuffle.]
+
+  Description [Fixes the ZDD variable group tree after a
+  shuffle. Assumes that the order of the variables in a terminal node
+  has not been changed.]
+
+  SideEffects [Changes the ZDD variable group tree.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddFixTree(
+  DdManager * table,
+  MtrNode * treenode)
+{
+    if (treenode == NULL) return;
+    treenode->low = ((int) treenode->index < table->sizeZ) ?
+	table->permZ[treenode->index] : treenode->index;
+    if (treenode->child != NULL) {
+	zddFixTree(table, treenode->child);
+    }
+    if (treenode->younger != NULL)
+	zddFixTree(table, treenode->younger);
+    if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
+	treenode->parent->low = treenode->low;
+	treenode->parent->index = treenode->index;
+    }
+    return;
+
+} /* end of zddFixTree */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddSetop.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddSetop.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddSetop.c	(revision 8)
@@ -0,0 +1,1166 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddSetop.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Set operations on ZDDs.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddIte()
+		    <li> Cudd_zddUnion()
+		    <li> Cudd_zddIntersect()
+		    <li> Cudd_zddDiff()
+		    <li> Cudd_zddDiffConst()
+		    <li> Cudd_zddSubset1()
+		    <li> Cudd_zddSubset0()
+		    <li> Cudd_zddChange()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    <li> cuddZddIte()
+		    <li> cuddZddUnion()
+		    <li> cuddZddIntersect()
+		    <li> cuddZddDiff()
+		    <li> cuddZddChangeAux()
+		    <li> cuddZddSubset1()
+		    <li> cuddZddSubset0()
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    <li> zdd_subset1_aux()
+		    <li> zdd_subset0_aux()
+		    <li> zddVarToConst()
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddSetop.c,v 1.25 2004/08/13 18:04:54 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * zdd_subset1_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
+static DdNode * zdd_subset0_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
+static void zddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the ITE of three ZDDs.]
+
+  Description [Computes the ITE of three ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddIte(dd, f, g, h);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddIte */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the union of two ZDDs.]
+
+  Description [Computes the union of two ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddUnion(
+  DdManager * dd,
+  DdNode * P,
+  DdNode * Q)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddUnion(dd, P, Q);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddUnion */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the intersection of two ZDDs.]
+
+  Description [Computes the intersection of two ZDDs. Returns a pointer to
+  the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddIntersect(
+  DdManager * dd,
+  DdNode * P,
+  DdNode * Q)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddIntersect(dd, P, Q);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddIntersect */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the difference of two ZDDs.]
+
+  Description [Computes the difference of two ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDiffConst]
+
+******************************************************************************/
+DdNode *
+Cudd_zddDiff(
+  DdManager * dd,
+  DdNode * P,
+  DdNode * Q)
+{
+    DdNode *res;
+
+    do {
+	dd->reordered = 0;
+	res = cuddZddDiff(dd, P, Q);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the inclusion test for ZDDs (P implies Q).]
+
+  Description [Inclusion test for ZDDs (P implies Q). No new nodes are
+  generated by this procedure. Returns empty if true;
+  a valid pointer different from empty or DD_NON_CONSTANT otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddDiff]
+
+******************************************************************************/
+DdNode *
+Cudd_zddDiffConst(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int		p_top, q_top;
+    DdNode	*empty = DD_ZERO(zdd), *t, *res;
+    DdManager	*table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+	return(empty);
+    if (Q == empty)
+	return(P);
+    if (P == Q)
+	return(empty);
+
+    /* Check cache.  The cache is shared by cuddZddDiff(). */
+    res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
+    if (res != NULL)
+	return(res);
+
+    if (cuddIsConstant(P))
+	p_top = P->index;
+    else
+	p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+	q_top = Q->index;
+    else
+	q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+	res = DD_NON_CONSTANT;
+    } else if (p_top > q_top) {
+	res = Cudd_zddDiffConst(zdd, P, cuddE(Q));
+    } else {
+	t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q));
+	if (t != empty)
+	    res = DD_NON_CONSTANT;
+	else
+	    res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q));
+    }
+
+    cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
+
+    return(res);
+
+} /* end of Cudd_zddDiffConst */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the positive cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is asserted. Returns a pointer to
+  the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddSubset0]
+
+******************************************************************************/
+DdNode *
+Cudd_zddSubset1(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode	*r;
+
+    do {
+	dd->reordered = 0;
+	r = cuddZddSubset1(dd, P, var);
+    } while (dd->reordered == 1);
+
+    return(r);
+
+} /* end of Cudd_zddSubset1 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the negative cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is negated. Returns a pointer to
+  the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddSubset1]
+
+******************************************************************************/
+DdNode *
+Cudd_zddSubset0(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode	*r;
+
+    do {
+	dd->reordered = 0;
+	r = cuddZddSubset0(dd, P, var);
+    } while (dd->reordered == 1);
+
+    return(r);
+
+} /* end of Cudd_zddSubset0 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Substitutes a variable with its complement in a ZDD.]
+
+  Description [Substitutes a variable with its complement in a ZDD.
+  returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+Cudd_zddChange(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode	*res;
+
+    if ((unsigned int) var >= CUDD_MAXINDEX - 1) return(NULL);
+    
+    do {
+	dd->reordered = 0;
+	res = cuddZddChange(dd, P, var);
+    } while (dd->reordered == 1);
+    return(res);
+
+} /* end of Cudd_zddChange */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddIte.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddIte(
+  DdManager * dd,
+  DdNode * f,
+  DdNode * g,
+  DdNode * h)
+{
+    DdNode *tautology, *empty;
+    DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e;
+    unsigned int topf,topg,toph,v,top;
+    int index;
+
+    statLine(dd);
+    /* Trivial cases. */
+    /* One variable cases. */
+    if (f == (empty = DD_ZERO(dd))) {	/* ITE(0,G,H) = H */
+	return(h);
+    }
+    topf = cuddIZ(dd,f->index);
+    topg = cuddIZ(dd,g->index);
+    toph = cuddIZ(dd,h->index);
+    v = ddMin(topg,toph);
+    top  = ddMin(topf,v);
+
+    tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top];
+    if (f == tautology) {			/* ITE(1,G,H) = G */
+    	return(g);
+    }
+
+    /* From now on, f is known to not be a constant. */
+    zddVarToConst(f,&g,&h,tautology,empty);
+
+    /* Check remaining one variable cases. */
+    if (g == h) {			/* ITE(F,G,G) = G */
+	return(g);
+    }
+
+    if (g == tautology) {			/* ITE(F,1,0) = F */
+	if (h == empty) return(f);
+    }
+
+    /* Check cache. */
+    r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h);
+    if (r != NULL) {
+	return(r);
+    }
+
+    /* Recompute these because they may have changed in zddVarToConst. */
+    topg = cuddIZ(dd,g->index);
+    toph = cuddIZ(dd,h->index);
+    v = ddMin(topg,toph);
+
+    if (topf < v) {
+	r = cuddZddIte(dd,cuddE(f),g,h);
+	if (r == NULL) return(NULL);
+    } else if (topf > v) {
+	if (topg > v) {
+	    Gvn = g;
+	    index = h->index;
+	} else {
+	    Gvn = cuddE(g);
+	    index = g->index;
+	}
+	if (toph > v) {
+	    Hv = empty; Hvn = h;
+	} else {
+	    Hv = cuddT(h); Hvn = cuddE(h);
+	}
+	e = cuddZddIte(dd,f,Gvn,Hvn);
+	if (e == NULL) return(NULL);
+	cuddRef(e);
+	r = cuddZddGetNode(dd,index,Hv,e);
+	if (r == NULL) {
+	    Cudd_RecursiveDerefZdd(dd,e);
+	    return(NULL);
+	}
+	cuddDeref(e);
+    } else {
+	index = f->index;
+	if (topg > v) {
+	    Gv = empty; Gvn = g;
+	} else {
+	    Gv = cuddT(g); Gvn = cuddE(g);
+	}
+	if (toph > v) {
+	    Hv = empty; Hvn = h;
+	} else {
+	    Hv = cuddT(h); Hvn = cuddE(h);
+	}
+	e = cuddZddIte(dd,cuddE(f),Gvn,Hvn);
+	if (e == NULL) return(NULL);
+	cuddRef(e);
+	t = cuddZddIte(dd,cuddT(f),Gv,Hv);
+	if (t == NULL) {
+	    Cudd_RecursiveDerefZdd(dd,e);
+	    return(NULL);
+	}
+	cuddRef(t);
+	r = cuddZddGetNode(dd,index,t,e);
+	if (r == NULL) {
+	    Cudd_RecursiveDerefZdd(dd,e);
+	    Cudd_RecursiveDerefZdd(dd,t);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r);
+
+    return(r);
+
+} /* end of cuddZddIte */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddUnion.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddUnion(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int		p_top, q_top;
+    DdNode	*empty = DD_ZERO(zdd), *t, *e, *res;
+    DdManager	*table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+	return(Q);
+    if (Q == empty)
+	return(P);
+    if (P == Q)
+	return(P);
+
+    /* Check cache */
+    res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q);
+    if (res != NULL)
+	return(res);
+
+    if (cuddIsConstant(P))
+	p_top = P->index;
+    else
+	p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+	q_top = Q->index;
+    else
+	q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+	e = cuddZddUnion(zdd, cuddE(P), Q);
+	if (e == NULL) return (NULL);
+	cuddRef(e);
+	res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(table, e);
+	    return(NULL);
+	}
+	cuddDeref(e);
+    } else if (p_top > q_top) {
+	e = cuddZddUnion(zdd, P, cuddE(Q));
+	if (e == NULL) return(NULL);
+	cuddRef(e);
+	res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(table, e);
+	    return(NULL);
+	}
+	cuddDeref(e);
+    } else {
+	t = cuddZddUnion(zdd, cuddT(P), cuddT(Q));
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddZddUnion(zdd, cuddE(P), cuddE(Q));
+	if (e == NULL) {
+	    Cudd_RecursiveDerefZdd(table, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+	res = cuddZddGetNode(zdd, P->index, t, e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(table, t);
+	    Cudd_RecursiveDerefZdd(table, e);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert2(table, cuddZddUnion, P, Q, res);
+
+    return(res);
+
+} /* end of cuddZddUnion */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddIntersect.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddIntersect(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int		p_top, q_top;
+    DdNode	*empty = DD_ZERO(zdd), *t, *e, *res;
+    DdManager	*table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+	return(empty);
+    if (Q == empty)
+	return(empty);
+    if (P == Q)
+	return(P);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q);
+    if (res != NULL)
+	return(res);
+
+    if (cuddIsConstant(P))
+	p_top = P->index;
+    else
+	p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+	q_top = Q->index;
+    else
+	q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+	res = cuddZddIntersect(zdd, cuddE(P), Q);
+	if (res == NULL) return(NULL);
+    } else if (p_top > q_top) {
+	res = cuddZddIntersect(zdd, P, cuddE(Q));
+	if (res == NULL) return(NULL);
+    } else {
+	t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q));
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q));
+	if (e == NULL) {
+	    Cudd_RecursiveDerefZdd(table, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+	res = cuddZddGetNode(zdd, P->index, t, e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(table, t);
+	    Cudd_RecursiveDerefZdd(table, e);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert2(table, cuddZddIntersect, P, Q, res);
+
+    return(res);
+
+} /* end of cuddZddIntersect */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddDiff.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddDiff(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * Q)
+{
+    int		p_top, q_top;
+    DdNode	*empty = DD_ZERO(zdd), *t, *e, *res;
+    DdManager	*table = zdd;
+
+    statLine(zdd);
+    if (P == empty)
+	return(empty);
+    if (Q == empty)
+	return(P);
+    if (P == Q)
+	return(empty);
+
+    /* Check cache.  The cache is shared by Cudd_zddDiffConst(). */
+    res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
+    if (res != NULL && res != DD_NON_CONSTANT)
+	return(res);
+
+    if (cuddIsConstant(P))
+	p_top = P->index;
+    else
+	p_top = zdd->permZ[P->index];
+    if (cuddIsConstant(Q))
+	q_top = Q->index;
+    else
+	q_top = zdd->permZ[Q->index];
+    if (p_top < q_top) {
+	e = cuddZddDiff(zdd, cuddE(P), Q);
+	if (e == NULL) return(NULL);
+	cuddRef(e);
+	res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(table, e);
+	    return(NULL);
+	}
+	cuddDeref(e);
+    } else if (p_top > q_top) {
+	res = cuddZddDiff(zdd, P, cuddE(Q));
+	if (res == NULL) return(NULL);
+    } else {
+	t = cuddZddDiff(zdd, cuddT(P), cuddT(Q));
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddZddDiff(zdd, cuddE(P), cuddE(Q));
+	if (e == NULL) {
+	    Cudd_RecursiveDerefZdd(table, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+	res = cuddZddGetNode(zdd, P->index, t, e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(table, t);
+	    Cudd_RecursiveDerefZdd(table, e);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
+
+    return(res);
+
+} /* end of cuddZddDiff */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddChange.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+cuddZddChangeAux(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * zvar)
+{
+    int		top_var, level;
+    DdNode	*res, *t, *e;
+    DdNode	*base = DD_ONE(zdd);
+    DdNode	*empty = DD_ZERO(zdd);
+
+    statLine(zdd);
+    if (P == empty)
+	return(empty);
+    if (P == base)
+	return(zvar);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar);
+    if (res != NULL)
+	return(res);
+
+    top_var = zdd->permZ[P->index];
+    level = zdd->permZ[zvar->index];
+
+    if (top_var > level) {
+	res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd));
+	if (res == NULL) return(NULL);
+    } else if (top_var == level) {
+	res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P));
+	if (res == NULL) return(NULL);
+    } else {
+	t = cuddZddChangeAux(zdd, cuddT(P), zvar);
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+	e = cuddZddChangeAux(zdd, cuddE(P), zvar);
+	if (e == NULL) {
+	    Cudd_RecursiveDerefZdd(zdd, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+	res = cuddZddGetNode(zdd, P->index, t, e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(zdd, t);
+	    Cudd_RecursiveDerefZdd(zdd, e);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res);
+
+    return(res);
+
+} /* end of cuddZddChangeAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the positive cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is asserted. Returns a pointer to
+  the result if successful; NULL otherwise. cuddZddSubset1 performs
+  the same function as Cudd_zddSubset1, but does not restart if
+  reordering has taken place. Therefore it can be called from within a
+  recursive procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSubset0 Cudd_zddSubset1]
+
+******************************************************************************/
+DdNode *
+cuddZddSubset1(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode	*zvar, *r;
+    DdNode	*base, *empty;
+
+    base = DD_ONE(dd);
+    empty = DD_ZERO(dd);
+
+    zvar = cuddUniqueInterZdd(dd, var, base, empty);
+    if (zvar == NULL) {
+	return(NULL);
+    } else {
+	cuddRef(zvar);
+	r = zdd_subset1_aux(dd, P, zvar);
+	if (r == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, zvar);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_RecursiveDerefZdd(dd, zvar);
+    }
+
+    cuddDeref(r);
+    return(r);
+
+} /* end of cuddZddSubset1 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]
+
+  Description [Computes the negative cofactor of a ZDD w.r.t. a
+  variable. In terms of combinations, the result is the set of all
+  combinations in which the variable is negated. Returns a pointer to
+  the result if successful; NULL otherwise. cuddZddSubset0 performs
+  the same function as Cudd_zddSubset0, but does not restart if
+  reordering has taken place. Therefore it can be called from within a
+  recursive procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSubset1 Cudd_zddSubset0]
+
+******************************************************************************/
+DdNode *
+cuddZddSubset0(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode	*zvar, *r;
+    DdNode	*base, *empty;
+
+    base = DD_ONE(dd);
+    empty = DD_ZERO(dd);
+
+    zvar = cuddUniqueInterZdd(dd, var, base, empty);
+    if (zvar == NULL) {
+	return(NULL);
+    } else {
+	cuddRef(zvar);
+	r = zdd_subset0_aux(dd, P, zvar);
+	if (r == NULL) {
+	    Cudd_RecursiveDerefZdd(dd, zvar);
+	    return(NULL);
+	}
+	cuddRef(r);
+	Cudd_RecursiveDerefZdd(dd, zvar);
+    }
+
+    cuddDeref(r);
+    return(r);
+
+} /* end of cuddZddSubset0 */
+
+
+/**Function********************************************************************
+
+  Synopsis [Substitutes a variable with its complement in a ZDD.]
+
+  Description [Substitutes a variable with its complement in a ZDD.
+  returns a pointer to the result if successful; NULL
+  otherwise. cuddZddChange performs the same function as
+  Cudd_zddChange, but does not restart if reordering has taken
+  place. Therefore it can be called from within a recursive
+  procedure.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddChange]
+
+******************************************************************************/
+DdNode *
+cuddZddChange(
+  DdManager * dd,
+  DdNode * P,
+  int  var)
+{
+    DdNode	*zvar, *res;
+
+    zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd));
+    if (zvar == NULL) return(NULL);
+    cuddRef(zvar);
+
+    res = cuddZddChangeAux(dd, P, zvar);
+    if (res == NULL) {
+	Cudd_RecursiveDerefZdd(dd,zvar);
+	return(NULL);
+    }
+    cuddRef(res);
+    Cudd_RecursiveDerefZdd(dd,zvar);
+    cuddDeref(res);
+    return(res);
+
+} /* end of cuddZddChange */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddSubset1.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zdd_subset1_aux(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * zvar)
+{
+    int		top_var, level;
+    DdNode	*res, *t, *e;
+    DdNode	*empty;
+
+    statLine(zdd);
+    empty = DD_ZERO(zdd);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar);
+    if (res != NULL)
+	return(res);
+
+    if (cuddIsConstant(P)) {
+	res = empty;
+	cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
+	return(res);
+    }
+
+    top_var = zdd->permZ[P->index];
+    level = zdd->permZ[zvar->index];
+
+    if (top_var > level) {
+        res = empty;
+    } else if (top_var == level) {
+	res = cuddT(P);
+    } else {
+        t = zdd_subset1_aux(zdd, cuddT(P), zvar);
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+        e = zdd_subset1_aux(zdd, cuddE(P), zvar);
+	if (e == NULL) {
+	    Cudd_RecursiveDerefZdd(zdd, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(zdd, t);
+	    Cudd_RecursiveDerefZdd(zdd, e);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
+
+    return(res);
+
+} /* end of zdd_subset1_aux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of Cudd_zddSubset0.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+zdd_subset0_aux(
+  DdManager * zdd,
+  DdNode * P,
+  DdNode * zvar)
+{
+    int		top_var, level;
+    DdNode	*res, *t, *e;
+
+    statLine(zdd);
+
+    /* Check cache. */
+    res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar);
+    if (res != NULL)
+	return(res);
+
+    if (cuddIsConstant(P)) {
+	res = P;
+	cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
+	return(res);
+    }
+
+    top_var = zdd->permZ[P->index];
+    level = zdd->permZ[zvar->index];
+
+    if (top_var > level) {
+        res = P;
+    }
+    else if (top_var == level) {
+        res = cuddE(P);
+    }
+    else {
+        t = zdd_subset0_aux(zdd, cuddT(P), zvar);
+	if (t == NULL) return(NULL);
+	cuddRef(t);
+        e = zdd_subset0_aux(zdd, cuddE(P), zvar);
+	if (e == NULL) {
+	    Cudd_RecursiveDerefZdd(zdd, t);
+	    return(NULL);
+	}
+	cuddRef(e);
+        res = cuddZddGetNode(zdd, P->index, t, e);
+	if (res == NULL) {
+	    Cudd_RecursiveDerefZdd(zdd, t);
+	    Cudd_RecursiveDerefZdd(zdd, e);
+	    return(NULL);
+	}
+	cuddDeref(t);
+	cuddDeref(e);
+    }
+
+    cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
+
+    return(res);
+
+} /* end of zdd_subset0_aux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replaces variables with constants if possible (part of
+  canonical form).]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddVarToConst(
+  DdNode * f,
+  DdNode ** gp,
+  DdNode ** hp,
+  DdNode * base,
+  DdNode * empty)
+{
+    DdNode *g = *gp;
+    DdNode *h = *hp;
+
+    if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
+	*gp = base;
+    }
+
+    if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
+	*hp = empty;
+    }
+
+} /* end of zddVarToConst */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddSymm.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddSymm.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddSymm.c	(revision 8)
@@ -0,0 +1,1699 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddSymm.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Functions for symmetry-based ZDD variable reordering.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddSymmProfile()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    <li> cuddZddSymmCheck()
+		    <li> cuddZddSymmSifting()
+		    <li> cuddZddSymmSiftingConv()
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    <li> cuddZddUniqueCompare()
+		    <li> cuddZddSymmSiftingAux()
+		    <li> cuddZddSymmSiftingConvAux()
+		    <li> cuddZddSymmSifting_up()
+		    <li> cuddZddSymmSifting_down()
+		    <li> zdd_group_move()
+		    <li> cuddZddSymmSiftingBackward()
+		    <li> zdd_group_move_backward()
+		    </ul>
+	      ]
+
+  SeeAlso     [cuddSymmetry.c]
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define ZDD_MV_OOM (Move *)1
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio Exp $";
+#endif
+
+extern int   	*zdd_entry;
+
+extern int	zddTotalNumberSwapping;
+
+static DdNode	*empty;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high);
+static int cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high);
+static Move * cuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size);
+static Move * cuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size);
+static int cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size);
+static int zdd_group_move (DdManager *table, int x, int y, Move **moves);
+static int zdd_group_move_backward (DdManager *table, int x, int y);
+static void cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints statistics on symmetric ZDD variables.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Cudd_zddSymmProfile(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int		i, x, gbot;
+    int		TotalSymm = 0;
+    int 	TotalSymmGroups = 0;
+
+    for (i = lower; i < upper; i++) {
+	if (table->subtableZ[i].next != (unsigned) i) {
+	    x = i;
+	    (void) fprintf(table->out,"Group:");
+	    do {
+		(void) fprintf(table->out,"  %d", table->invpermZ[x]);
+		TotalSymm++;
+		gbot = x;
+		x = table->subtableZ[x].next;
+	    } while (x != i);
+	    TotalSymmGroups++;
+#ifdef DD_DEBUG
+	    assert(table->subtableZ[gbot].next == (unsigned) i);
+#endif
+	    i = gbot;
+	    (void) fprintf(table->out,"\n");
+	}
+    }
+    (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm);
+    (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups);
+
+} /* end of Cudd_zddSymmProfile */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks for symmetry of x and y.]
+
+  Description [Checks for symmetry of x and y. Ignores projection
+  functions, unless they are isolated. Returns 1 in case of
+  symmetry; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+cuddZddSymmCheck(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int		i;
+    DdNode	*f, *f0, *f1, *f01, *f00, *f11, *f10;
+    int		yindex;
+    int 	xsymmy = 1;
+    int		xsymmyp = 1;
+    int 	arccount = 0;
+    int 	TotalRefCount = 0;
+    int 	symm_found;
+
+    empty = table->zero;
+
+    yindex = table->invpermZ[y];
+    for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
+	f = table->subtableZ[x].nodelist[i];
+	while (f != NULL) {
+	    /* Find f1, f0, f11, f10, f01, f00 */
+	    f1 = cuddT(f);
+	    f0 = cuddE(f);
+	    if ((int) f1->index == yindex) {
+		f11 = cuddT(f1);
+		f10 = cuddE(f1);
+		if (f10 != empty)
+		    arccount++;
+	    } else {
+		if ((int) f0->index != yindex) {
+		    return(0); /* f bypasses layer y */
+		}
+		f11 = empty;
+		f10 = f1;
+	    }
+	    if ((int) f0->index == yindex) {
+		f01 = cuddT(f0);
+		f00 = cuddE(f0);
+		if (f00 != empty)
+		    arccount++;
+	    } else {
+		f01 = empty;
+		f00 = f0;
+	    }
+	    if (f01 != f10)
+		xsymmy = 0;
+	    if (f11 != f00)
+		xsymmyp = 0;
+	    if ((xsymmy == 0) && (xsymmyp == 0))
+		return(0);
+
+	    f = f->next;
+	} /* for each element of the collision list */
+    } /* for each slot of the subtable */
+
+    /* Calculate the total reference counts of y
+    ** whose else arc is not empty.
+    */
+    for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
+	f = table->subtableZ[y].nodelist[i];
+	while (f != NIL(DdNode)) {
+	    if (cuddE(f) != empty)
+		TotalRefCount += f->ref;
+	    f = f->next;
+	}
+    }
+
+    symm_found = (arccount == TotalRefCount);
+#if defined(DD_DEBUG) && defined(DD_VERBOSE)
+    if (symm_found) {
+	int xindex = table->invpermZ[x];
+	(void) fprintf(table->out,
+		       "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
+		       xindex,yindex,x,y);
+    }
+#endif
+
+    return(symm_found);
+
+} /* end cuddZddSymmCheck */
+
+
+/**Function********************************************************************
+
+  Synopsis [Symmetric sifting algorithm for ZDDs.]
+
+  Description [Symmetric sifting algorithm.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the ZDD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSymmSiftingConv]
+
+******************************************************************************/
+int
+cuddZddSymmSifting(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int		i;
+    int		*var;
+    int		nvars;
+    int		x;
+    int		result;
+    int		symvars;
+    int		symgroups;
+    int		iteration;
+#ifdef DD_STATS
+    int		previousSize;
+#endif
+
+    nvars = table->sizeZ;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ALLOC(int, nvars);
+    if (zdd_entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSymmSiftingOutOfMem;
+    }
+    var = ALLOC(int, nvars);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSymmSiftingOutOfMem;
+    }
+
+    for (i = 0; i < nvars; i++) {
+	x = table->permZ[i];
+	zdd_entry[i] = table->subtableZ[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself. */
+    for (i = lower; i <= upper; i++)
+	table->subtableZ[i].next = i;
+
+    iteration = ddMin(table->siftMaxVar, nvars);
+    for (i = 0; i < iteration; i++) {
+	if (zddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	x = table->permZ[var[i]];
+#ifdef DD_STATS
+	previousSize = table->keysZ;
+#endif
+	if (x < lower || x > upper) continue;
+	if (table->subtableZ[x].next == (unsigned) x) {
+	    result = cuddZddSymmSiftingAux(table, x, lower, upper);
+	    if (!result)
+		goto cuddZddSymmSiftingOutOfMem;
+#ifdef DD_STATS
+	    if (table->keysZ < (unsigned) previousSize) {
+		(void) fprintf(table->out,"-");
+	    } else if (table->keysZ > (unsigned) previousSize) {
+		(void) fprintf(table->out,"+");
+#ifdef DD_VERBOSE
+		(void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
+#endif
+	    } else {
+		(void) fprintf(table->out,"=");
+	    }
+	    fflush(table->out);
+#endif
+	}
+    }
+
+    FREE(var);
+    FREE(zdd_entry);
+
+    cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
+    (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
+#endif
+
+    return(1+symvars);
+
+cuddZddSymmSiftingOutOfMem:
+
+    if (zdd_entry != NULL)
+	FREE(zdd_entry);
+    if (var != NULL)
+	FREE(var);
+
+    return(0);
+
+} /* end of cuddZddSymmSifting */
+
+
+/**Function********************************************************************
+
+  Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]
+
+  Description [Symmetric sifting to convergence algorithm for ZDDs.
+  Assumes that no dead nodes are present.
+    <ol>
+    <li> Order all the variables according to the number of entries in
+    each unique subtable.
+    <li> Sift the variable up and down, remembering each time the total
+    size of the ZDD heap and grouping variables that are symmetric.
+    <li> Select the best permutation.
+    <li> Repeat 3 and 4 for all variables.
+    <li> Repeat 1-4 until no further improvement.
+    </ol>
+  Returns 1 plus the number of symmetric variables if successful; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddZddSymmSifting]
+
+******************************************************************************/
+int
+cuddZddSymmSiftingConv(
+  DdManager * table,
+  int  lower,
+  int  upper)
+{
+    int		i;
+    int		*var;
+    int		nvars;
+    int		initialSize;
+    int		x;
+    int		result;
+    int		symvars;
+    int		symgroups;
+    int		classes;
+    int		iteration;
+#ifdef DD_STATS
+    int         previousSize;
+#endif
+
+    initialSize = table->keysZ;
+
+    nvars = table->sizeZ;
+
+    /* Find order in which to sift variables. */
+    var = NULL;
+    zdd_entry = ALLOC(int, nvars);
+    if (zdd_entry == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSymmSiftingConvOutOfMem;
+    }
+    var = ALLOC(int, nvars);
+    if (var == NULL) {
+	table->errorCode = CUDD_MEMORY_OUT;
+	goto cuddZddSymmSiftingConvOutOfMem;
+    }
+
+    for (i = 0; i < nvars; i++) {
+	x = table->permZ[i];
+	zdd_entry[i] = table->subtableZ[x].keys;
+	var[i] = i;
+    }
+
+    qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
+
+    /* Initialize the symmetry of each subtable to itself
+    ** for first pass of converging symmetric sifting.
+    */
+    for (i = lower; i <= upper; i++)
+	table->subtableZ[i].next = i;
+
+    iteration = ddMin(table->siftMaxVar, table->sizeZ);
+    for (i = 0; i < iteration; i++) {
+	if (zddTotalNumberSwapping >= table->siftMaxSwap)
+	    break;
+	x = table->permZ[var[i]];
+	if (x < lower || x > upper) continue;
+	/* Only sift if not in symmetry group already. */
+	if (table->subtableZ[x].next == (unsigned) x) {
+#ifdef DD_STATS
+	    previousSize = table->keysZ;
+#endif
+	    result = cuddZddSymmSiftingAux(table, x, lower, upper);
+	    if (!result)
+		goto cuddZddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+	    if (table->keysZ < (unsigned) previousSize) {
+		(void) fprintf(table->out,"-");
+	    } else if (table->keysZ > (unsigned) previousSize) {
+		(void) fprintf(table->out,"+");
+#ifdef DD_VERBOSE
+		(void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
+#endif
+	    } else {
+		(void) fprintf(table->out,"=");
+	    }
+	    fflush(table->out);
+#endif
+	}
+    }
+
+    /* Sifting now until convergence. */
+    while ((unsigned) initialSize > table->keysZ) {
+	initialSize = table->keysZ;
+#ifdef DD_STATS
+	(void) fprintf(table->out,"\n");
+#endif
+	/* Here we consider only one representative for each symmetry class. */
+	for (x = lower, classes = 0; x <= upper; x++, classes++) {
+	    while ((unsigned) x < table->subtableZ[x].next)
+		x = table->subtableZ[x].next;
+	    /* Here x is the largest index in a group.
+	    ** Groups consists of adjacent variables.
+	    ** Hence, the next increment of x will move it to a new group.
+	    */
+	    i = table->invpermZ[x];
+	    zdd_entry[i] = table->subtableZ[x].keys;
+	    var[classes] = i;
+	}
+
+	qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);
+
+	/* Now sift. */
+	iteration = ddMin(table->siftMaxVar, nvars);
+	for (i = 0; i < iteration; i++) {
+	    if (zddTotalNumberSwapping >= table->siftMaxSwap)
+		break;
+	    x = table->permZ[var[i]];
+	    if ((unsigned) x >= table->subtableZ[x].next) {
+#ifdef DD_STATS
+		previousSize = table->keysZ;
+#endif
+		result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
+		if (!result)
+		    goto cuddZddSymmSiftingConvOutOfMem;
+#ifdef DD_STATS
+		if (table->keysZ < (unsigned) previousSize) {
+		    (void) fprintf(table->out,"-");
+		} else if (table->keysZ > (unsigned) previousSize) {
+		    (void) fprintf(table->out,"+");
+#ifdef DD_VERBOSE
+		(void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
+#endif
+		} else {
+		    (void) fprintf(table->out,"=");
+		}
+		fflush(table->out);
+#endif
+	    }
+	} /* for */
+    }
+
+    cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
+
+#ifdef DD_STATS
+    (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
+		   symvars);
+    (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
+		   symgroups);
+#endif
+
+    FREE(var);
+    FREE(zdd_entry);
+
+    return(1+symvars);
+
+cuddZddSymmSiftingConvOutOfMem:
+
+    if (zdd_entry != NULL)
+	FREE(zdd_entry);
+    if (var != NULL)
+	FREE(var);
+
+    return(0);
+
+} /* end of cuddZddSymmSiftingConv */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Given x_low <= x <= x_high moves x up and down between the
+  boundaries.]
+
+  Description [Given x_low <= x <= x_high moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is not part of a symmetry group. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSymmSiftingAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high)
+{
+    Move *move;
+    Move *move_up;	/* list of up move */
+    Move *move_down;	/* list of down move */
+    int	 initial_size;
+    int	 result;
+    int	 i;
+    int  topbot;	/* index to either top or bottom of symmetry group */
+    int	 init_group_size, final_group_size;
+
+    initial_size = table->keysZ;
+
+    move_down = NULL;
+    move_up = NULL;
+
+    /* Look for consecutive symmetries above x. */
+    for (i = x; i > x_low; i--) {
+	if (!cuddZddSymmCheck(table, i - 1, i))
+            break;
+	/* find top of i-1's symmetry */
+	topbot = table->subtableZ[i - 1].next;
+	table->subtableZ[i - 1].next = i;
+	table->subtableZ[x].next = topbot;
+	/* x is bottom of group so its symmetry is top of i-1's
+	   group */
+	i = topbot + 1; /* add 1 for i--, new i is top of symm group */
+    }
+    /* Look for consecutive symmetries below x. */
+    for (i = x; i < x_high; i++) {
+	if (!cuddZddSymmCheck(table, i, i + 1))
+            break;
+	/* find bottom of i+1's symm group */
+	topbot = i + 1;
+	while ((unsigned) topbot < table->subtableZ[topbot].next)
+	    topbot = table->subtableZ[topbot].next;
+
+	table->subtableZ[topbot].next = table->subtableZ[i].next;
+	table->subtableZ[i].next = i + 1;
+	i = topbot - 1; /* add 1 for i++,
+			   new i is bottom of symm group */
+    }
+
+    /* Now x maybe in the middle of a symmetry group. */
+    if (x == x_low) { /* Sift down */
+	/* Find bottom of x's symm group */
+	while ((unsigned) x < table->subtableZ[x].next)
+	    x = table->subtableZ[x].next;
+
+	i = table->subtableZ[x].next;
+	init_group_size = x - i + 1;
+
+	move_down = cuddZddSymmSifting_down(table, x, x_high,
+	    initial_size);
+	/* after that point x --> x_high, unless early term */
+	if (move_down == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+
+	if (move_down == NULL ||
+	    table->subtableZ[move_down->y].next != move_down->y) {
+	    /* symmetry detected may have to make another complete
+	       pass */
+            if (move_down != NULL)
+		x = move_down->y;
+	    else
+		x = table->subtableZ[x].next;
+	    i = x;
+	    while ((unsigned) i < table->subtableZ[i].next) {
+		i = table->subtableZ[i].next;
+	    }
+	    final_group_size = i - x + 1;
+
+	    if (init_group_size == final_group_size) {
+		/* No new symmetry groups detected,
+		   return to best position */
+		result = cuddZddSymmSiftingBackward(table,
+		    move_down, initial_size);
+	    }
+	    else {
+		initial_size = table->keysZ;
+		move_up = cuddZddSymmSifting_up(table, x, x_low,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_down,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+    else if (x == x_high) { /* Sift up */
+	/* Find top of x's symm group */
+	while ((unsigned) x < table->subtableZ[x].next)
+	    x = table->subtableZ[x].next;
+	x = table->subtableZ[x].next;
+
+	i = x;
+	while ((unsigned) i < table->subtableZ[i].next) {
+	    i = table->subtableZ[i].next;
+	}
+	init_group_size = i - x + 1;
+
+	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+	/* after that point x --> x_low, unless early term */
+	if (move_up == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+
+	if (move_up == NULL ||
+	    table->subtableZ[move_up->x].next != move_up->x) {
+	    /* symmetry detected may have to make another complete
+		pass */
+            if (move_up != NULL)
+		x = move_up->x;
+	    else {
+		while ((unsigned) x < table->subtableZ[x].next)
+		    x = table->subtableZ[x].next;
+	    }
+	    i = table->subtableZ[x].next;
+	    final_group_size = x - i + 1;
+
+	    if (init_group_size == final_group_size) {
+		/* No new symmetry groups detected,
+		   return to best position */
+		result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+	    }
+	    else {
+		initial_size = table->keysZ;
+		move_down = cuddZddSymmSifting_down(table, x, x_high,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_down,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_up,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+    else if ((x - x_low) > (x_high - x)) { /* must go down first:
+						shorter */
+	/* Find bottom of x's symm group */
+	while ((unsigned) x < table->subtableZ[x].next)
+	    x = table->subtableZ[x].next;
+
+	move_down = cuddZddSymmSifting_down(table, x, x_high,
+	    initial_size);
+	/* after that point x --> x_high, unless early term */
+	if (move_down == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+
+	if (move_down != NULL) {
+	    x = move_down->y;
+	}
+	else {
+	    x = table->subtableZ[x].next;
+	}
+	i = x;
+	while ((unsigned) i < table->subtableZ[i].next) {
+	    i = table->subtableZ[i].next;
+	}
+	init_group_size = i - x + 1;
+
+	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+	if (move_up == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+
+	if (move_up == NULL ||
+	    table->subtableZ[move_up->x].next != move_up->x) {
+	    /* symmetry detected may have to make another complete
+	       pass */
+	    if (move_up != NULL) {
+		x = move_up->x;
+	    }
+	    else {
+		while ((unsigned) x < table->subtableZ[x].next)
+		    x = table->subtableZ[x].next;
+	    }
+	    i = table->subtableZ[x].next;
+	    final_group_size = x - i + 1;
+
+	    if (init_group_size == final_group_size) {
+		/* No new symmetry groups detected,
+		   return to best position */
+		result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+	    }
+	    else {
+		while (move_down != NULL) {
+		    move = move_down->next;
+		    cuddDeallocMove(table, move_down);
+		    move_down = move;
+		}
+		initial_size = table->keysZ;
+		move_down = cuddZddSymmSifting_down(table, x, x_high,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_down,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_up,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+    else { /* moving up first:shorter */
+        /* Find top of x's symmetry group */
+	while ((unsigned) x < table->subtableZ[x].next)
+	    x = table->subtableZ[x].next;
+	x = table->subtableZ[x].next;
+
+	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+	/* after that point x --> x_high, unless early term */
+	if (move_up == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+
+	if (move_up != NULL) {
+	    x = move_up->x;
+	}
+	else {
+	    while ((unsigned) x < table->subtableZ[x].next)
+		x = table->subtableZ[x].next;
+	}
+	i = table->subtableZ[x].next;
+	init_group_size = x - i + 1;
+
+	move_down = cuddZddSymmSifting_down(table, x, x_high,
+	    initial_size);
+	if (move_down == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+
+	if (move_down == NULL ||
+	    table->subtableZ[move_down->y].next != move_down->y) {
+	    /* symmetry detected may have to make another complete
+	       pass */
+            if (move_down != NULL) {
+		x = move_down->y;
+	    }
+	    else {
+		x = table->subtableZ[x].next;
+	    }
+	    i = x;
+	    while ((unsigned) i < table->subtableZ[i].next) {
+		i = table->subtableZ[i].next;
+	    }
+	    final_group_size = i - x + 1;
+
+	    if (init_group_size == final_group_size) {
+		/* No new symmetries detected,
+		   go back to best position */
+		result = cuddZddSymmSiftingBackward(table, move_down,
+		    initial_size);
+	    }
+	    else {
+		while (move_up != NULL) {
+		    move = move_up->next;
+		    cuddDeallocMove(table, move_up);
+		    move_up = move;
+		}
+		initial_size = table->keysZ;
+		move_up = cuddZddSymmSifting_up(table, x, x_low,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_down,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingAuxOutOfMem;
+    }
+
+    while (move_down != NULL) {
+	move = move_down->next;
+	cuddDeallocMove(table, move_down);
+	move_down = move;
+    }
+    while (move_up != NULL) {
+	move = move_up->next;
+	cuddDeallocMove(table, move_up);
+	move_up = move;
+    }
+
+    return(1);
+
+cuddZddSymmSiftingAuxOutOfMem:
+    if (move_down != ZDD_MV_OOM) {
+	while (move_down != NULL) {
+	    move = move_down->next;
+	    cuddDeallocMove(table, move_down);
+	    move_down = move;
+	}
+    }
+    if (move_up != ZDD_MV_OOM) {
+	while (move_up != NULL) {
+	    move = move_up->next;
+	    cuddDeallocMove(table, move_up);
+	    move_up = move;
+	}
+    }
+
+    return(0);
+
+} /* end of cuddZddSymmSiftingAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Given x_low <= x <= x_high moves x up and down between the
+  boundaries.]
+
+  Description [Given x_low <= x <= x_high moves x up and down between the
+  boundaries. Finds the best position and does the required changes.
+  Assumes that x is either an isolated variable, or it is the bottom of
+  a symmetry group. All symmetries may not have been found, because of
+  exceeded growth limit. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSymmSiftingConvAux(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  x_high)
+{
+    Move	*move;
+    Move	*move_up;	/* list of up move */
+    Move	*move_down;	/* list of down move */
+    int		initial_size;
+    int		result;
+    int		i;
+    int		init_group_size, final_group_size;
+
+    initial_size = table->keysZ;
+
+    move_down = NULL;
+    move_up = NULL;
+
+    if (x == x_low) { /* Sift down */
+        i = table->subtableZ[x].next;
+	init_group_size = x - i + 1;
+
+	move_down = cuddZddSymmSifting_down(table, x, x_high,
+	    initial_size);
+	/* after that point x --> x_high, unless early term */
+	if (move_down == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+	if (move_down == NULL ||
+	    table->subtableZ[move_down->y].next != move_down->y) {
+	    /* symmetry detected may have to make another complete
+		pass */
+            if (move_down != NULL)
+		x = move_down->y;
+	    else {
+		while ((unsigned) x < table->subtableZ[x].next)
+		    x = table->subtableZ[x].next;
+		x = table->subtableZ[x].next;
+	    }
+	    i = x;
+	    while ((unsigned) i < table->subtableZ[i].next) {
+		i = table->subtableZ[i].next;
+	    }
+	    final_group_size = i - x + 1;
+
+	    if (init_group_size == final_group_size) {
+		/* No new symmetries detected,
+		   go back to best position */
+		result = cuddZddSymmSiftingBackward(table, move_down,
+		    initial_size);
+	    }
+	    else {
+		initial_size = table->keysZ;
+		move_up = cuddZddSymmSifting_up(table, x, x_low,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_down,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+    else if (x == x_high) { /* Sift up */
+	/* Find top of x's symm group */
+	while ((unsigned) x < table->subtableZ[x].next)
+	    x = table->subtableZ[x].next;
+	x = table->subtableZ[x].next;
+
+	i = x;
+	while ((unsigned) i < table->subtableZ[i].next) {
+	    i = table->subtableZ[i].next;
+	}
+	init_group_size = i - x + 1;
+
+	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+	/* after that point x --> x_low, unless early term */
+	if (move_up == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+	if (move_up == NULL ||
+	    table->subtableZ[move_up->x].next != move_up->x) {
+	    /* symmetry detected may have to make another complete
+	       pass */
+            if (move_up != NULL)
+		x = move_up->x;
+	    else {
+		while ((unsigned) x < table->subtableZ[x].next)
+		    x = table->subtableZ[x].next;
+	    }
+	    i = table->subtableZ[x].next;
+	    final_group_size = x - i + 1;
+
+	    if (init_group_size == final_group_size) {
+		/* No new symmetry groups detected,
+		   return to best position */
+		result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+	    }
+	    else {
+		initial_size = table->keysZ;
+		move_down = cuddZddSymmSifting_down(table, x, x_high,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_down,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_up,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+    else if ((x - x_low) > (x_high - x)) { /* must go down first:
+						shorter */
+	move_down = cuddZddSymmSifting_down(table, x, x_high,
+	    initial_size);
+	/* after that point x --> x_high */
+	if (move_down == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+	if (move_down != NULL) {
+	    x = move_down->y;
+	}
+	else {
+	    while ((unsigned) x < table->subtableZ[x].next)
+		x = table->subtableZ[x].next;
+	    x = table->subtableZ[x].next;
+	}
+	i = x;
+	while ((unsigned) i < table->subtableZ[i].next) {
+	    i = table->subtableZ[i].next;
+	}
+	init_group_size = i - x + 1;
+
+	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+	if (move_up == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+	if (move_up == NULL ||
+	    table->subtableZ[move_up->x].next != move_up->x) {
+	    /* symmetry detected may have to make another complete
+	       pass */
+	    if (move_up != NULL) {
+		x = move_up->x;
+	    }
+	    else {
+		while ((unsigned) x < table->subtableZ[x].next)
+		    x = table->subtableZ[x].next;
+	    }
+            i = table->subtableZ[x].next;
+            final_group_size = x - i + 1;
+
+            if (init_group_size == final_group_size) {
+		/* No new symmetry groups detected,
+		   return to best position */
+                result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+            }
+	    else {
+		while (move_down != NULL) {
+		    move = move_down->next;
+		    cuddDeallocMove(table, move_down);
+		    move_down = move;
+		}
+		initial_size = table->keysZ;
+		move_down = cuddZddSymmSifting_down(table, x, x_high,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_down,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_up,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+    else { /* moving up first:shorter */
+	/* Find top of x's symmetry group */
+	x = table->subtableZ[x].next;
+
+	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
+	/* after that point x --> x_high, unless early term */
+	if (move_up == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+	if (move_up != NULL) {
+	    x = move_up->x;
+	}
+	else {
+	    while ((unsigned) x < table->subtableZ[x].next)
+		x = table->subtableZ[x].next;
+	}
+        i = table->subtableZ[x].next;
+        init_group_size = x - i + 1;
+
+	move_down = cuddZddSymmSifting_down(table, x, x_high,
+	    initial_size);
+	if (move_down == ZDD_MV_OOM)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+
+	if (move_down == NULL ||
+	    table->subtableZ[move_down->y].next != move_down->y) {
+	    /* symmetry detected may have to make another complete
+	       pass */
+            if (move_down != NULL) {
+		x = move_down->y;
+	    }
+	    else {
+		while ((unsigned) x < table->subtableZ[x].next)
+		    x = table->subtableZ[x].next;
+		x = table->subtableZ[x].next;
+	    }
+            i = x;
+            while ((unsigned) i < table->subtableZ[i].next) {
+                i = table->subtableZ[i].next;
+            }
+	    final_group_size = i - x + 1;
+
+            if (init_group_size == final_group_size) {
+		/* No new symmetries detected,
+		   go back to best position */
+                result = cuddZddSymmSiftingBackward(table, move_down,
+		    initial_size);
+            }
+	    else {
+		while (move_up != NULL) {
+		    move = move_up->next;
+		    cuddDeallocMove(table, move_up);
+		    move_up = move;
+		}
+		initial_size = table->keysZ;
+		move_up = cuddZddSymmSifting_up(table, x, x_low,
+		    initial_size);
+		result = cuddZddSymmSiftingBackward(table, move_up,
+		    initial_size);
+	    }
+	}
+	else {
+	    result = cuddZddSymmSiftingBackward(table, move_down,
+		initial_size);
+	    /* move backward and stop at best position */
+	}
+	if (!result)
+	    goto cuddZddSymmSiftingConvAuxOutOfMem;
+    }
+
+    while (move_down != NULL) {
+	move = move_down->next;
+	cuddDeallocMove(table, move_down);
+	move_down = move;
+    }
+    while (move_up != NULL) {
+	move = move_up->next;
+	cuddDeallocMove(table, move_up);
+	move_up = move;
+    }
+
+    return(1);
+
+cuddZddSymmSiftingConvAuxOutOfMem:
+    if (move_down != ZDD_MV_OOM) {
+	while (move_down != NULL) {
+	    move = move_down->next;
+	    cuddDeallocMove(table, move_down);
+	    move_down = move;
+	}
+    }
+    if (move_up != ZDD_MV_OOM) {
+	while (move_up != NULL) {
+	    move = move_up->next;
+	    cuddDeallocMove(table, move_up);
+	    move_up = move;
+	}
+    }
+
+    return(0);
+
+} /* end of cuddZddSymmSiftingConvAux */
+
+
+/**Function********************************************************************
+
+  Synopsis [Moves x up until either it reaches the bound (x_low) or
+  the size of the ZDD heap increases too much.]
+
+  Description [Moves x up until either it reaches the bound (x_low) or
+  the size of the ZDD heap increases too much. Assumes that x is the top
+  of a symmetry group.  Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; ZDD_MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSymmSifting_up(
+  DdManager * table,
+  int  x,
+  int  x_low,
+  int  initial_size)
+{
+    Move	*moves;
+    Move	*move;
+    int		y;
+    int		size;
+    int		limit_size = initial_size;
+    int		i, gytop;
+
+    moves = NULL;
+    y = cuddZddNextLow(table, x);
+    while (y >= x_low) {
+	gytop = table->subtableZ[y].next;
+	if (cuddZddSymmCheck(table, y, x)) {
+	    /* Symmetry found, attach symm groups */
+	    table->subtableZ[y].next = x;
+	    i = table->subtableZ[x].next;
+	    while (table->subtableZ[i].next != (unsigned) x)
+		i = table->subtableZ[i].next;
+	    table->subtableZ[i].next = gytop;
+	}
+	else if ((table->subtableZ[x].next == (unsigned) x) &&
+	    (table->subtableZ[y].next == (unsigned) y)) {
+	    /* x and y have self symmetry */
+	    size = cuddZddSwapInPlace(table, y, x);
+	    if (size == 0)
+		goto cuddZddSymmSifting_upOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto cuddZddSymmSifting_upOutOfMem;
+	    move->x = y;
+	    move->y = x;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    if ((double)size >
+		(double)limit_size * table->maxGrowth)
+		return(moves);
+	    if (size < limit_size)
+		limit_size = size;
+	}
+	else { /* Group move */
+	    size = zdd_group_move(table, y, x, &moves);
+	    if ((double)size >
+		(double)limit_size * table->maxGrowth)
+		return(moves);
+	    if (size < limit_size)
+		limit_size = size;
+	}
+	x = gytop;
+	y = cuddZddNextLow(table, x);
+    }
+
+    return(moves);
+
+cuddZddSymmSifting_upOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(ZDD_MV_OOM);
+
+} /* end of cuddZddSymmSifting_up */
+
+
+/**Function********************************************************************
+
+  Synopsis [Moves x down until either it reaches the bound (x_high) or
+  the size of the ZDD heap increases too much.]
+
+  Description [Moves x down until either it reaches the bound (x_high)
+  or the size of the ZDD heap increases too much. Assumes that x is the
+  bottom of a symmetry group. Checks x for symmetry to the adjacent
+  variables. If symmetry is found, the symmetry group of x is merged
+  with the symmetry group of the other variable. Returns the set of
+  moves in case of success; ZDD_MV_OOM if memory is full.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Move *
+cuddZddSymmSifting_down(
+  DdManager * table,
+  int  x,
+  int  x_high,
+  int  initial_size)
+{
+    Move	*moves;
+    Move	*move;
+    int		y;
+    int		size;
+    int		limit_size = initial_size;
+    int		i, gxtop, gybot;
+
+    moves = NULL;
+    y = cuddZddNextHigh(table, x);
+    while (y <= x_high) {
+	gybot = table->subtableZ[y].next;
+	while (table->subtableZ[gybot].next != (unsigned) y)
+	    gybot = table->subtableZ[gybot].next;
+	if (cuddZddSymmCheck(table, x, y)) {
+	    /* Symmetry found, attach symm groups */
+	    gxtop = table->subtableZ[x].next;
+	    table->subtableZ[x].next = y;
+	    i = table->subtableZ[y].next;
+	    while (table->subtableZ[i].next != (unsigned) y)
+		i = table->subtableZ[i].next;
+	    table->subtableZ[i].next = gxtop;
+	}
+	else if ((table->subtableZ[x].next == (unsigned) x) &&
+	    (table->subtableZ[y].next == (unsigned) y)) {
+	    /* x and y have self symmetry */
+	    size = cuddZddSwapInPlace(table, x, y);
+	    if (size == 0)
+		goto cuddZddSymmSifting_downOutOfMem;
+	    move = (Move *)cuddDynamicAllocNode(table);
+	    if (move == NULL)
+		goto cuddZddSymmSifting_downOutOfMem;
+	    move->x = x;
+	    move->y = y;
+	    move->size = size;
+	    move->next = moves;
+	    moves = move;
+	    if ((double)size >
+		(double)limit_size * table->maxGrowth)
+		return(moves);
+	    if (size < limit_size)
+		limit_size = size;
+	    x = y;
+	    y = cuddZddNextHigh(table, x);
+	}
+	else { /* Group move */
+	    size = zdd_group_move(table, x, y, &moves);
+	    if ((double)size >
+		(double)limit_size * table->maxGrowth)
+		return(moves);
+	    if (size < limit_size)
+		limit_size = size;
+	}
+	x = gybot;
+	y = cuddZddNextHigh(table, x);
+    }
+
+    return(moves);
+
+cuddZddSymmSifting_downOutOfMem:
+    while (moves != NULL) {
+	move = moves->next;
+	cuddDeallocMove(table, moves);
+	moves = move;
+    }
+    return(ZDD_MV_OOM);
+
+} /* end of cuddZddSymmSifting_down */
+
+
+/**Function********************************************************************
+
+  Synopsis [Given a set of moves, returns the ZDD heap to the position
+  giving the minimum size.]
+
+  Description [Given a set of moves, returns the ZDD heap to the
+  position giving the minimum size. In case of ties, returns to the
+  closest position giving the minimum size. Returns 1 in case of
+  success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+cuddZddSymmSiftingBackward(
+  DdManager * table,
+  Move * moves,
+  int  size)
+{
+    int		i;
+    int		i_best;
+    Move	*move;
+    int		res;
+
+    i_best = -1;
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+	if (move->size < size) {
+	    i_best = i;
+	    size = move->size;
+	}
+    }
+
+    for (move = moves, i = 0; move != NULL; move = move->next, i++) {
+	if (i == i_best) break;
+	if ((table->subtableZ[move->x].next == move->x) &&
+	    (table->subtableZ[move->y].next == move->y)) {
+	    res = cuddZddSwapInPlace(table, move->x, move->y);
+	    if (!res) return(0);
+	}
+	else { /* Group move necessary */
+	    res = zdd_group_move_backward(table, move->x, move->y);
+	}
+	if (i_best == -1 && res == size)
+	    break;
+    }
+
+    return(1);
+
+} /* end of cuddZddSymmSiftingBackward */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swaps two groups.]
+
+  Description [Swaps two groups. x is assumed to be the bottom variable
+  of the first group. y is assumed to be the top variable of the second
+  group.  Updates the list of moves. Returns the number of keys in the
+  table if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zdd_group_move(
+  DdManager * table,
+  int  x,
+  int  y,
+  Move ** moves)
+{
+    Move	*move;
+    int		size;
+    int		i, temp, gxtop, gxbot, gybot, yprev;
+    int		swapx, swapy;
+
+#ifdef DD_DEBUG
+    assert(x < y);	/* we assume that x < y */
+#endif
+    /* Find top and bottom for the two groups. */
+    gxtop = table->subtableZ[x].next;
+    gxbot = x;
+    gybot = table->subtableZ[y].next;
+    while (table->subtableZ[gybot].next != (unsigned) y)
+	gybot = table->subtableZ[gybot].next;
+    yprev = gybot;
+
+    while (x <= y) {
+	while (y > gxtop) {
+	    /* Set correct symmetries. */
+	    temp = table->subtableZ[x].next;
+	    if (temp == x)
+		temp = y;
+	    i = gxtop;
+	    for (;;) {
+		if (table->subtableZ[i].next == (unsigned) x) {
+		    table->subtableZ[i].next = y;
+		    break;
+		} else {
+		    i = table->subtableZ[i].next;
+		}
+	    }
+	    if (table->subtableZ[y].next != (unsigned) y) {
+		table->subtableZ[x].next = table->subtableZ[y].next;
+	    } else {
+		table->subtableZ[x].next = x;
+	    }
+
+	    if (yprev != y) {
+		table->subtableZ[yprev].next = x;
+	    } else {
+		yprev = x;
+	    }
+	    table->subtableZ[y].next = temp;
+
+	    size = cuddZddSwapInPlace(table, x, y);
+	    if (size == 0)
+		goto zdd_group_moveOutOfMem;
+            swapx = x;
+	    swapy = y;
+	    y = x;
+	    x--;
+	} /* while y > gxtop */
+
+	/* Trying to find the next y. */
+	if (table->subtableZ[y].next <= (unsigned) y) {
+	    gybot = y;
+	} else {
+	    y = table->subtableZ[y].next;
+	}
+
+	yprev = gxtop;
+	gxtop++;
+	gxbot++;
+	x = gxbot;
+    } /* while x <= y, end of group movement */
+    move = (Move *)cuddDynamicAllocNode(table);
+    if (move == NULL)
+	goto zdd_group_moveOutOfMem;
+    move->x = swapx;
+    move->y = swapy;
+    move->size = table->keysZ;
+    move->next = *moves;
+    *moves = move;
+
+    return(table->keysZ);
+
+zdd_group_moveOutOfMem:
+    while (*moves != NULL) {
+	move = (*moves)->next;
+	cuddDeallocMove(table, *moves);
+	*moves = move;
+    }
+    return(0);
+
+} /* end of zdd_group_move */
+
+
+/**Function********************************************************************
+
+  Synopsis [Undoes the swap of two groups.]
+
+  Description [Undoes the swap of two groups. x is assumed to be the
+  bottom variable of the first group. y is assumed to be the top
+  variable of the second group.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zdd_group_move_backward(
+  DdManager * table,
+  int  x,
+  int  y)
+{
+    int	       size;
+    int        i, temp, gxtop, gxbot, gybot, yprev;
+
+#ifdef DD_DEBUG
+    assert(x < y);	/* we assume that x < y */
+#endif
+    /* Find top and bottom of the two groups. */
+    gxtop = table->subtableZ[x].next;
+    gxbot = x;
+    gybot = table->subtableZ[y].next;
+    while (table->subtableZ[gybot].next != (unsigned) y)
+	gybot = table->subtableZ[gybot].next;
+    yprev = gybot;
+
+    while (x <= y) {
+	while (y > gxtop) {
+	    /* Set correct symmetries. */
+	    temp = table->subtableZ[x].next;
+	    if (temp == x)
+		temp = y;
+	    i = gxtop;
+	    for (;;) {
+		if (table->subtableZ[i].next == (unsigned) x) {
+		    table->subtableZ[i].next = y;
+		    break;
+		} else {
+		    i = table->subtableZ[i].next;
+		}
+	    }
+	    if (table->subtableZ[y].next != (unsigned) y) {
+		table->subtableZ[x].next = table->subtableZ[y].next;
+	    } else {
+		table->subtableZ[x].next = x;
+	    }
+
+	    if (yprev != y) {
+		table->subtableZ[yprev].next = x;
+	    } else {
+		yprev = x;
+	    }
+	    table->subtableZ[y].next = temp;
+
+	    size = cuddZddSwapInPlace(table, x, y);
+	    if (size == 0)
+		return(0);
+	    y = x;
+	    x--;
+	} /* while y > gxtop */
+
+	/* Trying to find the next y. */
+	if (table->subtableZ[y].next <= (unsigned) y) {
+	    gybot = y;
+	} else {
+	    y = table->subtableZ[y].next;
+	}
+
+	yprev = gxtop;
+	gxtop++;
+	gxbot++;
+	x = gxbot;
+    } /* while x <= y, end of group movement backward */
+
+    return(size);
+
+} /* end of zdd_group_move_backward */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts numbers of symmetric variables and symmetry
+  groups.]
+
+  Description []
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+cuddZddSymmSummary(
+  DdManager * table,
+  int  lower,
+  int  upper,
+  int * symvars,
+  int * symgroups)
+{
+    int i,x,gbot;
+    int TotalSymm = 0;
+    int TotalSymmGroups = 0;
+
+    for (i = lower; i <= upper; i++) {
+	if (table->subtableZ[i].next != (unsigned) i) {
+	    TotalSymmGroups++;
+	    x = i;
+	    do {
+		TotalSymm++;
+		gbot = x;
+		x = table->subtableZ[x].next;
+	    } while (x != i);
+#ifdef DD_DEBUG
+	    assert(table->subtableZ[gbot].next == (unsigned) i);
+#endif
+	    i = gbot;
+	}
+    }
+    *symvars = TotalSymm;
+    *symgroups = TotalSymmGroups;
+
+    return;
+
+} /* end of cuddZddSymmSummary */
+
Index: /vis_dev/glu-2.1/src/cuBdd/cuddZddUtil.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/cuddZddUtil.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/cuddZddUtil.c	(revision 8)
@@ -0,0 +1,1063 @@
+/**CFile***********************************************************************
+
+  FileName    [cuddZddUtil.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Utility functions for ZDDs.]
+
+  Description [External procedures included in this module:
+		    <ul>
+		    <li> Cudd_zddPrintMinterm()
+		    <li> Cudd_zddPrintCover()
+		    <li> Cudd_zddPrintDebug()
+		    <li> Cudd_zddFirstPath()
+		    <li> Cudd_zddNextPath()
+		    <li> Cudd_zddCoverPathToString()
+		    <li> Cudd_zddDumpDot()
+		    </ul>
+	       Internal procedures included in this module:
+		    <ul>
+		    <li> cuddZddP()
+		    </ul>
+	       Static procedures included in this module:
+		    <ul>
+		    <li> zp2()
+		    <li> zdd_print_minterm_aux()
+		    <li> zddPrintCoverAux()
+		    </ul>
+	      ]
+
+  SeeAlso     []
+
+  Author      [Hyong-Kyoon Shin, In-Ho Moon, Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.24 2004/08/13 18:04:54 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int zp2 (DdManager *zdd, DdNode *f, st_table *t);
+static void zdd_print_minterm_aux (DdManager *zdd, DdNode *node, int level, int *list);
+static void zddPrintCoverAux (DdManager *zdd, DdNode *node, int level, int *list);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a disjoint sum of product form for a ZDD.]
+
+  Description [Prints a disjoint sum of product form for a ZDD. Returns 1
+  if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPrintDebug Cudd_zddPrintCover]
+
+******************************************************************************/
+int
+Cudd_zddPrintMinterm(
+  DdManager * zdd,
+  DdNode * node)
+{
+    int		i, size;
+    int		*list;
+
+    size = (int)zdd->sizeZ;
+    list = ALLOC(int, size);
+    if (list == NULL) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */
+    zdd_print_minterm_aux(zdd, node, 0, list);
+    FREE(list);
+    return(1);
+
+} /* end of Cudd_zddPrintMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a sum of products from a ZDD representing a cover.]
+
+  Description [Prints a sum of products from a ZDD representing a cover.
+  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPrintMinterm]
+
+******************************************************************************/
+int
+Cudd_zddPrintCover(
+  DdManager * zdd,
+  DdNode * node)
+{
+    int		i, size;
+    int		*list;
+
+    size = (int)zdd->sizeZ;
+    if (size % 2 != 0) return(0); /* number of variables should be even */
+    list = ALLOC(int, size);
+    if (list == NULL) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+	return(0);
+    }
+    for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */
+    zddPrintCoverAux(zdd, node, 0, list);
+    FREE(list);
+    return(1);
+
+} /* end of Cudd_zddPrintCover */
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints to the standard output a ZDD and its statistics.]
+
+  Description [Prints to the standard output a DD and its statistics.
+  The statistics include the number of nodes and the number of minterms.
+  (The number of minterms is also the number of combinations in the set.)
+  The statistics are printed if pr &gt; 0.  Specifically:
+  <ul>
+  <li> pr = 0 : prints nothing
+  <li> pr = 1 : prints counts of nodes and minterms
+  <li> pr = 2 : prints counts + disjoint sum of products
+  <li> pr = 3 : prints counts + list of nodes
+  <li> pr &gt; 3 : prints counts + disjoint sum of products + list of nodes
+  </ul>
+  Returns 1 if successful; 0 otherwise.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Cudd_zddPrintDebug(
+  DdManager * zdd,
+  DdNode * f,
+  int  n,
+  int  pr)
+{
+    DdNode	*empty = DD_ZERO(zdd);
+    int		nodes;
+    double	minterms;
+    int		retval = 1;
+
+    if (f == empty && pr > 0) {
+	(void) fprintf(zdd->out,": is the empty ZDD\n");
+	(void) fflush(zdd->out);
+	return(1);
+    }
+
+    if (pr > 0) {
+	nodes = Cudd_zddDagSize(f);
+	if (nodes == CUDD_OUT_OF_MEM) retval = 0;
+	minterms = Cudd_zddCountMinterm(zdd, f, n);
+	if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0;
+	(void) fprintf(zdd->out,": %d nodes %g minterms\n",
+		       nodes, minterms);
+	if (pr > 2)
+	    if (!cuddZddP(zdd, f)) retval = 0;
+	if (pr == 2 || pr > 3) {
+	    if (!Cudd_zddPrintMinterm(zdd, f)) retval = 0;
+	    (void) fprintf(zdd->out,"\n");
+	}
+	(void) fflush(zdd->out);
+    }
+    return(retval);
+
+} /* end of Cudd_zddPrintDebug */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the first path of a ZDD.]
+
+  Description [Defines an iterator on the paths of a ZDD
+  and finds its first path. Returns a generator that contains the
+  information necessary to continue the enumeration if successful; NULL
+  otherwise.<p>
+  A path is represented as an array of literals, which are integers in
+  {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc
+  out of a node, and 2 stands for the absence of a node.
+  The size of the array equals the number of variables in the manager at
+  the time Cudd_zddFirstCube is called.<p>
+  The paths that end in the empty terminal are not enumerated.]
+
+  SideEffects [The first path is returned as a side effect.]
+
+  SeeAlso     [Cudd_zddForeachPath Cudd_zddNextPath Cudd_GenFree
+  Cudd_IsGenEmpty]
+
+******************************************************************************/
+DdGen *
+Cudd_zddFirstPath(
+  DdManager * zdd,
+  DdNode * f,
+  int ** path)
+{
+    DdGen *gen;
+    DdNode *top, *next, *prev;
+    int i;
+    int nvars;
+
+    /* Sanity Check. */
+    if (zdd == NULL || f == NULL) return(NULL);
+
+    /* Allocate generator an initialize it. */
+    gen = ALLOC(DdGen,1);
+    if (gen == NULL) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+	return(NULL);
+    }
+
+    gen->manager = zdd;
+    gen->type = CUDD_GEN_ZDD_PATHS;
+    gen->status = CUDD_GEN_EMPTY;
+    gen->gen.cubes.cube = NULL;
+    gen->gen.cubes.value = DD_ZERO_VAL;
+    gen->stack.sp = 0;
+    gen->stack.stack = NULL;
+    gen->node = NULL;
+
+    nvars = zdd->sizeZ;
+    gen->gen.cubes.cube = ALLOC(int,nvars);
+    if (gen->gen.cubes.cube == NULL) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+	FREE(gen);
+	return(NULL);
+    }
+    for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
+
+    /* The maximum stack depth is one plus the number of variables.
+    ** because a path may have nodes at all levels, including the
+    ** constant level.
+    */
+    gen->stack.stack = ALLOC(DdNodePtr, nvars+1);
+    if (gen->stack.stack == NULL) {
+	zdd->errorCode = CUDD_MEMORY_OUT;
+	FREE(gen->gen.cubes.cube);
+	FREE(gen);
+	return(NULL);
+    }
+    for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
+
+    /* Find the first path of the ZDD. */
+    gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
+
+    while (1) {
+	top = gen->stack.stack[gen->stack.sp-1];
+	if (!cuddIsConstant(Cudd_Regular(top))) {
+	    /* Take the else branch first. */
+	    gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0;
+	    next = cuddE(Cudd_Regular(top));
+	    gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++;
+	} else if (Cudd_Regular(top) == DD_ZERO(zdd)) {
+	    /* Backtrack. */
+	    while (1) {
+		if (gen->stack.sp == 1) {
+		    /* The current node has no predecessor. */
+		    gen->status = CUDD_GEN_EMPTY;
+		    gen->stack.sp--;
+		    goto done;
+		}
+		prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]);
+		next = cuddT(prev);
+		if (next != top) { /* follow the then branch next */
+		    gen->gen.cubes.cube[prev->index] = 1;
+		    gen->stack.stack[gen->stack.sp-1] = next;
+		    break;
+		}
+		/* Pop the stack and try again. */
+		gen->gen.cubes.cube[prev->index] = 2;
+		gen->stack.sp--;
+		top = gen->stack.stack[gen->stack.sp-1];
+	    }
+	} else {
+	    gen->status = CUDD_GEN_NONEMPTY;
+	    gen->gen.cubes.value = cuddV(Cudd_Regular(top));
+	    goto done;
+	}
+    }
+
+done:
+    *path = gen->gen.cubes.cube;
+    return(gen);
+
+} /* end of Cudd_zddFirstPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the next path of a ZDD.]
+
+  Description [Generates the next path of a ZDD onset,
+  using generator gen. Returns 0 if the enumeration is completed; 1
+  otherwise.]
+
+  SideEffects [The path is returned as a side effect. The
+  generator is modified.]
+
+  SeeAlso     [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree
+  Cudd_IsGenEmpty]
+
+******************************************************************************/
+int
+Cudd_zddNextPath(
+  DdGen * gen,
+  int ** path)
+{
+    DdNode *top, *next, *prev;
+    DdManager *zdd = gen->manager;
+
+    /* Backtrack from previously reached terminal node. */
+    while (1) {
+	if (gen->stack.sp == 1) {
+	    /* The current node has no predecessor. */
+	    gen->status = CUDD_GEN_EMPTY;
+	    gen->stack.sp--;
+	    goto done;
+	}
+	top = gen->stack.stack[gen->stack.sp-1];
+	prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]);
+	next = cuddT(prev);
+	if (next != top) { /* follow the then branch next */
+	    gen->gen.cubes.cube[prev->index] = 1;
+	    gen->stack.stack[gen->stack.sp-1] = next;
+	    break;
+	}
+	/* Pop the stack and try again. */
+	gen->gen.cubes.cube[prev->index] = 2;
+	gen->stack.sp--;
+    }
+
+    while (1) {
+	top = gen->stack.stack[gen->stack.sp-1];
+	if (!cuddIsConstant(Cudd_Regular(top))) {
+	    /* Take the else branch first. */
+	    gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0;
+	    next = cuddE(Cudd_Regular(top));
+	    gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++;
+	} else if (Cudd_Regular(top) == DD_ZERO(zdd)) {
+	    /* Backtrack. */
+	    while (1) {
+		if (gen->stack.sp == 1) {
+		    /* The current node has no predecessor. */
+		    gen->status = CUDD_GEN_EMPTY;
+		    gen->stack.sp--;
+		    goto done;
+		}
+		prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]);
+		next = cuddT(prev);
+		if (next != top) { /* follow the then branch next */
+		    gen->gen.cubes.cube[prev->index] = 1;
+		    gen->stack.stack[gen->stack.sp-1] = next;
+		    break;
+		}
+		/* Pop the stack and try again. */
+		gen->gen.cubes.cube[prev->index] = 2;
+		gen->stack.sp--;
+		top = gen->stack.stack[gen->stack.sp-1];
+	    }
+	} else {
+	    gen->status = CUDD_GEN_NONEMPTY;
+	    gen->gen.cubes.value = cuddV(Cudd_Regular(top));
+	    goto done;
+	}
+    }
+
+done:
+    if (gen->status == CUDD_GEN_EMPTY) return(0);
+    *path = gen->gen.cubes.cube;
+    return(1);
+
+} /* end of Cudd_zddNextPath */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a path of a ZDD representing a cover to a string.]
+
+  Description [Converts a path of a ZDD representing a cover to a
+  string.  The string represents an implicant of the cover.  The path
+  is typically produced by Cudd_zddForeachPath.  Returns a pointer to
+  the string if successful; NULL otherwise.  If the str input is NULL,
+  it allocates a new string.  The string passed to this function must
+  have enough room for all variables and for the terminator.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddForeachPath]
+
+******************************************************************************/
+char *
+Cudd_zddCoverPathToString(
+  DdManager *zdd		/* DD manager */,
+  int *path			/* path of ZDD representing a cover */,
+  char *str			/* pointer to string to use if != NULL */
+  )
+{
+    int nvars = zdd->sizeZ;
+    int i;
+    char *res;
+
+    if (nvars & 1) return(NULL);
+    nvars >>= 1;
+    if (str == NULL) {
+	res = ALLOC(char, nvars+1);
+	if (res == NULL) return(NULL);
+    } else {
+	res = str;
+    }
+    for (i = 0; i < nvars; i++) {
+	int v = (path[2*i] << 2) | path[2*i+1];
+	switch (v) {
+	case 0:
+	case 2:
+	case 8:
+	case 10:
+	    res[i] = '-';
+	    break;
+	case 1:
+	case 9:
+	    res[i] = '0';
+	    break;
+	case 4:
+	case 6:
+	    res[i] = '1';
+	    break;
+	default:
+	    res[i] = '?';
+	}
+    }
+    res[nvars] = 0;
+
+    return(res);
+
+} /* end of Cudd_zddCoverPathToString */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a dot file representing the argument ZDDs.]
+
+  Description [Writes a file representing the argument ZDDs in a format
+  suitable for the graph drawing program dot.
+  It returns 1 in case of success; 0 otherwise (e.g., out-of-memory,
+  file system full).
+  Cudd_zddDumpDot does not close the file: This is the caller
+  responsibility. Cudd_zddDumpDot uses a minimal unique subset of the
+  hexadecimal address of a node as name for it.
+  If the argument inames is non-null, it is assumed to hold the pointers
+  to the names of the inputs. Similarly for onames.
+  Cudd_zddDumpDot uses the following convention to draw arcs:
+    <ul>
+    <li> solid line: THEN arcs;
+    <li> dashed line: ELSE arcs.
+    </ul>
+  The dot options are chosen so that the drawing fits on a letter-size
+  sheet.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_DumpDot Cudd_zddPrintDebug]
+
+******************************************************************************/
+int
+Cudd_zddDumpDot(
+  DdManager * dd /* manager */,
+  int  n /* number of output nodes to be dumped */,
+  DdNode ** f /* array of output nodes to be dumped */,
+  char ** inames /* array of input names (or NULL) */,
+  char ** onames /* array of output names (or NULL) */,
+  FILE * fp /* pointer to the dump file */)
+{
+    DdNode	*support = NULL;
+    DdNode	*scan;
+    int		*sorted = NULL;
+    int		nvars = dd->sizeZ;
+    st_table	*visited = NULL;
+    st_generator *gen;
+    int		retval;
+    int		i, j;
+    int		slots;
+    DdNodePtr	*nodelist;
+    long	refAddr, diff, mask;
+
+    /* Build a bit array with the support of f. */
+    sorted = ALLOC(int,nvars);
+    if (sorted == NULL) {
+	dd->errorCode = CUDD_MEMORY_OUT;
+	goto failure;
+    }
+    for (i = 0; i < nvars; i++) sorted[i] = 0;
+
+    /* Take the union of the supports of each output function. */
+    for (i = 0; i < n; i++) {
+	support = Cudd_Support(dd,f[i]);
+	if (support == NULL) goto failure;
+	cuddRef(support);
+	scan = support;
+	while (!cuddIsConstant(scan)) {
+	    sorted[scan->index] = 1;
+	    scan = cuddT(scan);
+	}
+	Cudd_RecursiveDeref(dd,support);
+    }
+    support = NULL; /* so that we do not try to free it in case of failure */
+
+    /* Initialize symbol table for visited nodes. */
+    visited = st_init_table(st_ptrcmp, st_ptrhash);
+    if (visited == NULL) goto failure;
+
+    /* Collect all the nodes of this DD in the symbol table. */
+    for (i = 0; i < n; i++) {
+	retval = cuddCollectNodes(f[i],visited);
+	if (retval == 0) goto failure;
+    }
+
+    /* Find how many most significant hex digits are identical
+    ** in the addresses of all the nodes. Build a mask based
+    ** on this knowledge, so that digits that carry no information
+    ** will not be printed. This is done in two steps.
+    **  1. We scan the symbol table to find the bits that differ
+    **     in at least 2 addresses.
+    **  2. We choose one of the possible masks. There are 8 possible
+    **     masks for 32-bit integer, and 16 possible masks for 64-bit
+    **     integers.
+    */
+
+    /* Find the bits that are different. */
+    refAddr = (long) f[0];
+    diff = 0;
+    gen = st_init_gen(visited);
+    while (st_gen(gen, &scan, NULL)) {
+	diff |= refAddr ^ (long) scan;
+    }
+    st_free_gen(gen);
+
+    /* Choose the mask. */
+    for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) {
+	mask = (1 << i) - 1;
+	if (diff <= mask) break;
+    }
+
+    /* Write the header and the global attributes. */
+    retval = fprintf(fp,"digraph \"ZDD\" {\n");
+    if (retval == EOF) return(0);
+    retval = fprintf(fp,
+	"size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
+    if (retval == EOF) return(0);
+
+    /* Write the input name subgraph by scanning the support array. */
+    retval = fprintf(fp,"{ node [shape = plaintext];\n");
+    if (retval == EOF) goto failure;
+    retval = fprintf(fp,"  edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    /* We use a name ("CONST NODES") with an embedded blank, because
+    ** it is unlikely to appear as an input name.
+    */
+    retval = fprintf(fp,"  \"CONST NODES\" [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invpermZ[i]]) {
+	    if (inames == NULL) {
+		retval = fprintf(fp,"\" %d \" -> ", dd->invpermZ[i]);
+	    } else {
+		retval = fprintf(fp,"\" %s \" -> ", inames[dd->invpermZ[i]]);
+	    }
+            if (retval == EOF) goto failure;
+        }
+    }
+    retval = fprintf(fp,"\"CONST NODES\"; \n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write the output node subgraph. */
+    retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n");
+    if (retval == EOF) goto failure;
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp,"\"F%d\"", i);
+	} else {
+	    retval = fprintf(fp,"\"  %s  \"", onames[i]);
+	}
+	if (retval == EOF) goto failure;
+	if (i == n - 1) {
+	    retval = fprintf(fp,"; }\n");
+	} else {
+	    retval = fprintf(fp," -> ");
+	}
+	if (retval == EOF) goto failure;
+    }
+
+    /* Write rank info: All nodes with the same index have the same rank. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invpermZ[i]]) {
+	    retval = fprintf(fp,"{ rank = same; ");
+	    if (retval == EOF) goto failure;
+	    if (inames == NULL) {
+		retval = fprintf(fp,"\" %d \";\n", dd->invpermZ[i]);
+	    } else {
+		retval = fprintf(fp,"\" %s \";\n", inames[dd->invpermZ[i]]);
+	    }
+            if (retval == EOF) goto failure;
+	    nodelist = dd->subtableZ[i].nodelist;
+	    slots = dd->subtableZ[i].slots;
+	    for (j = 0; j < slots; j++) {
+		scan = nodelist[j];
+		while (scan != NULL) {
+		    if (st_is_member(visited,(char *) scan)) {
+			retval = fprintf(fp,"\"%lx\";\n", (unsigned long)
+					 ((mask & (long) scan) /
+					  sizeof(DdNode)));
+			if (retval == EOF) goto failure;
+		    }
+		    scan = scan->next;
+		}
+	    }
+	    retval = fprintf(fp,"}\n");
+	    if (retval == EOF) goto failure;
+	}
+    }
+
+    /* All constants have the same rank. */
+    retval = fprintf(fp,
+	"{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
+    if (retval == EOF) goto failure;
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+	scan = nodelist[j];
+	while (scan != NULL) {
+	    if (st_is_member(visited,(char *) scan)) {
+		retval = fprintf(fp,"\"%lx\";\n", (unsigned long)
+				 ((mask & (long) scan) / sizeof(DdNode)));
+		if (retval == EOF) goto failure;
+	    }
+	    scan = scan->next;
+	}
+    }
+    retval = fprintf(fp,"}\n}\n");
+    if (retval == EOF) goto failure;
+
+    /* Write edge info. */
+    /* Edges from the output nodes. */
+    for (i = 0; i < n; i++) {
+	if (onames == NULL) {
+	    retval = fprintf(fp,"\"F%d\"", i);
+	} else {
+	    retval = fprintf(fp,"\"  %s  \"", onames[i]);
+	}
+	if (retval == EOF) goto failure;
+	retval = fprintf(fp," -> \"%lx\" [style = solid];\n",
+			 (unsigned long) ((mask & (long) f[i]) /
+					  sizeof(DdNode)));
+	if (retval == EOF) goto failure;
+    }
+
+    /* Edges from internal nodes. */
+    for (i = 0; i < nvars; i++) {
+        if (sorted[dd->invpermZ[i]]) {
+	    nodelist = dd->subtableZ[i].nodelist;
+	    slots = dd->subtableZ[i].slots;
+	    for (j = 0; j < slots; j++) {
+		scan = nodelist[j];
+		while (scan != NULL) {
+		    if (st_is_member(visited,(char *) scan)) {
+			retval = fprintf(fp,
+			    "\"%lx\" -> \"%lx\";\n",
+			    (unsigned long) ((mask & (long) scan) /
+					     sizeof(DdNode)),
+			    (unsigned long) ((mask & (long) cuddT(scan)) /
+					     sizeof(DdNode)));
+			if (retval == EOF) goto failure;
+			retval = fprintf(fp,
+					 "\"%lx\" -> \"%lx\" [style = dashed];\n",
+					 (unsigned long) ((mask & (long) scan)
+							  / sizeof(DdNode)),
+					 (unsigned long) ((mask & (long)
+							   cuddE(scan)) /
+							  sizeof(DdNode)));
+			if (retval == EOF) goto failure;
+		    }
+		    scan = scan->next;
+		}
+	    }
+	}
+    }
+
+    /* Write constant labels. */
+    nodelist = dd->constants.nodelist;
+    slots = dd->constants.slots;
+    for (j = 0; j < slots; j++) {
+	scan = nodelist[j];
+	while (scan != NULL) {
+	    if (st_is_member(visited,(char *) scan)) {
+		retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n",
+				 (unsigned long) ((mask & (long) scan) /
+						  sizeof(DdNode)),
+				 cuddV(scan));
+		if (retval == EOF) goto failure;
+	    }
+	    scan = scan->next;
+	}
+    }
+
+    /* Write trailer and return. */
+    retval = fprintf(fp,"}\n");
+    if (retval == EOF) goto failure;
+
+    st_free_table(visited);
+    FREE(sorted);
+    return(1);
+
+failure:
+    if (sorted != NULL) FREE(sorted);
+    if (support != NULL) Cudd_RecursiveDeref(dd,support);
+    if (visited != NULL) st_free_table(visited);
+    return(0);
+
+} /* end of Cudd_zddDumpBlif */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints a ZDD to the standard output. One line per node is
+  printed.]
+
+  Description [Prints a ZDD to the standard output. One line per node is 
+  printed. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Cudd_zddPrintDebug]
+
+******************************************************************************/
+int
+cuddZddP(
+  DdManager * zdd,
+  DdNode * f)
+{
+    int retval;
+    st_table *table = st_init_table(st_ptrcmp, st_ptrhash);
+
+    if (table == NULL) return(0);
+
+    retval = zp2(zdd, f, table);
+    st_free_table(table);
+    (void) fputc('\n', zdd->out);
+    return(retval);
+
+} /* end of cuddZddP */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the recursive step of cuddZddP.]
+
+  Description [Performs the recursive step of cuddZddP. Returns 1 in
+  case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+zp2(
+  DdManager * zdd,
+  DdNode * f,
+  st_table * t)
+{
+    DdNode	*n;
+    int		T, E;
+    DdNode	*base = DD_ONE(zdd);
+    
+    if (f == NULL)
+	return(0);
+
+    if (Cudd_IsConstant(f)) {
+        (void)fprintf(zdd->out, "ID = %d\n", (f == base));
+	return(1);
+    }
+    if (st_is_member(t, (char *)f) == 1)
+	return(1);
+
+    if (st_insert(t, (char *) f, NULL) == ST_OUT_OF_MEM)
+	return(0);
+
+#if SIZEOF_VOID_P == 8
+    (void) fprintf(zdd->out, "ID = 0x%lx\tindex = %d\tr = %d\t",
+	(unsigned long)f / (unsigned long) sizeof(DdNode), f->index, f->ref);
+#else
+    (void) fprintf(zdd->out, "ID = 0x%x\tindex = %d\tr = %d\t",
+	(unsigned)f / (unsigned) sizeof(DdNode), f->index, f->ref);
+#endif
+
+    n = cuddT(f);
+    if (Cudd_IsConstant(n)) {
+        (void) fprintf(zdd->out, "T = %d\t\t", (n == base));
+	T = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(zdd->out, "T = 0x%lx\t", (unsigned long) n /
+		       (unsigned long) sizeof(DdNode));
+#else
+        (void) fprintf(zdd->out, "T = 0x%x\t", (unsigned) n / (unsigned) sizeof(DdNode));
+#endif
+	T = 0;
+    }
+
+    n = cuddE(f);
+    if (Cudd_IsConstant(n)) {
+        (void) fprintf(zdd->out, "E = %d\n", (n == base));
+	E = 1;
+    } else {
+#if SIZEOF_VOID_P == 8
+        (void) fprintf(zdd->out, "E = 0x%lx\n", (unsigned long) n /
+		      (unsigned long) sizeof(DdNode));
+#else
+        (void) fprintf(zdd->out, "E = 0x%x\n", (unsigned) n / (unsigned) sizeof(DdNode));
+#endif
+	E = 0;
+    }
+
+    if (E == 0)
+	if (zp2(zdd, cuddE(f), t) == 0) return(0);
+    if (T == 0)
+	if (zp2(zdd, cuddT(f), t) == 0) return(0);
+    return(1);
+
+} /* end of zp2 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddPrintMinterm.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zdd_print_minterm_aux(
+  DdManager * zdd /* manager */,
+  DdNode * node /* current node */,
+  int  level /* depth in the recursion */,
+  int * list /* current recursion path */)
+{
+    DdNode	*Nv, *Nnv;
+    int		i, v;
+    DdNode	*base = DD_ONE(zdd);
+
+    if (Cudd_IsConstant(node)) {
+	if (node == base) {
+	    /* Check for missing variable. */
+	    if (level != zdd->sizeZ) {
+		list[zdd->invpermZ[level]] = 0;
+		zdd_print_minterm_aux(zdd, node, level + 1, list);
+		return;
+	    }
+	    /* Terminal case: Print one cube based on the current recursion
+	    ** path.
+	    */
+	    for (i = 0; i < zdd->sizeZ; i++) {
+		v = list[i];
+		if (v == 0)
+		    (void) fprintf(zdd->out,"0");
+		else if (v == 1)
+		    (void) fprintf(zdd->out,"1");
+		else if (v == 3)
+		    (void) fprintf(zdd->out,"@");	/* should never happen */
+		else
+		    (void) fprintf(zdd->out,"-");
+	    }
+	    (void) fprintf(zdd->out," 1\n");
+	}
+    } else {
+	/* Check for missing variable. */
+	if (level != cuddIZ(zdd,node->index)) {
+	    list[zdd->invpermZ[level]] = 0;
+	    zdd_print_minterm_aux(zdd, node, level + 1, list);
+	    return;
+	}
+
+	Nnv = cuddE(node);
+	Nv = cuddT(node);
+	if (Nv == Nnv) {
+	    list[node->index] = 2;
+	    zdd_print_minterm_aux(zdd, Nnv, level + 1, list);
+	    return;
+	}
+
+	list[node->index] = 1;
+	zdd_print_minterm_aux(zdd, Nv, level + 1, list);
+	list[node->index] = 0;
+	zdd_print_minterm_aux(zdd, Nnv, level + 1, list);
+    }
+    return;
+
+} /* end of zdd_print_minterm_aux */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive step of Cudd_zddPrintCover.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+zddPrintCoverAux(
+  DdManager * zdd /* manager */,
+  DdNode * node /* current node */,
+  int  level /* depth in the recursion */,
+  int * list /* current recursion path */)
+{
+    DdNode	*Nv, *Nnv;
+    int		i, v;
+    DdNode	*base = DD_ONE(zdd);
+
+    if (Cudd_IsConstant(node)) {
+	if (node == base) {
+	    /* Check for missing variable. */
+	    if (level != zdd->sizeZ) {
+		list[zdd->invpermZ[level]] = 0;
+		zddPrintCoverAux(zdd, node, level + 1, list);
+		return;
+	    }
+	    /* Terminal case: Print one cube based on the current recursion
+	    ** path.
+	    */
+	    for (i = 0; i < zdd->sizeZ; i += 2) {
+		v = list[i] * 4 + list[i+1];
+		if (v == 0)
+		    (void) putc('-',zdd->out);
+		else if (v == 4)
+		    (void) putc('1',zdd->out);
+		else if (v == 1)
+		    (void) putc('0',zdd->out);
+		else
+		    (void) putc('@',zdd->out); /* should never happen */
+	    }
+	    (void) fprintf(zdd->out," 1\n");
+	}
+    } else {
+	/* Check for missing variable. */
+	if (level != cuddIZ(zdd,node->index)) {
+	    list[zdd->invpermZ[level]] = 0;
+	    zddPrintCoverAux(zdd, node, level + 1, list);
+	    return;
+	}
+
+	Nnv = cuddE(node);
+	Nv = cuddT(node);
+	if (Nv == Nnv) {
+	    list[node->index] = 2;
+	    zddPrintCoverAux(zdd, Nnv, level + 1, list);
+	    return;
+	}
+
+	list[node->index] = 1;
+	zddPrintCoverAux(zdd, Nv, level + 1, list);
+	list[node->index] = 0;
+	zddPrintCoverAux(zdd, Nnv, level + 1, list);
+    }
+    return;
+
+} /* end of zddPrintCoverAux */
Index: /vis_dev/glu-2.1/src/cuBdd/doc/cuddAllAbs.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/cuddAllAbs.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/cuddAllAbs.html	(revision 8)
@@ -0,0 +1,1905 @@
+<html>
+<head><title>cudd package abstract (Internal)</title></head>
+<body>
+
+<h1>cudd package abstract (Internal)</h1>
+<h2>Internal data structures of the CUDD package.</h2>
+<hr>
+
+<!-- Function Abstracts -->
+
+<dl>
+<dt> <a href="cuddAllDet.html#Cudd_AddHook"><code>Cudd_AddHook()</code></a>
+<dd> Adds a function to a hook.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaAdd"><code>Cudd_ApaAdd()</code></a>
+<dd> Adds two arbitrary precision integers.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaCompareRatios"><code>Cudd_ApaCompareRatios()</code></a>
+<dd> Compares the ratios of two arbitrary precision integers to two unsigned ints.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaCompare"><code>Cudd_ApaCompare()</code></a>
+<dd> Compares two arbitrary precision integers.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaCopy"><code>Cudd_ApaCopy()</code></a>
+<dd> Makes a copy of an arbitrary precision integer.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaCountMinterm"><code>Cudd_ApaCountMinterm()</code></a>
+<dd> Counts the number of minterms of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaIntDivision"><code>Cudd_ApaIntDivision()</code></a>
+<dd> Divides an arbitrary precision integer by an integer.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaNumberOfDigits"><code>Cudd_ApaNumberOfDigits()</code></a>
+<dd> Finds the number of digits for an arbitrary precision integer.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaPowerOfTwo"><code>Cudd_ApaPowerOfTwo()</code></a>
+<dd> Sets an arbitrary precision integer to a power of two.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaPrintDecimal"><code>Cudd_ApaPrintDecimal()</code></a>
+<dd> Prints an arbitrary precision integer in decimal format.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaPrintDensity"><code>Cudd_ApaPrintDensity()</code></a>
+<dd> Prints the density of a BDD or ADD using arbitrary precision arithmetic.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaPrintExponential"><code>Cudd_ApaPrintExponential()</code></a>
+<dd> Prints an arbitrary precision integer in exponential format.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaPrintHex"><code>Cudd_ApaPrintHex()</code></a>
+<dd> Prints an arbitrary precision integer in hexadecimal format.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaPrintMintermExp"><code>Cudd_ApaPrintMintermExp()</code></a>
+<dd> Prints the number of minterms of a BDD or ADD in exponential format using arbitrary precision arithmetic.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaPrintMinterm"><code>Cudd_ApaPrintMinterm()</code></a>
+<dd> Prints the number of minterms of a BDD or ADD using arbitrary precision arithmetic.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaSetToLiteral"><code>Cudd_ApaSetToLiteral()</code></a>
+<dd> Sets an arbitrary precision integer to a one-digit literal.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaShiftRight"><code>Cudd_ApaShiftRight()</code></a>
+<dd> Shifts right an arbitrary precision integer by one binary place.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaShortDivision"><code>Cudd_ApaShortDivision()</code></a>
+<dd> Divides an arbitrary precision integer by a digit.
+
+<dt> <a href="cuddAllDet.html#Cudd_ApaSubtract"><code>Cudd_ApaSubtract()</code></a>
+<dd> Subtracts two arbitrary precision integers.
+
+<dt> <a href="cuddAllDet.html#Cudd_AutodynDisableZdd"><code>Cudd_AutodynDisableZdd()</code></a>
+<dd> Disables automatic dynamic reordering of ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_AutodynDisable"><code>Cudd_AutodynDisable()</code></a>
+<dd> Disables automatic dynamic reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_AutodynEnableZdd"><code>Cudd_AutodynEnableZdd()</code></a>
+<dd> Enables automatic dynamic reordering of ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_AutodynEnable"><code>Cudd_AutodynEnable()</code></a>
+<dd> Enables automatic dynamic reordering of BDDs and ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_AverageDistance"><code>Cudd_AverageDistance()</code></a>
+<dd> Computes the average distance between adjacent nodes.
+
+<dt> <a href="cuddAllDet.html#Cudd_BddToAdd"><code>Cudd_BddToAdd()</code></a>
+<dd> Converts a BDD to a 0-1 ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_BddToCubeArray"><code>Cudd_BddToCubeArray()</code></a>
+<dd> Builds a positional array from the BDD of a cube.
+
+<dt> <a href="cuddAllDet.html#Cudd_BiasedOverApprox"><code>Cudd_BiasedOverApprox()</code></a>
+<dd> Extracts a dense superset from a BDD with the biased underapproximation method.
+
+<dt> <a href="cuddAllDet.html#Cudd_BiasedUnderApprox"><code>Cudd_BiasedUnderApprox()</code></a>
+<dd> Extracts a dense subset from a BDD with the biased underapproximation method.
+
+<dt> <a href="cuddAllDet.html#Cudd_CProjection"><code>Cudd_CProjection()</code></a>
+<dd> Computes the compatible projection of R w.r.t. cube Y.
+
+<dt> <a href="cuddAllDet.html#Cudd_CheckKeys"><code>Cudd_CheckKeys()</code></a>
+<dd> Checks for several conditions that should not occur.
+
+<dt> <a href="cuddAllDet.html#Cudd_CheckZeroRef"><code>Cudd_CheckZeroRef()</code></a>
+<dd> Checks the unique table for nodes with non-zero reference counts.
+
+<dt> <a href="cuddAllDet.html#Cudd_ClassifySupport"><code>Cudd_ClassifySupport()</code></a>
+<dd> Classifies the variables in the support of two DDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_ClearErrorCode"><code>Cudd_ClearErrorCode()</code></a>
+<dd> Clear the error code of a manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_CofMinterm"><code>Cudd_CofMinterm()</code></a>
+<dd> Computes the fraction of minterms in the on-set of all the positive cofactors of a BDD or ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_Cofactor"><code>Cudd_Cofactor()</code></a>
+<dd> Computes the cofactor of f with respect to g.
+
+<dt> <a href="cuddAllDet.html#Cudd_Complement"><code>Cudd_Complement()</code></a>
+<dd> Returns the complemented version of a pointer.
+
+<dt> <a href="cuddAllDet.html#Cudd_CountLeaves"><code>Cudd_CountLeaves()</code></a>
+<dd> Counts the number of leaves in a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_CountMinterm"><code>Cudd_CountMinterm()</code></a>
+<dd> Counts the number of minterms of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_CountPathsToNonZero"><code>Cudd_CountPathsToNonZero()</code></a>
+<dd> Counts the number of paths to a non-zero terminal of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_CountPath"><code>Cudd_CountPath()</code></a>
+<dd> Counts the number of paths of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_CubeArrayToBdd"><code>Cudd_CubeArrayToBdd()</code></a>
+<dd> Builds the BDD of a cube from a positional array.
+
+<dt> <a href="cuddAllDet.html#Cudd_DagSize"><code>Cudd_DagSize()</code></a>
+<dd> Counts the number of nodes in a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_DeadAreCounted"><code>Cudd_DeadAreCounted()</code></a>
+<dd> Tells whether dead nodes are counted towards triggering reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_DebugCheck"><code>Cudd_DebugCheck()</code></a>
+<dd> Checks for inconsistencies in the DD heap.
+
+<dt> <a href="cuddAllDet.html#Cudd_Decreasing"><code>Cudd_Decreasing()</code></a>
+<dd> Determines whether a BDD is negative unate in a variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_DelayedDerefBdd"><code>Cudd_DelayedDerefBdd()</code></a>
+<dd> Decreases the reference count of BDD node n.
+
+<dt> <a href="cuddAllDet.html#Cudd_Density"><code>Cudd_Density()</code></a>
+<dd> Computes the density of a BDD or ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_Deref"><code>Cudd_Deref()</code></a>
+<dd> Decreases the reference count of node.
+
+<dt> <a href="cuddAllDet.html#Cudd_DisableGarbageCollection"><code>Cudd_DisableGarbageCollection()</code></a>
+<dd> Disables garbage collection.
+
+<dt> <a href="cuddAllDet.html#Cudd_DisableReorderingReporting"><code>Cudd_DisableReorderingReporting()</code></a>
+<dd> Disables reporting of reordering stats.
+
+<dt> <a href="cuddAllDet.html#Cudd_DumpBlifBody"><code>Cudd_DumpBlifBody()</code></a>
+<dd> Writes a blif body representing the argument BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_DumpBlif"><code>Cudd_DumpBlif()</code></a>
+<dd> Writes a blif file representing the argument BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_DumpDDcal"><code>Cudd_DumpDDcal()</code></a>
+<dd> Writes a DDcal file representing the argument BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_DumpDaVinci"><code>Cudd_DumpDaVinci()</code></a>
+<dd> Writes a daVinci file representing the argument BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_DumpDot"><code>Cudd_DumpDot()</code></a>
+<dd> Writes a dot file representing the argument DDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_DumpFactoredForm"><code>Cudd_DumpFactoredForm()</code></a>
+<dd> Writes factored forms representing the argument BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_Dxygtdxz"><code>Cudd_Dxygtdxz()</code></a>
+<dd> Generates a BDD for the function d(x,y) &gt; d(x,z).
+
+<dt> <a href="cuddAllDet.html#Cudd_Dxygtdyz"><code>Cudd_Dxygtdyz()</code></a>
+<dd> Generates a BDD for the function d(x,y) &gt; d(y,z).
+
+<dt> <a href="cuddAllDet.html#Cudd_EnableGarbageCollection"><code>Cudd_EnableGarbageCollection()</code></a>
+<dd> Enables garbage collection.
+
+<dt> <a href="cuddAllDet.html#Cudd_EnableReorderingReporting"><code>Cudd_EnableReorderingReporting()</code></a>
+<dd> Enables reporting of reordering stats.
+
+<dt> <a href="cuddAllDet.html#Cudd_EpdCountMinterm"><code>Cudd_EpdCountMinterm()</code></a>
+<dd> Counts the number of minterms of a DD with extended precision.
+
+<dt> <a href="cuddAllDet.html#Cudd_EqualSupNorm"><code>Cudd_EqualSupNorm()</code></a>
+<dd> Compares two ADDs for equality within tolerance.
+
+<dt> <a href="cuddAllDet.html#Cudd_EquivDC"><code>Cudd_EquivDC()</code></a>
+<dd> Tells whether F and G are identical wherever D is 0.
+
+<dt> <a href="cuddAllDet.html#Cudd_EstimateCofactorSimple"><code>Cudd_EstimateCofactorSimple()</code></a>
+<dd> Estimates the number of nodes in a cofactor of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_EstimateCofactor"><code>Cudd_EstimateCofactor()</code></a>
+<dd> Estimates the number of nodes in a cofactor of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_Eval"><code>Cudd_Eval()</code></a>
+<dd> Returns the value of a DD for a given variable assignment.
+
+<dt> <a href="cuddAllDet.html#Cudd_ExpectedUsedSlots"><code>Cudd_ExpectedUsedSlots()</code></a>
+<dd> Computes the expected fraction of used slots in the unique table.
+
+<dt> <a href="cuddAllDet.html#Cudd_E"><code>Cudd_E()</code></a>
+<dd> Returns the else child of an internal node.
+
+<dt> <a href="cuddAllDet.html#Cudd_FindEssential"><code>Cudd_FindEssential()</code></a>
+<dd> Finds the essential variables of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_FindTwoLiteralClauses"><code>Cudd_FindTwoLiteralClauses()</code></a>
+<dd> Finds the two literal clauses of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_FirstCube"><code>Cudd_FirstCube()</code></a>
+<dd> Finds the first cube of a decision diagram.
+
+<dt> <a href="cuddAllDet.html#Cudd_FirstNode"><code>Cudd_FirstNode()</code></a>
+<dd> Finds the first node of a decision diagram.
+
+<dt> <a href="cuddAllDet.html#Cudd_FirstPrime"><code>Cudd_FirstPrime()</code></a>
+<dd> Finds the first prime of a Boolean function.
+
+<dt> <a href="cuddAllDet.html#Cudd_ForeachCube"><code>Cudd_ForeachCube()</code></a>
+<dd> Iterates over the cubes of a decision diagram.
+
+<dt> <a href="cuddAllDet.html#Cudd_ForeachNode"><code>Cudd_ForeachNode()</code></a>
+<dd> Iterates over the nodes of a decision diagram.
+
+<dt> <a href="cuddAllDet.html#Cudd_ForeachPrime"><code>Cudd_ForeachPrime()</code></a>
+<dd> Iterates over the primes of a Boolean function.
+
+<dt> <a href="cuddAllDet.html#Cudd_FreeTree"><code>Cudd_FreeTree()</code></a>
+<dd> Frees the variable group tree of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_FreeZddTree"><code>Cudd_FreeZddTree()</code></a>
+<dd> Frees the variable group tree of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_GarbageCollectionEnabled"><code>Cudd_GarbageCollectionEnabled()</code></a>
+<dd> Tells whether garbage collection is enabled.
+
+<dt> <a href="cuddAllDet.html#Cudd_GenFree"><code>Cudd_GenFree()</code></a>
+<dd> Frees a CUDD generator.
+
+<dt> <a href="cuddAllDet.html#Cudd_Increasing"><code>Cudd_Increasing()</code></a>
+<dd> Determines whether a BDD is positive unate in a variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_IndicesToCube"><code>Cudd_IndicesToCube()</code></a>
+<dd> Builds a cube of BDD variables from an array of indices.
+
+<dt> <a href="cuddAllDet.html#Cudd_Init"><code>Cudd_Init()</code></a>
+<dd> Creates a new DD manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_IsComplement"><code>Cudd_IsComplement()</code></a>
+<dd> Returns 1 if a pointer is complemented.
+
+<dt> <a href="cuddAllDet.html#Cudd_IsConstant"><code>Cudd_IsConstant()</code></a>
+<dd> Returns 1 if the node is a constant node.
+
+<dt> <a href="cuddAllDet.html#Cudd_IsGenEmpty"><code>Cudd_IsGenEmpty()</code></a>
+<dd> Queries the status of a generator.
+
+<dt> <a href="cuddAllDet.html#Cudd_IsInHook"><code>Cudd_IsInHook()</code></a>
+<dd> Checks whether a function is in a hook.
+
+<dt> <a href="cuddAllDet.html#Cudd_IsNonConstant"><code>Cudd_IsNonConstant()</code></a>
+<dd> Returns 1 if a DD node is not constant.
+
+<dt> <a href="cuddAllDet.html#Cudd_IterDerefBdd"><code>Cudd_IterDerefBdd()</code></a>
+<dd> Decreases the reference count of BDD node n.
+
+<dt> <a href="cuddAllDet.html#Cudd_LargestCube"><code>Cudd_LargestCube()</code></a>
+<dd> Finds a largest cube in a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_MakeBddFromZddCover"><code>Cudd_MakeBddFromZddCover()</code></a>
+<dd> Converts a ZDD cover to a BDD graph.
+
+<dt> <a href="cuddAllDet.html#Cudd_MakeTreeNode"><code>Cudd_MakeTreeNode()</code></a>
+<dd> Creates a new variable group.
+
+<dt> <a href="cuddAllDet.html#Cudd_MakeZddTreeNode"><code>Cudd_MakeZddTreeNode()</code></a>
+<dd> Creates a new ZDD variable group.
+
+<dt> <a href="cuddAllDet.html#Cudd_MinHammingDist"><code>Cudd_MinHammingDist()</code></a>
+<dd> Returns the minimum Hamming distance between f and minterm.
+
+<dt> <a href="cuddAllDet.html#Cudd_NewApaNumber"><code>Cudd_NewApaNumber()</code></a>
+<dd> Allocates memory for an arbitrary precision integer.
+
+<dt> <a href="cuddAllDet.html#Cudd_NextCube"><code>Cudd_NextCube()</code></a>
+<dd> Generates the next cube of a decision diagram onset.
+
+<dt> <a href="cuddAllDet.html#Cudd_NextNode"><code>Cudd_NextNode()</code></a>
+<dd> Finds the next node of a decision diagram.
+
+<dt> <a href="cuddAllDet.html#Cudd_NextPrime"><code>Cudd_NextPrime()</code></a>
+<dd> Generates the next prime of a Boolean function.
+
+<dt> <a href="cuddAllDet.html#Cudd_NodeReadIndex"><code>Cudd_NodeReadIndex()</code></a>
+<dd> Returns the index of the node.
+
+<dt> <a href="cuddAllDet.html#Cudd_NotCond"><code>Cudd_NotCond()</code></a>
+<dd> Complements a DD if a condition is true.
+
+<dt> <a href="cuddAllDet.html#Cudd_Not"><code>Cudd_Not()</code></a>
+<dd> Complements a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_OutOfMem"><code>Cudd_OutOfMem()</code></a>
+<dd> Warns that a memory allocation failed.
+
+<dt> <a href="cuddAllDet.html#Cudd_OverApprox"><code>Cudd_OverApprox()</code></a>
+<dd> Extracts a dense superset from a BDD with Shiple's underapproximation method.
+
+<dt> <a href="cuddAllDet.html#Cudd_Prime"><code>Cudd_Prime()</code></a>
+<dd> Returns the next prime &gt;= p.
+
+<dt> <a href="cuddAllDet.html#Cudd_PrintDebug"><code>Cudd_PrintDebug()</code></a>
+<dd> Prints to the standard output a DD and its statistics.
+
+<dt> <a href="cuddAllDet.html#Cudd_PrintInfo"><code>Cudd_PrintInfo()</code></a>
+<dd> Prints out statistics and settings for a CUDD manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_PrintLinear"><code>Cudd_PrintLinear()</code></a>
+<dd> Prints the linear transform matrix.
+
+<dt> <a href="cuddAllDet.html#Cudd_PrintMinterm"><code>Cudd_PrintMinterm()</code></a>
+<dd> Prints a disjoint sum of products.
+
+<dt> <a href="cuddAllDet.html#Cudd_PrintTwoLiteralClauses"><code>Cudd_PrintTwoLiteralClauses()</code></a>
+<dd> Prints the two literal clauses of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_PrintVersion"><code>Cudd_PrintVersion()</code></a>
+<dd> Prints the package version number.
+
+<dt> <a href="cuddAllDet.html#Cudd_PrioritySelect"><code>Cudd_PrioritySelect()</code></a>
+<dd> Selects pairs from R using a priority function.
+
+<dt> <a href="cuddAllDet.html#Cudd_Quit"><code>Cudd_Quit()</code></a>
+<dd> Deletes resources associated with a DD manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_Random"><code>Cudd_Random()</code></a>
+<dd> Portable random number generator.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadArcviolation"><code>Cudd_ReadArcviolation()</code></a>
+<dd> Returns the current value of the arcviolation parameter used in group sifting.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadBackground"><code>Cudd_ReadBackground()</code></a>
+<dd> Reads the background constant of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadCacheHits"><code>Cudd_ReadCacheHits()</code></a>
+<dd> Returns the number of cache hits.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadCacheLookUps"><code>Cudd_ReadCacheLookUps()</code></a>
+<dd> Returns the number of cache look-ups.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadCacheSlots"><code>Cudd_ReadCacheSlots()</code></a>
+<dd> Reads the number of slots in the cache.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadCacheUsedSlots"><code>Cudd_ReadCacheUsedSlots()</code></a>
+<dd> Reads the fraction of used slots in the cache.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadDead"><code>Cudd_ReadDead()</code></a>
+<dd> Returns the number of dead nodes in the unique table.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadEpsilon"><code>Cudd_ReadEpsilon()</code></a>
+<dd> Reads the epsilon parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadErrorCode"><code>Cudd_ReadErrorCode()</code></a>
+<dd> Returns the code of the last error.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadGarbageCollectionTime"><code>Cudd_ReadGarbageCollectionTime()</code></a>
+<dd> Returns the time spent in garbage collection.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadGarbageCollections"><code>Cudd_ReadGarbageCollections()</code></a>
+<dd> Returns the number of times garbage collection has occurred.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadGroupcheck"><code>Cudd_ReadGroupcheck()</code></a>
+<dd> Reads the groupcheck parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadIndex"><code>Cudd_ReadIndex()</code></a>
+<dd> Returns the current position in the order of variable index.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadInvPermZdd"><code>Cudd_ReadInvPermZdd()</code></a>
+<dd> Returns the index of the ZDD variable currently in the i-th position of the order.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadInvPerm"><code>Cudd_ReadInvPerm()</code></a>
+<dd> Returns the index of the variable currently in the i-th position of the order.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadIthClause"><code>Cudd_ReadIthClause()</code></a>
+<dd> Accesses the i-th clause of a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadKeys"><code>Cudd_ReadKeys()</code></a>
+<dd> Returns the number of nodes in the unique table.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadLinear"><code>Cudd_ReadLinear()</code></a>
+<dd> Reads an entry of the linear transform matrix.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadLogicZero"><code>Cudd_ReadLogicZero()</code></a>
+<dd> Returns the logic zero constant of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadLooseUpTo"><code>Cudd_ReadLooseUpTo()</code></a>
+<dd> Reads the looseUpTo parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMaxCacheHard"><code>Cudd_ReadMaxCacheHard()</code></a>
+<dd> Reads the maxCacheHard parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMaxCache"><code>Cudd_ReadMaxCache()</code></a>
+<dd> Returns the soft limit for the cache size.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate"><code>Cudd_ReadMaxGrowthAlternate()</code></a>
+<dd> Reads the maxGrowthAlt parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMaxGrowth"><code>Cudd_ReadMaxGrowth()</code></a>
+<dd> Reads the maxGrowth parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMaxLive"><code>Cudd_ReadMaxLive()</code></a>
+<dd> Reads the maximum allowed number of live nodes.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMaxMemory"><code>Cudd_ReadMaxMemory()</code></a>
+<dd> Reads the maximum allowed memory.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMemoryInUse"><code>Cudd_ReadMemoryInUse()</code></a>
+<dd> Returns the memory in use by the manager measured in bytes.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMinDead"><code>Cudd_ReadMinDead()</code></a>
+<dd> Reads the minDead parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMinHit"><code>Cudd_ReadMinHit()</code></a>
+<dd> Reads the hit rate that causes resizinig of the computed table.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadMinusInfinity"><code>Cudd_ReadMinusInfinity()</code></a>
+<dd> Reads the minus-infinity constant from the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadNextReordering"><code>Cudd_ReadNextReordering()</code></a>
+<dd> Returns the threshold for the next dynamic reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadNodeCount"><code>Cudd_ReadNodeCount()</code></a>
+<dd> Reports the number of nodes in BDDs and ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadNodesDropped"><code>Cudd_ReadNodesDropped()</code></a>
+<dd> Returns the number of nodes dropped.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadNodesFreed"><code>Cudd_ReadNodesFreed()</code></a>
+<dd> Returns the number of nodes freed.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadNumberXovers"><code>Cudd_ReadNumberXovers()</code></a>
+<dd> Reads the current number of crossovers used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadOne"><code>Cudd_ReadOne()</code></a>
+<dd> Returns the one constant of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadPeakLiveNodeCount"><code>Cudd_ReadPeakLiveNodeCount()</code></a>
+<dd> Reports the peak number of live nodes.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadPeakNodeCount"><code>Cudd_ReadPeakNodeCount()</code></a>
+<dd> Reports the peak number of nodes.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadPermZdd"><code>Cudd_ReadPermZdd()</code></a>
+<dd> Returns the current position of the i-th ZDD variable in the order.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadPerm"><code>Cudd_ReadPerm()</code></a>
+<dd> Returns the current position of the i-th variable in the order.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadPlusInfinity"><code>Cudd_ReadPlusInfinity()</code></a>
+<dd> Reads the plus-infinity constant from the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadPopulationSize"><code>Cudd_ReadPopulationSize()</code></a>
+<dd> Reads the current size of the population used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadRecomb"><code>Cudd_ReadRecomb()</code></a>
+<dd> Returns the current value of the recombination parameter used in group sifting.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadRecursiveCalls"><code>Cudd_ReadRecursiveCalls()</code></a>
+<dd> Returns the number of recursive calls.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadReorderingCycle"><code>Cudd_ReadReorderingCycle()</code></a>
+<dd> Reads the reordCycle parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadReorderingTime"><code>Cudd_ReadReorderingTime()</code></a>
+<dd> Returns the time spent in reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadReorderings"><code>Cudd_ReadReorderings()</code></a>
+<dd> Returns the number of times reordering has occurred.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadSiftMaxSwap"><code>Cudd_ReadSiftMaxSwap()</code></a>
+<dd> Reads the siftMaxSwap parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadSiftMaxVar"><code>Cudd_ReadSiftMaxVar()</code></a>
+<dd> Reads the siftMaxVar parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadSize"><code>Cudd_ReadSize()</code></a>
+<dd> Returns the number of BDD variables in existance.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadSlots"><code>Cudd_ReadSlots()</code></a>
+<dd> Returns the total number of slots of the unique table.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadStderr"><code>Cudd_ReadStderr()</code></a>
+<dd> Reads the stderr of a manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadStdout"><code>Cudd_ReadStdout()</code></a>
+<dd> Reads the stdout of a manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadSwapSteps"><code>Cudd_ReadSwapSteps()</code></a>
+<dd> Reads the number of elementary reordering steps.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadSymmviolation"><code>Cudd_ReadSymmviolation()</code></a>
+<dd> Returns the current value of the symmviolation parameter used in group sifting.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadTree"><code>Cudd_ReadTree()</code></a>
+<dd> Returns the variable group tree of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadUniqueLinks"><code>Cudd_ReadUniqueLinks()</code></a>
+<dd> Returns the number of links followed in the unique table.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadUniqueLookUps"><code>Cudd_ReadUniqueLookUps()</code></a>
+<dd> Returns the number of look-ups in the unique table.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadUsedSlots"><code>Cudd_ReadUsedSlots()</code></a>
+<dd> Reads the fraction of used slots in the unique table.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadVars"><code>Cudd_ReadVars()</code></a>
+<dd> Returns the i-th element of the vars array.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadZddOne"><code>Cudd_ReadZddOne()</code></a>
+<dd> Returns the ZDD for the constant 1 function.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadZddSize"><code>Cudd_ReadZddSize()</code></a>
+<dd> Returns the number of ZDD variables in existance.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadZddTree"><code>Cudd_ReadZddTree()</code></a>
+<dd> Returns the variable group tree of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReadZero"><code>Cudd_ReadZero()</code></a>
+<dd> Returns the zero constant of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_RecursiveDerefZdd"><code>Cudd_RecursiveDerefZdd()</code></a>
+<dd> Decreases the reference count of ZDD node n.
+
+<dt> <a href="cuddAllDet.html#Cudd_RecursiveDeref"><code>Cudd_RecursiveDeref()</code></a>
+<dd> Decreases the reference count of node n.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReduceHeap"><code>Cudd_ReduceHeap()</code></a>
+<dd> Main dynamic reordering routine.
+
+<dt> <a href="cuddAllDet.html#Cudd_Ref"><code>Cudd_Ref()</code></a>
+<dd> Increases the reference count of a node, if it is not saturated.
+
+<dt> <a href="cuddAllDet.html#Cudd_Regular"><code>Cudd_Regular()</code></a>
+<dd> Returns the regular version of a pointer.
+
+<dt> <a href="cuddAllDet.html#Cudd_RemapOverApprox"><code>Cudd_RemapOverApprox()</code></a>
+<dd> Extracts a dense superset from a BDD with the remapping underapproximation method.
+
+<dt> <a href="cuddAllDet.html#Cudd_RemapUnderApprox"><code>Cudd_RemapUnderApprox()</code></a>
+<dd> Extracts a dense subset from a BDD with the remapping underapproximation method.
+
+<dt> <a href="cuddAllDet.html#Cudd_RemoveHook"><code>Cudd_RemoveHook()</code></a>
+<dd> Removes a function from a hook.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReorderingReporting"><code>Cudd_ReorderingReporting()</code></a>
+<dd> Returns 1 if reporting of reordering stats is enabled.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReorderingStatusZdd"><code>Cudd_ReorderingStatusZdd()</code></a>
+<dd> Reports the status of automatic dynamic reordering of ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_ReorderingStatus"><code>Cudd_ReorderingStatus()</code></a>
+<dd> Reports the status of automatic dynamic reordering of BDDs and ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetArcviolation"><code>Cudd_SetArcviolation()</code></a>
+<dd> Sets the value of the arcviolation parameter used in group sifting.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetBackground"><code>Cudd_SetBackground()</code></a>
+<dd> Sets the background constant of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetEpsilon"><code>Cudd_SetEpsilon()</code></a>
+<dd> Sets the epsilon parameter of the manager to ep.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetGroupcheck"><code>Cudd_SetGroupcheck()</code></a>
+<dd> Sets the parameter groupcheck of the manager to gc.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetLooseUpTo"><code>Cudd_SetLooseUpTo()</code></a>
+<dd> Sets the looseUpTo parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetMaxCacheHard"><code>Cudd_SetMaxCacheHard()</code></a>
+<dd> Sets the maxCacheHard parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate"><code>Cudd_SetMaxGrowthAlternate()</code></a>
+<dd> Sets the maxGrowthAlt parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetMaxGrowth"><code>Cudd_SetMaxGrowth()</code></a>
+<dd> Sets the maxGrowth parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetMaxLive"><code>Cudd_SetMaxLive()</code></a>
+<dd> Sets the maximum allowed number of live nodes.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetMaxMemory"><code>Cudd_SetMaxMemory()</code></a>
+<dd> Sets the maximum allowed memory.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetMinHit"><code>Cudd_SetMinHit()</code></a>
+<dd> Sets the hit rate that causes resizinig of the computed table.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetNextReordering"><code>Cudd_SetNextReordering()</code></a>
+<dd> Sets the threshold for the next dynamic reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetNumberXovers"><code>Cudd_SetNumberXovers()</code></a>
+<dd> Sets the number of crossovers used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetPopulationSize"><code>Cudd_SetPopulationSize()</code></a>
+<dd> Sets the size of the population used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetRecomb"><code>Cudd_SetRecomb()</code></a>
+<dd> Sets the value of the recombination parameter used in group sifting.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetReorderingCycle"><code>Cudd_SetReorderingCycle()</code></a>
+<dd> Sets the reordCycle parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetSiftMaxSwap"><code>Cudd_SetSiftMaxSwap()</code></a>
+<dd> Sets the siftMaxSwap parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetSiftMaxVar"><code>Cudd_SetSiftMaxVar()</code></a>
+<dd> Sets the siftMaxVar parameter of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetStderr"><code>Cudd_SetStderr()</code></a>
+<dd> Sets the stderr of a manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetStdout"><code>Cudd_SetStdout()</code></a>
+<dd> Sets the stdout of a manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetSymmviolation"><code>Cudd_SetSymmviolation()</code></a>
+<dd> Sets the value of the symmviolation parameter used in group sifting.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetTree"><code>Cudd_SetTree()</code></a>
+<dd> Sets the variable group tree of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetVarMap"><code>Cudd_SetVarMap()</code></a>
+<dd> Registers a variable mapping with the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SetZddTree"><code>Cudd_SetZddTree()</code></a>
+<dd> Sets the ZDD variable group tree of the manager.
+
+<dt> <a href="cuddAllDet.html#Cudd_SharingSize"><code>Cudd_SharingSize()</code></a>
+<dd> Counts the number of nodes in an array of DDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_ShortestLength"><code>Cudd_ShortestLength()</code></a>
+<dd> Find the length of the shortest path(s) in a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_ShortestPath"><code>Cudd_ShortestPath()</code></a>
+<dd> Finds a shortest path in a DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_ShuffleHeap"><code>Cudd_ShuffleHeap()</code></a>
+<dd> Reorders variables according to given permutation.
+
+<dt> <a href="cuddAllDet.html#Cudd_SolveEqn"><code>Cudd_SolveEqn()</code></a>
+<dd> Implements the solution of F(x,y) = 0.
+
+<dt> <a href="cuddAllDet.html#Cudd_SplitSet"><code>Cudd_SplitSet()</code></a>
+<dd> Returns m minterms from a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_Srandom"><code>Cudd_Srandom()</code></a>
+<dd> Initializer for the portable random number generator.
+
+<dt> <a href="cuddAllDet.html#Cudd_StdPostReordHook"><code>Cudd_StdPostReordHook()</code></a>
+<dd> Sample hook function to call after reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_StdPreReordHook"><code>Cudd_StdPreReordHook()</code></a>
+<dd> Sample hook function to call before reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_SubsetCompress"><code>Cudd_SubsetCompress()</code></a>
+<dd> Find a dense subset of BDD <code>f</code>.
+
+<dt> <a href="cuddAllDet.html#Cudd_SubsetHeavyBranch"><code>Cudd_SubsetHeavyBranch()</code></a>
+<dd> Extracts a dense subset from a BDD with the heavy branch heuristic.
+
+<dt> <a href="cuddAllDet.html#Cudd_SubsetShortPaths"><code>Cudd_SubsetShortPaths()</code></a>
+<dd> Extracts a dense subset from a BDD with the shortest paths heuristic.
+
+<dt> <a href="cuddAllDet.html#Cudd_SubsetWithMaskVars"><code>Cudd_SubsetWithMaskVars()</code></a>
+<dd> Extracts a subset from a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_SupersetCompress"><code>Cudd_SupersetCompress()</code></a>
+<dd> Find a dense superset of BDD <code>f</code>.
+
+<dt> <a href="cuddAllDet.html#Cudd_SupersetHeavyBranch"><code>Cudd_SupersetHeavyBranch()</code></a>
+<dd> Extracts a dense superset from a BDD with the heavy branch heuristic.
+
+<dt> <a href="cuddAllDet.html#Cudd_SupersetShortPaths"><code>Cudd_SupersetShortPaths()</code></a>
+<dd> Extracts a dense superset from a BDD with the shortest paths heuristic.
+
+<dt> <a href="cuddAllDet.html#Cudd_SupportIndex"><code>Cudd_SupportIndex()</code></a>
+<dd> Finds the variables on which a DD depends.
+
+<dt> <a href="cuddAllDet.html#Cudd_SupportSize"><code>Cudd_SupportSize()</code></a>
+<dd> Counts the variables on which a DD depends.
+
+<dt> <a href="cuddAllDet.html#Cudd_Support"><code>Cudd_Support()</code></a>
+<dd> Finds the variables on which a DD depends.
+
+<dt> <a href="cuddAllDet.html#Cudd_SymmProfile"><code>Cudd_SymmProfile()</code></a>
+<dd> Prints statistics on symmetric variables.
+
+<dt> <a href="cuddAllDet.html#Cudd_TurnOffCountDead"><code>Cudd_TurnOffCountDead()</code></a>
+<dd> Causes the dead nodes not to be counted towards triggering reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_TurnOnCountDead"><code>Cudd_TurnOnCountDead()</code></a>
+<dd> Causes the dead nodes to be counted towards triggering reordering.
+
+<dt> <a href="cuddAllDet.html#Cudd_T"><code>Cudd_T()</code></a>
+<dd> Returns the then child of an internal node.
+
+<dt> <a href="cuddAllDet.html#Cudd_UnderApprox"><code>Cudd_UnderApprox()</code></a>
+<dd> Extracts a dense subset from a BDD with Shiple's underapproximation method.
+
+<dt> <a href="cuddAllDet.html#Cudd_VectorSupportIndex"><code>Cudd_VectorSupportIndex()</code></a>
+<dd> Finds the variables on which a set of DDs depends.
+
+<dt> <a href="cuddAllDet.html#Cudd_VectorSupportSize"><code>Cudd_VectorSupportSize()</code></a>
+<dd> Counts the variables on which a set of DDs depends.
+
+<dt> <a href="cuddAllDet.html#Cudd_VectorSupport"><code>Cudd_VectorSupport()</code></a>
+<dd> Finds the variables on which a set of DDs depends.
+
+<dt> <a href="cuddAllDet.html#Cudd_VerifySol"><code>Cudd_VerifySol()</code></a>
+<dd> Checks the solution of F(x,y) = 0.
+
+<dt> <a href="cuddAllDet.html#Cudd_V"><code>Cudd_V()</code></a>
+<dd> Returns the value of a constant node.
+
+<dt> <a href="cuddAllDet.html#Cudd_Xeqy"><code>Cudd_Xeqy()</code></a>
+<dd> Generates a BDD for the function x==y.
+
+<dt> <a href="cuddAllDet.html#Cudd_Xgty"><code>Cudd_Xgty()</code></a>
+<dd> Generates a BDD for the function x &gt; y.
+
+<dt> <a href="cuddAllDet.html#Cudd_addAgreement"><code>Cudd_addAgreement()</code></a>
+<dd> f if f==g; background if f!=g.
+
+<dt> <a href="cuddAllDet.html#Cudd_addApply"><code>Cudd_addApply()</code></a>
+<dd> Applies op to the corresponding discriminants of f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_addBddInterval"><code>Cudd_addBddInterval()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addBddIthBit"><code>Cudd_addBddIthBit()</code></a>
+<dd> Converts an ADD to a BDD by extracting the i-th bit from the leaves.
+
+<dt> <a href="cuddAllDet.html#Cudd_addBddPattern"><code>Cudd_addBddPattern()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addBddStrictThreshold"><code>Cudd_addBddStrictThreshold()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addBddThreshold"><code>Cudd_addBddThreshold()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addCmpl"><code>Cudd_addCmpl()</code></a>
+<dd> Computes the complement of an ADD a la C language.
+
+<dt> <a href="cuddAllDet.html#Cudd_addCompose"><code>Cudd_addCompose()</code></a>
+<dd> Substitutes g for x_v in the ADD for f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addComputeCube"><code>Cudd_addComputeCube()</code></a>
+<dd> Computes the cube of an array of ADD variables.
+
+<dt> <a href="cuddAllDet.html#Cudd_addConstrain"><code>Cudd_addConstrain()</code></a>
+<dd> Computes f constrain c for ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addConst"><code>Cudd_addConst()</code></a>
+<dd> Returns the ADD for constant c.
+
+<dt> <a href="cuddAllDet.html#Cudd_addDiff"><code>Cudd_addDiff()</code></a>
+<dd> Returns plusinfinity if f=g; returns min(f,g) if f!=g.
+
+<dt> <a href="cuddAllDet.html#Cudd_addDivide"><code>Cudd_addDivide()</code></a>
+<dd> Integer and floating point division.
+
+<dt> <a href="cuddAllDet.html#Cudd_addEvalConst"><code>Cudd_addEvalConst()</code></a>
+<dd> Checks whether ADD g is constant whenever ADD f is 1.
+
+<dt> <a href="cuddAllDet.html#Cudd_addExistAbstract"><code>Cudd_addExistAbstract()</code></a>
+<dd> Existentially Abstracts all the variables in cube from f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addFindMax"><code>Cudd_addFindMax()</code></a>
+<dd> Finds the maximum discriminant of f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addFindMin"><code>Cudd_addFindMin()</code></a>
+<dd> Finds the minimum discriminant of f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addGeneralVectorCompose"><code>Cudd_addGeneralVectorCompose()</code></a>
+<dd> Composes an ADD with a vector of ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addHamming"><code>Cudd_addHamming()</code></a>
+<dd> Computes the Hamming distance ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addHarwell"><code>Cudd_addHarwell()</code></a>
+<dd> Reads in a matrix in the format of the Harwell-Boeing benchmark suite.
+
+<dt> <a href="cuddAllDet.html#Cudd_addIteConstant"><code>Cudd_addIteConstant()</code></a>
+<dd> Implements ITEconstant for ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addIte"><code>Cudd_addIte()</code></a>
+<dd> Implements ITE(f,g,h).
+
+<dt> <a href="cuddAllDet.html#Cudd_addIthBit"><code>Cudd_addIthBit()</code></a>
+<dd> Extracts the i-th bit from an ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addIthVar"><code>Cudd_addIthVar()</code></a>
+<dd> Returns the ADD variable with index i.
+
+<dt> <a href="cuddAllDet.html#Cudd_addLeq"><code>Cudd_addLeq()</code></a>
+<dd> Determines whether f is less than or equal to g.
+
+<dt> <a href="cuddAllDet.html#Cudd_addLog"><code>Cudd_addLog()</code></a>
+<dd> Natural logarithm of an ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addMatrixMultiply"><code>Cudd_addMatrixMultiply()</code></a>
+<dd> Calculates the product of two matrices represented as ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addMaximum"><code>Cudd_addMaximum()</code></a>
+<dd> Integer and floating point max.
+
+<dt> <a href="cuddAllDet.html#Cudd_addMinimum"><code>Cudd_addMinimum()</code></a>
+<dd> Integer and floating point min.
+
+<dt> <a href="cuddAllDet.html#Cudd_addMinus"><code>Cudd_addMinus()</code></a>
+<dd> Integer and floating point subtraction.
+
+<dt> <a href="cuddAllDet.html#Cudd_addMonadicApply"><code>Cudd_addMonadicApply()</code></a>
+<dd> Applies op to the discriminants of f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addNand"><code>Cudd_addNand()</code></a>
+<dd> NAND of two 0-1 ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addNegate"><code>Cudd_addNegate()</code></a>
+<dd> Computes the additive inverse of an ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addNewVarAtLevel"><code>Cudd_addNewVarAtLevel()</code></a>
+<dd> Returns a new ADD variable at a specified level.
+
+<dt> <a href="cuddAllDet.html#Cudd_addNewVar"><code>Cudd_addNewVar()</code></a>
+<dd> Returns a new ADD variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_addNonSimCompose"><code>Cudd_addNonSimCompose()</code></a>
+<dd> Composes an ADD with a vector of 0-1 ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addNor"><code>Cudd_addNor()</code></a>
+<dd> NOR of two 0-1 ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addOneZeroMaximum"><code>Cudd_addOneZeroMaximum()</code></a>
+<dd> Returns 1 if f &gt; g and 0 otherwise.
+
+<dt> <a href="cuddAllDet.html#Cudd_addOrAbstract"><code>Cudd_addOrAbstract()</code></a>
+<dd> Disjunctively abstracts all the variables in cube from the 0-1 ADD f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addOr"><code>Cudd_addOr()</code></a>
+<dd> Disjunction of two 0-1 ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addOuterSum"><code>Cudd_addOuterSum()</code></a>
+<dd> Takes the minimum of a matrix and the outer sum of two vectors.
+
+<dt> <a href="cuddAllDet.html#Cudd_addPermute"><code>Cudd_addPermute()</code></a>
+<dd> Permutes the variables of an ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addPlus"><code>Cudd_addPlus()</code></a>
+<dd> Integer and floating point addition.
+
+<dt> <a href="cuddAllDet.html#Cudd_addRead"><code>Cudd_addRead()</code></a>
+<dd> Reads in a sparse matrix.
+
+<dt> <a href="cuddAllDet.html#Cudd_addResidue"><code>Cudd_addResidue()</code></a>
+<dd> Builds an ADD for the residue modulo m of an n-bit number.
+
+<dt> <a href="cuddAllDet.html#Cudd_addRestrict"><code>Cudd_addRestrict()</code></a>
+<dd> ADD restrict according to Coudert and Madre's algorithm (ICCAD90).
+
+<dt> <a href="cuddAllDet.html#Cudd_addRoundOff"><code>Cudd_addRoundOff()</code></a>
+<dd> Rounds off the discriminants of an ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addScalarInverse"><code>Cudd_addScalarInverse()</code></a>
+<dd> Computes the scalar inverse of an ADD.
+
+<dt> <a href="cuddAllDet.html#Cudd_addSetNZ"><code>Cudd_addSetNZ()</code></a>
+<dd> This operator sets f to the value of g wherever g != 0.
+
+<dt> <a href="cuddAllDet.html#Cudd_addSwapVariables"><code>Cudd_addSwapVariables()</code></a>
+<dd> Swaps two sets of variables of the same size (x and y) in the ADD f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addThreshold"><code>Cudd_addThreshold()</code></a>
+<dd> f if f&gt;=g; 0 if f&lt;g.
+
+<dt> <a href="cuddAllDet.html#Cudd_addTimesPlus"><code>Cudd_addTimesPlus()</code></a>
+<dd> Calculates the product of two matrices represented as ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addTimes"><code>Cudd_addTimes()</code></a>
+<dd> Integer and floating point multiplication.
+
+<dt> <a href="cuddAllDet.html#Cudd_addTriangle"><code>Cudd_addTriangle()</code></a>
+<dd> Performs the triangulation step for the shortest path computation.
+
+<dt> <a href="cuddAllDet.html#Cudd_addUnivAbstract"><code>Cudd_addUnivAbstract()</code></a>
+<dd> Universally Abstracts all the variables in cube from f.
+
+<dt> <a href="cuddAllDet.html#Cudd_addVectorCompose"><code>Cudd_addVectorCompose()</code></a>
+<dd> Composes an ADD with a vector of 0-1 ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addWalsh"><code>Cudd_addWalsh()</code></a>
+<dd> Generates a Walsh matrix in ADD form.
+
+<dt> <a href="cuddAllDet.html#Cudd_addXeqy"><code>Cudd_addXeqy()</code></a>
+<dd> Generates an ADD for the function x==y.
+
+<dt> <a href="cuddAllDet.html#Cudd_addXnor"><code>Cudd_addXnor()</code></a>
+<dd> XNOR of two 0-1 ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_addXor"><code>Cudd_addXor()</code></a>
+<dd> XOR of two 0-1 ADDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddAdjPermuteX"><code>Cudd_bddAdjPermuteX()</code></a>
+<dd> Rearranges a set of variables in the BDD B.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddAndAbstractLimit"><code>Cudd_bddAndAbstractLimit()</code></a>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube. Returns NULL if too many nodes are required.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddAndAbstract"><code>Cudd_bddAndAbstract()</code></a>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddAndLimit"><code>Cudd_bddAndLimit()</code></a>
+<dd> Computes the conjunction of two BDDs f and g. Returns NULL if too many nodes are required.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddAnd"><code>Cudd_bddAnd()</code></a>
+<dd> Computes the conjunction of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddApproxConjDecomp"><code>Cudd_bddApproxConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp"><code>Cudd_bddApproxDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddBindVar"><code>Cudd_bddBindVar()</code></a>
+<dd> Prevents sifting of a variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddBooleanDiff"><code>Cudd_bddBooleanDiff()</code></a>
+<dd> Computes the boolean difference of f with respect to x.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddCharToVect"><code>Cudd_bddCharToVect()</code></a>
+<dd> Computes a vector whose image equals a non-zero function.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddClippingAndAbstract"><code>Cudd_bddClippingAndAbstract()</code></a>
+<dd> Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddClippingAnd"><code>Cudd_bddClippingAnd()</code></a>
+<dd> Approximates the conjunction of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddClosestCube"><code>Cudd_bddClosestCube()</code></a>
+<dd> Finds a cube of f at minimum Hamming distance from g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddCompose"><code>Cudd_bddCompose()</code></a>
+<dd> Substitutes g for x_v in the BDD for f.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddComputeCube"><code>Cudd_bddComputeCube()</code></a>
+<dd> Computes the cube of an array of BDD variables.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddConstrainDecomp"><code>Cudd_bddConstrainDecomp()</code></a>
+<dd> BDD conjunctive decomposition as in McMillan's CAV96 paper.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddConstrain"><code>Cudd_bddConstrain()</code></a>
+<dd> Computes f constrain c.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddCorrelationWeights"><code>Cudd_bddCorrelationWeights()</code></a>
+<dd> Computes the correlation of f and g for given input probabilities.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddCorrelation"><code>Cudd_bddCorrelation()</code></a>
+<dd> Computes the correlation of f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddExistAbstract"><code>Cudd_bddExistAbstract()</code></a>
+<dd> Existentially abstracts all the variables in cube from f.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddGenConjDecomp"><code>Cudd_bddGenConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddGenDisjDecomp"><code>Cudd_bddGenDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIntersect"><code>Cudd_bddIntersect()</code></a>
+<dd> Returns a function included in the intersection of f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsNsVar"><code>Cudd_bddIsNsVar()</code></a>
+<dd> Checks whether a variable is next state.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsPiVar"><code>Cudd_bddIsPiVar()</code></a>
+<dd> Checks whether a variable is primary input.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsPsVar"><code>Cudd_bddIsPsVar()</code></a>
+<dd> Checks whether a variable is present state.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsVarEssential"><code>Cudd_bddIsVarEssential()</code></a>
+<dd> Determines whether a given variable is essential with a given phase in a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsVarHardGroup"><code>Cudd_bddIsVarHardGroup()</code></a>
+<dd> Checks whether a variable is set to be in a hard group.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsVarToBeGrouped"><code>Cudd_bddIsVarToBeGrouped()</code></a>
+<dd> Checks whether a variable is set to be grouped.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsVarToBeUngrouped"><code>Cudd_bddIsVarToBeUngrouped()</code></a>
+<dd> Checks whether a variable is set to be ungrouped.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIsop"><code>Cudd_bddIsop()</code></a>
+<dd> Computes a BDD in the interval between L and U with a simple sum-of-produuct cover.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIteConstant"><code>Cudd_bddIteConstant()</code></a>
+<dd> Implements ITEconstant(f,g,h).
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIterConjDecomp"><code>Cudd_bddIterConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIterDisjDecomp"><code>Cudd_bddIterDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIte"><code>Cudd_bddIte()</code></a>
+<dd> Implements ITE(f,g,h).
+
+<dt> <a href="cuddAllDet.html#Cudd_bddIthVar"><code>Cudd_bddIthVar()</code></a>
+<dd> Returns the BDD variable with index i.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddLICompaction"><code>Cudd_bddLICompaction()</code></a>
+<dd> Performs safe minimization of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddLeqUnless"><code>Cudd_bddLeqUnless()</code></a>
+<dd> Tells whether f is less than of equal to G unless D is 1.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddLeq"><code>Cudd_bddLeq()</code></a>
+<dd> Determines whether f is less than or equal to g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddLiteralSetIntersection"><code>Cudd_bddLiteralSetIntersection()</code></a>
+<dd> Computes the intesection of two sets of literals represented as BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddMakePrime"><code>Cudd_bddMakePrime()</code></a>
+<dd> Expands cube to a prime implicant of f.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddMinimize"><code>Cudd_bddMinimize()</code></a>
+<dd> Finds a small BDD that agrees with <code>f</code> over <code>c</code>.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddNPAnd"><code>Cudd_bddNPAnd()</code></a>
+<dd> Computes f non-polluting-and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddNand"><code>Cudd_bddNand()</code></a>
+<dd> Computes the NAND of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddNewVarAtLevel"><code>Cudd_bddNewVarAtLevel()</code></a>
+<dd> Returns a new BDD variable at a specified level.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddNewVar"><code>Cudd_bddNewVar()</code></a>
+<dd> Returns a new BDD variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddNor"><code>Cudd_bddNor()</code></a>
+<dd> Computes the NOR of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddOr"><code>Cudd_bddOr()</code></a>
+<dd> Computes the disjunction of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddPermute"><code>Cudd_bddPermute()</code></a>
+<dd> Permutes the variables of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddPickArbitraryMinterms"><code>Cudd_bddPickArbitraryMinterms()</code></a>
+<dd> Picks k on-set minterms evenly distributed from given DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddPickOneCube"><code>Cudd_bddPickOneCube()</code></a>
+<dd> Picks one on-set cube randomly from the given DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddPickOneMinterm"><code>Cudd_bddPickOneMinterm()</code></a>
+<dd> Picks one on-set minterm randomly from the given DD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddPrintCover"><code>Cudd_bddPrintCover()</code></a>
+<dd> Prints a sum of prime implicants of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddReadPairIndex"><code>Cudd_bddReadPairIndex()</code></a>
+<dd> Reads a corresponding pair index for a given index.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddRead"><code>Cudd_bddRead()</code></a>
+<dd> Reads in a graph (without labels) given as a list of arcs.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddRealignDisable"><code>Cudd_bddRealignDisable()</code></a>
+<dd> Disables realignment of ZDD order to BDD order.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddRealignEnable"><code>Cudd_bddRealignEnable()</code></a>
+<dd> Enables realignment of BDD order to ZDD order.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddRealignmentEnabled"><code>Cudd_bddRealignmentEnabled()</code></a>
+<dd> Tells whether the realignment of BDD order to ZDD order is enabled.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddResetVarToBeGrouped"><code>Cudd_bddResetVarToBeGrouped()</code></a>
+<dd> Resets a variable not to be grouped.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddRestrict"><code>Cudd_bddRestrict()</code></a>
+<dd> BDD restrict according to Coudert and Madre's algorithm (ICCAD90).
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSetNsVar"><code>Cudd_bddSetNsVar()</code></a>
+<dd> Sets a variable type to next state.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSetPairIndex"><code>Cudd_bddSetPairIndex()</code></a>
+<dd> Sets a corresponding pair index for a given index.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSetPiVar"><code>Cudd_bddSetPiVar()</code></a>
+<dd> Sets a variable type to primary input.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSetPsVar"><code>Cudd_bddSetPsVar()</code></a>
+<dd> Sets a variable type to present state.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSetVarHardGroup"><code>Cudd_bddSetVarHardGroup()</code></a>
+<dd> Sets a variable to be a hard group.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSetVarToBeGrouped"><code>Cudd_bddSetVarToBeGrouped()</code></a>
+<dd> Sets a variable to be grouped.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSetVarToBeUngrouped"><code>Cudd_bddSetVarToBeUngrouped()</code></a>
+<dd> Sets a variable to be ungrouped.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSqueeze"><code>Cudd_bddSqueeze()</code></a>
+<dd> Finds a small BDD in a function interval.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddSwapVariables"><code>Cudd_bddSwapVariables()</code></a>
+<dd> Swaps two sets of variables of the same size (x and y) in the BDD f.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddTransfer"><code>Cudd_bddTransfer()</code></a>
+<dd> Convert a BDD from a manager to another one.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddUnbindVar"><code>Cudd_bddUnbindVar()</code></a>
+<dd> Allows the sifting of a variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddUnivAbstract"><code>Cudd_bddUnivAbstract()</code></a>
+<dd> Universally abstracts all the variables in cube from f.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddVarConjDecomp"><code>Cudd_bddVarConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddVarDisjDecomp"><code>Cudd_bddVarDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddVarIsBound"><code>Cudd_bddVarIsBound()</code></a>
+<dd> Tells whether a variable can be sifted.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddVarIsDependent"><code>Cudd_bddVarIsDependent()</code></a>
+<dd> Checks whether a variable is dependent on others in a function.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddVarMap"><code>Cudd_bddVarMap()</code></a>
+<dd> Remaps the variables of a BDD using the default variable map.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddVectorCompose"><code>Cudd_bddVectorCompose()</code></a>
+<dd> Composes a BDD with a vector of BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddXnor"><code>Cudd_bddXnor()</code></a>
+<dd> Computes the exclusive NOR of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddXorExistAbstract"><code>Cudd_bddXorExistAbstract()</code></a>
+<dd> Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddAllDet.html#Cudd_bddXor"><code>Cudd_bddXor()</code></a>
+<dd> Computes the exclusive OR of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#Cudd_tlcInfoFree"><code>Cudd_tlcInfoFree()</code></a>
+<dd> Frees a DdTlcInfo Structure.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddChange"><code>Cudd_zddChange()</code></a>
+<dd> Substitutes a variable with its complement in a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddComplement"><code>Cudd_zddComplement()</code></a>
+<dd> Computes a complement cover for a ZDD node.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddCountDouble"><code>Cudd_zddCountDouble()</code></a>
+<dd> Counts the number of minterms of a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddCountMinterm"><code>Cudd_zddCountMinterm()</code></a>
+<dd> Counts the number of minterms of a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddCount"><code>Cudd_zddCount()</code></a>
+<dd> Counts the number of minterms in a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddCoverPathToString"><code>Cudd_zddCoverPathToString()</code></a>
+<dd> Converts a path of a ZDD representing a cover to a string.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddDagSize"><code>Cudd_zddDagSize()</code></a>
+<dd> Counts the number of nodes in a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddDiffConst"><code>Cudd_zddDiffConst()</code></a>
+<dd> Performs the inclusion test for ZDDs (P implies Q).
+
+<dt> <a href="cuddAllDet.html#Cudd_zddDiff"><code>Cudd_zddDiff()</code></a>
+<dd> Computes the difference of two ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddDivideF"><code>Cudd_zddDivideF()</code></a>
+<dd> Modified version of Cudd_zddDivide.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddDivide"><code>Cudd_zddDivide()</code></a>
+<dd> Computes the quotient of two unate covers.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddDumpDot"><code>Cudd_zddDumpDot()</code></a>
+<dd> Writes a dot file representing the argument ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddFirstPath"><code>Cudd_zddFirstPath()</code></a>
+<dd> Finds the first path of a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddForeachPath"><code>Cudd_zddForeachPath()</code></a>
+<dd> Iterates over the paths of a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddIntersect"><code>Cudd_zddIntersect()</code></a>
+<dd> Computes the intersection of two ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddIsop"><code>Cudd_zddIsop()</code></a>
+<dd> Computes an ISOP in ZDD form from BDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddIte"><code>Cudd_zddIte()</code></a>
+<dd> Computes the ITE of three ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddIthVar"><code>Cudd_zddIthVar()</code></a>
+<dd> Returns the ZDD variable with index i.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddNextPath"><code>Cudd_zddNextPath()</code></a>
+<dd> Generates the next path of a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddPortFromBdd"><code>Cudd_zddPortFromBdd()</code></a>
+<dd> Converts a BDD into a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddPortToBdd"><code>Cudd_zddPortToBdd()</code></a>
+<dd> Converts a ZDD into a BDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddPrintCover"><code>Cudd_zddPrintCover()</code></a>
+<dd> Prints a sum of products from a ZDD representing a cover.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddPrintDebug"><code>Cudd_zddPrintDebug()</code></a>
+<dd> Prints to the standard output a ZDD and its statistics.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddPrintMinterm"><code>Cudd_zddPrintMinterm()</code></a>
+<dd> Prints a disjoint sum of product form for a ZDD.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddPrintSubtable"><code>Cudd_zddPrintSubtable()</code></a>
+<dd> Prints the ZDD table.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddProduct"><code>Cudd_zddProduct()</code></a>
+<dd> Computes the product of two covers represented by ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddReadNodeCount"><code>Cudd_zddReadNodeCount()</code></a>
+<dd> Reports the number of nodes in ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddRealignDisable"><code>Cudd_zddRealignDisable()</code></a>
+<dd> Disables realignment of ZDD order to BDD order.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddRealignEnable"><code>Cudd_zddRealignEnable()</code></a>
+<dd> Enables realignment of ZDD order to BDD order.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddRealignmentEnabled"><code>Cudd_zddRealignmentEnabled()</code></a>
+<dd> Tells whether the realignment of ZDD order to BDD order is enabled.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddReduceHeap"><code>Cudd_zddReduceHeap()</code></a>
+<dd> Main dynamic reordering routine for ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddShuffleHeap"><code>Cudd_zddShuffleHeap()</code></a>
+<dd> Reorders ZDD variables according to given permutation.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddSubset0"><code>Cudd_zddSubset0()</code></a>
+<dd> Computes the negative cofactor of a ZDD w.r.t. a variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddSubset1"><code>Cudd_zddSubset1()</code></a>
+<dd> Computes the positive cofactor of a ZDD w.r.t. a variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddSymmProfile"><code>Cudd_zddSymmProfile()</code></a>
+<dd> Prints statistics on symmetric ZDD variables.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddUnateProduct"><code>Cudd_zddUnateProduct()</code></a>
+<dd> Computes the product of two unate covers.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddUnion"><code>Cudd_zddUnion()</code></a>
+<dd> Computes the union of two ZDDs.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddVarsFromBddVars"><code>Cudd_zddVarsFromBddVars()</code></a>
+<dd> Creates one or more ZDD variables for each BDD variable.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddWeakDivF"><code>Cudd_zddWeakDivF()</code></a>
+<dd> Modified version of Cudd_zddWeakDiv.
+
+<dt> <a href="cuddAllDet.html#Cudd_zddWeakDiv"><code>Cudd_zddWeakDiv()</code></a>
+<dd> Applies weak division to two covers.
+
+<dt> <a href="cuddAllDet.html#DD_LSDIGIT"><code>DD_LSDIGIT()</code></a>
+<dd> Extract the least significant digit of a double digit.
+
+<dt> <a href="cuddAllDet.html#DD_MINUS_INFINITY"><code>DD_MINUS_INFINITY()</code></a>
+<dd> Returns the minus infinity constant node.
+
+<dt> <a href="cuddAllDet.html#DD_MSDIGIT"><code>DD_MSDIGIT()</code></a>
+<dd> Extract the most significant digit of a double digit.
+
+<dt> <a href="cuddAllDet.html#DD_ONE"><code>DD_ONE()</code></a>
+<dd> Returns the constant 1 node.
+
+<dt> <a href="cuddAllDet.html#DD_PLUS_INFINITY"><code>DD_PLUS_INFINITY()</code></a>
+<dd> Returns the plus infinity constant node.
+
+<dt> <a href="cuddAllDet.html#DD_ZERO"><code>DD_ZERO()</code></a>
+<dd> Returns the arithmetic 0 constant node.
+
+<dt> <a href="cuddAllDet.html#cuddAddApplyRecur"><code>cuddAddApplyRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addApply.
+
+<dt> <a href="cuddAllDet.html#cuddAddBddDoPattern"><code>cuddAddBddDoPattern()</code></a>
+<dd> Performs the recursive step for Cudd_addBddPattern.
+
+<dt> <a href="cuddAllDet.html#cuddAddCmplRecur"><code>cuddAddCmplRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addCmpl.
+
+<dt> <a href="cuddAllDet.html#cuddAddComposeRecur"><code>cuddAddComposeRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addCompose.
+
+<dt> <a href="cuddAllDet.html#cuddAddConstrainRecur"><code>cuddAddConstrainRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addConstrain.
+
+<dt> <a href="cuddAllDet.html#cuddAddExistAbstractRecur"><code>cuddAddExistAbstractRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addExistAbstract.
+
+<dt> <a href="cuddAllDet.html#cuddAddIteRecur"><code>cuddAddIteRecur()</code></a>
+<dd> Implements the recursive step of Cudd_addIte(f,g,h).
+
+<dt> <a href="cuddAllDet.html#cuddAddMonadicApplyRecur"><code>cuddAddMonadicApplyRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addMonadicApply.
+
+<dt> <a href="cuddAllDet.html#cuddAddNegateRecur"><code>cuddAddNegateRecur()</code></a>
+<dd> Implements the recursive step of Cudd_addNegate.
+
+<dt> <a href="cuddAllDet.html#cuddAddOrAbstractRecur"><code>cuddAddOrAbstractRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addOrAbstract.
+
+<dt> <a href="cuddAllDet.html#cuddAddRestrictRecur"><code>cuddAddRestrictRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addRestrict.
+
+<dt> <a href="cuddAllDet.html#cuddAddRoundOffRecur"><code>cuddAddRoundOffRecur()</code></a>
+<dd> Implements the recursive step of Cudd_addRoundOff.
+
+<dt> <a href="cuddAllDet.html#cuddAddScalarInverseRecur"><code>cuddAddScalarInverseRecur()</code></a>
+<dd> Performs the recursive step of addScalarInverse.
+
+<dt> <a href="cuddAllDet.html#cuddAddUnivAbstractRecur"><code>cuddAddUnivAbstractRecur()</code></a>
+<dd> Performs the recursive step of Cudd_addUnivAbstract.
+
+<dt> <a href="cuddAllDet.html#cuddAdjust"><code>cuddAdjust()</code></a>
+<dd> Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.
+
+<dt> <a href="cuddAllDet.html#cuddAllocNode"><code>cuddAllocNode()</code></a>
+<dd> Fast storage allocation for DdNodes in the table.
+
+<dt> <a href="cuddAllDet.html#cuddAnnealing"><code>cuddAnnealing()</code></a>
+<dd> Get new variable-order by simulated annealing algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddBddAlignToZdd"><code>cuddBddAlignToZdd()</code></a>
+<dd> Reorders BDD variables according to the order of the ZDD variables.
+
+<dt> <a href="cuddAllDet.html#cuddBddAndAbstractRecur"><code>cuddBddAndAbstractRecur()</code></a>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddAllDet.html#cuddBddAndRecur"><code>cuddBddAndRecur()</code></a>
+<dd> Implements the recursive step of Cudd_bddAnd.
+
+<dt> <a href="cuddAllDet.html#cuddBddBooleanDiffRecur"><code>cuddBddBooleanDiffRecur()</code></a>
+<dd> Performs the recursive steps of Cudd_bddBoleanDiff.
+
+<dt> <a href="cuddAllDet.html#cuddBddClippingAndAbstract"><code>cuddBddClippingAndAbstract()</code></a>
+<dd> Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddAllDet.html#cuddBddClippingAnd"><code>cuddBddClippingAnd()</code></a>
+<dd> Approximates the conjunction of two BDDs f and g.
+
+<dt> <a href="cuddAllDet.html#cuddBddClosestCube"><code>cuddBddClosestCube()</code></a>
+<dd> Performs the recursive step of Cudd_bddClosestCube.
+
+<dt> <a href="cuddAllDet.html#cuddBddComposeRecur"><code>cuddBddComposeRecur()</code></a>
+<dd> Performs the recursive step of Cudd_bddCompose.
+
+<dt> <a href="cuddAllDet.html#cuddBddConstrainRecur"><code>cuddBddConstrainRecur()</code></a>
+<dd> Performs the recursive step of Cudd_bddConstrain.
+
+<dt> <a href="cuddAllDet.html#cuddBddExistAbstractRecur"><code>cuddBddExistAbstractRecur()</code></a>
+<dd> Performs the recursive steps of Cudd_bddExistAbstract.
+
+<dt> <a href="cuddAllDet.html#cuddBddIntersectRecur"><code>cuddBddIntersectRecur()</code></a>
+<dd> Implements the recursive step of Cudd_bddIntersect.
+
+<dt> <a href="cuddAllDet.html#cuddBddIsop"><code>cuddBddIsop()</code></a>
+<dd> Performs the recursive step of Cudd_bddIsop.
+
+<dt> <a href="cuddAllDet.html#cuddBddIteRecur"><code>cuddBddIteRecur()</code></a>
+<dd> Implements the recursive step of Cudd_bddIte.
+
+<dt> <a href="cuddAllDet.html#cuddBddLICompaction"><code>cuddBddLICompaction()</code></a>
+<dd> Performs safe minimization of a BDD.
+
+<dt> <a href="cuddAllDet.html#cuddBddLiteralSetIntersectionRecur"><code>cuddBddLiteralSetIntersectionRecur()</code></a>
+<dd> Performs the recursive step of Cudd_bddLiteralSetIntersection.
+
+<dt> <a href="cuddAllDet.html#cuddBddMakePrime"><code>cuddBddMakePrime()</code></a>
+<dd> Performs the recursive step of Cudd_bddMakePrime.
+
+<dt> <a href="cuddAllDet.html#cuddBddNPAndRecur"><code>cuddBddNPAndRecur()</code></a>
+<dd> Implements the recursive step of Cudd_bddAnd.
+
+<dt> <a href="cuddAllDet.html#cuddBddRestrictRecur"><code>cuddBddRestrictRecur()</code></a>
+<dd> Performs the recursive step of Cudd_bddRestrict.
+
+<dt> <a href="cuddAllDet.html#cuddBddTransfer"><code>cuddBddTransfer()</code></a>
+<dd> Convert a BDD from a manager to another one.
+
+<dt> <a href="cuddAllDet.html#cuddBddXorExistAbstractRecur"><code>cuddBddXorExistAbstractRecur()</code></a>
+<dd> Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddAllDet.html#cuddBddXorRecur"><code>cuddBddXorRecur()</code></a>
+<dd> Implements the recursive step of Cudd_bddXor.
+
+<dt> <a href="cuddAllDet.html#cuddBiasedUnderApprox"><code>cuddBiasedUnderApprox()</code></a>
+<dd> Applies the biased remapping underappoximation algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddCProjectionRecur"><code>cuddCProjectionRecur()</code></a>
+<dd> Performs the recursive step of Cudd_CProjection.
+
+<dt> <a href="cuddAllDet.html#cuddCacheFlush"><code>cuddCacheFlush()</code></a>
+<dd> Flushes the cache.
+
+<dt> <a href="cuddAllDet.html#cuddCacheInsert1"><code>cuddCacheInsert1()</code></a>
+<dd> Inserts a result in the cache for a function with two operands.
+
+<dt> <a href="cuddAllDet.html#cuddCacheInsert2"><code>cuddCacheInsert2()</code></a>
+<dd> Inserts a result in the cache for a function with two operands.
+
+<dt> <a href="cuddAllDet.html#cuddCacheInsert"><code>cuddCacheInsert()</code></a>
+<dd> Inserts a result in the cache.
+
+<dt> <a href="cuddAllDet.html#cuddCacheLookup1Zdd"><code>cuddCacheLookup1Zdd()</code></a>
+<dd> Looks up in the cache for the result of op applied to f.
+
+<dt> <a href="cuddAllDet.html#cuddCacheLookup1"><code>cuddCacheLookup1()</code></a>
+<dd> Looks up in the cache for the result of op applied to f.
+
+<dt> <a href="cuddAllDet.html#cuddCacheLookup2Zdd"><code>cuddCacheLookup2Zdd()</code></a>
+<dd> Looks up in the cache for the result of op applied to f and g.
+
+<dt> <a href="cuddAllDet.html#cuddCacheLookup2"><code>cuddCacheLookup2()</code></a>
+<dd> Looks up in the cache for the result of op applied to f and g.
+
+<dt> <a href="cuddAllDet.html#cuddCacheLookupZdd"><code>cuddCacheLookupZdd()</code></a>
+<dd> Looks up in the cache for the result of op applied to f, g, and h.
+
+<dt> <a href="cuddAllDet.html#cuddCacheLookup"><code>cuddCacheLookup()</code></a>
+<dd> Looks up in the cache for the result of op applied to f, g, and h.
+
+<dt> <a href="cuddAllDet.html#cuddCacheProfile"><code>cuddCacheProfile()</code></a>
+<dd> Computes and prints a profile of the cache usage.
+
+<dt> <a href="cuddAllDet.html#cuddCacheResize"><code>cuddCacheResize()</code></a>
+<dd> Resizes the cache.
+
+<dt> <a href="cuddAllDet.html#cuddCheckCube"><code>cuddCheckCube()</code></a>
+<dd> Checks whether g is the BDD of a cube.
+
+<dt> <a href="cuddAllDet.html#cuddClean"><code>cuddClean()</code></a>
+<dd> Clears the 4 least significant bits of a pointer.
+
+<dt> <a href="cuddAllDet.html#cuddClearDeathRow"><code>cuddClearDeathRow()</code></a>
+<dd> Clears the death row.
+
+<dt> <a href="cuddAllDet.html#cuddCofactorRecur"><code>cuddCofactorRecur()</code></a>
+<dd> Performs the recursive step of Cudd_Cofactor.
+
+<dt> <a href="cuddAllDet.html#cuddCollectNodes"><code>cuddCollectNodes()</code></a>
+<dd> Recursively collects all the nodes of a DD in a symbol table.
+
+<dt> <a href="cuddAllDet.html#cuddComputeFloorLog2"><code>cuddComputeFloorLog2()</code></a>
+<dd> Returns the floor of the logarithm to the base 2.
+
+<dt> <a href="cuddAllDet.html#cuddConstantLookup"><code>cuddConstantLookup()</code></a>
+<dd> Looks up in the cache for the result of op applied to f, g, and h.
+
+<dt> <a href="cuddAllDet.html#cuddDeallocMove"><code>cuddDeallocMove()</code></a>
+<dd> Adds node to the head of the free list.
+
+<dt> <a href="cuddAllDet.html#cuddDeallocNode"><code>cuddDeallocNode()</code></a>
+<dd> Adds node to the head of the free list.
+
+<dt> <a href="cuddAllDet.html#cuddDeref"><code>cuddDeref()</code></a>
+<dd> Decreases the reference count of a node, if it is not saturated.
+
+<dt> <a href="cuddAllDet.html#cuddDestroySubtables"><code>cuddDestroySubtables()</code></a>
+<dd> Destroys the n most recently created subtables in a unique table.
+
+<dt> <a href="cuddAllDet.html#cuddDynamicAllocNode"><code>cuddDynamicAllocNode()</code></a>
+<dd> Dynamically allocates a Node.
+
+<dt> <a href="cuddAllDet.html#cuddExact"><code>cuddExact()</code></a>
+<dd> Exact variable ordering algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddE"><code>cuddE()</code></a>
+<dd> Returns the else child of an internal node.
+
+<dt> <a href="cuddAllDet.html#cuddFreeTable"><code>cuddFreeTable()</code></a>
+<dd> Frees the resources associated to a unique table.
+
+<dt> <a href="cuddAllDet.html#cuddGarbageCollect"><code>cuddGarbageCollect()</code></a>
+<dd> Performs garbage collection on the unique tables.
+
+<dt> <a href="cuddAllDet.html#cuddGa"><code>cuddGa()</code></a>
+<dd> Genetic algorithm for DD reordering.
+
+<dt> <a href="cuddAllDet.html#cuddGetBranches"><code>cuddGetBranches()</code></a>
+<dd> Computes the children of g.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableInit"><code>cuddHashTableInit()</code></a>
+<dd> Initializes a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableInsert1"><code>cuddHashTableInsert1()</code></a>
+<dd> Inserts an item in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableInsert2"><code>cuddHashTableInsert2()</code></a>
+<dd> Inserts an item in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableInsert3"><code>cuddHashTableInsert3()</code></a>
+<dd> Inserts an item in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableInsert"><code>cuddHashTableInsert()</code></a>
+<dd> Inserts an item in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableLookup1"><code>cuddHashTableLookup1()</code></a>
+<dd> Looks up a key consisting of one pointer in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableLookup2"><code>cuddHashTableLookup2()</code></a>
+<dd> Looks up a key consisting of two pointers in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableLookup3"><code>cuddHashTableLookup3()</code></a>
+<dd> Looks up a key consisting of three pointers in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableLookup"><code>cuddHashTableLookup()</code></a>
+<dd> Looks up a key in a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHashTableQuit"><code>cuddHashTableQuit()</code></a>
+<dd> Shuts down a hash table.
+
+<dt> <a href="cuddAllDet.html#cuddHeapProfile"><code>cuddHeapProfile()</code></a>
+<dd> Prints information about the heap.
+
+<dt> <a href="cuddAllDet.html#cuddIZ"><code>cuddIZ()</code></a>
+<dd> Finds the current position of ZDD variable index in the order.
+
+<dt> <a href="cuddAllDet.html#cuddInitCache"><code>cuddInitCache()</code></a>
+<dd> Initializes the computed table.
+
+<dt> <a href="cuddAllDet.html#cuddInitInteract"><code>cuddInitInteract()</code></a>
+<dd> Initializes the interaction matrix.
+
+<dt> <a href="cuddAllDet.html#cuddInitLinear"><code>cuddInitLinear()</code></a>
+<dd> Initializes the linear transform matrix.
+
+<dt> <a href="cuddAllDet.html#cuddInitTable"><code>cuddInitTable()</code></a>
+<dd> Creates and initializes the unique table.
+
+<dt> <a href="cuddAllDet.html#cuddInsertSubtables"><code>cuddInsertSubtables()</code></a>
+<dd> Inserts n new subtables in a unique table at level.
+
+<dt> <a href="cuddAllDet.html#cuddIsConstant"><code>cuddIsConstant()</code></a>
+<dd> Returns 1 if the node is a constant node.
+
+<dt> <a href="cuddAllDet.html#cuddIsInDeathRow"><code>cuddIsInDeathRow()</code></a>
+<dd> Checks whether a node is in the death row.
+
+<dt> <a href="cuddAllDet.html#cuddI"><code>cuddI()</code></a>
+<dd> Finds the current position of variable index in the order.
+
+<dt> <a href="cuddAllDet.html#cuddLevelQueueDequeue"><code>cuddLevelQueueDequeue()</code></a>
+<dd> Remove an item from the front of a level queue.
+
+<dt> <a href="cuddAllDet.html#cuddLevelQueueEnqueue"><code>cuddLevelQueueEnqueue()</code></a>
+<dd> Inserts a new key in a level queue.
+
+<dt> <a href="cuddAllDet.html#cuddLevelQueueInit"><code>cuddLevelQueueInit()</code></a>
+<dd> Initializes a level queue.
+
+<dt> <a href="cuddAllDet.html#cuddLevelQueueQuit"><code>cuddLevelQueueQuit()</code></a>
+<dd> Shuts down a level queue.
+
+<dt> <a href="cuddAllDet.html#cuddLinearAndSifting"><code>cuddLinearAndSifting()</code></a>
+<dd> BDD reduction based on combination of sifting and linear transformations.
+
+<dt> <a href="cuddAllDet.html#cuddLinearInPlace"><code>cuddLinearInPlace()</code></a>
+<dd> Linearly combines two adjacent variables.
+
+<dt> <a href="cuddAllDet.html#cuddLocalCacheClearAll"><code>cuddLocalCacheClearAll()</code></a>
+<dd> Clears the local caches of a manager.
+
+<dt> <a href="cuddAllDet.html#cuddLocalCacheClearDead"><code>cuddLocalCacheClearDead()</code></a>
+<dd> Clears the dead entries of the local caches of a manager.
+
+<dt> <a href="cuddAllDet.html#cuddLocalCacheInit"><code>cuddLocalCacheInit()</code></a>
+<dd> Initializes a local computed table.
+
+<dt> <a href="cuddAllDet.html#cuddLocalCacheInsert"><code>cuddLocalCacheInsert()</code></a>
+<dd> Inserts a result in a local cache.
+
+<dt> <a href="cuddAllDet.html#cuddLocalCacheLookup"><code>cuddLocalCacheLookup()</code></a>
+<dd> Looks up in a local cache.
+
+<dt> <a href="cuddAllDet.html#cuddLocalCacheProfile"><code>cuddLocalCacheProfile()</code></a>
+<dd> Computes and prints a profile of a local cache usage.
+
+<dt> <a href="cuddAllDet.html#cuddLocalCacheQuit"><code>cuddLocalCacheQuit()</code></a>
+<dd> Shuts down a local computed table.
+
+<dt> <a href="cuddAllDet.html#cuddMakeBddFromZddCover"><code>cuddMakeBddFromZddCover()</code></a>
+<dd> Converts a ZDD cover to a BDD graph.
+
+<dt> <a href="cuddAllDet.html#cuddNextHigh"><code>cuddNextHigh()</code></a>
+<dd> Finds the next subtable with a larger index.
+
+<dt> <a href="cuddAllDet.html#cuddNextLow"><code>cuddNextLow()</code></a>
+<dd> Finds the next subtable with a smaller index.
+
+<dt> <a href="cuddAllDet.html#cuddNodeArray"><code>cuddNodeArray()</code></a>
+<dd> Recursively collects all the nodes of a DD in an array.
+
+<dt> <a href="cuddAllDet.html#cuddPrintNode"><code>cuddPrintNode()</code></a>
+<dd> Prints out information on a node.
+
+<dt> <a href="cuddAllDet.html#cuddPrintVarGroups"><code>cuddPrintVarGroups()</code></a>
+<dd> Prints the variable groups as a parenthesized list.
+
+<dt> <a href="cuddAllDet.html#cuddP"><code>cuddP()</code></a>
+<dd> Prints a DD to the standard output. One line per node is printed.
+
+<dt> <a href="cuddAllDet.html#cuddReclaimZdd"><code>cuddReclaimZdd()</code></a>
+<dd> Brings children of a dead ZDD node back.
+
+<dt> <a href="cuddAllDet.html#cuddReclaim"><code>cuddReclaim()</code></a>
+<dd> Brings children of a dead node back.
+
+<dt> <a href="cuddAllDet.html#cuddRef"><code>cuddRef()</code></a>
+<dd> Increases the reference count of a node, if it is not saturated.
+
+<dt> <a href="cuddAllDet.html#cuddRehash"><code>cuddRehash()</code></a>
+<dd> Rehashes a unique subtable.
+
+<dt> <a href="cuddAllDet.html#cuddRemapUnderApprox"><code>cuddRemapUnderApprox()</code></a>
+<dd> Applies the remapping underappoximation algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddResizeLinear"><code>cuddResizeLinear()</code></a>
+<dd> Resizes the linear transform matrix.
+
+<dt> <a href="cuddAllDet.html#cuddResizeTableZdd"><code>cuddResizeTableZdd()</code></a>
+<dd> Increases the number of ZDD subtables in a unique table so that it meets or exceeds index.
+
+<dt> <a href="cuddAllDet.html#cuddSatDec"><code>cuddSatDec()</code></a>
+<dd> Saturating decrement operator.
+
+<dt> <a href="cuddAllDet.html#cuddSatInc"><code>cuddSatInc()</code></a>
+<dd> Saturating increment operator.
+
+<dt> <a href="cuddAllDet.html#cuddSetInteract"><code>cuddSetInteract()</code></a>
+<dd> Set interaction matrix entries.
+
+<dt> <a href="cuddAllDet.html#cuddShrinkDeathRow"><code>cuddShrinkDeathRow()</code></a>
+<dd> Shrinks the death row.
+
+<dt> <a href="cuddAllDet.html#cuddShrinkSubtable"><code>cuddShrinkSubtable()</code></a>
+<dd> Shrinks a subtable.
+
+<dt> <a href="cuddAllDet.html#cuddSifting"><code>cuddSifting()</code></a>
+<dd> Implementation of Rudell's sifting algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddSlowTableGrowth"><code>cuddSlowTableGrowth()</code></a>
+<dd> Adjusts parameters of a table to slow down its growth.
+
+<dt> <a href="cuddAllDet.html#cuddSolveEqnRecur"><code>cuddSolveEqnRecur()</code></a>
+<dd> Implements the recursive step of Cudd_SolveEqn.
+
+<dt> <a href="cuddAllDet.html#cuddSplitSetRecur"><code>cuddSplitSetRecur()</code></a>
+<dd> Implements the recursive step of Cudd_SplitSet.
+
+<dt> <a href="cuddAllDet.html#cuddStCountfree"><code>cuddStCountfree()</code></a>
+<dd> Frees the memory used to store the minterm counts recorded in the visited table.
+
+<dt> <a href="cuddAllDet.html#cuddSubsetHeavyBranch"><code>cuddSubsetHeavyBranch()</code></a>
+<dd> The main procedure that returns a subset by choosing the heavier branch in the BDD.
+
+<dt> <a href="cuddAllDet.html#cuddSubsetShortPaths"><code>cuddSubsetShortPaths()</code></a>
+<dd> The outermost procedure to return a subset of the given BDD with the shortest path lengths.
+
+<dt> <a href="cuddAllDet.html#cuddSwapInPlace"><code>cuddSwapInPlace()</code></a>
+<dd> Swaps two adjacent variables.
+
+<dt> <a href="cuddAllDet.html#cuddSwapping"><code>cuddSwapping()</code></a>
+<dd> Reorders variables by a sequence of (non-adjacent) swaps.
+
+<dt> <a href="cuddAllDet.html#cuddSymmCheck"><code>cuddSymmCheck()</code></a>
+<dd> Checks for symmetry of x and y.
+
+<dt> <a href="cuddAllDet.html#cuddSymmSiftingConv"><code>cuddSymmSiftingConv()</code></a>
+<dd> Symmetric sifting to convergence algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddSymmSifting"><code>cuddSymmSifting()</code></a>
+<dd> Symmetric sifting algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddTestInteract"><code>cuddTestInteract()</code></a>
+<dd> Test interaction matrix entries.
+
+<dt> <a href="cuddAllDet.html#cuddTimesInDeathRow"><code>cuddTimesInDeathRow()</code></a>
+<dd> Counts how many times a node is in the death row.
+
+<dt> <a href="cuddAllDet.html#cuddTreeSifting"><code>cuddTreeSifting()</code></a>
+<dd> Tree sifting algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddT"><code>cuddT()</code></a>
+<dd> Returns the then child of an internal node.
+
+<dt> <a href="cuddAllDet.html#cuddUnderApprox"><code>cuddUnderApprox()</code></a>
+<dd> Applies Tom Shiple's underappoximation algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddUniqueConst"><code>cuddUniqueConst()</code></a>
+<dd> Checks the unique table for the existence of a constant node.
+
+<dt> <a href="cuddAllDet.html#cuddUniqueInterIVO"><code>cuddUniqueInterIVO()</code></a>
+<dd> Wrapper for cuddUniqueInter that is independent of variable ordering.
+
+<dt> <a href="cuddAllDet.html#cuddUniqueInterZdd"><code>cuddUniqueInterZdd()</code></a>
+<dd> Checks the unique table for the existence of an internal ZDD node.
+
+<dt> <a href="cuddAllDet.html#cuddUniqueInter"><code>cuddUniqueInter()</code></a>
+<dd> Checks the unique table for the existence of an internal node.
+
+<dt> <a href="cuddAllDet.html#cuddUpdateInteractionMatrix"><code>cuddUpdateInteractionMatrix()</code></a>
+<dd> Updates the interaction matrix.
+
+<dt> <a href="cuddAllDet.html#cuddVerifySol"><code>cuddVerifySol()</code></a>
+<dd> Implements the recursive step of Cudd_VerifySol.
+
+<dt> <a href="cuddAllDet.html#cuddV"><code>cuddV()</code></a>
+<dd> Returns the value of a constant node.
+
+<dt> <a href="cuddAllDet.html#cuddWindowReorder"><code>cuddWindowReorder()</code></a>
+<dd> Reorders by applying the method of the sliding window.
+
+<dt> <a href="cuddAllDet.html#cuddZddAlignToBdd"><code>cuddZddAlignToBdd()</code></a>
+<dd> Reorders ZDD variables according to the order of the BDD variables.
+
+<dt> <a href="cuddAllDet.html#cuddZddChangeAux"><code>cuddZddChangeAux()</code></a>
+<dd> Performs the recursive step of Cudd_zddChange.
+
+<dt> <a href="cuddAllDet.html#cuddZddChange"><code>cuddZddChange()</code></a>
+<dd> Substitutes a variable with its complement in a ZDD.
+
+<dt> <a href="cuddAllDet.html#cuddZddComplement"><code>cuddZddComplement()</code></a>
+<dd> Computes a complement of a ZDD node.
+
+<dt> <a href="cuddAllDet.html#cuddZddDiff"><code>cuddZddDiff()</code></a>
+<dd> Performs the recursive step of Cudd_zddDiff.
+
+<dt> <a href="cuddAllDet.html#cuddZddDivideF"><code>cuddZddDivideF()</code></a>
+<dd> Performs the recursive step of Cudd_zddDivideF.
+
+<dt> <a href="cuddAllDet.html#cuddZddDivide"><code>cuddZddDivide()</code></a>
+<dd> Performs the recursive step of Cudd_zddDivide.
+
+<dt> <a href="cuddAllDet.html#cuddZddFreeUniv"><code>cuddZddFreeUniv()</code></a>
+<dd> Frees the ZDD universe.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetCofactors2"><code>cuddZddGetCofactors2()</code></a>
+<dd> Computes the two-way decomposition of f w.r.t. v.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetCofactors3"><code>cuddZddGetCofactors3()</code></a>
+<dd> Computes the three-way decomposition of f w.r.t. v.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetNegVarIndex"><code>cuddZddGetNegVarIndex()</code></a>
+<dd> Returns the index of negative ZDD variable.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetNegVarLevel"><code>cuddZddGetNegVarLevel()</code></a>
+<dd> Returns the level of negative ZDD variable.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetNodeIVO"><code>cuddZddGetNodeIVO()</code></a>
+<dd> Wrapper for cuddUniqueInterZdd that is independent of variable ordering.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetNode"><code>cuddZddGetNode()</code></a>
+<dd> Wrapper for cuddUniqueInterZdd.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetPosVarIndex"><code>cuddZddGetPosVarIndex()</code></a>
+<dd> Returns the index of positive ZDD variable.
+
+<dt> <a href="cuddAllDet.html#cuddZddGetPosVarLevel"><code>cuddZddGetPosVarLevel()</code></a>
+<dd> Returns the level of positive ZDD variable.
+
+<dt> <a href="cuddAllDet.html#cuddZddInitUniv"><code>cuddZddInitUniv()</code></a>
+<dd> Initializes the ZDD universe.
+
+<dt> <a href="cuddAllDet.html#cuddZddIntersect"><code>cuddZddIntersect()</code></a>
+<dd> Performs the recursive step of Cudd_zddIntersect.
+
+<dt> <a href="cuddAllDet.html#cuddZddIsop"><code>cuddZddIsop()</code></a>
+<dd> Performs the recursive step of Cudd_zddIsop.
+
+<dt> <a href="cuddAllDet.html#cuddZddIte"><code>cuddZddIte()</code></a>
+<dd> Performs the recursive step of Cudd_zddIte.
+
+<dt> <a href="cuddAllDet.html#cuddZddLinearSifting"><code>cuddZddLinearSifting()</code></a>
+<dd> Implementation of the linear sifting algorithm for ZDDs.
+
+<dt> <a href="cuddAllDet.html#cuddZddNextHigh"><code>cuddZddNextHigh()</code></a>
+<dd> Finds the next subtable with a larger index.
+
+<dt> <a href="cuddAllDet.html#cuddZddNextLow"><code>cuddZddNextLow()</code></a>
+<dd> Finds the next subtable with a smaller index.
+
+<dt> <a href="cuddAllDet.html#cuddZddProduct"><code>cuddZddProduct()</code></a>
+<dd> Performs the recursive step of Cudd_zddProduct.
+
+<dt> <a href="cuddAllDet.html#cuddZddP"><code>cuddZddP()</code></a>
+<dd> Prints a ZDD to the standard output. One line per node is printed.
+
+<dt> <a href="cuddAllDet.html#cuddZddSifting"><code>cuddZddSifting()</code></a>
+<dd> Implementation of Rudell's sifting algorithm.
+
+<dt> <a href="cuddAllDet.html#cuddZddSubset0"><code>cuddZddSubset0()</code></a>
+<dd> Computes the negative cofactor of a ZDD w.r.t. a variable.
+
+<dt> <a href="cuddAllDet.html#cuddZddSubset1"><code>cuddZddSubset1()</code></a>
+<dd> Computes the positive cofactor of a ZDD w.r.t. a variable.
+
+<dt> <a href="cuddAllDet.html#cuddZddSwapInPlace"><code>cuddZddSwapInPlace()</code></a>
+<dd> Swaps two adjacent variables.
+
+<dt> <a href="cuddAllDet.html#cuddZddSwapping"><code>cuddZddSwapping()</code></a>
+<dd> Reorders variables by a sequence of (non-adjacent) swaps.
+
+<dt> <a href="cuddAllDet.html#cuddZddSymmCheck"><code>cuddZddSymmCheck()</code></a>
+<dd> Checks for symmetry of x and y.
+
+<dt> <a href="cuddAllDet.html#cuddZddSymmSiftingConv"><code>cuddZddSymmSiftingConv()</code></a>
+<dd> Symmetric sifting to convergence algorithm for ZDDs.
+
+<dt> <a href="cuddAllDet.html#cuddZddSymmSifting"><code>cuddZddSymmSifting()</code></a>
+<dd> Symmetric sifting algorithm for ZDDs.
+
+<dt> <a href="cuddAllDet.html#cuddZddTreeSifting"><code>cuddZddTreeSifting()</code></a>
+<dd> Tree sifting algorithm for ZDDs.
+
+<dt> <a href="cuddAllDet.html#cuddZddUnateProduct"><code>cuddZddUnateProduct()</code></a>
+<dd> Performs the recursive step of Cudd_zddUnateProduct.
+
+<dt> <a href="cuddAllDet.html#cuddZddUnion"><code>cuddZddUnion()</code></a>
+<dd> Performs the recursive step of Cudd_zddUnion.
+
+<dt> <a href="cuddAllDet.html#cuddZddUniqueCompare"><code>cuddZddUniqueCompare()</code></a>
+<dd> Comparison function used by qsort.
+
+<dt> <a href="cuddAllDet.html#cuddZddWeakDivF"><code>cuddZddWeakDivF()</code></a>
+<dd> Performs the recursive step of Cudd_zddWeakDivF.
+
+<dt> <a href="cuddAllDet.html#cuddZddWeakDiv"><code>cuddZddWeakDiv()</code></a>
+<dd> Performs the recursive step of Cudd_zddWeakDiv.
+
+<dt> <a href="cuddAllDet.html#ddAbs"><code>ddAbs()</code></a>
+<dd> Computes the absolute value of a number.
+
+<dt> <a href="cuddAllDet.html#ddCHash2"><code>ddCHash2()</code></a>
+<dd> Hash function for the cache for functions with two operands.
+
+<dt> <a href="cuddAllDet.html#ddCHash"><code>ddCHash()</code></a>
+<dd> Hash function for the cache.
+
+<dt> <a href="cuddAllDet.html#ddEqualVal"><code>ddEqualVal()</code></a>
+<dd> Returns 1 if the absolute value of the difference of the two arguments x and y is less than e.
+
+<dt> <a href="cuddAllDet.html#ddHash"><code>ddHash()</code></a>
+<dd> Hash function for the unique table.
+
+<dt> <a href="cuddAllDet.html#ddLCHash2"><code>ddLCHash2()</code></a>
+<dd> Computes hash function for keys of two operands.
+
+<dt> <a href="cuddAllDet.html#ddLCHash3"><code>ddLCHash3()</code></a>
+<dd> Computes hash function for keys of three operands.
+
+<dt> <a href="cuddAllDet.html#ddMax"><code>ddMax()</code></a>
+<dd> Computes the maximum of two numbers.
+
+<dt> <a href="cuddAllDet.html#ddMin"><code>ddMin()</code></a>
+<dd> Computes the minimum of two numbers.
+
+<dt> <a href="cuddAllDet.html#lqHash"><code>lqHash()</code></a>
+<dd> Hash function for the table of a level queue.
+
+<dt> <a href="cuddAllDet.html#statLine"><code>statLine()</code></a>
+<dd> Outputs a line of stats.
+
+</dl>
+
+<hr>
+
+Generated automatically by <code>extdoc</code> on 20050517
+
+</body></html>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/cuddAllDet.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/cuddAllDet.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/cuddAllDet.html	(revision 8)
@@ -0,0 +1,10696 @@
+<html>
+<head><title>The cudd package (Internal) </title></head>
+<body>
+
+<h1>The cudd package (Internal) </h1>
+<h2>Internal data structures of the CUDD package.</h2>
+<h3></h3>
+<hr>
+<ul>
+<li><a href="cuddExtAbs.html"><h3>External abstracts</h3></a>
+<li><a href="cuddAllAbs.html"><h3>All abstracts</h3></a>
+<li><a href="cuddExtDet.html#prototypes"><h3>External functions</h3></a>
+<li><a href="cuddAllDet.html#prototypes"><h3>All functions</h3></a>
+</ul>
+
+<hr>
+
+<a name="description">
+
+</a>
+
+<hr>
+<!-- Function Prototypes and description -->
+
+<dl>
+<a name="prototypes"></a>
+<dt><pre>
+int <i></i>
+<a name="Cudd_AddHook"><b>Cudd_AddHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_HFP  <b>f</b>, <i></i>
+  Cudd_HookType  <b>where</b> <i></i>
+)
+</pre>
+<dd> Adds a function to a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if the function is successfully added; 2 if the function was already in the list; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RemoveHook">Cudd_RemoveHook</a>
+</code>
+
+<dt><pre>
+DdApaDigit <i></i>
+<a name="Cudd_ApaAdd"><b>Cudd_ApaAdd</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>a</b>, <i></i>
+  DdApaNumber  <b>b</b>, <i></i>
+  DdApaNumber  <b>sum</b> <i></i>
+)
+</pre>
+<dd> Adds two arbitrary precision integers. Returns the carry out of the most significant digit.
+<p>
+
+<dd> <b>Side Effects</b> The result of the sum is stored in parameter <code>sum</code>.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaCompareRatios"><b>Cudd_ApaCompareRatios</b></a>(
+  int  <b>digitsFirst</b>, <i></i>
+  DdApaNumber  <b>firstNum</b>, <i></i>
+  unsigned int  <b>firstDen</b>, <i></i>
+  int  <b>digitsSecond</b>, <i></i>
+  DdApaNumber  <b>secondNum</b>, <i></i>
+  unsigned int  <b>secondDen</b> <i></i>
+)
+</pre>
+<dd> Compares the ratios of two arbitrary precision integers to two unsigned ints. Returns 1 if the first number is larger; 0 if they are equal; -1 if the second number is larger.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaCompare"><b>Cudd_ApaCompare</b></a>(
+  int  <b>digitsFirst</b>, <i></i>
+  DdApaNumber  <b>first</b>, <i></i>
+  int  <b>digitsSecond</b>, <i></i>
+  DdApaNumber  <b>second</b> <i></i>
+)
+</pre>
+<dd> Compares two arbitrary precision integers. Returns 1 if the first number is larger; 0 if they are equal; -1 if the second number is larger.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaCopy"><b>Cudd_ApaCopy</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>source</b>, <i></i>
+  DdApaNumber  <b>dest</b> <i></i>
+)
+</pre>
+<dd> Makes a copy of an arbitrary precision integer.
+<p>
+
+<dd> <b>Side Effects</b> Changes parameter <code>dest</code>.
+<p>
+
+<dt><pre>
+DdApaNumber <i></i>
+<a name="Cudd_ApaCountMinterm"><b>Cudd_ApaCountMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b>, <i></i>
+  int * <b>digits</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a DD. The function is assumed to depend on nvars variables. The minterm count is represented as an arbitrary precision unsigned integer, to allow for any number of variables CUDD supports. Returns a pointer to the array representing the number of minterms of the function rooted at node if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The number of digits of the result is returned in parameter <code>digits</code>.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ApaIntDivision"><b>Cudd_ApaIntDivision</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>dividend</b>, <i></i>
+  unsigned int  <b>divisor</b>, <i></i>
+  DdApaNumber  <b>quotient</b> <i></i>
+)
+</pre>
+<dd> Divides an arbitrary precision integer by a 32-bit unsigned integer. Returns the remainder of the division. This procedure relies on the assumption that the number of bits of a DdApaDigit plus the number of bits of an unsigned int is less the number of bits of the mantissa of a double. This guarantees that the product of a DdApaDigit and an unsigned int can be represented without loss of precision by a double. On machines where this assumption is not satisfied, this procedure will malfunction.
+<p>
+
+<dd> <b>Side Effects</b> The quotient is returned in parameter <code>quotient</code>.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaShortDivision">Cudd_ApaShortDivision</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaNumberOfDigits"><b>Cudd_ApaNumberOfDigits</b></a>(
+  int  <b>binaryDigits</b> <i></i>
+)
+</pre>
+<dd> Finds the number of digits for an arbitrary precision integer given the maximum number of binary digits. The number of binary digits should be positive. Returns the number of digits if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaPowerOfTwo"><b>Cudd_ApaPowerOfTwo</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b>, <i></i>
+  int  <b>power</b> <i></i>
+)
+</pre>
+<dd> Sets an arbitrary precision integer to a power of two. If the power of two is too large to be represented, the number is set to 0.
+<p>
+
+<dd> <b>Side Effects</b> The result is returned in parameter <code>number</code>.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintDecimal"><b>Cudd_ApaPrintDecimal</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b> <i></i>
+)
+</pre>
+<dd> Prints an arbitrary precision integer in decimal format. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintHex">Cudd_ApaPrintHex</a>
+<a href="cuddAllDet.html#Cudd_ApaPrintExponential">Cudd_ApaPrintExponential</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintDensity"><b>Cudd_ApaPrintDensity</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b> <i></i>
+)
+</pre>
+<dd> Prints the density of a BDD or ADD using arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintExponential"><b>Cudd_ApaPrintExponential</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b>, <i></i>
+  int  <b>precision</b> <i></i>
+)
+</pre>
+<dd> Prints an arbitrary precision integer in exponential format. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintHex">Cudd_ApaPrintHex</a>
+<a href="cuddAllDet.html#Cudd_ApaPrintDecimal">Cudd_ApaPrintDecimal</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintHex"><b>Cudd_ApaPrintHex</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b> <i></i>
+)
+</pre>
+<dd> Prints an arbitrary precision integer in hexadecimal format. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintDecimal">Cudd_ApaPrintDecimal</a>
+<a href="cuddAllDet.html#Cudd_ApaPrintExponential">Cudd_ApaPrintExponential</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintMintermExp"><b>Cudd_ApaPrintMintermExp</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b>, <i></i>
+  int  <b>precision</b> <i></i>
+)
+</pre>
+<dd> Prints the number of minterms of a BDD or ADD in exponential format using arbitrary precision arithmetic. Parameter precision controls the number of signficant digits printed. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintMinterm">Cudd_ApaPrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintMinterm"><b>Cudd_ApaPrintMinterm</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b> <i></i>
+)
+</pre>
+<dd> Prints the number of minterms of a BDD or ADD using arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintMintermExp">Cudd_ApaPrintMintermExp</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaSetToLiteral"><b>Cudd_ApaSetToLiteral</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b>, <i></i>
+  DdApaDigit  <b>literal</b> <i></i>
+)
+</pre>
+<dd> Sets an arbitrary precision integer to a one-digit literal.
+<p>
+
+<dd> <b>Side Effects</b> The result is returned in parameter <code>number</code>.
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaShiftRight"><b>Cudd_ApaShiftRight</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaDigit  <b>in</b>, <i></i>
+  DdApaNumber  <b>a</b>, <i></i>
+  DdApaNumber  <b>b</b> <i></i>
+)
+</pre>
+<dd> Shifts right an arbitrary precision integer by one binary place. The most significant binary digit of the result is taken from parameter <code>in</code>.
+<p>
+
+<dd> <b>Side Effects</b> The result is returned in parameter <code>b</code>.
+<p>
+
+<dt><pre>
+DdApaDigit <i></i>
+<a name="Cudd_ApaShortDivision"><b>Cudd_ApaShortDivision</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>dividend</b>, <i></i>
+  DdApaDigit  <b>divisor</b>, <i></i>
+  DdApaNumber  <b>quotient</b> <i></i>
+)
+</pre>
+<dd> Divides an arbitrary precision integer by a digit.
+<p>
+
+<dd> <b>Side Effects</b> The quotient is returned in parameter <code>quotient</code>.
+<p>
+
+<dt><pre>
+DdApaDigit <i></i>
+<a name="Cudd_ApaSubtract"><b>Cudd_ApaSubtract</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>a</b>, <i></i>
+  DdApaNumber  <b>b</b>, <i></i>
+  DdApaNumber  <b>diff</b> <i></i>
+)
+</pre>
+<dd> Subtracts two arbitrary precision integers. Returns the borrow out of the most significant digit.
+<p>
+
+<dd> <b>Side Effects</b> The result of the subtraction is stored in parameter <code>diff</code>.
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynDisableZdd"><b>Cudd_AutodynDisableZdd</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables automatic dynamic reordering of ZDDs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnableZdd">Cudd_AutodynEnableZdd</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatusZdd">Cudd_ReorderingStatusZdd</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynDisable"><b>Cudd_AutodynDisable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables automatic dynamic reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnable">Cudd_AutodynEnable</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatus">Cudd_ReorderingStatus</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisableZdd">Cudd_AutodynDisableZdd</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynEnableZdd"><b>Cudd_AutodynEnableZdd</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType  <b>method</b> <i></i>
+)
+</pre>
+<dd> Enables automatic dynamic reordering of ZDDs. Parameter method is used to determine the method used for reordering ZDDs. If CUDD_REORDER_SAME is passed, the method is unchanged.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynDisableZdd">Cudd_AutodynDisableZdd</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatusZdd">Cudd_ReorderingStatusZdd</a>
+<a href="cuddAllDet.html#Cudd_AutodynEnable">Cudd_AutodynEnable</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynEnable"><b>Cudd_AutodynEnable</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType  <b>method</b> <i></i>
+)
+</pre>
+<dd> Enables automatic dynamic reordering of BDDs and ADDs. Parameter method is used to determine the method used for reordering. If CUDD_REORDER_SAME is passed, the method is unchanged.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatus">Cudd_ReorderingStatus</a>
+<a href="cuddAllDet.html#Cudd_AutodynEnableZdd">Cudd_AutodynEnableZdd</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_AverageDistance"><b>Cudd_AverageDistance</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Computes the average distance between adjacent nodes in the manager. Adjacent nodes are node pairs such that the second node is the then child, else child, or next node in the collision list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_BddToAdd"><b>Cudd_BddToAdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>B</b> <i></i>
+)
+</pre>
+<dd> Converts a BDD to a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_BddToCubeArray"><b>Cudd_BddToCubeArray</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>cube</b>, <i></i>
+  int * <b>array</b> <i></i>
+)
+</pre>
+<dd> Builds a positional array from the BDD of a cube. Array must have one entry for each BDD variable. The positional array has 1 in i-th position if the variable of index i appears in true form in the cube; it has 0 in i-th position if the variable of index i appears in complemented form in the cube; finally, it has 2 in i-th position if the variable of index i does not appear in the cube. Returns 1 if successful (the BDD is indeed a cube); 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The result is in the array passed by reference.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CubeArrayToBdd">Cudd_CubeArrayToBdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_BiasedOverApprox"><b>Cudd_BiasedOverApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  DdNode * <b>b</b>, <i>bias function</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality1</b>, <i>minimum improvement for accepted changes when b=1</i>
+  double  <b>quality0</b> <i>minimum improvement for accepted changes when b=0</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_RemapOverApprox">Cudd_RemapOverApprox</a>
+<a href="cuddAllDet.html#Cudd_BiasedUnderApprox">Cudd_BiasedUnderApprox</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_BiasedUnderApprox"><b>Cudd_BiasedUnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  DdNode * <b>b</b>, <i>bias function</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality1</b>, <i>minimum improvement for accepted changes when b=1</i>
+  double  <b>quality0</b> <i>minimum improvement for accepted changes when b=0</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure uses a biased remapping technique and density as the cost function. The bias is a function. This procedure tries to approximate where the bias is 0 and preserve the given function where the bias is 1. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_UnderApprox">Cudd_UnderApprox</a>
+<a href="cuddAllDet.html#Cudd_RemapUnderApprox">Cudd_RemapUnderApprox</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_CProjection"><b>Cudd_CProjection</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>R</b>, <i></i>
+  DdNode * <b>Y</b> <i></i>
+)
+</pre>
+<dd> Computes the compatible projection of relation R with respect to cube Y. Returns a pointer to the c-projection if successful; NULL otherwise. For a comparison between Cudd_CProjection and Cudd_PrioritySelect, see the documentation of the latter.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_CheckKeys"><b>Cudd_CheckKeys</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Checks for the following conditions: <ul> <li>Wrong sizes of subtables. <li>Wrong number of keys found in unique subtable. <li>Wrong number of dead found in unique subtable. <li>Wrong number of keys found in the constant table <li>Wrong number of dead found in the constant table <li>Wrong number of total slots found <li>Wrong number of maximum keys found <li>Wrong number of total dead found </ul> Reports the average length of non-empty lists. Returns the number of subtables for which the number of keys is wrong.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DebugCheck">Cudd_DebugCheck</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_CheckZeroRef"><b>Cudd_CheckZeroRef</b></a>(
+  DdManager * <b>manager</b> <i></i>
+)
+</pre>
+<dd> Checks the unique table for nodes with non-zero reference counts. It is normally called before Cudd_Quit to make sure that there are no memory leaks due to missing Cudd_RecursiveDeref's. Takes into account that reference counts may saturate and that the basic constants and the projection functions are referenced by the manager. Returns the number of nodes with non-zero reference count. (Except for the cases mentioned above.)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ClassifySupport"><b>Cudd_ClassifySupport</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first DD</i>
+  DdNode * <b>g</b>, <i>second DD</i>
+  DdNode ** <b>common</b>, <i>cube of shared variables</i>
+  DdNode ** <b>onlyF</b>, <i>cube of variables only in f</i>
+  DdNode ** <b>onlyG</b> <i>cube of variables only in g</i>
+)
+</pre>
+<dd> Classifies the variables in the support of two DDs <code>f</code> and <code>g</code>, depending on whther they appear in both DDs, only in <code>f</code>, or only in <code>g</code>. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The cubes of the three classes of variables are returned as side effects.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+<a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ClearErrorCode"><b>Cudd_ClearErrorCode</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Clear the error code of a manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadErrorCode">Cudd_ReadErrorCode</a>
+</code>
+
+<dt><pre>
+double * <i></i>
+<a name="Cudd_CofMinterm"><b>Cudd_CofMinterm</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Computes the fraction of minterms in the on-set of all the positive cofactors of DD. Returns the pointer to an array of doubles if successful; NULL otherwise. The array has as many positions as there are BDD variables in the manager plus one. The last position of the array contains the fraction of the minterms in the ON-set of the function represented by the BDD or ADD. The other positions of the array hold the variable signatures.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Cofactor"><b>Cudd_Cofactor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the cofactor of f with respect to g; g must be the BDD or the ADD of a cube. Returns a pointer to the cofactor if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_Complement"><b>Cudd_Complement</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the complemented version of a pointer.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Regular">Cudd_Regular</a>
+<a href="cuddAllDet.html#Cudd_IsComplement">Cudd_IsComplement</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_CountLeaves"><b>Cudd_CountLeaves</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of leaves in a DD. Returns the number of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_CountMinterm"><b>Cudd_CountMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a DD. The function is assumed to depend on nvars variables. The minterm count is represented as a double, to allow for a larger number of variables. Returns the number of minterms of the function rooted at node if successful; (double) CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_CountPath">Cudd_CountPath</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_CountPathsToNonZero"><b>Cudd_CountPathsToNonZero</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of paths to a non-zero terminal of a DD. The path count is represented as a double, to allow for a larger number of variables. Returns the number of paths of the function rooted at node.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+<a href="cuddAllDet.html#Cudd_CountPath">Cudd_CountPath</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_CountPath"><b>Cudd_CountPath</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of paths of a DD. Paths to all terminal nodes are counted. The path count is represented as a double, to allow for a larger number of variables. Returns the number of paths of the function rooted at node if successful; (double) CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_CubeArrayToBdd"><b>Cudd_CubeArrayToBdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int * <b>array</b> <i></i>
+)
+</pre>
+<dd> Builds a cube from a positional array. The array must have one integer entry for each BDD variable. If the i-th entry is 1, the variable of index i appears in true form in the cube; If the i-th entry is 0, the variable of index i appears complemented in the cube; otherwise the variable does not appear in the cube. Returns a pointer to the BDD for the cube if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddComputeCube">Cudd_bddComputeCube</a>
+<a href="cuddAllDet.html#Cudd_IndicesToCube">Cudd_IndicesToCube</a>
+<a href="cuddAllDet.html#Cudd_BddToCubeArray">Cudd_BddToCubeArray</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DagSize"><b>Cudd_DagSize</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of nodes in a DD. Returns the number of nodes in the graph rooted at node.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SharingSize">Cudd_SharingSize</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DeadAreCounted"><b>Cudd_DeadAreCounted</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Tells whether dead nodes are counted towards triggering reordering. Returns 1 if dead nodes are counted; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_TurnOnCountDead">Cudd_TurnOnCountDead</a>
+<a href="cuddAllDet.html#Cudd_TurnOffCountDead">Cudd_TurnOffCountDead</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DebugCheck"><b>Cudd_DebugCheck</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Checks for inconsistencies in the DD heap: <ul> <li> node has illegal index <li> live node has dead children <li> node has illegal Then or Else pointers <li> BDD/ADD node has identical children <li> ZDD node has zero then child <li> wrong number of total nodes <li> wrong number of dead nodes <li> ref count error at node </ul> Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is not enough memory; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CheckKeys">Cudd_CheckKeys</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Decreasing"><b>Cudd_Decreasing</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Determines whether the function represented by BDD f is negative unate (monotonic decreasing) in variable i. Returns the constant one is f is unate and the (logical) constant zero if it is not. This function does not generate any new nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Increasing">Cudd_Increasing</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_DelayedDerefBdd"><b>Cudd_DelayedDerefBdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Enqueues node n for later dereferencing. If the queue is full decreases the reference count of the oldest node N to make room for n. If N dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is currently not needed, but may be useful again in the near future. The dereferencing proper is done as in Cudd_IterDerefBdd.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_IterDerefBdd">Cudd_IterDerefBdd</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_Density"><b>Cudd_Density</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function whose density is sought</i>
+  int  <b>nvars</b> <i>size of the support of f</i>
+)
+</pre>
+<dd> Computes the density of a BDD or ADD. The density is the ratio of the number of minterms to the number of nodes. If 0 is passed as number of variables, the number of variables existing in the manager is used. Returns the density if successful; (double) CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+<a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Deref"><b>Cudd_Deref</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous Cudd_Ref.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_RecursiveDerefZdd">Cudd_RecursiveDerefZdd</a>
+<a href="cuddAllDet.html#Cudd_Ref">Cudd_Ref</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_DisableGarbageCollection"><b>Cudd_DisableGarbageCollection</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Disables garbage collection. Garbage collection is initially enabled. This function may be called to disable it. However, garbage collection will still occur when a new node must be created and no memory is left, or when garbage collection is required for correctness. (E.g., before reordering.)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableGarbageCollection">Cudd_EnableGarbageCollection</a>
+<a href="cuddAllDet.html#Cudd_GarbageCollectionEnabled">Cudd_GarbageCollectionEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DisableReorderingReporting"><b>Cudd_DisableReorderingReporting</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Disables reporting of reordering stats. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Removes functions from the pre-reordering and post-reordering hooks.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableReorderingReporting">Cudd_EnableReorderingReporting</a>
+<a href="cuddAllDet.html#Cudd_ReorderingReporting">Cudd_ReorderingReporting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpBlifBody"><b>Cudd_DumpBlifBody</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a blif body representing the argument BDDs as a network of multiplexers. No header (.model, .inputs, and .outputs) and footer (.end) are produced by this function. One multiplexer is written for each BDD node. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full, or an ADD with constants different from 0 and 1). Cudd_DumpBlifBody does not close the file: This is the caller responsibility. Cudd_DumpBlifBody uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. This function prints out only .names part.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpBlif"><b>Cudd_DumpBlif</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  char * <b>mname</b>, <i>model name (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a blif file representing the argument BDDs as a network of multiplexers. One multiplexer is written for each BDD node. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full, or an ADD with constants different from 0 and 1). Cudd_DumpBlif does not close the file: This is the caller responsibility. Cudd_DumpBlif uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpBlifBody">Cudd_DumpBlifBody</a>
+<a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpDDcal"><b>Cudd_DumpDDcal</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a DDcal file representing the argument BDDs. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or file system full). Cudd_DumpDDcal does not close the file: This is the caller responsibility. Cudd_DumpDDcal uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpDaVinci"><b>Cudd_DumpDaVinci</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a daVinci file representing the argument BDDs. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or file system full). Cudd_DumpDaVinci does not close the file: This is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpDot"><b>Cudd_DumpDot</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a file representing the argument DDs in a format suitable for the graph drawing program dot. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full). Cudd_DumpDot does not close the file: This is the caller responsibility. Cudd_DumpDot uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. Cudd_DumpDot uses the following convention to draw arcs: <ul> <li> solid line: THEN arcs; <li> dotted line: complement arcs; <li> dashed line: regular ELSE arcs. </ul> The dot options are chosen so that the drawing fits on a letter-size sheet.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpFactoredForm"><b>Cudd_DumpFactoredForm</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes factored forms representing the argument BDDs. The format of the factored form is the one used in the genlib files for technology mapping in sis. It returns 1 in case of success; 0 otherwise (e.g., file system full). Cudd_DumpFactoredForm does not close the file: This is the caller responsibility. Caution must be exercised because a factored form may be exponentially larger than the argument BDD. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Dxygtdxz"><b>Cudd_Dxygtdxz</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x, y, and z variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b>, <i>array of y variables</i>
+  DdNode ** <b>z</b> <i>array of z variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function d(x,y) &gt; d(x,z); x, y, and z are N-bit numbers, x[0] x[1] ... x[N-1], y[0] y[1] ... y[N-1], and z[0] z[1] ... z[N-1], with 0 the most significant bit. The distance d(x,y) is defined as: sum_{i=0}^{N-1}(|x_i - y_i| cdot 2^{N-i-1}). The BDD is built bottom-up. It has 7*N-3 internal nodes, if the variables are ordered as follows: x[0] y[0] z[0] x[1] y[1] z[1] ... x[N-1] y[N-1] z[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+<a href="cuddAllDet.html#Cudd_Xgty">Cudd_Xgty</a>
+<a href="cuddAllDet.html#Cudd_bddAdjPermuteX">Cudd_bddAdjPermuteX</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Dxygtdyz"><b>Cudd_Dxygtdyz</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x, y, and z variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b>, <i>array of y variables</i>
+  DdNode ** <b>z</b> <i>array of z variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function d(x,y) &gt; d(y,z); x, y, and z are N-bit numbers, x[0] x[1] ... x[N-1], y[0] y[1] ... y[N-1], and z[0] z[1] ... z[N-1], with 0 the most significant bit. The distance d(x,y) is defined as: sum_{i=0}^{N-1}(|x_i - y_i| cdot 2^{N-i-1}). The BDD is built bottom-up. It has 7*N-3 internal nodes, if the variables are ordered as follows: x[0] y[0] z[0] x[1] y[1] z[1] ... x[N-1] y[N-1] z[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Xgty">Cudd_Xgty</a>
+<a href="cuddAllDet.html#Cudd_bddAdjPermuteX">Cudd_bddAdjPermuteX</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_EnableGarbageCollection"><b>Cudd_EnableGarbageCollection</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Enables garbage collection. Garbage collection is initially enabled. Therefore it is necessary to call this function only if garbage collection has been explicitly disabled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DisableGarbageCollection">Cudd_DisableGarbageCollection</a>
+<a href="cuddAllDet.html#Cudd_GarbageCollectionEnabled">Cudd_GarbageCollectionEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EnableReorderingReporting"><b>Cudd_EnableReorderingReporting</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Enables reporting of reordering stats. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Installs functions in the pre-reordering and post-reordering hooks.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DisableReorderingReporting">Cudd_DisableReorderingReporting</a>
+<a href="cuddAllDet.html#Cudd_ReorderingReporting">Cudd_ReorderingReporting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EpdCountMinterm"><b>Cudd_EpdCountMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b>, <i></i>
+  EpDouble * <b>epd</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a DD with extended precision. The function is assumed to depend on nvars variables. The minterm count is represented as an EpDouble, to allow any number of variables. Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_CountPath">Cudd_CountPath</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EqualSupNorm"><b>Cudd_EqualSupNorm</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first ADD</i>
+  DdNode * <b>g</b>, <i>second ADD</i>
+  CUDD_VALUE_TYPE  <b>tolerance</b>, <i>maximum allowed difference</i>
+  int  <b>pr</b> <i>verbosity level</i>
+)
+</pre>
+<dd> Compares two ADDs for equality within tolerance. Two ADDs are reported to be equal if the maximum difference between them (the sup norm of their difference) is less than or equal to the tolerance parameter. Returns 1 if the two ADDs are equal (within tolerance); 0 otherwise. If parameter <code>pr</code> is positive the first failure is reported to the standard output.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EquivDC"><b>Cudd_EquivDC</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>F</b>, <i></i>
+  DdNode * <b>G</b>, <i></i>
+  DdNode * <b>D</b> <i></i>
+)
+</pre>
+<dd> Tells whether F and G are identical wherever D is 0. F and G are either two ADDs or two BDDs. D is either a 0-1 ADD or a BDD. The function returns 1 if F and G are equivalent, and 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddLeqUnless">Cudd_bddLeqUnless</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EstimateCofactorSimple"><b>Cudd_EstimateCofactorSimple</b></a>(
+  DdNode * <b>node</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Estimates the number of nodes in a cofactor of a DD. Returns an estimate of the number of nodes in the positive cofactor of the graph rooted at node with respect to the variable whose index is i. This procedure implements with minor changes the algorithm of Cabodi et al. (ICCAD96). It does not allocate any memory, it does not change the state of the manager, and it is fast. However, it has been observed to overestimate the size of the cofactor by as much as a factor of 2.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EstimateCofactor"><b>Cudd_EstimateCofactor</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function</i>
+  int  <b>i</b>, <i>index of variable</i>
+  int  <b>phase</b> <i>1: positive; 0: negative</i>
+)
+</pre>
+<dd> Estimates the number of nodes in a cofactor of a DD. Returns an estimate of the number of nodes in a cofactor of the graph rooted at node with respect to the variable whose index is i. In case of failure, returns CUDD_OUT_OF_MEM. This function uses a refinement of the algorithm of Cabodi et al. (ICCAD96). The refinement allows the procedure to account for part of the recombination that may occur in the part of the cofactor above the cofactoring variable. This procedure does no create any new node. It does keep a small table of results; therefore it may run out of memory. If this is a concern, one should use Cudd_EstimateCofactorSimple, which is faster, does not allocate any memory, but is less accurate.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+<a href="cuddAllDet.html#Cudd_EstimateCofactorSimple">Cudd_EstimateCofactorSimple</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Eval"><b>Cudd_Eval</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>inputs</b> <i></i>
+)
+</pre>
+<dd> Finds the value of a DD for a given variable assignment. The variable assignment is passed in an array of int's, that should specify a zero or a one for each variable in the support of the function. Returns a pointer to a constant node. No new nodes are produced.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ExpectedUsedSlots"><b>Cudd_ExpectedUsedSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Computes the fraction of slots in the unique table that should be in use. This expected value is based on the assumption that the hash function distributes the keys randomly; it can be compared with the result of Cudd_ReadUsedSlots to monitor the performance of the unique table hash function.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSlots">Cudd_ReadSlots</a>
+<a href="cuddAllDet.html#Cudd_ReadUsedSlots">Cudd_ReadUsedSlots</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_E"><b>Cudd_E</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the else child of an internal node. If <code>node</code> is a constant node, the result is unpredictable.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_T">Cudd_T</a>
+<a href="cuddAllDet.html#Cudd_V">Cudd_V</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_FindEssential"><b>Cudd_FindEssential</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns the cube of the essential variables. A positive literal means that the variable must be set to 1 for the function to be 1. A negative literal means that the variable must be set to 0 for the function to be 1. Returns a pointer to the cube BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIsVarEssential">Cudd_bddIsVarEssential</a>
+</code>
+
+<dt><pre>
+DdTlcInfo * <i></i>
+<a name="Cudd_FindTwoLiteralClauses"><b>Cudd_FindTwoLiteralClauses</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns the one- and two-literal clauses of a DD. Returns a pointer to the structure holding the clauses if successful; NULL otherwise. For a constant DD, the empty set of clauses is returned. This is obviously correct for a non-zero constant. For the constant zero, it is based on the assumption that only those clauses containing variables in the support of the function are considered. Since the support of a constant function is empty, no clauses are returned.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindEssential">Cudd_FindEssential</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_FirstCube"><b>Cudd_FirstCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int ** <b>cube</b>, <i></i>
+  CUDD_VALUE_TYPE * <b>value</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on the onset of a decision diagram and finds its first cube. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.<p> A cube is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents a complemented literal, 1 represents an uncomplemented literal, and 2 stands for don't care. The enumeration produces a disjoint cover of the function associated with the diagram. The size of the array equals the number of variables in the manager at the time Cudd_FirstCube is called.<p> For each cube, a value is also returned. This value is always 1 for a BDD, while it may be different from 1 for an ADD. For BDDs, the offset is the set of cubes whose value is the logical zero. For ADDs, the offset is the set of cubes whose value is the background value. The cubes of the offset are not enumerated.
+<p>
+
+<dd> <b>Side Effects</b> The first cube and its value are returned as side effects.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_FirstNode"><b>Cudd_FirstNode</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>node</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on the nodes of a decision diagram and finds its first node. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise. The nodes are enumerated in a reverse topological order, so that a node is always preceded in the enumeration by its descendants.
+<p>
+
+<dd> <b>Side Effects</b> The first node is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_FirstPrime"><b>Cudd_FirstPrime</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>l</b>, <i></i>
+  DdNode * <b>u</b>, <i></i>
+  int ** <b>cube</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on a pair of BDDs describing a (possibly incompletely specified) Boolean functions and finds the first cube of a cover of the function. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.<p> The two argument BDDs are the lower and upper bounds of an interval. It is a mistake to call this function with a lower bound that is not less than or equal to the upper bound.<p> A cube is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents a complemented literal, 1 represents an uncomplemented literal, and 2 stands for don't care. The enumeration produces a prime and irredundant cover of the function associated with the two BDDs. The size of the array equals the number of variables in the manager at the time Cudd_FirstCube is called.<p> This iterator can only be used on BDDs.
+<p>
+
+<dd> <b>Side Effects</b> The first cube is returned as side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachPrime">Cudd_ForeachPrime</a>
+<a href="cuddAllDet.html#Cudd_NextPrime">Cudd_NextPrime</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ForeachCube"><b>Cudd_ForeachCube</b></a>(
+   <b>manager</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>cube</b>, <i></i>
+   <b>value</b> <i></i>
+)
+</pre>
+<dd> Iterates over the cubes of a decision diagram f. <ul> <li> DdManager *manager; <li> DdNode *f; <li> DdGen *gen; <li> int *cube; <li> CUDD_VALUE_TYPE value; </ul> Cudd_ForeachCube allocates and frees the generator. Therefore the application should not try to do that. Also, the cube is freed at the end of Cudd_ForeachCube and hence is not available outside of the loop.<p> CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ForeachNode"><b>Cudd_ForeachNode</b></a>(
+   <b>manager</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Iterates over the nodes of a decision diagram f. <ul> <li> DdManager *manager; <li> DdNode *f; <li> DdGen *gen; <li> DdNode *node; </ul> The nodes are returned in a seemingly random order. Cudd_ForeachNode allocates and frees the generator. Therefore the application should not try to do that.<p> CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ForeachPrime"><b>Cudd_ForeachPrime</b></a>(
+   <b>manager</b>, <i></i>
+   <b>l</b>, <i></i>
+   <b>u</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>cube</b> <i></i>
+)
+</pre>
+<dd> Iterates over the primes of a Boolean function producing a prime and irredundant cover. <ul> <li> DdManager *manager; <li> DdNode *l; <li> DdNode *u; <li> DdGen *gen; <li> int *cube; </ul> The Boolean function is described by an upper bound and a lower bound. If the function is completely specified, the two bounds coincide. Cudd_ForeachPrime allocates and frees the generator. Therefore the application should not try to do that. Also, the cube is freed at the end of Cudd_ForeachPrime and hence is not available outside of the loop.<p> CAUTION: It is a mistake to change a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_FirstPrime">Cudd_FirstPrime</a>
+<a href="cuddAllDet.html#Cudd_NextPrime">Cudd_NextPrime</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_FreeTree"><b>Cudd_FreeTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Frees the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetTree">Cudd_SetTree</a>
+<a href="cuddAllDet.html#Cudd_ReadTree">Cudd_ReadTree</a>
+<a href="cuddAllDet.html#Cudd_FreeZddTree">Cudd_FreeZddTree</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_FreeZddTree"><b>Cudd_FreeZddTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Frees the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetZddTree">Cudd_SetZddTree</a>
+<a href="cuddAllDet.html#Cudd_ReadZddTree">Cudd_ReadZddTree</a>
+<a href="cuddAllDet.html#Cudd_FreeTree">Cudd_FreeTree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_GarbageCollectionEnabled"><b>Cudd_GarbageCollectionEnabled</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if garbage collection is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableGarbageCollection">Cudd_EnableGarbageCollection</a>
+<a href="cuddAllDet.html#Cudd_DisableGarbageCollection">Cudd_DisableGarbageCollection</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_GenFree"><b>Cudd_GenFree</b></a>(
+  DdGen * <b>gen</b> <i></i>
+)
+</pre>
+<dd> Frees a CUDD generator. Always returns 0, so that it can be used in mis-like foreach constructs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Increasing"><b>Cudd_Increasing</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Determines whether the function represented by BDD f is positive unate (monotonic increasing) in variable i. It is based on Cudd_Decreasing and the fact that f is monotonic increasing in i if and only if its complement is monotonic decreasing in i.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Decreasing">Cudd_Decreasing</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_IndicesToCube"><b>Cudd_IndicesToCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int * <b>array</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Builds a cube of BDD variables from an array of indices. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddComputeCube">Cudd_bddComputeCube</a>
+<a href="cuddAllDet.html#Cudd_CubeArrayToBdd">Cudd_CubeArrayToBdd</a>
+</code>
+
+<dt><pre>
+DdManager * <i></i>
+<a name="Cudd_Init"><b>Cudd_Init</b></a>(
+  unsigned int  <b>numVars</b>, <i>initial number of BDD variables (i.e., subtables)</i>
+  unsigned int  <b>numVarsZ</b>, <i>initial number of ZDD variables (i.e., subtables)</i>
+  unsigned int  <b>numSlots</b>, <i>initial size of the unique tables</i>
+  unsigned int  <b>cacheSize</b>, <i>initial size of the cache</i>
+  unsigned long  <b>maxMemory</b> <i>target maximum memory occupation</i>
+)
+</pre>
+<dd> Creates a new DD manager, initializes the table, the basic constants and the projection functions. If maxMemory is 0, Cudd_Init decides suitable values for the maximum size of the cache and for the limit for fast unique table growth based on the available memory. Returns a pointer to the manager if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Quit">Cudd_Quit</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_IsComplement"><b>Cudd_IsComplement</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if a pointer is complemented.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Regular">Cudd_Regular</a>
+<a href="cuddAllDet.html#Cudd_Complement">Cudd_Complement</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_IsConstant"><b>Cudd_IsConstant</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the node is a constant node (rather than an internal node). All constant nodes have the same index (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either regular or complemented.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_IsGenEmpty"><b>Cudd_IsGenEmpty</b></a>(
+  DdGen * <b>gen</b> <i></i>
+)
+</pre>
+<dd> Queries the status of a generator. Returns 1 if the generator is empty or NULL; 0 otherswise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_IsInHook"><b>Cudd_IsInHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_HFP  <b>f</b>, <i></i>
+  Cudd_HookType  <b>where</b> <i></i>
+)
+</pre>
+<dd> Checks whether a function is in a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if the function is found; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AddHook">Cudd_AddHook</a>
+<a href="cuddAllDet.html#Cudd_RemoveHook">Cudd_RemoveHook</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_IsNonConstant"><b>Cudd_IsNonConstant</b></a>(
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if a DD node is not constant. This function is useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant, Cudd_addEvalConst. These results may be a special value signifying non-constant. In the other cases the macro Cudd_IsConstant can be used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_IsConstant">Cudd_IsConstant</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_IterDerefBdd"><b>Cudd_IterDerefBdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is no longer needed. It is more efficient than Cudd_RecursiveDeref, but it cannot be used on ADDs. The greater efficiency comes from being able to assume that no constant node will ever die as a result of a call to this procedure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_DelayedDerefBdd">Cudd_DelayedDerefBdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_LargestCube"><b>Cudd_LargestCube</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>length</b> <i></i>
+)
+</pre>
+<dd> Finds a largest cube in a DD. f is the DD we want to get the largest cube for. The problem is translated into the one of finding a shortest path in f, when both THEN and ELSE arcs are assumed to have unit length. This yields a largest cube in the disjoint cover corresponding to the DD. Therefore, it is not necessarily the largest implicant of f. Returns the largest cube as a BDD.
+<p>
+
+<dd> <b>Side Effects</b> The number of literals of the cube is returned in length.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ShortestPath">Cudd_ShortestPath</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_MakeBddFromZddCover"><b>Cudd_MakeBddFromZddCover</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, otherwise it returns NULL.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddMakeBddFromZddCover">cuddMakeBddFromZddCover</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_MakeTreeNode"><b>Cudd_MakeTreeNode</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  unsigned int  <b>low</b>, <i>index of the first group variable</i>
+  unsigned int  <b>size</b>, <i>number of variables in the group</i>
+  unsigned int  <b>type</b> <i>MTR_DEFAULT or MTR_FIXED</i>
+)
+</pre>
+<dd> Creates a new variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The variable tree is changed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_MakeZddTreeNode">Cudd_MakeZddTreeNode</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_MakeZddTreeNode"><b>Cudd_MakeZddTreeNode</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  unsigned int  <b>low</b>, <i>index of the first group variable</i>
+  unsigned int  <b>size</b>, <i>number of variables in the group</i>
+  unsigned int  <b>type</b> <i>MTR_DEFAULT or MTR_FIXED</i>
+)
+</pre>
+<dd> Creates a new ZDD variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The ZDD variable tree is changed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_MakeTreeNode">Cudd_MakeTreeNode</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_MinHammingDist"><b>Cudd_MinHammingDist</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode * <b>f</b>, <i>function to examine</i>
+  int * <b>minterm</b>, <i>reference minterm</i>
+  int  <b>upperBound</b> <i>distance above which an approximate answer is OK</i>
+)
+</pre>
+<dd> Returns the minimum Hamming distance between the minterms of a function f and a reference minterm. The function is given as a BDD; the minterm is given as an array of integers, one for each variable in the manager. Returns the minimum distance if it is less than the upper bound; the upper bound if the minimum distance is at least as large; CUDD_OUT_OF_MEM in case of failure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addHamming">Cudd_addHamming</a>
+<a href="cuddAllDet.html#Cudd_bddClosestCube">Cudd_bddClosestCube</a>
+</code>
+
+<dt><pre>
+DdApaNumber <i></i>
+<a name="Cudd_NewApaNumber"><b>Cudd_NewApaNumber</b></a>(
+  int  <b>digits</b> <i></i>
+)
+</pre>
+<dd> Allocates memory for an arbitrary precision integer. Returns a pointer to the allocated memory if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_NextCube"><b>Cudd_NextCube</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  int ** <b>cube</b>, <i></i>
+  CUDD_VALUE_TYPE * <b>value</b> <i></i>
+)
+</pre>
+<dd> Generates the next cube of a decision diagram onset, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The cube and its value are returned as side effects. The generator is modified.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_NextNode"><b>Cudd_NextNode</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  DdNode ** <b>node</b> <i></i>
+)
+</pre>
+<dd> Finds the node of a decision diagram, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The next node is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_NextPrime"><b>Cudd_NextPrime</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  int ** <b>cube</b> <i></i>
+)
+</pre>
+<dd> Generates the next cube of a Boolean function, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The cube and is returned as side effects. The generator is modified.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachPrime">Cudd_ForeachPrime</a>
+<a href="cuddAllDet.html#Cudd_FirstPrime">Cudd_FirstPrime</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_NodeReadIndex"><b>Cudd_NodeReadIndex</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the node. The node pointer can be either regular or complemented.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadIndex">Cudd_ReadIndex</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_NotCond"><b>Cudd_NotCond</b></a>(
+   <b>node</b>, <i></i>
+   <b>c</b> <i></i>
+)
+</pre>
+<dd> Complements a DD if condition c is true; c should be either 0 or 1, because it is used directly (for efficiency). If in doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Not">Cudd_Not</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_Not"><b>Cudd_Not</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Complements a DD by flipping the complement attribute of the pointer (the least significant bit).
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_NotCond">Cudd_NotCond</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_OutOfMem"><b>Cudd_OutOfMem</b></a>(
+  long  <b>size</b> <i>size of the allocation that failed</i>
+)
+</pre>
+<dd> Warns that a memory allocation failed. This function can be used as replacement of MMout_of_memory to prevent the safe_mem functions of the util package from exiting when malloc returns NULL. One possible use is in case of discretionary allocations; for instance, the allocation of memory to enlarge the computed table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_OverApprox"><b>Cudd_OverApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  int  <b>safe</b>, <i>enforce safe approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_Prime"><b>Cudd_Prime</b></a>(
+  unsigned int  <b>p</b> <i></i>
+)
+</pre>
+<dd> Returns the next prime &gt;= p.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintDebug"><b>Cudd_PrintDebug</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  int  <b>pr</b> <i></i>
+)
+</pre>
+<dd> Prints to the standard output a DD and its statistics. The statistics include the number of nodes, the number of leaves, and the number of minterms. (The number of minterms is the number of assignments to the variables that cause the function to be different from the logical zero (for BDDs) and from the background value (for ADDs.) The statistics are printed if pr &gt; 0. Specifically: <ul> <li> pr = 0 : prints nothing <li> pr = 1 : prints counts of nodes and minterms <li> pr = 2 : prints counts + disjoint sum of product <li> pr = 3 : prints counts + list of nodes <li> pr &gt; 3 : prints counts + disjoint sum of product + list of nodes </ul> For the purpose of counting the number of minterms, the function is supposed to depend on n variables. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+<a href="cuddAllDet.html#Cudd_CountLeaves">Cudd_CountLeaves</a>
+<a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+<a href="cuddAllDet.html#Cudd_PrintMinterm">Cudd_PrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintInfo"><b>Cudd_PrintInfo</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints out statistics and settings for a CUDD manager. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintLinear"><b>Cudd_PrintLinear</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Prints the linear transform matrix. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintMinterm"><b>Cudd_PrintMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Prints a disjoint sum of product cover for the function rooted at node. Each product corresponds to a path from node to a leaf node different from the logical zero, and different from the background value. Uses the package default output file. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_bddPrintCover">Cudd_bddPrintCover</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintTwoLiteralClauses"><b>Cudd_PrintTwoLiteralClauses</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  char ** <b>names</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints the one- and two-literal clauses. Returns 1 if successful; 0 otherwise. The argument "names" can be NULL, in which case the variable indices are printed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindTwoLiteralClauses">Cudd_FindTwoLiteralClauses</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_PrintVersion"><b>Cudd_PrintVersion</b></a>(
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints the package version number.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_PrioritySelect"><b>Cudd_PrioritySelect</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>R</b>, <i>BDD of the relation</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b>, <i>array of y variables</i>
+  DdNode ** <b>z</b>, <i>array of z variables (optional: may be NULL)</i>
+  DdNode * <b>Pi</b>, <i>BDD of the priority function (optional: may be NULL)</i>
+  int  <b>n</b>, <i>size of x, y, and z</i>
+  DD_PRFP  <b>Pifunc</b> <i>function used to build Pi if it is NULL</i>
+)
+</pre>
+<dd> Selects pairs from a relation R(x,y) (given as a BDD) in such a way that a given x appears in one pair only. Uses a priority function to determine which y should be paired to a given x. Cudd_PrioritySelect returns a pointer to the selected function if successful; NULL otherwise. Three of the arguments--x, y, and z--are vectors of BDD variables. The first two are the variables on which R depends. The third vectore is a vector of auxiliary variables, used during the computation. This vector is optional. If a NULL value is passed instead, Cudd_PrioritySelect will create the working variables on the fly. The sizes of x and y (and z if it is not NULL) should equal n. The priority function Pi can be passed as a BDD, or can be built by Cudd_PrioritySelect. If NULL is passed instead of a DdNode *, parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the priority function. (Pifunc is a pointer to a C function.) If Pi is not NULL, then Pifunc is ignored. Pifunc should have the same interface as the standard priority functions (e.g., Cudd_Dxygtdxz). Cudd_PrioritySelect and Cudd_CProjection can sometimes be used interchangeably. Specifically, calling Cudd_PrioritySelect with Cudd_Xgty as Pifunc produces the same result as calling Cudd_CProjection with the all-zero minterm as reference minterm. However, depending on the application, one or the other may be preferable: <ul> <li> When extracting representatives from an equivalence relation, Cudd_CProjection has the advantage of nor requiring the auxiliary variables. <li> When computing matchings in general bipartite graphs, Cudd_PrioritySelect normally obtains better results because it can use more powerful matching schemes (e.g., Cudd_Dxygtdxz). </ul>
+<p>
+
+<dd> <b>Side Effects</b> If called with z == NULL, will create new variables in the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+<a href="cuddAllDet.html#Cudd_Xgty">Cudd_Xgty</a>
+<a href="cuddAllDet.html#Cudd_bddAdjPermuteX">Cudd_bddAdjPermuteX</a>
+<a href="cuddAllDet.html#Cudd_CProjection">Cudd_CProjection</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Quit"><b>Cudd_Quit</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Deletes resources associated with a DD manager and resets the global statistical counters. (Otherwise, another manaqger subsequently created would inherit the stats of this one.)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Init">Cudd_Init</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_Random"><b>Cudd_Random</b></a>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> Portable number generator based on ran2 from "Numerical Recipes in C." It is a long period (> 2 * 10^18) random number generator of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly distributed between 0 and 2147483561 (inclusive of the endpoint values). The random generator can be explicitly initialized by calling Cudd_Srandom. If no explicit initialization is performed, then the seed 1 is assumed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Srandom">Cudd_Srandom</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadArcviolation"><b>Cudd_ReadArcviolation</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the current value of the arcviolation parameter. This parameter is used in group sifting to decide how many arcs into <code>y</code> not coming from <code>x</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetArcviolation">Cudd_SetArcviolation</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadBackground"><b>Cudd_ReadBackground</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the background constant of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadCacheHits"><b>Cudd_ReadCacheHits</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of cache hits.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheLookUps">Cudd_ReadCacheLookUps</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadCacheLookUps"><b>Cudd_ReadCacheLookUps</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of cache look-ups.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheHits">Cudd_ReadCacheHits</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadCacheSlots"><b>Cudd_ReadCacheSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the number of slots in the cache.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheUsedSlots">Cudd_ReadCacheUsedSlots</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadCacheUsedSlots"><b>Cudd_ReadCacheUsedSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the fraction of used slots in the cache. The unused slots are those in which no valid data is stored. Garbage collection, variable reordering, and cache resizing may cause used slots to become unused.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheSlots">Cudd_ReadCacheSlots</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadDead"><b>Cudd_ReadDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of dead nodes in the unique table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadKeys">Cudd_ReadKeys</a>
+</code>
+
+<dt><pre>
+CUDD_VALUE_TYPE <i></i>
+<a name="Cudd_ReadEpsilon"><b>Cudd_ReadEpsilon</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the epsilon parameter of the manager. The epsilon parameter control the comparison between floating point numbers.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetEpsilon">Cudd_SetEpsilon</a>
+</code>
+
+<dt><pre>
+Cudd_ErrorType <i></i>
+<a name="Cudd_ReadErrorCode"><b>Cudd_ReadErrorCode</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the code of the last error. The error codes are defined in cudd.h.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ClearErrorCode">Cudd_ClearErrorCode</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadGarbageCollectionTime"><b>Cudd_ReadGarbageCollectionTime</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of milliseconds spent doing garbage collection since the manager was initialized.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadGarbageCollections">Cudd_ReadGarbageCollections</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadGarbageCollections"><b>Cudd_ReadGarbageCollections</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of times garbage collection has occurred in the manager. The number includes both the calls from reordering procedures and those caused by requests to create new nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadGarbageCollectionTime">Cudd_ReadGarbageCollectionTime</a>
+</code>
+
+<dt><pre>
+Cudd_AggregationType <i></i>
+<a name="Cudd_ReadGroupcheck"><b>Cudd_ReadGroupcheck</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the groupcheck parameter of the manager. The groupcheck parameter determines the aggregation criterion in group sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetGroupcheck">Cudd_SetGroupcheck</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ReadIndex"><b>Cudd_ReadIndex</b></a>(
+   <b>dd</b>, <i></i>
+   <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the current position in the order of variable index. This macro is obsolete and is kept for compatibility. New applications should use Cudd_ReadPerm instead.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadInvPermZdd"><b>Cudd_ReadInvPermZdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the ZDD variable currently in the i-th position of the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+<a href="cuddAllDet.html#Cudd_ReadInvPermZdd">Cudd_ReadInvPermZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadInvPerm"><b>Cudd_ReadInvPerm</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the variable currently in the i-th position of the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+<a href="cuddAllDet.html#Cudd_ReadInvPermZdd">Cudd_ReadInvPermZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadIthClause"><b>Cudd_ReadIthClause</b></a>(
+  DdTlcInfo * <b>tlc</b>, <i></i>
+  int  <b>i</b>, <i></i>
+  DdHalfWord * <b>var1</b>, <i></i>
+  DdHalfWord * <b>var2</b>, <i></i>
+  int * <b>phase1</b>, <i></i>
+  int * <b>phase2</b> <i></i>
+)
+</pre>
+<dd> Accesses the i-th clause of a DD given the clause set which must be already computed. Returns 1 if successful; 0 if i is out of range, or in case of error.
+<p>
+
+<dd> <b>Side Effects</b> the four components of a clause are returned as side effects.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindTwoLiteralClauses">Cudd_FindTwoLiteralClauses</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadKeys"><b>Cudd_ReadKeys</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the total number of nodes currently in the unique table, including the dead nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadDead">Cudd_ReadDead</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadLinear"><b>Cudd_ReadLinear</b></a>(
+  DdManager * <b>table</b>, <i>CUDD manager</i>
+  int  <b>x</b>, <i>row index</i>
+  int  <b>y</b> <i>column index</i>
+)
+</pre>
+<dd> Reads an entry of the linear transform matrix.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadLogicZero"><b>Cudd_ReadLogicZero</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the zero constant of the manager. The logic zero constant is the complement of the one constant, and is distinct from the arithmetic zero.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadOne">Cudd_ReadOne</a>
+<a href="cuddAllDet.html#Cudd_ReadZero">Cudd_ReadZero</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadLooseUpTo"><b>Cudd_ReadLooseUpTo</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the looseUpTo parameter of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetLooseUpTo">Cudd_SetLooseUpTo</a>
+<a href="cuddAllDet.html#Cudd_ReadMinHit">Cudd_ReadMinHit</a>
+<a href="cuddAllDet.html#Cudd_ReadMinDead">Cudd_ReadMinDead</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMaxCacheHard"><b>Cudd_ReadMaxCacheHard</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maxCacheHard parameter of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxCacheHard">Cudd_SetMaxCacheHard</a>
+<a href="cuddAllDet.html#Cudd_ReadMaxCache">Cudd_ReadMaxCache</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMaxCache"><b>Cudd_ReadMaxCache</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the soft limit for the cache size. The soft limit
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxCache">Cudd_ReadMaxCache</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadMaxGrowthAlternate"><b>Cudd_ReadMaxGrowthAlternate</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maxGrowthAlt parameter of the manager. This parameter is analogous to the maxGrowth paramter, and is used every given number of reorderings instead of maxGrowth. The number of reorderings is set with Cudd_SetReorderingCycle. If the number of reorderings is 0 (default) maxGrowthAlt is never used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowth">Cudd_ReadMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetReorderingCycle">Cudd_SetReorderingCycle</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingCycle">Cudd_ReadReorderingCycle</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadMaxGrowth"><b>Cudd_ReadMaxGrowth</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maxGrowth parameter of the manager. This parameter determines how much the number of nodes can grow during sifting of a variable. Overall, sifting never increases the size of the decision diagrams. This parameter only refers to intermediate results. A lower value will speed up sifting, possibly at the expense of quality.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxGrowth">Cudd_SetMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMaxLive"><b>Cudd_ReadMaxLive</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maximum allowed number of live nodes. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxLive">Cudd_SetMaxLive</a>
+</code>
+
+<dt><pre>
+unsigned long <i></i>
+<a name="Cudd_ReadMaxMemory"><b>Cudd_ReadMaxMemory</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maximum allowed memory. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxMemory">Cudd_SetMaxMemory</a>
+</code>
+
+<dt><pre>
+unsigned long <i></i>
+<a name="Cudd_ReadMemoryInUse"><b>Cudd_ReadMemoryInUse</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the memory in use by the manager measured in bytes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMinDead"><b>Cudd_ReadMinDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the minDead parameter of the manager. The minDead parameter is used by the package to decide whether to collect garbage or resize a subtable of the unique table when the subtable becomes too full. The application can indirectly control the value of minDead by setting the looseUpTo parameter.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadDead">Cudd_ReadDead</a>
+<a href="cuddAllDet.html#Cudd_ReadLooseUpTo">Cudd_ReadLooseUpTo</a>
+<a href="cuddAllDet.html#Cudd_SetLooseUpTo">Cudd_SetLooseUpTo</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMinHit"><b>Cudd_ReadMinHit</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the hit rate that causes resizinig of the computed table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMinHit">Cudd_SetMinHit</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadMinusInfinity"><b>Cudd_ReadMinusInfinity</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the minus-infinity constant from the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadNextReordering"><b>Cudd_ReadNextReordering</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the threshold for the next dynamic reordering. The threshold is in terms of number of nodes and is in effect only if reordering is enabled. The count does not include the dead nodes, unless the countDead parameter of the manager has been changed from its default setting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetNextReordering">Cudd_SetNextReordering</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadNodeCount"><b>Cudd_ReadNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the number of live nodes in BDDs and ADDs. This number does not include the isolated projection functions and the unused constants. These nodes that are not counted are not part of the DDs manipulated by the application.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPeakNodeCount">Cudd_ReadPeakNodeCount</a>
+<a href="cuddAllDet.html#Cudd_zddReadNodeCount">Cudd_zddReadNodeCount</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadNodesDropped"><b>Cudd_ReadNodesDropped</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of nodes killed by dereferencing if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_STATS defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodesFreed">Cudd_ReadNodesFreed</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadNodesFreed"><b>Cudd_ReadNodesFreed</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of nodes returned to the free list if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_STATS defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodesDropped">Cudd_ReadNodesDropped</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadNumberXovers"><b>Cudd_ReadNumberXovers</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the current number of crossovers used by the genetic algorithm for variable reordering. A larger number of crossovers will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as number of crossovers, with a maximum of 60.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetNumberXovers">Cudd_SetNumberXovers</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadOne"><b>Cudd_ReadOne</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the one constant of the manager. The one constant is common to ADDs and BDDs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadZero">Cudd_ReadZero</a>
+<a href="cuddAllDet.html#Cudd_ReadLogicZero">Cudd_ReadLogicZero</a>
+<a href="cuddAllDet.html#Cudd_ReadZddOne">Cudd_ReadZddOne</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPeakLiveNodeCount"><b>Cudd_ReadPeakLiveNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the peak number of live nodes. This count is kept only if CUDD is compiled with DD_STATS defined. If DD_STATS is not defined, this function returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodeCount">Cudd_ReadNodeCount</a>
+<a href="cuddAllDet.html#Cudd_PrintInfo">Cudd_PrintInfo</a>
+<a href="cuddAllDet.html#Cudd_ReadPeakNodeCount">Cudd_ReadPeakNodeCount</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadPeakNodeCount"><b>Cudd_ReadPeakNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the peak number of nodes. This number includes node on the free list. At the peak, the number of nodes on the free list is guaranteed to be less than DD_MEM_CHUNK.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodeCount">Cudd_ReadNodeCount</a>
+<a href="cuddAllDet.html#Cudd_PrintInfo">Cudd_PrintInfo</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPermZdd"><b>Cudd_ReadPermZdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the current position of the i-th ZDD variable in the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadInvPermZdd">Cudd_ReadInvPermZdd</a>
+<a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPerm"><b>Cudd_ReadPerm</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the current position of the i-th variable in the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadInvPerm">Cudd_ReadInvPerm</a>
+<a href="cuddAllDet.html#Cudd_ReadPermZdd">Cudd_ReadPermZdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadPlusInfinity"><b>Cudd_ReadPlusInfinity</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the plus-infinity constant from the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPopulationSize"><b>Cudd_ReadPopulationSize</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the current size of the population used by the genetic algorithm for variable reordering. A larger population size will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as population size, with a maximum of 120.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetPopulationSize">Cudd_SetPopulationSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadRecomb"><b>Cudd_ReadRecomb</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the current value of the recombination parameter used in group sifting. A larger (positive) value makes the aggregation of variables due to the second difference criterion more likely. A smaller (negative) value makes aggregation less likely.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetRecomb">Cudd_SetRecomb</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadRecursiveCalls"><b>Cudd_ReadRecursiveCalls</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of recursive calls if the package is compiled with DD_COUNT defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadReorderingCycle"><b>Cudd_ReadReorderingCycle</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the reordCycle parameter of the manager. This parameter determines how often the alternate threshold on maximum growth is used in reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetReorderingCycle">Cudd_SetReorderingCycle</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadReorderingTime"><b>Cudd_ReadReorderingTime</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of milliseconds spent reordering variables since the manager was initialized. The time spent in collecting garbage before reordering is included.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadReorderings">Cudd_ReadReorderings</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadReorderings"><b>Cudd_ReadReorderings</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of times reordering has occurred in the manager. The number includes both the calls to Cudd_ReduceHeap from the application program and those automatically performed by the package. However, calls that do not even initiate reordering are not counted. A call may not initiate reordering if there are fewer than minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified as reordering method. The calls to Cudd_ShuffleHeap are not counted.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReduceHeap">Cudd_ReduceHeap</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingTime">Cudd_ReadReorderingTime</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSiftMaxSwap"><b>Cudd_ReadSiftMaxSwap</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the siftMaxSwap parameter of the manager. This parameter gives the maximum number of swaps that will be attempted for each invocation of sifting. The real number of swaps may exceed the set limit because the package will always complete the sifting of the variable that causes the limit to be reached.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSiftMaxVar">Cudd_ReadSiftMaxVar</a>
+<a href="cuddAllDet.html#Cudd_SetSiftMaxSwap">Cudd_SetSiftMaxSwap</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSiftMaxVar"><b>Cudd_ReadSiftMaxVar</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the siftMaxVar parameter of the manager. This parameter gives the maximum number of variables that will be sifted for each invocation of sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSiftMaxSwap">Cudd_ReadSiftMaxSwap</a>
+<a href="cuddAllDet.html#Cudd_SetSiftMaxVar">Cudd_SetSiftMaxVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSize"><b>Cudd_ReadSize</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of BDD variables in existance.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadZddSize">Cudd_ReadZddSize</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadSlots"><b>Cudd_ReadSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the total number of slots of the unique table. This number ismainly for diagnostic purposes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+FILE * <i></i>
+<a name="Cudd_ReadStderr"><b>Cudd_ReadStderr</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the stderr of a manager. This is the file pointer to which messages normally going to stderr are written. It is initialized to stderr. Cudd_SetStderr allows the application to redirect it.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetStderr">Cudd_SetStderr</a>
+<a href="cuddAllDet.html#Cudd_ReadStdout">Cudd_ReadStdout</a>
+</code>
+
+<dt><pre>
+FILE * <i></i>
+<a name="Cudd_ReadStdout"><b>Cudd_ReadStdout</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the stdout of a manager. This is the file pointer to which messages normally going to stdout are written. It is initialized to stdout. Cudd_SetStdout allows the application to redirect it.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetStdout">Cudd_SetStdout</a>
+<a href="cuddAllDet.html#Cudd_ReadStderr">Cudd_ReadStderr</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadSwapSteps"><b>Cudd_ReadSwapSteps</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the number of elementary reordering steps.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSymmviolation"><b>Cudd_ReadSymmviolation</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the current value of the symmviolation parameter. This parameter is used in group sifting to decide how many violations to the symmetry conditions <code>f10 = f01</code> or <code>f11 = f00</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetSymmviolation">Cudd_SetSymmviolation</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_ReadTree"><b>Cudd_ReadTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetTree">Cudd_SetTree</a>
+<a href="cuddAllDet.html#Cudd_FreeTree">Cudd_FreeTree</a>
+<a href="cuddAllDet.html#Cudd_ReadZddTree">Cudd_ReadZddTree</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadUniqueLinks"><b>Cudd_ReadUniqueLinks</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of links followed during look-ups in the unique table if the keeping of this statistic is enabled; -1 otherwise. If an item is found in the first position of its collision list, the number of links followed is taken to be 0. If it is in second position, the number of links is 1, and so on. This statistic is enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadUniqueLookUps">Cudd_ReadUniqueLookUps</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadUniqueLookUps"><b>Cudd_ReadUniqueLookUps</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of look-ups in the unique table if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadUniqueLinks">Cudd_ReadUniqueLinks</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadUsedSlots"><b>Cudd_ReadUsedSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the fraction of used slots in the unique table. The unused slots are those in which no valid data is stored. Garbage collection, variable reordering, and subtable resizing may cause used slots to become unused.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSlots">Cudd_ReadSlots</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadVars"><b>Cudd_ReadVars</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the i-th element of the vars array if it falls within the array bounds; NULL otherwise. If i is the index of an existing variable, this function produces the same result as Cudd_bddIthVar. However, if the i-th var does not exist yet, Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadZddOne"><b>Cudd_ReadZddOne</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the ZDD for the constant 1 function. The representation of the constant 1 function as a ZDD depends on how many variables it (nominally) depends on. The index of the topmost variable in the support is given as argument <code>i</code>.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadOne">Cudd_ReadOne</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadZddSize"><b>Cudd_ReadZddSize</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of ZDD variables in existance.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_ReadZddTree"><b>Cudd_ReadZddTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetZddTree">Cudd_SetZddTree</a>
+<a href="cuddAllDet.html#Cudd_FreeZddTree">Cudd_FreeZddTree</a>
+<a href="cuddAllDet.html#Cudd_ReadTree">Cudd_ReadTree</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadZero"><b>Cudd_ReadZero</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the zero constant of the manager. The zero constant is the arithmetic zero, rather than the logic zero. The latter is the complement of the one constant.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadOne">Cudd_ReadOne</a>
+<a href="cuddAllDet.html#Cudd_ReadLogicZero">Cudd_ReadLogicZero</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_RecursiveDerefZdd"><b>Cudd_RecursiveDerefZdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of ZDD node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a ZDD that is no longer needed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Deref">Cudd_Deref</a>
+<a href="cuddAllDet.html#Cudd_Ref">Cudd_Ref</a>
+<a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_RecursiveDeref"><b>Cudd_RecursiveDeref</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a DD that is no longer needed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Deref">Cudd_Deref</a>
+<a href="cuddAllDet.html#Cudd_Ref">Cudd_Ref</a>
+<a href="cuddAllDet.html#Cudd_RecursiveDerefZdd">Cudd_RecursiveDerefZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReduceHeap"><b>Cudd_ReduceHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  Cudd_ReorderingType  <b>heuristic</b>, <i>method used for reordering</i>
+  int  <b>minsize</b> <i>bound below which no reordering occurs</i>
+)
+</pre>
+<dd> Main dynamic reordering routine. Calls one of the possible reordering procedures: <ul> <li>Swapping <li>Sifting <li>Symmetric Sifting <li>Group Sifting <li>Window Permutation <li>Simulated Annealing <li>Genetic Algorithm <li>Dynamic Programming (exact) </ul> For sifting, symmetric sifting, group sifting, and window permutation it is possible to request reordering to convergence.<p> The core of all methods is the reordering procedure cuddSwapInPlace() which swaps two adjacent variables and is based on Rudell's paper. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.
+<p>
+
+<dd> <b>Side Effects</b> Changes the variable order for all diagrams and clears the cache.
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Ref"><b>Cudd_Ref</b></a>(
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Increases the reference count of a node, if it is not saturated.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_Deref">Cudd_Deref</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_Regular"><b>Cudd_Regular</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the regular version of a pointer.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Complement">Cudd_Complement</a>
+<a href="cuddAllDet.html#Cudd_IsComplement">Cudd_IsComplement</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_RemapOverApprox"><b>Cudd_RemapOverApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_RemapUnderApprox"><b>Cudd_RemapUnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure uses a remapping technique and density as the cost function. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_UnderApprox">Cudd_UnderApprox</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_RemoveHook"><b>Cudd_RemoveHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_HFP  <b>f</b>, <i></i>
+  Cudd_HookType  <b>where</b> <i></i>
+)
+</pre>
+<dd> Removes a function from a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if successful; 0 the function was not in the list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AddHook">Cudd_AddHook</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReorderingReporting"><b>Cudd_ReorderingReporting</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if reporting of reordering stats is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableReorderingReporting">Cudd_EnableReorderingReporting</a>
+<a href="cuddAllDet.html#Cudd_DisableReorderingReporting">Cudd_DisableReorderingReporting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReorderingStatusZdd"><b>Cudd_ReorderingStatusZdd</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType * <b>method</b> <i></i>
+)
+</pre>
+<dd> Reports the status of automatic dynamic reordering of ZDDs. Parameter method is set to the ZDD reordering method currently selected. Returns 1 if automatic reordering is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Parameter method is set to the ZDD reordering method currently selected.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnableZdd">Cudd_AutodynEnableZdd</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisableZdd">Cudd_AutodynDisableZdd</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatus">Cudd_ReorderingStatus</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReorderingStatus"><b>Cudd_ReorderingStatus</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType * <b>method</b> <i></i>
+)
+</pre>
+<dd> Reports the status of automatic dynamic reordering of BDDs and ADDs. Parameter method is set to the reordering method currently selected. Returns 1 if automatic reordering is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Parameter method is set to the reordering method currently selected.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnable">Cudd_AutodynEnable</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatusZdd">Cudd_ReorderingStatusZdd</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetArcviolation"><b>Cudd_SetArcviolation</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>arcviolation</b> <i></i>
+)
+</pre>
+<dd> Sets the value of the arcviolation parameter. This parameter is used in group sifting to decide how many arcs into <code>y</code> not coming from <code>x</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadArcviolation">Cudd_ReadArcviolation</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetBackground"><b>Cudd_SetBackground</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>bck</b> <i></i>
+)
+</pre>
+<dd> Sets the background constant of the manager. It assumes that the DdNode pointer bck is already referenced.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetEpsilon"><b>Cudd_SetEpsilon</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>ep</b> <i></i>
+)
+</pre>
+<dd> Sets the epsilon parameter of the manager to ep. The epsilon parameter control the comparison between floating point numbers.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadEpsilon">Cudd_ReadEpsilon</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetGroupcheck"><b>Cudd_SetGroupcheck</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  Cudd_AggregationType  <b>gc</b> <i></i>
+)
+</pre>
+<dd> Sets the parameter groupcheck of the manager to gc. The groupcheck parameter determines the aggregation criterion in group sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadGroupCheck">Cudd_ReadGroupCheck</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetLooseUpTo"><b>Cudd_SetLooseUpTo</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>lut</b> <i></i>
+)
+</pre>
+<dd> Sets the looseUpTo parameter of the manager. This parameter of the manager controls the threshold beyond which no fast growth of the unique table is allowed. The threshold is given as a number of slots. If the value passed to this function is 0, the function determines a suitable value based on the available memory.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadLooseUpTo">Cudd_ReadLooseUpTo</a>
+<a href="cuddAllDet.html#Cudd_SetMinHit">Cudd_SetMinHit</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxCacheHard"><b>Cudd_SetMaxCacheHard</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>mc</b> <i></i>
+)
+</pre>
+<dd> Sets the maxCacheHard parameter of the manager. The cache cannot grow larger than maxCacheHard entries. This parameter allows an application to control the trade-off of memory versus speed. If the value passed to this function is 0, the function determines a suitable maximum cache size based on the available memory.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxCacheHard">Cudd_ReadMaxCacheHard</a>
+<a href="cuddAllDet.html#Cudd_SetMaxCache">Cudd_SetMaxCache</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxGrowthAlternate"><b>Cudd_SetMaxGrowthAlternate</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  double  <b>mg</b> <i></i>
+)
+</pre>
+<dd> Sets the maxGrowthAlt parameter of the manager. This parameter is analogous to the maxGrowth paramter, and is used every given number of reorderings instead of maxGrowth. The number of reorderings is set with Cudd_SetReorderingCycle. If the number of reorderings is 0 (default) maxGrowthAlt is never used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowth">Cudd_SetMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_SetReorderingCycle">Cudd_SetReorderingCycle</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingCycle">Cudd_ReadReorderingCycle</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxGrowth"><b>Cudd_SetMaxGrowth</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  double  <b>mg</b> <i></i>
+)
+</pre>
+<dd> Sets the maxGrowth parameter of the manager. This parameter determines how much the number of nodes can grow during sifting of a variable. Overall, sifting never increases the size of the decision diagrams. This parameter only refers to intermediate results. A lower value will speed up sifting, possibly at the expense of quality.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowth">Cudd_ReadMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxLive"><b>Cudd_SetMaxLive</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>maxLive</b> <i></i>
+)
+</pre>
+<dd> Sets the maximum allowed number of live nodes. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxLive">Cudd_ReadMaxLive</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxMemory"><b>Cudd_SetMaxMemory</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned long  <b>maxMemory</b> <i></i>
+)
+</pre>
+<dd> Sets the maximum allowed memory. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxMemory">Cudd_ReadMaxMemory</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMinHit"><b>Cudd_SetMinHit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>hr</b> <i></i>
+)
+</pre>
+<dd> Sets the minHit parameter of the manager. This parameter controls the resizing of the computed table. If the hit rate is larger than the specified value, and the cache is not already too large, then its size is doubled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMinHit">Cudd_ReadMinHit</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetNextReordering"><b>Cudd_SetNextReordering</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>next</b> <i></i>
+)
+</pre>
+<dd> Sets the threshold for the next dynamic reordering. The threshold is in terms of number of nodes and is in effect only if reordering is enabled. The count does not include the dead nodes, unless the countDead parameter of the manager has been changed from its default setting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNextReordering">Cudd_ReadNextReordering</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetNumberXovers"><b>Cudd_SetNumberXovers</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>numberXovers</b> <i></i>
+)
+</pre>
+<dd> Sets the number of crossovers used by the genetic algorithm for variable reordering. A larger number of crossovers will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as number of crossovers, with a maximum of 60.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNumberXovers">Cudd_ReadNumberXovers</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetPopulationSize"><b>Cudd_SetPopulationSize</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>populationSize</b> <i></i>
+)
+</pre>
+<dd> Sets the size of the population used by the genetic algorithm for variable reordering. A larger population size will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as population size, with a maximum of 120.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPopulationSize">Cudd_ReadPopulationSize</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetRecomb"><b>Cudd_SetRecomb</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>recomb</b> <i></i>
+)
+</pre>
+<dd> Sets the value of the recombination parameter used in group sifting. A larger (positive) value makes the aggregation of variables due to the second difference criterion more likely. A smaller (negative) value makes aggregation less likely. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadRecomb">Cudd_ReadRecomb</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetReorderingCycle"><b>Cudd_SetReorderingCycle</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>cycle</b> <i></i>
+)
+</pre>
+<dd> Sets the reordCycle parameter of the manager. This parameter determines how often the alternate threshold on maximum growth is used in reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingCycle">Cudd_ReadReorderingCycle</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetSiftMaxSwap"><b>Cudd_SetSiftMaxSwap</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>sms</b> <i></i>
+)
+</pre>
+<dd> Sets the siftMaxSwap parameter of the manager. This parameter gives the maximum number of swaps that will be attempted for each invocation of sifting. The real number of swaps may exceed the set limit because the package will always complete the sifting of the variable that causes the limit to be reached.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetSiftMaxVar">Cudd_SetSiftMaxVar</a>
+<a href="cuddAllDet.html#Cudd_ReadSiftMaxSwap">Cudd_ReadSiftMaxSwap</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetSiftMaxVar"><b>Cudd_SetSiftMaxVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>smv</b> <i></i>
+)
+</pre>
+<dd> Sets the siftMaxVar parameter of the manager. This parameter gives the maximum number of variables that will be sifted for each invocation of sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetSiftMaxSwap">Cudd_SetSiftMaxSwap</a>
+<a href="cuddAllDet.html#Cudd_ReadSiftMaxVar">Cudd_ReadSiftMaxVar</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetStderr"><b>Cudd_SetStderr</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Sets the stderr of a manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadStderr">Cudd_ReadStderr</a>
+<a href="cuddAllDet.html#Cudd_SetStdout">Cudd_SetStdout</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetStdout"><b>Cudd_SetStdout</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Sets the stdout of a manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadStdout">Cudd_ReadStdout</a>
+<a href="cuddAllDet.html#Cudd_SetStderr">Cudd_SetStderr</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetSymmviolation"><b>Cudd_SetSymmviolation</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>symmviolation</b> <i></i>
+)
+</pre>
+<dd> Sets the value of the symmviolation parameter. This parameter is used in group sifting to decide how many violations to the symmetry conditions <code>f10 = f01</code> or <code>f11 = f00</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSymmviolation">Cudd_ReadSymmviolation</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetTree"><b>Cudd_SetTree</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  MtrNode * <b>tree</b> <i></i>
+)
+</pre>
+<dd> Sets the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FreeTree">Cudd_FreeTree</a>
+<a href="cuddAllDet.html#Cudd_ReadTree">Cudd_ReadTree</a>
+<a href="cuddAllDet.html#Cudd_SetZddTree">Cudd_SetZddTree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_SetVarMap"><b>Cudd_SetVarMap</b></a>(
+  DdManager * <b>manager</b>, <i>DD manager</i>
+  DdNode ** <b>x</b>, <i>first array of variables</i>
+  DdNode ** <b>y</b>, <i>second array of variables</i>
+  int  <b>n</b> <i>length of both arrays</i>
+)
+</pre>
+<dd> Registers with the manager a variable mapping described by two sets of variables. This variable mapping is then used by functions like Cudd_bddVarMap. This function is convenient for those applications that perform the same mapping several times. However, if several different permutations are used, it may be more efficient not to rely on the registered mapping, because changing mapping causes the cache to be cleared. (The initial setting, however, does not clear the cache.) The two sets of variables (x and y) must have the same size (x and y). The size is given by n. The two sets of variables are normally disjoint, but this restriction is not imposeded by the function. When new variables are created, the map is automatically extended (each new variable maps to itself). The typical use, however, is to wait until all variables are created, and then create the map. Returns 1 if the mapping is successfully registered with the manager; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Modifies the manager. May clear the cache.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddVarMap">Cudd_bddVarMap</a>
+<a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetZddTree"><b>Cudd_SetZddTree</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  MtrNode * <b>tree</b> <i></i>
+)
+</pre>
+<dd> Sets the ZDD variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FreeZddTree">Cudd_FreeZddTree</a>
+<a href="cuddAllDet.html#Cudd_ReadZddTree">Cudd_ReadZddTree</a>
+<a href="cuddAllDet.html#Cudd_SetTree">Cudd_SetTree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_SharingSize"><b>Cudd_SharingSize</b></a>(
+  DdNode ** <b>nodeArray</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Counts the number of nodes in an array of DDs. Shared nodes are counted only once. Returns the total number of nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ShortestLength"><b>Cudd_ShortestLength</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>weight</b> <i></i>
+)
+</pre>
+<dd> Find the length of the shortest path(s) in a DD. f is the DD we want to get the shortest path for; weight[i] is the weight of the THEN edge coming from the node whose index is i. All ELSE edges have 0 weight. Returns the length of the shortest path(s) if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ShortestPath">Cudd_ShortestPath</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ShortestPath"><b>Cudd_ShortestPath</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>weight</b>, <i></i>
+  int * <b>support</b>, <i></i>
+  int * <b>length</b> <i></i>
+)
+</pre>
+<dd> Finds a shortest path in a DD. f is the DD we want to get the shortest path for; weight[i] is the weight of the THEN arc coming from the node whose index is i. If weight is NULL, then unit weights are assumed for all THEN arcs. All ELSE arcs have 0 weight. If non-NULL, both weight and support should point to arrays with at least as many entries as there are variables in the manager. Returns the shortest path as the BDD of a cube.
+<p>
+
+<dd> <b>Side Effects</b> support contains on return the true support of f. If support is NULL on entry, then Cudd_ShortestPath does not compute the true support info. length contains the length of the path.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ShortestLength">Cudd_ShortestLength</a>
+<a href="cuddAllDet.html#Cudd_LargestCube">Cudd_LargestCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ShuffleHeap"><b>Cudd_ShuffleHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  int * <b>permutation</b> <i>required variable permutation</i>
+)
+</pre>
+<dd> Reorders variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Changes the variable order for all diagrams and clears the cache.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReduceHeap">Cudd_ReduceHeap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SolveEqn"><b>Cudd_SolveEqn</b></a>(
+  DdManager * <b>bdd</b>, <i></i>
+  DdNode * <b>F</b>, <i>the left-hand side of the equation</i>
+  DdNode * <b>Y</b>, <i>the cube of the y variables</i>
+  DdNode ** <b>G</b>, <i>the array of solutions (return parameter)</i>
+  int ** <b>yIndex</b>, <i>index of y variables</i>
+  int  <b>n</b> <i>numbers of unknowns</i>
+)
+</pre>
+<dd> Implements the solution for F(x,y) = 0. The return value is the consistency condition. The y variables are the unknowns and the remaining variables are the parameters. Returns the consistency condition if successful; NULL otherwise. Cudd_SolveEqn allocates an array and fills it with the indices of the unknowns. This array is used by Cudd_VerifySol.
+<p>
+
+<dd> <b>Side Effects</b> The solution is returned in G; the indices of the y variables are returned in yIndex.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_VerifySol">Cudd_VerifySol</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SplitSet"><b>Cudd_SplitSet</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>S</b>, <i></i>
+  DdNode ** <b>xVars</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  double  <b>m</b> <i></i>
+)
+</pre>
+<dd> Returns <code>m</code> minterms from a BDD whose support has <code>n</code> variables at most. The procedure tries to create as few extra nodes as possible. The function represented by <code>S</code> depends on at most <code>n</code> of the variables in <code>xVars</code>. Returns a BDD with <code>m</code> minterms of the on-set of S if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Srandom"><b>Cudd_Srandom</b></a>(
+  long  <b>seed</b> <i></i>
+)
+</pre>
+<dd> Initializer for the portable number generator based on ran2 in "Numerical Recipes in C." The input is the seed for the generator. If it is negative, its absolute value is taken as seed. If it is 0, then 1 is taken as seed. The initialized sets up the two recurrences used to generate a long-period stream, and sets up the shuffle table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Random">Cudd_Random</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_StdPostReordHook"><b>Cudd_StdPostReordHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  const char * <b>str</b>, <i></i>
+  void * <b>data</b> <i></i>
+)
+</pre>
+<dd> Sample hook function to call after reordering. Prints on the manager's stdout final size and reordering time. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_StdPreReordHook">Cudd_StdPreReordHook</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_StdPreReordHook"><b>Cudd_StdPreReordHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  const char * <b>str</b>, <i></i>
+  void * <b>data</b> <i></i>
+)
+</pre>
+<dd> Sample hook function to call before reordering. Prints on the manager's stdout reordering method and initial size. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_StdPostReordHook">Cudd_StdPostReordHook</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetCompress"><b>Cudd_SubsetCompress</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>BDD whose subset is sought</i>
+  int  <b>nvars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the subset</i>
+)
+</pre>
+<dd> Finds a dense subset of BDD <code>f</code>. Density is the ratio of number of minterms to number of nodes. Uses several techniques in series. It is more expensive than other subsetting procedures, but often produces better results. See Cudd_SubsetShortPaths for a description of the threshold and nvars parameters. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetRemap">Cudd_SubsetRemap</a>
+<a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetHeavyBranch"><b>Cudd_SubsetHeavyBranch</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the subset</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure builds a subset by throwing away one of the children of each node, starting from the root, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetShortPaths"><b>Cudd_SubsetShortPaths</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>maximum number of nodes in the subset</i>
+  int  <b>hardlimit</b> <i>flag: 1 if threshold is a hard limit</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure tries to preserve the shortest paths of the input BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the subset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the subset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVars. If 0 is passed, then the value returned by Cudd_ReadSize is used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetWithMaskVars"><b>Cudd_SubsetWithMaskVars</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function from which to pick a cube</i>
+  DdNode ** <b>vars</b>, <i>array of variables</i>
+  int  <b>nvars</b>, <i>size of <code>vars</code></i>
+  DdNode ** <b>maskVars</b>, <i>array of variables</i>
+  int  <b>mvars</b> <i>size of <code>maskVars</code></i>
+)
+</pre>
+<dd> Extracts a subset from a BDD in the following procedure. 1. Compute the weight for each mask variable by counting the number of minterms for both positive and negative cofactors of the BDD with respect to each mask variable. (weight = #positive - #negative) 2. Find a representative cube of the BDD by using the weight. From the top variable of the BDD, for each variable, if the weight is greater than 0.0, choose THEN branch, othereise ELSE branch, until meeting the constant 1. 3. Quantify out the variables not in maskVars from the representative cube and if a variable in maskVars is don't care, replace the variable with a constant(1 or 0) depending on the weight. 4. Make a subset of the BDD by multiplying with the modified cube.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SupersetCompress"><b>Cudd_SupersetCompress</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>BDD whose superset is sought</i>
+  int  <b>nvars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the superset</i>
+)
+</pre>
+<dd> Finds a dense superset of BDD <code>f</code>. Density is the ratio of number of minterms to number of nodes. Uses several techniques in series. It is more expensive than other supersetting procedures, but often produces better results. See Cudd_SupersetShortPaths for a description of the threshold and nvars parameters. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetCompress">Cudd_SubsetCompress</a>
+<a href="cuddAllDet.html#Cudd_SupersetRemap">Cudd_SupersetRemap</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SupersetHeavyBranch"><b>Cudd_SupersetHeavyBranch</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the superset</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure builds a superset by throwing away one of the children of each node starting from the root of the complement function, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SupersetShortPaths"><b>Cudd_SupersetShortPaths</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>maximum number of nodes in the subset</i>
+  int  <b>hardlimit</b> <i>flag: 1 if threshold is a hard limit</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure tries to preserve the shortest paths of the complement BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the superset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the superset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVar. If 0 is passed, then the value returned by Cudd_ReadSize is used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+int * <i></i>
+<a name="Cudd_SupportIndex"><b>Cudd_SupportIndex</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b> <i>DD whose support is sought</i>
+)
+</pre>
+<dd> Finds the variables on which a DD depends. Returns an index array of the variables if successful; NULL otherwise. The size of the array equals the number of variables in the manager. Each entry of the array is 1 if the corresponding variable is in the support of the DD and 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+<a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_SupportSize"><b>Cudd_SupportSize</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b> <i>DD whose support size is sought</i>
+)
+</pre>
+<dd> Counts the variables on which a DD depends. Returns the number of the variables if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Support"><b>Cudd_Support</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b> <i>DD whose support is sought</i>
+)
+</pre>
+<dd> Finds the variables on which a DD depends. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SymmProfile"><b>Cudd_SymmProfile</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Prints statistics on symmetric variables.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_TurnOffCountDead"><b>Cudd_TurnOffCountDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Causes the dead nodes not to be counted towards triggering reordering. This causes less frequent reorderings. By default dead nodes are not counted. Therefore there is no need to call this function unless Cudd_TurnOnCountDead has been previously called.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_TurnOnCountDead">Cudd_TurnOnCountDead</a>
+<a href="cuddAllDet.html#Cudd_DeadAreCounted">Cudd_DeadAreCounted</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_TurnOnCountDead"><b>Cudd_TurnOnCountDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Causes the dead nodes to be counted towards triggering reordering. This causes more frequent reorderings. By default dead nodes are not counted.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_TurnOffCountDead">Cudd_TurnOffCountDead</a>
+<a href="cuddAllDet.html#Cudd_DeadAreCounted">Cudd_DeadAreCounted</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_T"><b>Cudd_T</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the then child of an internal node. If <code>node</code> is a constant node, the result is unpredictable.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_E">Cudd_E</a>
+<a href="cuddAllDet.html#Cudd_V">Cudd_V</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_UnderApprox"><b>Cudd_UnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  int  <b>safe</b>, <i>enforce safe approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure uses a variant of Tom Shiple's underapproximation method. The main difference from the original method is that density is used as cost function. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+int * <i></i>
+<a name="Cudd_VectorSupportIndex"><b>Cudd_VectorSupportIndex</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode ** <b>F</b>, <i>array of DDs whose support is sought</i>
+  int  <b>n</b> <i>size of the array</i>
+)
+</pre>
+<dd> Finds the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns an index array of the variables if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupportIndex">Cudd_SupportIndex</a>
+<a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_VectorSupportSize"><b>Cudd_VectorSupportSize</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode ** <b>F</b>, <i>array of DDs whose support is sought</i>
+  int  <b>n</b> <i>size of the array</i>
+)
+</pre>
+<dd> Counts the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns the number of the variables if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_SupportSize">Cudd_SupportSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_VectorSupport"><b>Cudd_VectorSupport</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode ** <b>F</b>, <i>array of DDs whose support is sought</i>
+  int  <b>n</b> <i>size of the array</i>
+)
+</pre>
+<dd> Finds the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_VerifySol"><b>Cudd_VerifySol</b></a>(
+  DdManager * <b>bdd</b>, <i></i>
+  DdNode * <b>F</b>, <i>the left-hand side of the equation</i>
+  DdNode ** <b>G</b>, <i>the array of solutions</i>
+  int * <b>yIndex</b>, <i>index of y variables</i>
+  int  <b>n</b> <i>numbers of unknowns</i>
+)
+</pre>
+<dd> Checks the solution of F(x,y) = 0. This procedure substitutes the solution components for the unknowns of F and returns the resulting BDD for F.
+<p>
+
+<dd> <b>Side Effects</b> Frees the memory pointed by yIndex.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SolveEqn">Cudd_SolveEqn</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_V"><b>Cudd_V</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the value of a constant node. If <code>node</code> is an internal node, the result is unpredictable.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_T">Cudd_T</a>
+<a href="cuddAllDet.html#Cudd_E">Cudd_E</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Xeqy"><b>Cudd_Xeqy</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x and y variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b> <i>array of y variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function x==y. Both x and y are N-bit numbers, x[0] x[1] ... x[N-1] and y[0] y[1] ... y[N-1], with 0 the most significant bit. The BDD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x[0] y[0] x[1] y[1] ... x[N-1] y[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addXeqy">Cudd_addXeqy</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Xgty"><b>Cudd_Xgty</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x and y variables</i>
+  DdNode ** <b>z</b>, <i>array of z variables: unused</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b> <i>array of y variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function x &gt; y. Both x and y are N-bit numbers, x[0] x[1] ... x[N-1] and y[0] y[1] ... y[N-1], with 0 the most significant bit. The BDD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x[0] y[0] x[1] y[1] ... x[N-1] y[N-1]. Argument z is not used by Cudd_Xgty: it is included to make it call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addAgreement"><b>Cudd_addAgreement</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns NULL if not a terminal case; f op g otherwise, where f op g is f if f==g; background if f!=g.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addApply"><b>Cudd_addApply</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_AOP  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Applies op to the corresponding discriminants of f and g. Returns a pointer to the result if succssful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMonadicApply">Cudd_addMonadicApply</a>
+<a href="cuddAllDet.html#Cudd_addPlus">Cudd_addPlus</a>
+<a href="cuddAllDet.html#Cudd_addTimes">Cudd_addTimes</a>
+<a href="cuddAllDet.html#Cudd_addThreshold">Cudd_addThreshold</a>
+<a href="cuddAllDet.html#Cudd_addSetNZ">Cudd_addSetNZ</a>
+<a href="cuddAllDet.html#Cudd_addDivide">Cudd_addDivide</a>
+<a href="cuddAllDet.html#Cudd_addMinus">Cudd_addMinus</a>
+<a href="cuddAllDet.html#Cudd_addMinimum">Cudd_addMinimum</a>
+<a href="cuddAllDet.html#Cudd_addMaximum">Cudd_addMaximum</a>
+<a href="cuddAllDet.html#Cudd_addOneZeroMaximum">Cudd_addOneZeroMaximum</a>
+<a href="cuddAllDet.html#Cudd_addDiff">Cudd_addDiff</a>
+<a href="cuddAllDet.html#Cudd_addAgreement">Cudd_addAgreement</a>
+<a href="cuddAllDet.html#Cudd_addOr">Cudd_addOr</a>
+<a href="cuddAllDet.html#Cudd_addNand">Cudd_addNand</a>
+<a href="cuddAllDet.html#Cudd_addNor">Cudd_addNor</a>
+<a href="cuddAllDet.html#Cudd_addXor">Cudd_addXor</a>
+<a href="cuddAllDet.html#Cudd_addXnor">Cudd_addXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddInterval"><b>Cudd_addBddInterval</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>lower</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants greater than or equal to lower and less than or equal to upper with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddIthBit"><b>Cudd_addBddIthBit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>bit</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants whose i-th bit is equal to 1 with 1, and all other discriminants with 0. The i-th bit refers to the integer representation of the leaf value. If the value is has a fractional part, it is ignored. Repeated calls to this procedure allow one to transform an integer-valued ADD into an array of BDDs, one for each bit of the leaf values. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddPattern"><b>Cudd_addBddPattern</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants different from 0 with 1. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+<a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddStrictThreshold"><b>Cudd_addBddStrictThreshold</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>value</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants STRICTLY greater than value with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+<a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddThreshold"><b>Cudd_addBddThreshold</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>value</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants greater than or equal to value with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addCmpl"><b>Cudd_addCmpl</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Computes the complement of an ADD a la C language: The complement of 0 is 1 and the complement of everything else is 0. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNegate">Cudd_addNegate</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addCompose"><b>Cudd_addCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  int  <b>v</b> <i></i>
+)
+</pre>
+<dd> Substitutes g for x_v in the ADD for f. v is the index of the variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes the corresponding projection function to the recursive procedure, so that the cache may be used. Returns the composed ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddCompose">Cudd_bddCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addComputeCube"><b>Cudd_addComputeCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>vars</b>, <i></i>
+  int * <b>phase</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Computes the cube of an array of ADD variables. If non-null, the phase argument indicates which literal of each variable should appear in the cube. If phase[i] is nonzero, then the positive literal is used. If phase is NULL, the cube is positive unate. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddComputeCube">Cudd_bddComputeCube</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addConstrain"><b>Cudd_addConstrain</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Computes f constrain c (f @ c), for f an ADD and c a 0-1 ADD. List of special cases: <ul> <li> F @ 0 = 0 <li> F @ 1 = F <li> 0 @ c = 0 <li> 1 @ c = 1 <li> F @ F = 1 </ul> Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addConst"><b>Cudd_addConst</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>c</b> <i></i>
+)
+</pre>
+<dd> Retrieves the ADD for constant c if it already exists, or creates a new ADD. Returns a pointer to the ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addDiff"><b>Cudd_addDiff</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns NULL if not a terminal case; f op g otherwise, where f op g is plusinfinity if f=g; min(f,g) if f!=g.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addDivide"><b>Cudd_addDivide</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point division. Returns NULL if not a terminal case; f / g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addEvalConst"><b>Cudd_addEvalConst</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Checks whether ADD g is constant whenever ADD f is 1. f must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may or may not be constant) or DD_NON_CONSTANT. If f is identically 0, the check is assumed to be successful, and the background value is returned. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addLeq">Cudd_addLeq</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addExistAbstract"><b>Cudd_addExistAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Abstracts all the variables in cube from f by summing over all possible values taken by the variables. Returns the abstracted ADD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addUnivAbstract">Cudd_addUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_addOrAbstract">Cudd_addOrAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addFindMax"><b>Cudd_addFindMax</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns a pointer to a constant ADD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addFindMin"><b>Cudd_addFindMin</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns a pointer to a constant ADD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addGeneralVectorCompose"><b>Cudd_addGeneralVectorCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vectorOn</b>, <i></i>
+  DdNode ** <b>vectorOff</b> <i></i>
+)
+</pre>
+<dd> Given a vector of ADDs, creates a new ADD by substituting the ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted for the x_v and vectorOff the ADDs to be substituted for x_v'. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addVectorCompose">Cudd_addVectorCompose</a>
+<a href="cuddAllDet.html#Cudd_addNonSimCompose">Cudd_addNonSimCompose</a>
+<a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+<a href="cuddAllDet.html#Cudd_bddVectorCompose">Cudd_bddVectorCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addHamming"><b>Cudd_addHamming</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>xVars</b>, <i></i>
+  DdNode ** <b>yVars</b>, <i></i>
+  int  <b>nVars</b> <i></i>
+)
+</pre>
+<dd> Computes the Hamming distance ADD. Returns an ADD that gives the Hamming distance between its two arguments if successful; NULL otherwise. The two vectors xVars and yVars identify the variables that form the two arguments.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_addHarwell"><b>Cudd_addHarwell</b></a>(
+  FILE * <b>fp</b>, <i>pointer to the input file</i>
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode ** <b>E</b>, <i>characteristic function of the graph</i>
+  DdNode *** <b>x</b>, <i>array of row variables</i>
+  DdNode *** <b>y</b>, <i>array of column variables</i>
+  DdNode *** <b>xn</b>, <i>array of complemented row variables</i>
+  DdNode *** <b>yn_</b>, <i>array of complemented column variables</i>
+  int * <b>nx</b>, <i>number or row variables</i>
+  int * <b>ny</b>, <i>number or column variables</i>
+  int * <b>m</b>, <i>number of rows</i>
+  int * <b>n</b>, <i>number of columns</i>
+  int  <b>bx</b>, <i>first index of row variables</i>
+  int  <b>sx</b>, <i>step of row variables</i>
+  int  <b>by</b>, <i>first index of column variables</i>
+  int  <b>sy</b>, <i>step of column variables</i>
+  int  <b>pr</b> <i>verbosity level</i>
+)
+</pre>
+<dd> Reads in a matrix in the format of the Harwell-Boeing benchmark suite. The variables are ordered as follows: <blockquote> x[0] y[0] x[1] y[1] ... </blockquote> 0 is the most significant bit. On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. Returns 1 on success; 0 otherwise. The ADD for the sparse matrix is returned in E, and its reference count is > 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addRead">Cudd_addRead</a>
+<a href="cuddAllDet.html#Cudd_bddRead">Cudd_bddRead</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIteConstant"><b>Cudd_addIteConstant</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITEconstant for ADDs. f must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may or may not be constant) or DD_NON_CONSTANT. No new nodes are created. This function can be used, for instance, to check that g has a constant value (specified by h) whenever f is 1. If the constant value is unknown, then one should use Cudd_addEvalConst.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIte">Cudd_addIte</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIte"><b>Cudd_addIte</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITE(f,g,h). This procedure assumes that f is a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIthBit"><b>Cudd_addIthBit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>bit</b> <i></i>
+)
+</pre>
+<dd> Produces an ADD from another ADD by replacing all discriminants whose i-th bit is equal to 1 with 1, and all other discriminants with 0. The i-th bit refers to the integer representation of the leaf value. If the value is has a fractional part, it is ignored. Repeated calls to this procedure allow one to transform an integer-valued ADD into an array of ADDs, one for each bit of the leaf values. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddIthBit">Cudd_addBddIthBit</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIthVar"><b>Cudd_addIthVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Retrieves the ADD variable with index i if it already exists, or creates a new ADD variable. Returns a pointer to the variable if successful; NULL otherwise. An ADD variable differs from a BDD variable because it points to the arithmetic zero, instead of having a complement pointer to 1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_addConst">Cudd_addConst</a>
+<a href="cuddAllDet.html#Cudd_addNewVarAtLevel">Cudd_addNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_addLeq"><b>Cudd_addLeq</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created. This procedure works for arbitrary ADDs. For 0-1 ADDs Cudd_addEvalConst is more efficient.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+<a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addLog"><b>Cudd_addLog</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Natural logarithm of an ADDs. Returns NULL if not a terminal case; log(f) otherwise. The discriminants of f must be positive double's.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMonadicApply">Cudd_addMonadicApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMatrixMultiply"><b>Cudd_addMatrixMultiply</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>A</b>, <i></i>
+  DdNode * <b>B</b>, <i></i>
+  DdNode ** <b>z</b>, <i></i>
+  int  <b>nz</b> <i></i>
+)
+</pre>
+<dd> Calculates the product of two matrices, A and B, represented as ADDs. This procedure implements the quasiring multiplication algorithm. A is assumed to depend on variables x (rows) and z (columns). B is assumed to depend on variables z (rows) and y (columns). The product of A and B then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "summation" variables. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addTimesPlus">Cudd_addTimesPlus</a>
+<a href="cuddAllDet.html#Cudd_addTriangle">Cudd_addTriangle</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMaximum"><b>Cudd_addMaximum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point max for Cudd_addApply. Returns NULL if not a terminal case; max(f,g) otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMinimum"><b>Cudd_addMinimum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point min for Cudd_addApply. Returns NULL if not a terminal case; min(f,g) otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMinus"><b>Cudd_addMinus</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point subtraction. Returns NULL if not a terminal case; f - g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMonadicApply"><b>Cudd_addMonadicApply</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_MAOP  <b>op</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Applies op to the discriminants of f. Returns a pointer to the result if succssful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_addLog">Cudd_addLog</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNand"><b>Cudd_addNand</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> NAND of two 0-1 ADDs. Returns NULL if not a terminal case; f NAND g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNegate"><b>Cudd_addNegate</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Computes the additive inverse of an ADD. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addCmpl">Cudd_addCmpl</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNewVarAtLevel"><b>Cudd_addNewVarAtLevel</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>level</b> <i></i>
+)
+</pre>
+<dd> Creates a new ADD variable. The new variable has an index equal to the largest previous index plus 1 and is positioned at the specified level in the order. Returns a pointer to the new variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNewVar"><b>Cudd_addNewVar</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Creates a new ADD variable. The new variable has an index equal to the largest previous index plus 1. Returns a pointer to the new variable if successful; NULL otherwise. An ADD variable differs from a BDD variable because it points to the arithmetic zero, instead of having a complement pointer to 1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+<a href="cuddAllDet.html#Cudd_addConst">Cudd_addConst</a>
+<a href="cuddAllDet.html#Cudd_addNewVarAtLevel">Cudd_addNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNonSimCompose"><b>Cudd_addNonSimCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vector</b> <i></i>
+)
+</pre>
+<dd> Given a vector of 0-1 ADDs, creates a new ADD by substituting the 0-1 ADDs for the variables of the ADD f. There should be an entry in vector for each variable in the manager. This function implements non-simultaneous composition. If any of the functions being composed depends on any of the variables being substituted, then the result depends on the order of composition, which in turn depends on the variable order: The variables farther from the roots in the order are substituted first. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addVectorCompose">Cudd_addVectorCompose</a>
+<a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNor"><b>Cudd_addNor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> NOR of two 0-1 ADDs. Returns NULL if not a terminal case; f NOR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOneZeroMaximum"><b>Cudd_addOneZeroMaximum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f &gt; g and 0 otherwise. Used in conjunction with Cudd_addApply. Returns NULL if not a terminal case.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOrAbstract"><b>Cudd_addOrAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Abstracts all the variables in cube from the 0-1 ADD f by taking the disjunction over all possible values taken by the variables. Returns the abstracted ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addUnivAbstract">Cudd_addUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_addExistAbstract">Cudd_addExistAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOr"><b>Cudd_addOr</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Disjunction of two 0-1 ADDs. Returns NULL if not a terminal case; f OR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOuterSum"><b>Cudd_addOuterSum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>M</b>, <i></i>
+  DdNode * <b>r</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Takes the pointwise minimum of a matrix and the outer sum of two vectors. This procedure is used in the Floyd-Warshall all-pair shortest path algorithm. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addPermute"><b>Cudd_addPermute</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int * <b>permut</b> <i></i>
+)
+</pre>
+<dd> Given a permutation in array permut, creates a new ADD with permuted variables. There should be an entry in array permut for each variable in the manager. The i-th entry of permut holds the index of the variable that is to substitute the i-th variable. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_addSwapVariables">Cudd_addSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addPlus"><b>Cudd_addPlus</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point addition. Returns NULL if not a terminal case; f+g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_addRead"><b>Cudd_addRead</b></a>(
+  FILE * <b>fp</b>, <i>input file pointer</i>
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode ** <b>E</b>, <i>characteristic function of the graph</i>
+  DdNode *** <b>x</b>, <i>array of row variables</i>
+  DdNode *** <b>y</b>, <i>array of column variables</i>
+  DdNode *** <b>xn</b>, <i>array of complemented row variables</i>
+  DdNode *** <b>yn_</b>, <i>array of complemented column variables</i>
+  int * <b>nx</b>, <i>number or row variables</i>
+  int * <b>ny</b>, <i>number or column variables</i>
+  int * <b>m</b>, <i>number of rows</i>
+  int * <b>n</b>, <i>number of columns</i>
+  int  <b>bx</b>, <i>first index of row variables</i>
+  int  <b>sx</b>, <i>step of row variables</i>
+  int  <b>by</b>, <i>first index of column variables</i>
+  int  <b>sy</b> <i>step of column variables</i>
+)
+</pre>
+<dd> Reads in a sparse matrix specified in a simple format. The first line of the input contains the numbers of rows and columns. The remaining lines contain the elements of the matrix, one per line. Given a background value (specified by the background field of the manager), only the values different from it are explicitly listed. Each foreground element is described by two integers, i.e., the row and column number, and a real number, i.e., the value.<p> Cudd_addRead produces an ADD that depends on two sets of variables: x and y. The x variables (x[0] ... x[nx-1]) encode the row index and the y variables (y[0] ... y[ny-1]) encode the column index. x[0] and y[0] are the most significant bits in the indices. The variables may already exist or may be created by the function. The index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy.<p> On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. When Cudd_addRead creates the variable arrays, the index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy. When some variables already exist Cudd_addRead expects the indices of the existing x variables to be bx+i*sx, and the indices of the existing y variables to be by+i*sy.<p> m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. The ADD for the sparse matrix is returned in E, and its reference count is > 0. Cudd_addRead returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> nx and ny are set to the numbers of row and column variables. m and n are set to the numbers of rows and columns. x and y are possibly extended to represent the array of row and column variables. Similarly for xn and yn_, which hold on return from Cudd_addRead the complements of the row and column variables.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addHarwell">Cudd_addHarwell</a>
+<a href="cuddAllDet.html#Cudd_bddRead">Cudd_bddRead</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addResidue"><b>Cudd_addResidue</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of bits</i>
+  int  <b>m</b>, <i>modulus</i>
+  int  <b>options</b>, <i>options</i>
+  int  <b>top</b> <i>index of top variable</i>
+)
+</pre>
+<dd> Builds an ADD for the residue modulo m of an n-bit number. The modulus must be at least 2, and the number of bits at least 1. Parameter options specifies whether the MSB should be on top or the LSB; and whther the number whose residue is computed is in two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's complement residue. To request MSB on top and two's complement residue simultaneously, one can OR the two macros: CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC. Cudd_addResidue returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addRestrict"><b>Cudd_addRestrict</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> ADD restrict according to Coudert and Madre's algorithm (ICCAD90). Returns the restricted ADD if successful; otherwise NULL. If application of restrict results in an ADD larger than the input ADD, the input ADD is returned.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addConstrain">Cudd_addConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addRoundOff"><b>Cudd_addRoundOff</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>N</b> <i></i>
+)
+</pre>
+<dd> Rounds off the discriminants of an ADD. The discriminants are rounded off to N digits after the decimal. Returns a pointer to the result ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addScalarInverse"><b>Cudd_addScalarInverse</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>epsilon</b> <i></i>
+)
+</pre>
+<dd> Computes an n ADD where the discriminants are the multiplicative inverses of the corresponding discriminants of the argument ADD. Returns a pointer to the resulting ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addSetNZ"><b>Cudd_addSetNZ</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> This operator sets f to the value of g wherever g != 0. Returns NULL if not a terminal case; f op g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addSwapVariables"><b>Cudd_addSwapVariables</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  DdNode ** <b>y</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Swaps two sets of variables of the same size (x and y) in the ADD f. The size is given by n. The two sets of variables are assumed to be disjoint. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addThreshold"><b>Cudd_addThreshold</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g). Returns NULL if not a terminal case; f op g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addTimesPlus"><b>Cudd_addTimesPlus</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>A</b>, <i></i>
+  DdNode * <b>B</b>, <i></i>
+  DdNode ** <b>z</b>, <i></i>
+  int  <b>nz</b> <i></i>
+)
+</pre>
+<dd> Calculates the product of two matrices, A and B, represented as ADDs, using the CMU matrix by matrix multiplication procedure by Clarke et al.. Matrix A has x's as row variables and z's as column variables, while matrix B has z's as row variables and y's as column variables. Returns the pointer to the result if successful; NULL otherwise. The resulting matrix has x's as row variables and y's as column variables.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMatrixMultiply">Cudd_addMatrixMultiply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addTimes"><b>Cudd_addTimes</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point multiplication. Returns NULL if not a terminal case; f * g otherwise. This function can be used also to take the AND of two 0-1 ADDs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addTriangle"><b>Cudd_addTriangle</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode ** <b>z</b>, <i></i>
+  int  <b>nz</b> <i></i>
+)
+</pre>
+<dd> Implements the semiring multiplication algorithm used in the triangulation step for the shortest path computation. f is assumed to depend on variables x (rows) and z (columns). g is assumed to depend on variables z (rows) and y (columns). The product of f and g then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "abstraction" variables. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMatrixMultiply">Cudd_addMatrixMultiply</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addUnivAbstract"><b>Cudd_addUnivAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Abstracts all the variables in cube from f by taking the product over all possible values taken by the variable. Returns the abstracted ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addExistAbstract">Cudd_addExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddUnivAbstract">Cudd_bddUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_addOrAbstract">Cudd_addOrAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addVectorCompose"><b>Cudd_addVectorCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vector</b> <i></i>
+)
+</pre>
+<dd> Given a vector of 0-1 ADDs, creates a new ADD by substituting the 0-1 ADDs for the variables of the ADD f. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNonSimCompose">Cudd_addNonSimCompose</a>
+<a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+<a href="cuddAllDet.html#Cudd_bddVectorCompose">Cudd_bddVectorCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addWalsh"><b>Cudd_addWalsh</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  DdNode ** <b>y</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Generates a Walsh matrix in ADD form. Returns a pointer to the matrixi if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addXeqy"><b>Cudd_addXeqy</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x and y variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b> <i>array of y variables</i>
+)
+</pre>
+<dd> This function generates an ADD for the function x==y. Both x and y are N-bit numbers, x[0] x[1] ... x[N-1] and y[0] y[1] ... y[N-1], with 0 the most significant bit. The ADD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x[0] y[0] x[1] y[1] ... x[N-1] y[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Xeqy">Cudd_Xeqy</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addXnor"><b>Cudd_addXnor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> XNOR of two 0-1 ADDs. Returns NULL if not a terminal case; f XNOR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addXor"><b>Cudd_addXor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> XOR of two 0-1 ADDs. Returns NULL if not a terminal case; f XOR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAdjPermuteX"><b>Cudd_bddAdjPermuteX</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>B</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Rearranges a set of variables in the BDD B. The size of the set is given by n. This procedure is intended for the `randomization' of the priority functions. Returns a pointer to the BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+<a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAndAbstractLimit"><b>Cudd_bddAndAbstractLimit</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b>, <i></i>
+  unsigned int  <b>limit</b> <i></i>
+)
+</pre>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise. In particular, if the number of new nodes created exceeds <code>limit</code>, this function returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAndAbstract"><b>Cudd_bddAndAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise. Cudd_bddAndAbstract implements the semiring matrix multiplication algorithm for the boolean semiring.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMatrixMultiply">Cudd_addMatrixMultiply</a>
+<a href="cuddAllDet.html#Cudd_addTriangle">Cudd_addTriangle</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAndLimit"><b>Cudd_bddAndLimit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  unsigned int  <b>limit</b> <i></i>
+)
+</pre>
+<dd> Computes the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up or more new nodes than <code>limit</code> are required.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAnd"><b>Cudd_bddAnd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddIntersect">Cudd_bddIntersect</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddApproxConjDecomp"><b>Cudd_bddApproxConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the first factor</i>
+)
+</pre>
+<dd> Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the use of supersetting to obtain an initial factor of the given function. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_RemapOverApprox">Cudd_RemapOverApprox</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddApproxDisjDecomp"><b>Cudd_bddApproxDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddBindVar"><b>Cudd_bddBindVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> This function sets a flag to prevent sifting of a variable. Returns 1 if successful; 0 otherwise (i.e., invalid variable index).
+<p>
+
+<dd> <b>Side Effects</b> Changes the "bindVar" flag in DdSubtable.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddUnbindVar">Cudd_bddUnbindVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddBooleanDiff"><b>Cudd_bddBooleanDiff</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>x</b> <i></i>
+)
+</pre>
+<dd> Computes the boolean difference of f with respect to the variable with index x. Returns the BDD of the boolean difference if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode ** <i></i>
+<a name="Cudd_bddCharToVect"><b>Cudd_bddCharToVect</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Computes a vector of BDDs whose image equals a non-zero function. The result depends on the variable order. The i-th component of the vector depends only on the first i variables in the order. Each BDD in the vector is not larger than the BDD of the given characteristic function. This function is based on the description of char-to-vect in "Verification of Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C. Berthet and J. C. Madre. Returns a pointer to an array containing the result if successful; NULL otherwise. The size of the array equals the number of variables in the manager. The components of the solution have their reference counts already incremented (unlike the results of most other functions in the package).
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddClippingAndAbstract"><b>Cudd_bddClippingAndAbstract</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first conjunct</i>
+  DdNode * <b>g</b>, <i>second conjunct</i>
+  DdNode * <b>cube</b>, <i>cube of variables to be abstracted</i>
+  int  <b>maxDepth</b>, <i>maximum recursion depth</i>
+  int  <b>direction</b> <i>under (0) or over (1) approximation</i>
+)
+</pre>
+<dd> Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddClippingAnd">Cudd_bddClippingAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddClippingAnd"><b>Cudd_bddClippingAnd</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first conjunct</i>
+  DdNode * <b>g</b>, <i>second conjunct</i>
+  int  <b>maxDepth</b>, <i>maximum recursion depth</i>
+  int  <b>direction</b> <i>under (0) or over (1) approximation</i>
+)
+</pre>
+<dd> Approximates the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddClosestCube"><b>Cudd_bddClosestCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  int * <b>distance</b> <i></i>
+)
+</pre>
+<dd> Finds a cube of f at minimum Hamming distance from the minterms of g. All the minterms of the cube are at the minimum distance. If the distance is 0, the cube belongs to the intersection of f and g. Returns the cube if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The distance is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_MinHammingDist">Cudd_MinHammingDist</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddCompose"><b>Cudd_bddCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  int  <b>v</b> <i></i>
+)
+</pre>
+<dd> Substitutes g for x_v in the BDD for f. v is the index of the variable to be substituted. Cudd_bddCompose passes the corresponding projection function to the recursive procedure, so that the cache may be used. Returns the composed BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddComputeCube"><b>Cudd_bddComputeCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>vars</b>, <i></i>
+  int * <b>phase</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Computes the cube of an array of BDD variables. If non-null, the phase argument indicates which literal of each variable should appear in the cube. If phase[i] is nonzero, then the positive literal is used. If phase is NULL, the cube is positive unate. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addComputeCube">Cudd_addComputeCube</a>
+<a href="cuddAllDet.html#Cudd_IndicesToCube">Cudd_IndicesToCube</a>
+<a href="cuddAllDet.html#Cudd_CubeArrayToBdd">Cudd_CubeArrayToBdd</a>
+</code>
+
+<dt><pre>
+DdNode ** <i></i>
+<a name="Cudd_bddConstrainDecomp"><b>Cudd_bddConstrainDecomp</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> BDD conjunctive decomposition as in McMillan's CAV96 paper. The decomposition is canonical only for a given variable order. If canonicity is required, variable ordering must be disabled after the decomposition has been computed. Returns an array with one entry for each BDD variable in the manager if successful; otherwise NULL. The components of the solution have their reference counts already incremented (unlike the results of most other functions in the package.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddConstrain"><b>Cudd_bddConstrain</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Computes f constrain c (f @ c). Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true for c.) List of special cases: <ul> <li> f @ 0 = 0 <li> f @ 1 = f <li> 0 @ c = 0 <li> 1 @ c = 1 <li> f @ f = 1 <li> f @ f'= 0 </ul> Returns a pointer to the result if successful; NULL otherwise. Note that if F=(f1,...,fn) and reordering takes place while computing F @ c, then the image restriction property (Img(F,c) = Img(F @ c)) is lost.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+<a href="cuddAllDet.html#Cudd_addConstrain">Cudd_addConstrain</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_bddCorrelationWeights"><b>Cudd_bddCorrelationWeights</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  double * <b>prob</b> <i></i>
+)
+</pre>
+<dd> Computes the correlation of f and g for given input probabilities. On input, prob[i] is supposed to contain the probability of the i-th input variable to be 1. If f == g, their correlation is 1. If f == g', their correlation is 0. Returns the probability that f and g have the same value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The correlation of f and the constant one gives the probability of f.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddCorrelation">Cudd_bddCorrelation</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_bddCorrelation"><b>Cudd_bddCorrelation</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the correlation of f and g. If f == g, their correlation is 1. If f == g', their correlation is 0. Returns the fraction of minterms in the ON-set of the EXNOR of f and g. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddCorrelationWeights">Cudd_bddCorrelationWeights</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddExistAbstract"><b>Cudd_bddExistAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Existentially abstracts all the variables in cube from f. Returns the abstracted BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddUnivAbstract">Cudd_bddUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_addExistAbstract">Cudd_addExistAbstract</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddGenConjDecomp"><b>Cudd_bddGenConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the array of conjuncts</i>
+)
+</pre>
+<dd> Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the fact tht it generalizes the decomposition based on the cofactors with respect to one variable. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be balanced.
+<p>
+
+<dd> <b>Side Effects</b> The two factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddGenDisjDecomp"><b>Cudd_bddGenDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be balanced.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIntersect"><b>Cudd_bddIntersect</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first operand</i>
+  DdNode * <b>g</b> <i>second operand</i>
+)
+</pre>
+<dd> Computes a function included in the intersection of f and g. (That is, a witness that the intersection is not empty.) Cudd_bddIntersect tries to build as few new nodes as possible. If the only result of interest is whether f and g intersect, Cudd_bddLeq should be used instead.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsNsVar"><b>Cudd_bddIsNsVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is next state. Returns 1 if the variable's type is present state; 0 if the variable exists but is not a present state; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetNsVar">Cudd_bddSetNsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPiVar">Cudd_bddIsPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPsVar">Cudd_bddIsPsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsPiVar"><b>Cudd_bddIsPiVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Checks whether a variable is primary input. Returns 1 if the variable's type is primary input; 0 if the variable exists but is not a primary input; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPiVar">Cudd_bddSetPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPsVar">Cudd_bddIsPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsNsVar">Cudd_bddIsNsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsPsVar"><b>Cudd_bddIsPsVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is present state. Returns 1 if the variable's type is present state; 0 if the variable exists but is not a present state; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPsVar">Cudd_bddSetPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPiVar">Cudd_bddIsPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsNsVar">Cudd_bddIsNsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarEssential"><b>Cudd_bddIsVarEssential</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>id</b>, <i></i>
+  int  <b>phase</b> <i></i>
+)
+</pre>
+<dd> Determines whether a given variable is essential with a given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1 and f-->x_id, or if phase == 0 and f-->x_id'.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindEssential">Cudd_FindEssential</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarHardGroup"><b>Cudd_bddIsVarHardGroup</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is set to be in a hard group. This function is used for lazy sifting. Returns 1 if the variable is marked to be in a hard group; 0 if the variable exists, but it is not marked to be in a hard group; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarHardGroup">Cudd_bddSetVarHardGroup</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarToBeGrouped"><b>Cudd_bddIsVarToBeGrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is set to be grouped. This function is used for lazy sifting.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarToBeUngrouped"><b>Cudd_bddIsVarToBeUngrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is set to be ungrouped. This function is used for lazy sifting. Returns 1 if the variable is marked to be ungrouped; 0 if the variable exists, but it is not marked to be ungrouped; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarToBeUngrouped">Cudd_bddSetVarToBeUngrouped</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_bddIsop"><b>Cudd_bddIsop</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>L</b>, <i></i>
+  DdNode * <b>U</b> <i></i>
+)
+</pre>
+<dd> Computes a BDD in the interval between L and U with a simple sum-of-produuct cover. This procedure is similar to Cudd_zddIsop, but it does not return the ZDD for the cover. Returns a pointer to the BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddIsop">Cudd_zddIsop</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIteConstant"><b>Cudd_bddIteConstant</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITEconstant(f,g,h). Returns a pointer to the resulting BDD (which may or may not be constant) or DD_NON_CONSTANT. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_bddIntersect">Cudd_bddIntersect</a>
+<a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIterConjDecomp"><b>Cudd_bddIterConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the array of conjuncts</i>
+)
+</pre>
+<dd> Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the iterated use of supersetting to obtain a factor of the given function. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_RemapOverApprox">Cudd_RemapOverApprox</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIterDisjDecomp"><b>Cudd_bddIterDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIte"><b>Cudd_bddIte</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITE(f,g,h). Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIte">Cudd_addIte</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+<a href="cuddAllDet.html#Cudd_bddIntersect">Cudd_bddIntersect</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIthVar"><b>Cudd_bddIthVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Retrieves the BDD variable with index i if it already exists, or creates a new BDD variable. Returns a pointer to the variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+<a href="cuddAllDet.html#Cudd_ReadVars">Cudd_ReadVars</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddLICompaction"><b>Cudd_bddLICompaction</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be minimized</i>
+  DdNode * <b>c</b> <i>constraint (care set)</i>
+)
+</pre>
+<dd> Performs safe minimization of a BDD. Given the BDD <code>f</code> of a function to be minimized and a BDD <code>c</code> representing the care set, Cudd_bddLICompaction produces the BDD of a function that agrees with <code>f</code> wherever <code>c</code> is 1. Safe minimization means that the size of the result is guaranteed not to exceed the size of <code>f</code>. This function is based on the DAC97 paper by Hong et al.. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddLeqUnless"><b>Cudd_bddLeqUnless</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>D</b> <i></i>
+)
+</pre>
+<dd> Tells whether f is less than of equal to G unless D is 1. f, g, and D are BDDs. The function returns 1 if f is less than of equal to G, and 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EquivDC">Cudd_EquivDC</a>
+<a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddLeq"><b>Cudd_bddLeq</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddLiteralSetIntersection"><b>Cudd_bddLiteralSetIntersection</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the intesection of two sets of literals represented as BDDs. Each set is represented as a cube of the literals in the set. The empty set is represented by the constant 1. No variable can be simultaneously present in both phases in a set. Returns a pointer to the BDD representing the intersected sets, if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddMakePrime"><b>Cudd_bddMakePrime</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>cube</b>, <i>cube to be expanded</i>
+  DdNode * <b>f</b> <i>function of which the cube is to be made a prime</i>
+)
+</pre>
+<dd> Expands cube to a prime implicant of f. Returns the prime if successful; NULL otherwise. In particular, NULL is returned if cube is not a real cube or is not an implicant of f.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddMinimize"><b>Cudd_bddMinimize</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Finds a small BDD that agrees with <code>f</code> over <code>c</code>. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNPAnd"><b>Cudd_bddNPAnd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes f non-polluting-and g. The non-polluting AND of f and g is a hybrid of AND and Restrict. From Restrict, this operation takes the idea of existentially quantifying the top variable of the second operand if it does not appear in the first. Therefore, the variables that appear in the result also appear in f. For the rest, the function behaves like AND. Since the two operands play different roles, non-polluting AND is not commutative. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNand"><b>Cudd_bddNand</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the NAND of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNewVarAtLevel"><b>Cudd_bddNewVarAtLevel</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>level</b> <i></i>
+)
+</pre>
+<dd> Creates a new BDD variable. The new variable has an index equal to the largest previous index plus 1 and is positioned at the specified level in the order. Returns a pointer to the new variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_addNewVarAtLevel">Cudd_addNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNewVar"><b>Cudd_bddNewVar</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Creates a new BDD variable. The new variable has an index equal to the largest previous index plus 1. Returns a pointer to the new variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNor"><b>Cudd_bddNor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the NOR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddOr"><b>Cudd_bddOr</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the disjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddPermute"><b>Cudd_bddPermute</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int * <b>permut</b> <i></i>
+)
+</pre>
+<dd> Given a permutation in array permut, creates a new BDD with permuted variables. There should be an entry in array permut for each variable in the manager. The i-th entry of permut holds the index of the variable that is to substitute the i-th variable. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode ** <i></i>
+<a name="Cudd_bddPickArbitraryMinterms"><b>Cudd_bddPickArbitraryMinterms</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function from which to pick k minterms</i>
+  DdNode ** <b>vars</b>, <i>array of variables</i>
+  int  <b>n</b>, <i>size of <code>vars</code></i>
+  int  <b>k</b> <i>number of minterms to find</i>
+)
+</pre>
+<dd> Picks k on-set minterms evenly distributed from given DD. The minterms are in terms of <code>vars</code>. The array <code>vars</code> should contain at least all variables in the support of <code>f</code>; if this condition is not met the minterms built by this procedure may not be contained in <code>f</code>. Builds an array of BDDs for the minterms and returns a pointer to it if successful; NULL otherwise. There are three reasons why the procedure may fail: <ul> <li> It may run out of memory; <li> the function <code>f</code> may be the constant 0; <li> the minterms may not be contained in <code>f</code>. </ul>
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPickOneMinterm">Cudd_bddPickOneMinterm</a>
+<a href="cuddAllDet.html#Cudd_bddPickOneCube">Cudd_bddPickOneCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddPickOneCube"><b>Cudd_bddPickOneCube</b></a>(
+  DdManager * <b>ddm</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  char * <b>string</b> <i></i>
+)
+</pre>
+<dd> Picks one on-set cube randomly from the given DD. The cube is written into an array of characters. The array must have at least as many entries as there are variables. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPickOneMinterm">Cudd_bddPickOneMinterm</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddPickOneMinterm"><b>Cudd_bddPickOneMinterm</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function from which to pick one minterm</i>
+  DdNode ** <b>vars</b>, <i>array of variables</i>
+  int  <b>n</b> <i>size of <code>vars</code></i>
+)
+</pre>
+<dd> Picks one on-set minterm randomly from the given DD. The minterm is in terms of <code>vars</code>. The array <code>vars</code> should contain at least all variables in the support of <code>f</code>; if this condition is not met the minterm built by this procedure may not be contained in <code>f</code>. Builds a BDD for the minterm and returns a pointer to it if successful; NULL otherwise. There are three reasons why the procedure may fail: <ul> <li> It may run out of memory; <li> the function <code>f</code> may be the constant 0; <li> the minterm may not be contained in <code>f</code>. </ul>
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPickOneCube">Cudd_bddPickOneCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddPrintCover"><b>Cudd_bddPrintCover</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>l</b>, <i></i>
+  DdNode * <b>u</b> <i></i>
+)
+</pre>
+<dd> Prints a sum of product cover for an incompletely specified function given by a lower bound and an upper bound. Each product is a prime implicant obtained by expanding the product corresponding to a path from node to the constant one. Uses the package default output file. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintMinterm">Cudd_PrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddReadPairIndex"><b>Cudd_bddReadPairIndex</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Reads a corresponding pair index for a given index. These pair indices are present and next state variable. Returns the corresponding variable index if the variable exists; -1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPairIndex">Cudd_bddSetPairIndex</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddRead"><b>Cudd_bddRead</b></a>(
+  FILE * <b>fp</b>, <i>input file pointer</i>
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode ** <b>E</b>, <i>characteristic function of the graph</i>
+  DdNode *** <b>x</b>, <i>array of row variables</i>
+  DdNode *** <b>y</b>, <i>array of column variables</i>
+  int * <b>nx</b>, <i>number or row variables</i>
+  int * <b>ny</b>, <i>number or column variables</i>
+  int * <b>m</b>, <i>number of rows</i>
+  int * <b>n</b>, <i>number of columns</i>
+  int  <b>bx</b>, <i>first index of row variables</i>
+  int  <b>sx</b>, <i>step of row variables</i>
+  int  <b>by</b>, <i>first index of column variables</i>
+  int  <b>sy</b> <i>step of column variables</i>
+)
+</pre>
+<dd> Reads in a graph (without labels) given as an adjacency matrix. The first line of the input contains the numbers of rows and columns of the adjacency matrix. The remaining lines contain the arcs of the graph, one per line. Each arc is described by two integers, i.e., the row and column number, or the indices of the two endpoints. Cudd_bddRead produces a BDD that depends on two sets of variables: x and y. The x variables (x[0] ... x[nx-1]) encode the row index and the y variables (y[0] ... y[ny-1]) encode the column index. x[0] and y[0] are the most significant bits in the indices. The variables may already exist or may be created by the function. The index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy.<p> On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. When Cudd_bddRead creates the variable arrays, the index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy. When some variables already exist, Cudd_bddRead expects the indices of the existing x variables to be bx+i*sx, and the indices of the existing y variables to be by+i*sy.<p> m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. The BDD for the graph is returned in E, and its reference count is > 0. Cudd_bddRead returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> nx and ny are set to the numbers of row and column variables. m and n are set to the numbers of rows and columns. x and y are possibly extended to represent the array of row and column variables.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addHarwell">Cudd_addHarwell</a>
+<a href="cuddAllDet.html#Cudd_addRead">Cudd_addRead</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_bddRealignDisable"><b>Cudd_bddRealignDisable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables realignment of ZDD order to BDD order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_bddRealignEnable"><b>Cudd_bddRealignEnable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Enables realignment of the BDD variable order to the ZDD variable order after the ZDDs have been reordered. The number of ZDD variables must be a multiple of the number of BDD variables for realignment to make sense. If this condition is not met, Cudd_zddReduceHeap will return 0. Let <code>M</code> be the ratio of the two numbers. For the purpose of realignment, the ZDD variables from <code>M*i</code> to <code>(M+1)*i-1</code> are reagarded as corresponding to BDD variable <code>i</code>. Realignment is initially disabled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddReduceHeap">Cudd_zddReduceHeap</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddRealignmentEnabled"><b>Cudd_bddRealignmentEnabled</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the realignment of BDD order to ZDD order is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddResetVarToBeGrouped"><b>Cudd_bddResetVarToBeGrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Resets a variable not to be grouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarToBeGrouped">Cudd_bddSetVarToBeGrouped</a>
+<a href="cuddAllDet.html#Cudd_bddSetVarHardGroup">Cudd_bddSetVarHardGroup</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddRestrict"><b>Cudd_bddRestrict</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> BDD restrict according to Coudert and Madre's algorithm (ICCAD90). Returns the restricted BDD if successful; otherwise NULL. If application of restrict results in a BDD larger than the input BDD, the input BDD is returned.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_addRestrict">Cudd_addRestrict</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetNsVar"><b>Cudd_bddSetNsVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Sets a variable type to next state. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPiVar">Cudd_bddSetPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddSetPsVar">Cudd_bddSetPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsNsVar">Cudd_bddIsNsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetPairIndex"><b>Cudd_bddSetPairIndex</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b>, <i>variable index</i>
+  int  <b>pairIndex</b> <i>corresponding variable index</i>
+)
+</pre>
+<dd> Sets a corresponding pair index for a given index. These pair indices are present and next state variable. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddReadPairIndex">Cudd_bddReadPairIndex</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetPiVar"><b>Cudd_bddSetPiVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Sets a variable type to primary input. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPsVar">Cudd_bddSetPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddSetNsVar">Cudd_bddSetNsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPiVar">Cudd_bddIsPiVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetPsVar"><b>Cudd_bddSetPsVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Sets a variable type to present state. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPiVar">Cudd_bddSetPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddSetNsVar">Cudd_bddSetNsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPsVar">Cudd_bddIsPsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetVarHardGroup"><b>Cudd_bddSetVarHardGroup</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Sets a variable to be a hard group. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarToBeGrouped">Cudd_bddSetVarToBeGrouped</a>
+<a href="cuddAllDet.html#Cudd_bddResetVarToBeGrouped">Cudd_bddResetVarToBeGrouped</a>
+<a href="cuddAllDet.html#Cudd_bddIsVarHardGroup">Cudd_bddIsVarHardGroup</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetVarToBeGrouped"><b>Cudd_bddSetVarToBeGrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Sets a variable to be grouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarHardGroup">Cudd_bddSetVarHardGroup</a>
+<a href="cuddAllDet.html#Cudd_bddResetVarToBeGrouped">Cudd_bddResetVarToBeGrouped</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetVarToBeUngrouped"><b>Cudd_bddSetVarToBeUngrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Sets a variable to be ungrouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIsVarToBeUngrouped">Cudd_bddIsVarToBeUngrouped</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddSqueeze"><b>Cudd_bddSqueeze</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>l</b>, <i>lower bound</i>
+  DdNode * <b>u</b> <i>upper bound</i>
+)
+</pre>
+<dd> Finds a small BDD in a function interval. Given BDDs <code>l</code> and <code>u</code>, representing the lower bound and upper bound of a function interval, Cudd_bddSqueeze produces the BDD of a function within the interval with a small BDD. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddSwapVariables"><b>Cudd_bddSwapVariables</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  DdNode ** <b>y</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Swaps two sets of variables of the same size (x and y) in the BDD f. The size is given by n. The two sets of variables are assumed to be disjoint. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_addSwapVariables">Cudd_addSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddTransfer"><b>Cudd_bddTransfer</b></a>(
+  DdManager * <b>ddSource</b>, <i></i>
+  DdManager * <b>ddDestination</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Convert a BDD from a manager to another one. The orders of the variables in the two managers may be different. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddUnbindVar"><b>Cudd_bddUnbindVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> This function resets the flag that prevents the sifting of a variable. In successive variable reorderings, the variable will NOT be skipped, that is, sifted. Initially all variables can be sifted. It is necessary to call this function only to re-enable sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0 otherwise (i.e., invalid variable index).
+<p>
+
+<dd> <b>Side Effects</b> Changes the "bindVar" flag in DdSubtable.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddBindVar">Cudd_bddBindVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddUnivAbstract"><b>Cudd_bddUnivAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Universally abstracts all the variables in cube from f. Returns the abstracted BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_addUnivAbstract">Cudd_addUnivAbstract</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarConjDecomp"><b>Cudd_bddVarConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the array of conjuncts</i>
+)
+</pre>
+<dd> Conjunctively decomposes one BDD according to a variable. If <code>f</code> is the function of the BDD and <code>x</code> is the variable, the decomposition is <code>(f+x)(f+x')</code>. The variable is chosen so as to balance the sizes of the two conjuncts and to keep them small. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The two factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarDisjDecomp"><b>Cudd_bddVarDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD according to a variable. If <code>f</code> is the function of the BDD and <code>x</code> is the variable, the decomposition is <code>f*x + f*x'</code>. The variable is chosen so as to balance the sizes of the two disjuncts and to keep them small. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarIsBound"><b>Cudd_bddVarIsBound</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> This function returns 1 if a variable is enabled for sifting. Initially all variables can be sifted. This function returns 0 only if there has been a previous call to Cudd_bddBindVar for that variable not followed by a call to Cudd_bddUnbindVar. The function returns 0 also in the case in which the index of the variable is out of bounds.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddBindVar">Cudd_bddBindVar</a>
+<a href="cuddAllDet.html#Cudd_bddUnbindVar">Cudd_bddUnbindVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarIsDependent"><b>Cudd_bddVarIsDependent</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>var</b> <i>variable</i>
+)
+</pre>
+<dd> Checks whether a variable is dependent on others in a function. Returns 1 if the variable is dependent; 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddVarMap"><b>Cudd_bddVarMap</b></a>(
+  DdManager * <b>manager</b>, <i>DD manager</i>
+  DdNode * <b>f</b> <i>function in which to remap variables</i>
+)
+</pre>
+<dd> Remaps the variables of a BDD using the default variable map. A typical use of this function is to swap two sets of variables. The variable map must be registered with Cudd_SetVarMap. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+<a href="cuddAllDet.html#Cudd_SetVarMap">Cudd_SetVarMap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddVectorCompose"><b>Cudd_bddVectorCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vector</b> <i></i>
+)
+</pre>
+<dd> Given a vector of BDDs, creates a new BDD by substituting the BDDs for the variables of the BDD f. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddCompose">Cudd_bddCompose</a>
+<a href="cuddAllDet.html#Cudd_addVectorCompose">Cudd_addVectorCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddXnor"><b>Cudd_bddXnor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the exclusive NOR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddXorExistAbstract"><b>Cudd_bddXorExistAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddUnivAbstract">Cudd_bddUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddXor"><b>Cudd_bddXor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the exclusive OR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_tlcInfoFree"><b>Cudd_tlcInfoFree</b></a>(
+  DdTlcInfo * <b>t</b> <i></i>
+)
+</pre>
+<dd> Frees a DdTlcInfo Structure as well as the memory pointed by it.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddChange"><b>Cudd_zddChange</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Substitutes a variable with its complement in a ZDD. returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddComplement"><b>Cudd_zddComplement</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Computes a complement cover for a ZDD node. For lack of a better method, we first extract the function BDD from the ZDD cover, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP. Returns a pointer to the resulting cover if successful; NULL otherwise. The result depends on current variable order.
+<p>
+
+<dd> <b>Side Effects</b> The result depends on current variable order.
+<p>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_zddCountDouble"><b>Cudd_zddCountDouble</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a ZDD. The result is returned as a double. If the procedure runs out of memory, it returns (double) CUDD_OUT_OF_MEM. This procedure is used in Cudd_zddCountMinterm.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddCountMinterm">Cudd_zddCountMinterm</a>
+<a href="cuddAllDet.html#Cudd_zddCount">Cudd_zddCount</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_zddCountMinterm"><b>Cudd_zddCountMinterm</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>path</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of the ZDD rooted at <code>node</code>. This procedure takes a parameter <code>path</code> that specifies how many variables are in the support of the function. If the procedure runs out of memory, it returns (double) CUDD_OUT_OF_MEM.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddCountDouble">Cudd_zddCountDouble</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddCount"><b>Cudd_zddCount</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b> <i></i>
+)
+</pre>
+<dd> Returns an integer representing the number of minterms in a ZDD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddCountDouble">Cudd_zddCountDouble</a>
+</code>
+
+<dt><pre>
+char * <i></i>
+<a name="Cudd_zddCoverPathToString"><b>Cudd_zddCoverPathToString</b></a>(
+  DdManager * <b>zdd</b>, <i>DD manager</i>
+  int * <b>path</b>, <i>path of ZDD representing a cover</i>
+  char * <b>str</b> <i>pointer to string to use if != NULL</i>
+)
+</pre>
+<dd> Converts a path of a ZDD representing a cover to a string. The string represents an implicant of the cover. The path is typically produced by Cudd_zddForeachPath. Returns a pointer to the string if successful; NULL otherwise. If the str input is NULL, it allocates a new string. The string passed to this function must have enough room for all variables and for the terminator.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddForeachPath">Cudd_zddForeachPath</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddDagSize"><b>Cudd_zddDagSize</b></a>(
+  DdNode * <b>p_node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of nodes in a ZDD. This function duplicates Cudd_DagSize and is only retained for compatibility.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddDiffConst"><b>Cudd_zddDiffConst</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Inclusion test for ZDDs (P implies Q). No new nodes are generated by this procedure. Returns empty if true; a valid pointer different from empty or DD_NON_CONSTANT otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDiff">Cudd_zddDiff</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddDiff"><b>Cudd_zddDiff</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Computes the difference of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDiffConst">Cudd_zddDiffConst</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddDivideF"><b>Cudd_zddDivideF</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Modified version of Cudd_zddDivide. This function may disappear in future releases.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddDivide"><b>Cudd_zddDivide</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the quotient of two unate covers represented by ZDDs. Unate covers use one ZDD variable for each BDD variable. Returns a pointer to the resulting ZDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddWeakDiv">Cudd_zddWeakDiv</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddDumpDot"><b>Cudd_zddDumpDot</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a file representing the argument ZDDs in a format suitable for the graph drawing program dot. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full). Cudd_zddDumpDot does not close the file: This is the caller responsibility. Cudd_zddDumpDot uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. Cudd_zddDumpDot uses the following convention to draw arcs: <ul> <li> solid line: THEN arcs; <li> dashed line: ELSE arcs. </ul> The dot options are chosen so that the drawing fits on a letter-size sheet.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_zddPrintDebug">Cudd_zddPrintDebug</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_zddFirstPath"><b>Cudd_zddFirstPath</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int ** <b>path</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on the paths of a ZDD and finds its first path. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.<p> A path is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc out of a node, and 2 stands for the absence of a node. The size of the array equals the number of variables in the manager at the time Cudd_zddFirstCube is called.<p> The paths that end in the empty terminal are not enumerated.
+<p>
+
+<dd> <b>Side Effects</b> The first path is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddForeachPath">Cudd_zddForeachPath</a>
+<a href="cuddAllDet.html#Cudd_zddNextPath">Cudd_zddNextPath</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_zddForeachPath"><b>Cudd_zddForeachPath</b></a>(
+   <b>manager</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>path</b> <i></i>
+)
+</pre>
+<dd> Iterates over the paths of a ZDD f. <ul> <li> DdManager *manager; <li> DdNode *f; <li> DdGen *gen; <li> int *path; </ul> Cudd_zddForeachPath allocates and frees the generator. Therefore the application should not try to do that. Also, the path is freed at the end of Cudd_zddForeachPath and hence is not available outside of the loop.<p> CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddFirstPath">Cudd_zddFirstPath</a>
+<a href="cuddAllDet.html#Cudd_zddNextPath">Cudd_zddNextPath</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddIntersect"><b>Cudd_zddIntersect</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Computes the intersection of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddIsop"><b>Cudd_zddIsop</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>L</b>, <i></i>
+  DdNode * <b>U</b>, <i></i>
+  DdNode ** <b>zdd_I</b> <i></i>
+)
+</pre>
+<dd> Computes an irredundant sum of products (ISOP) in ZDD form from BDDs. The two BDDs L and U represent the lower bound and the upper bound, respectively, of the function. The ISOP uses two ZDD variables for each BDD variable: One for the positive literal, and one for the negative literal. These two variables should be adjacent in the ZDD order. The two ZDD variables corresponding to BDD variable <code>i</code> should have indices <code>2i</code> and <code>2i+1</code>. The result of this procedure depends on the variable order. If successful, Cudd_zddIsop returns the BDD for the function chosen from the interval. The ZDD representing the irredundant cover is returned as a side effect in zdd_I. In case of failure, NULL is returned.
+<p>
+
+<dd> <b>Side Effects</b> zdd_I holds the pointer to the ZDD for the ISOP on successful return.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIsop">Cudd_bddIsop</a>
+<a href="cuddAllDet.html#Cudd_zddVarsFromBddVars">Cudd_zddVarsFromBddVars</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddIte"><b>Cudd_zddIte</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Computes the ITE of three ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddIthVar"><b>Cudd_zddIthVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Retrieves the ZDD variable with index i if it already exists, or creates a new ZDD variable. Returns a pointer to the variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddNextPath"><b>Cudd_zddNextPath</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  int ** <b>path</b> <i></i>
+)
+</pre>
+<dd> Generates the next path of a ZDD onset, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The path is returned as a side effect. The generator is modified.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddForeachPath">Cudd_zddForeachPath</a>
+<a href="cuddAllDet.html#Cudd_zddFirstPath">Cudd_zddFirstPath</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddPortFromBdd"><b>Cudd_zddPortFromBdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>B</b> <i></i>
+)
+</pre>
+<dd> Converts a BDD into a ZDD. This function assumes that there is a one-to-one correspondence between the BDD variables and the ZDD variables, and that the variable order is the same for both types of variables. These conditions are established if the ZDD variables are created by one call to Cudd_zddVarsFromBddVars with multiplicity = 1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddVarsFromBddVars">Cudd_zddVarsFromBddVars</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddPortToBdd"><b>Cudd_zddPortToBdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Converts a ZDD into a BDD. Returns a pointer to the resulting ZDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddPortFromBdd">Cudd_zddPortFromBdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddPrintCover"><b>Cudd_zddPrintCover</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Prints a sum of products from a ZDD representing a cover. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddPrintMinterm">Cudd_zddPrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddPrintDebug"><b>Cudd_zddPrintDebug</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  int  <b>pr</b> <i></i>
+)
+</pre>
+<dd> Prints to the standard output a DD and its statistics. The statistics include the number of nodes and the number of minterms. (The number of minterms is also the number of combinations in the set.) The statistics are printed if pr &gt; 0. Specifically: <ul> <li> pr = 0 : prints nothing <li> pr = 1 : prints counts of nodes and minterms <li> pr = 2 : prints counts + disjoint sum of products <li> pr = 3 : prints counts + list of nodes <li> pr &gt; 3 : prints counts + disjoint sum of products + list of nodes </ul> Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddPrintMinterm"><b>Cudd_zddPrintMinterm</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Prints a disjoint sum of product form for a ZDD. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddPrintDebug">Cudd_zddPrintDebug</a>
+<a href="cuddAllDet.html#Cudd_zddPrintCover">Cudd_zddPrintCover</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddPrintSubtable"><b>Cudd_zddPrintSubtable</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Prints the ZDD table for debugging purposes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddProduct"><b>Cudd_zddProduct</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the product of two covers represented by ZDDs. The result is also a ZDD. Returns a pointer to the result if successful; NULL otherwise. The covers on which Cudd_zddProduct operates use two ZDD variables for each function variable (one ZDD variable for each literal of the variable). Those two ZDD variables should be adjacent in the order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddUnateProduct">Cudd_zddUnateProduct</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_zddReadNodeCount"><b>Cudd_zddReadNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the number of nodes in ZDDs. This number always includes the two constants 1 and 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPeakNodeCount">Cudd_ReadPeakNodeCount</a>
+<a href="cuddAllDet.html#Cudd_ReadNodeCount">Cudd_ReadNodeCount</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddRealignDisable"><b>Cudd_zddRealignDisable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables realignment of ZDD order to BDD order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddRealignEnable"><b>Cudd_zddRealignEnable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Enables realignment of the ZDD variable order to the BDD variable order after the BDDs and ADDs have been reordered. The number of ZDD variables must be a multiple of the number of BDD variables for realignment to make sense. If this condition is not met, Cudd_ReduceHeap will return 0. Let <code>M</code> be the ratio of the two numbers. For the purpose of realignment, the ZDD variables from <code>M*i</code> to <code>(M+1)*i-1</code> are reagarded as corresponding to BDD variable <code>i</code>. Realignment is initially disabled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReduceHeap">Cudd_ReduceHeap</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddRealignmentEnabled"><b>Cudd_zddRealignmentEnabled</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the realignment of ZDD order to BDD order is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddReduceHeap"><b>Cudd_zddReduceHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  Cudd_ReorderingType  <b>heuristic</b>, <i>method used for reordering</i>
+  int  <b>minsize</b> <i>bound below which no reordering occurs</i>
+)
+</pre>
+<dd> Main dynamic reordering routine for ZDDs. Calls one of the possible reordering procedures: <ul> <li>Swapping <li>Sifting <li>Symmetric Sifting </ul> For sifting and symmetric sifting it is possible to request reordering to convergence.<p> The core of all methods is the reordering procedure cuddZddSwapInPlace() which swaps two adjacent variables. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.
+<p>
+
+<dd> <b>Side Effects</b> Changes the variable order for all ZDDs and clears the cache.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddShuffleHeap"><b>Cudd_zddShuffleHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  int * <b>permutation</b> <i>required variable permutation</i>
+)
+</pre>
+<dd> Reorders ZDD variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Changes the ZDD variable order for all diagrams and clears the cache.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddReduceHeap">Cudd_zddReduceHeap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddSubset0"><b>Cudd_zddSubset0</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Computes the negative cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is negated. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddSubset1">Cudd_zddSubset1</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddSubset1"><b>Cudd_zddSubset1</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Computes the positive cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is asserted. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddSubset0">Cudd_zddSubset0</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddSymmProfile"><b>Cudd_zddSymmProfile</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Prints statistics on symmetric ZDD variables.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddUnateProduct"><b>Cudd_zddUnateProduct</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the product of two unate covers represented as ZDDs. Unate covers use one ZDD variable for each BDD variable. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddProduct">Cudd_zddProduct</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddUnion"><b>Cudd_zddUnion</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Computes the union of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddVarsFromBddVars"><b>Cudd_zddVarsFromBddVars</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>multiplicity</b> <i>how many ZDD variables are created for each BDD variable</i>
+)
+</pre>
+<dd> Creates one or more ZDD variables for each BDD variable. If some ZDD variables already exist, only the missing variables are created. Parameter multiplicity allows the caller to control how many variables are created for each BDD variable in existence. For instance, if ZDDs are used to represent covers, two ZDD variables are required for each BDD variable. The order of the BDD variables is transferred to the ZDD variables. If a variable group tree exists for the BDD variables, a corresponding ZDD variable group tree is created by expanding the BDD variable tree. In any case, the ZDD variables derived from the same BDD variable are merged in a ZDD variable group. If a ZDD variable group tree exists, it is freed. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddWeakDivF"><b>Cudd_zddWeakDivF</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Modified version of Cudd_zddWeakDiv. This function may disappear in future releases.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddWeakDiv">Cudd_zddWeakDiv</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddWeakDiv"><b>Cudd_zddWeakDiv</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Applies weak division to two ZDDs representing two covers. Returns a pointer to the ZDD representing the result if successful; NULL otherwise. The result of weak division depends on the variable order. The covers on which Cudd_zddWeakDiv operates use two ZDD variables for each function variable (one ZDD variable for each literal of the variable). Those two ZDD variables should be adjacent in the order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDivide">Cudd_zddDivide</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="DD_LSDIGIT"><b>DD_LSDIGIT</b></a>(
+   <b>x</b> <i></i>
+)
+</pre>
+<dd> Extract the least significant digit of a double digit. Used in the manipulation of arbitrary precision integers.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>DD_MSDIGIT
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="DD_MINUS_INFINITY"><b>DD_MINUS_INFINITY</b></a>(
+   <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the minus infinity constant node.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code>DD_ONE
+DD_ZERO
+DD_PLUS_INFINITY
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="DD_MSDIGIT"><b>DD_MSDIGIT</b></a>(
+   <b>x</b> <i></i>
+)
+</pre>
+<dd> Extract the most significant digit of a double digit. Used in the manipulation of arbitrary precision integers.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>DD_LSDIGIT
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="DD_ONE"><b>DD_ONE</b></a>(
+   <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the constant 1 node.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code>DD_ZERO
+DD_PLUS_INFINITY
+DD_MINUS_INFINITY
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="DD_PLUS_INFINITY"><b>DD_PLUS_INFINITY</b></a>(
+   <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the plus infinity constant node.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code>DD_ONE
+DD_ZERO
+DD_MINUS_INFINITY
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="DD_ZERO"><b>DD_ZERO</b></a>(
+   <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the arithmetic 0 constant node. This is different from the logical zero. The latter is obtained by Cudd_Not(DD_ONE(dd)).
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code>DD_ONE
+<a href="cuddAllDet.html#Cudd_Not">Cudd_Not</a>
+DD_PLUS_INFINITY
+DD_MINUS_INFINITY
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddApplyRecur"><b>cuddAddApplyRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_AOP  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addApply. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddAddMonadicApplyRecur">cuddAddMonadicApplyRecur</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddBddDoPattern"><b>cuddAddBddDoPattern</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step for Cudd_addBddPattern. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddCmplRecur"><b>cuddAddCmplRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addCmpl. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addCmpl">Cudd_addCmpl</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddComposeRecur"><b>cuddAddComposeRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>proj</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addCompose. Returns the composed BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddConstrainRecur"><b>cuddAddConstrainRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addConstrain. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addConstrain">Cudd_addConstrain</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddExistAbstractRecur"><b>cuddAddExistAbstractRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addExistAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddIteRecur"><b>cuddAddIteRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_addIte(f,g,h). Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIte">Cudd_addIte</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddMonadicApplyRecur"><b>cuddAddMonadicApplyRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_MAOP  <b>op</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addMonadicApply. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddAddApplyRecur">cuddAddApplyRecur</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddNegateRecur"><b>cuddAddNegateRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_addNegate. Returns a pointer to the result.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddOrAbstractRecur"><b>cuddAddOrAbstractRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addOrAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddRestrictRecur"><b>cuddAddRestrictRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addRestrict. Returns the restricted ADD if successful; otherwise NULL.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addRestrict">Cudd_addRestrict</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddRoundOffRecur"><b>cuddAddRoundOffRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  double  <b>trunc</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_addRoundOff. Returns a pointer to the result.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddScalarInverseRecur"><b>cuddAddScalarInverseRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>epsilon</b> <i></i>
+)
+</pre>
+<dd> Returns a pointer to the resulting ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAddUnivAbstractRecur"><b>cuddAddUnivAbstractRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_addUnivAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+ <i></i>
+<a name="cuddAdjust"><b>cuddAdjust</b></a>(
+   <b>x</b> <i></i>
+)
+</pre>
+<dd> Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to DD_PLUS_INF_VAL. Normally this macro is a NOOP. However, if HAVE_IEEE_754 is not defined, it makes sure that a value does not get larger than infinity in absolute value, and once it gets to infinity, stays there. If the value overflows before this macro is applied, no recovery is possible.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddAllocNode"><b>cuddAllocNode</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Fast storage allocation for DdNodes in the table. The first 4 bytes of a chunk contain a pointer to the next block; the rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to a new node if successful; NULL is memory is full.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddDynamicAllocNode">cuddDynamicAllocNode</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddAnnealing"><b>cuddAnnealing</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Get x, y by random selection. Choose either exchange or jump randomly. In case of jump, choose between jump_up and jump_down randomly. Do exchange or jump and get optimal case. Loop until there is no improvement or temperature reaches minimum. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddBddAlignToZdd"><b>cuddBddAlignToZdd</b></a>(
+  DdManager * <b>table</b> <i>DD manager</i>
+)
+</pre>
+<dd> Reorders BDD variables according to the order of the ZDD variables. This function can be called at the end of ZDD reordering to insure that the order of the BDD variables is consistent with the order of the ZDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let <code>M</code> be the ratio of the two numbers. cuddBddAlignToZdd then considers the ZDD variables from <code>M*i</code> to <code>(M+1)*i-1</code> as corresponding to BDD variable <code>i</code>. This function should be normally called from Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Changes the BDD variable order for all diagrams and performs garbage collection of the BDD unique table.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ShuffleHeap">Cudd_ShuffleHeap</a>
+<a href="cuddAllDet.html#Cudd_zddReduceHeap">Cudd_zddReduceHeap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddAndAbstractRecur"><b>cuddBddAndAbstractRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddAndRecur"><b>cuddBddAndRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_bddAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddBooleanDiffRecur"><b>cuddBddBooleanDiffRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>var</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive steps of Cudd_bddBoleanDiff. Returns the BDD obtained by XORing the cofactors of f with respect to var if successful; NULL otherwise. Exploits the fact that dF/dx = dF'/dx.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddClippingAndAbstract"><b>cuddBddClippingAndAbstract</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first conjunct</i>
+  DdNode * <b>g</b>, <i>second conjunct</i>
+  DdNode * <b>cube</b>, <i>cube of variables to be abstracted</i>
+  int  <b>maxDepth</b>, <i>maximum recursion depth</i>
+  int  <b>direction</b> <i>under (0) or over (1) approximation</i>
+)
+</pre>
+<dd> Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddClippingAndAbstract">Cudd_bddClippingAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddClippingAnd"><b>cuddBddClippingAnd</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first conjunct</i>
+  DdNode * <b>g</b>, <i>second conjunct</i>
+  int  <b>maxDepth</b>, <i>maximum recursion depth</i>
+  int  <b>direction</b> <i>under (0) or over (1) approximation</i>
+)
+</pre>
+<dd> Approximates the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddClippingAnd">Cudd_bddClippingAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddClosestCube"><b>cuddBddClosestCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>bound</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_bddClosestCube. Returns the cube if succesful; NULL otherwise. The procedure uses a four-way recursion to examine all four combinations of cofactors of <code>f</code> and <code>g</code> according to the following formula. <pre> H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1) </pre> Bounding is based on the following observations. <ul> <li> If we already found two points at distance 0, there is no point in continuing. Furthermore, <li> If F == not(G) then the best we can hope for is a minimum distance of 1. If we have already found two points at distance 1, there is no point in continuing. (Indeed, H(F,G) == 1 in this case. We have to continue, though, to find the cube.) </ul> The variable <code>bound</code> is set at the largest value of the distance that we are still interested in. Therefore, we desist when <pre> (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)). </pre> If we were maximally aggressive in using the bound, we would always set the bound to the minimum distance seen thus far minus one. That is, we would maintain the invariant <pre> bound < minD, </pre> except at the very beginning, when we have no value for <code>minD</code>.<p> However, we do not use <code>bound < minD</code> when examining the two negative cofactors, because we try to find a large cube at minimum distance. To do so, we try to find a cube in the negative cofactors at the same or smaller distance from the cube found in the positive cofactors.<p> When we compute <code>H(ft,ge)</code> and <code>H(fe,gt)</code> we know that we are going to add 1 to the result of the recursive call to account for the difference in the splitting variable. Therefore, we decrease the bound correspondingly.<p> Another important observation concerns the need of examining all four pairs of cofators only when both <code>f</code> and <code>g</code> depend on the top variable.<p> Suppose <code>gt == ge == g</code>. (That is, <code>g</code> does not depend on the top variable.) Then <pre> H(f,g) = min(H(ft,g), H(fe,g), H(ft,g)+1, H(fe,g)+1) = min(H(ft,g), H(fe,g)) . </pre> Therefore, under these circumstances, we skip the two "cross" cases.<p> An interesting feature of this function is the scheme used for caching the results in the global computed table. Since we have a cube and a distance, we combine them to form an ADD. The combination replaces the zero child of the top node of the cube with the negative of the distance. (The use of the negative is to avoid ambiguity with 1.) The degenerate cases (zero and one) are treated specially because the distance is known (0 for one, and infinity for zero).
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddClosestCube">Cudd_bddClosestCube</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddComposeRecur"><b>cuddBddComposeRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>proj</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_bddCompose. Exploits the fact that the composition of f' with g produces the complement of the composition of f with g to better utilize the cache. Returns the composed BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddCompose">Cudd_bddCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddConstrainRecur"><b>cuddBddConstrainRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_bddConstrain. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddExistAbstractRecur"><b>cuddBddExistAbstractRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive steps of Cudd_bddExistAbstract. Returns the BDD obtained by abstracting the variables of cube from f if successful; NULL otherwise. It is also used by Cudd_bddUnivAbstract.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddUnivAbstract">Cudd_bddUnivAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddIntersectRecur"><b>cuddBddIntersectRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_bddIntersect.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIntersect">Cudd_bddIntersect</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddBddIsop"><b>cuddBddIsop</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>L</b>, <i></i>
+  DdNode * <b>U</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_bddIsop.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIsop">Cudd_bddIsop</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddIteRecur"><b>cuddBddIteRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_bddIte. Returns a pointer to the resulting BDD. NULL if the intermediate result blows up or if reordering occurs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddLICompaction"><b>cuddBddLICompaction</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be minimized</i>
+  DdNode * <b>c</b> <i>constraint (care set)</i>
+)
+</pre>
+<dd> Performs safe minimization of a BDD. Given the BDD <code>f</code> of a function to be minimized and a BDD <code>c</code> representing the care set, Cudd_bddLICompaction produces the BDD of a function that agrees with <code>f</code> wherever <code>c</code> is 1. Safe minimization means that the size of the result is guaranteed not to exceed the size of <code>f</code>. This function is based on the DAC97 paper by Hong et al.. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddLiteralSetIntersectionRecur"><b>cuddBddLiteralSetIntersectionRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, and checks whether they agree in phase. Returns a pointer to the resulting cube if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddMakePrime"><b>cuddBddMakePrime</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>cube</b>, <i>cube to be expanded</i>
+  DdNode * <b>f</b> <i>function of which the cube is to be made a prime</i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_bddMakePrime. Returns the prime if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddNPAndRecur"><b>cuddBddNPAndRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_bddNPAnd. Returns a pointer to the result is successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNPAnd">Cudd_bddNPAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddRestrictRecur"><b>cuddBddRestrictRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_bddRestrict. Returns the restricted BDD if successful; otherwise NULL.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddTransfer"><b>cuddBddTransfer</b></a>(
+  DdManager * <b>ddS</b>, <i></i>
+  DdManager * <b>ddD</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Convert a BDD from a manager to another one. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddTransfer">Cudd_bddTransfer</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddXorExistAbstractRecur"><b>cuddBddXorExistAbstractRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBddXorRecur"><b>cuddBddXorRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_bddXor by taking the exclusive OR of two BDDs. Returns a pointer to the result is successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddBiasedUnderApprox"><b>cuddBiasedUnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode * <b>f</b>, <i>current DD</i>
+  DdNode * <b>b</b>, <i>bias function</i>
+  int  <b>numVars</b>, <i>maximum number of variables</i>
+  int  <b>threshold</b>, <i>threshold under which approximation stops</i>
+  double  <b>quality1</b>, <i>minimum improvement for accepted changes when b=1</i>
+  double  <b>quality0</b> <i>minimum improvement for accepted changes when b=0</i>
+)
+</pre>
+<dd> Applies the biased remapping underappoximation algorithm. Proceeds in three phases: <ul> <li> collect information on each node in the BDD; this is done via DFS. <li> traverse the BDD in top-down fashion and compute for each node whether remapping increases density. <li> traverse the BDD via DFS and actually perform the elimination. </ul> Returns the approximated BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_BiasedUnderApprox">Cudd_BiasedUnderApprox</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCProjectionRecur"><b>cuddCProjectionRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>R</b>, <i></i>
+  DdNode * <b>Y</b>, <i></i>
+  DdNode * <b>Ysupp</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_CProjection. Returns the projection if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CProjection">Cudd_CProjection</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddCacheFlush"><b>cuddCacheFlush</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Flushes the cache.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddCacheInsert1"><b>cuddCacheInsert1</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DD_CTFP1  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>data</b> <i></i>
+)
+</pre>
+<dd> Inserts a result in the cache for a function with two operands.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheInsert">cuddCacheInsert</a>
+<a href="cuddAllDet.html#cuddCacheInsert2">cuddCacheInsert2</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddCacheInsert2"><b>cuddCacheInsert2</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DD_CTFP  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>data</b> <i></i>
+)
+</pre>
+<dd> Inserts a result in the cache for a function with two operands.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheInsert">cuddCacheInsert</a>
+<a href="cuddAllDet.html#cuddCacheInsert1">cuddCacheInsert1</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddCacheInsert"><b>cuddCacheInsert</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  ptruint  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b>, <i></i>
+  DdNode * <b>data</b> <i></i>
+)
+</pre>
+<dd> Inserts a result in the cache.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheInsert2">cuddCacheInsert2</a>
+<a href="cuddAllDet.html#cuddCacheInsert1">cuddCacheInsert1</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCacheLookup1Zdd"><b>cuddCacheLookup1Zdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DD_CTFP1  <b>op</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns the result if found; it returns NULL if no result is found.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheLookupZdd">cuddCacheLookupZdd</a>
+<a href="cuddAllDet.html#cuddCacheLookup2Zdd">cuddCacheLookup2Zdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCacheLookup1"><b>cuddCacheLookup1</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DD_CTFP1  <b>op</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns the result if found; it returns NULL if no result is found.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheLookup">cuddCacheLookup</a>
+<a href="cuddAllDet.html#cuddCacheLookup2">cuddCacheLookup2</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCacheLookup2Zdd"><b>cuddCacheLookup2Zdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DD_CTFP  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns the result if found; it returns NULL if no result is found.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheLookupZdd">cuddCacheLookupZdd</a>
+<a href="cuddAllDet.html#cuddCacheLookup1Zdd">cuddCacheLookup1Zdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCacheLookup2"><b>cuddCacheLookup2</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DD_CTFP  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns the result if found; it returns NULL if no result is found.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheLookup">cuddCacheLookup</a>
+<a href="cuddAllDet.html#cuddCacheLookup1">cuddCacheLookup1</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCacheLookupZdd"><b>cuddCacheLookupZdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  ptruint  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Returns the result if found; it returns NULL if no result is found.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheLookup2Zdd">cuddCacheLookup2Zdd</a>
+<a href="cuddAllDet.html#cuddCacheLookup1Zdd">cuddCacheLookup1Zdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCacheLookup"><b>cuddCacheLookup</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  ptruint  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Returns the result if found; it returns NULL if no result is found.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheLookup2">cuddCacheLookup2</a>
+<a href="cuddAllDet.html#cuddCacheLookup1">cuddCacheLookup1</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddCacheProfile"><b>cuddCacheProfile</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Computes and prints a profile of the cache usage. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddCacheResize"><b>cuddCacheResize</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Resizes the cache.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddCheckCube"><b>cuddCheckCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Checks whether g is the BDD of a cube. Returns 1 in case of success; 0 otherwise. The constant 1 is a valid cube, but all other constant functions cause cuddCheckCube to return 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+ <i></i>
+<a name="cuddClean"><b>cuddClean</b></a>(
+   <b>p</b> <i></i>
+)
+</pre>
+<dd> Clears the 4 least significant bits of a pointer.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddClearDeathRow"><b>cuddClearDeathRow</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Clears the death row.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DelayedDerefBdd">Cudd_DelayedDerefBdd</a>
+<a href="cuddAllDet.html#Cudd_IterDerefBdd">Cudd_IterDerefBdd</a>
+<a href="cuddAllDet.html#Cudd_CheckZeroRef">Cudd_CheckZeroRef</a>
+<a href="cuddAllDet.html#cuddGarbageCollect">cuddGarbageCollect</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddCofactorRecur"><b>cuddCofactorRecur</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_Cofactor. Returns a pointer to the cofactor if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Cofactor">Cudd_Cofactor</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddCollectNodes"><b>cuddCollectNodes</b></a>(
+  DdNode * <b>f</b>, <i></i>
+  st_table * <b>visited</b> <i></i>
+)
+</pre>
+<dd> Traverses the DD f and collects all its nodes in a symbol table. f is assumed to be a regular pointer and cuddCollectNodes guarantees this assumption in the recursive calls. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddComputeFloorLog2"><b>cuddComputeFloorLog2</b></a>(
+  unsigned int  <b>value</b> <i></i>
+)
+</pre>
+<dd> Returns the floor of the logarithm to the base 2. The input value is assumed to be greater than 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddConstantLookup"><b>cuddConstantLookup</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  ptruint  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Looks up in the cache for the result of op applied to f, g, and h. Assumes that the calling procedure (e.g., Cudd_bddIteConstant) is only interested in whether the result is constant or not. Returns the result if found (possibly DD_NON_CONSTANT); otherwise it returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddCacheLookup">cuddCacheLookup</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddDeallocMove"><b>cuddDeallocMove</b></a>(
+   <b>unique</b>, <i></i>
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddDeallocNode">cuddDeallocNode</a>
+<a href="cuddAllDet.html#cuddDynamicAllocNode">cuddDynamicAllocNode</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddDeallocNode"><b>cuddDeallocNode</b></a>(
+   <b>unique</b>, <i></i>
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddAllocNode">cuddAllocNode</a>
+<a href="cuddAllDet.html#cuddDynamicAllocNode">cuddDynamicAllocNode</a>
+<a href="cuddAllDet.html#cuddDeallocMove">cuddDeallocMove</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddDeref"><b>cuddDeref</b></a>(
+   <b>n</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous cuddRef. This being a macro, it is faster than Cudd_Deref, but it cannot be used in constructs like cuddDeref(a = b()).
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Deref">Cudd_Deref</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddDestroySubtables"><b>cuddDestroySubtables</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Destroys the n most recently created subtables in a unique table. n should be positive. The subtables should not contain any live nodes, except the (isolated) projection function. The projection functions are freed. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The variable map used for fast variable substitution is destroyed if it exists. In this case the cache is also cleared.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddInsertSubtables">cuddInsertSubtables</a>
+<a href="cuddAllDet.html#Cudd_SetVarMap">Cudd_SetVarMap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddDynamicAllocNode"><b>cuddDynamicAllocNode</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Dynamically allocates a Node. This procedure is similar to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage collection, because during reordering there are no dead nodes. Returns a pointer to a new node if successful; NULL is memory is full.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddAllocNode">cuddAllocNode</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddExact"><b>cuddExact</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Exact variable ordering algorithm. Finds an optimum order for the variables between lower and upper. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+ <i></i>
+<a name="cuddE"><b>cuddE</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the else child of an internal node. If <code>node</code> is a constant node, the result is unpredictable. The pointer passed to cuddE must be regular.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_E">Cudd_E</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddFreeTable"><b>cuddFreeTable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Frees the resources associated to a unique table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddInitTable">cuddInitTable</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddGarbageCollect"><b>cuddGarbageCollect</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>clearCache</b> <i></i>
+)
+</pre>
+<dd> Performs garbage collection on the BDD and ZDD unique tables. If clearCache is 0, the cache is not cleared. This should only be specified if the cache has been cleared right before calling cuddGarbageCollect. (As in the case of dynamic reordering.) Returns the total number of deleted nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddGa"><b>cuddGa</b></a>(
+  DdManager * <b>table</b>, <i>manager</i>
+  int  <b>lower</b>, <i>lowest level to be reordered</i>
+  int  <b>upper</b> <i>highest level to be reorderded</i>
+)
+</pre>
+<dd> Genetic algorithm for DD reordering. The two children of a crossover will be stored in storedd[popsize
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddGetBranches"><b>cuddGetBranches</b></a>(
+  DdNode * <b>g</b>, <i></i>
+  DdNode ** <b>g1</b>, <i></i>
+  DdNode ** <b>g0</b> <i></i>
+)
+</pre>
+<dd> Computes the children of g.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdHashTable * <i></i>
+<a name="cuddHashTableInit"><b>cuddHashTableInit</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  unsigned int  <b>keySize</b>, <i></i>
+  unsigned int  <b>initSize</b> <i></i>
+)
+</pre>
+<dd> Initializes a hash table. Returns a pointer to the new table if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableQuit">cuddHashTableQuit</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddHashTableInsert1"><b>cuddHashTableInsert1</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>value</b>, <i></i>
+  ptrint  <b>count</b> <i></i>
+)
+</pre>
+<dd> Inserts an item in a hash table when the key is one pointer. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableInsert">cuddHashTableInsert</a>
+<a href="cuddAllDet.html#cuddHashTableInsert2">cuddHashTableInsert2</a>
+<a href="cuddAllDet.html#cuddHashTableInsert3">cuddHashTableInsert3</a>
+<a href="cuddAllDet.html#cuddHashTableLookup1">cuddHashTableLookup1</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddHashTableInsert2"><b>cuddHashTableInsert2</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>value</b>, <i></i>
+  ptrint  <b>count</b> <i></i>
+)
+</pre>
+<dd> Inserts an item in a hash table when the key is composed of two pointers. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableInsert">cuddHashTableInsert</a>
+<a href="cuddAllDet.html#cuddHashTableInsert1">cuddHashTableInsert1</a>
+<a href="cuddAllDet.html#cuddHashTableInsert3">cuddHashTableInsert3</a>
+<a href="cuddAllDet.html#cuddHashTableLookup2">cuddHashTableLookup2</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddHashTableInsert3"><b>cuddHashTableInsert3</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b>, <i></i>
+  DdNode * <b>value</b>, <i></i>
+  ptrint  <b>count</b> <i></i>
+)
+</pre>
+<dd> Inserts an item in a hash table when the key is composed of three pointers. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableInsert">cuddHashTableInsert</a>
+<a href="cuddAllDet.html#cuddHashTableInsert1">cuddHashTableInsert1</a>
+<a href="cuddAllDet.html#cuddHashTableInsert2">cuddHashTableInsert2</a>
+<a href="cuddAllDet.html#cuddHashTableLookup3">cuddHashTableLookup3</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddHashTableInsert"><b>cuddHashTableInsert</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNodePtr * <b>key</b>, <i></i>
+  DdNode * <b>value</b>, <i></i>
+  ptrint  <b>count</b> <i></i>
+)
+</pre>
+<dd> Inserts an item in a hash table when the key has more than three pointers. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code>[cuddHashTableInsert1
+<a href="cuddAllDet.html#cuddHashTableInsert2">cuddHashTableInsert2</a>
+<a href="cuddAllDet.html#cuddHashTableInsert3">cuddHashTableInsert3</a>
+<a href="cuddAllDet.html#cuddHashTableLookup">cuddHashTableLookup</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddHashTableLookup1"><b>cuddHashTableLookup1</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Looks up a key consisting of one pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableLookup">cuddHashTableLookup</a>
+<a href="cuddAllDet.html#cuddHashTableLookup2">cuddHashTableLookup2</a>
+<a href="cuddAllDet.html#cuddHashTableLookup3">cuddHashTableLookup3</a>
+<a href="cuddAllDet.html#cuddHashTableInsert1">cuddHashTableInsert1</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddHashTableLookup2"><b>cuddHashTableLookup2</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Looks up a key consisting of two pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableLookup">cuddHashTableLookup</a>
+<a href="cuddAllDet.html#cuddHashTableLookup1">cuddHashTableLookup1</a>
+<a href="cuddAllDet.html#cuddHashTableLookup3">cuddHashTableLookup3</a>
+<a href="cuddAllDet.html#cuddHashTableInsert2">cuddHashTableInsert2</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddHashTableLookup3"><b>cuddHashTableLookup3</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Looks up a key consisting of three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableLookup">cuddHashTableLookup</a>
+<a href="cuddAllDet.html#cuddHashTableLookup1">cuddHashTableLookup1</a>
+<a href="cuddAllDet.html#cuddHashTableLookup2">cuddHashTableLookup2</a>
+<a href="cuddAllDet.html#cuddHashTableInsert3">cuddHashTableInsert3</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddHashTableLookup"><b>cuddHashTableLookup</b></a>(
+  DdHashTable * <b>hash</b>, <i></i>
+  DdNodePtr * <b>key</b> <i></i>
+)
+</pre>
+<dd> Looks up a key consisting of more than three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableLookup1">cuddHashTableLookup1</a>
+<a href="cuddAllDet.html#cuddHashTableLookup2">cuddHashTableLookup2</a>
+<a href="cuddAllDet.html#cuddHashTableLookup3">cuddHashTableLookup3</a>
+<a href="cuddAllDet.html#cuddHashTableInsert">cuddHashTableInsert</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddHashTableQuit"><b>cuddHashTableQuit</b></a>(
+  DdHashTable * <b>hash</b> <i></i>
+)
+</pre>
+<dd> Shuts down a hash table, dereferencing all the values.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddHashTableInit">cuddHashTableInit</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddHeapProfile"><b>cuddHeapProfile</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Prints to the manager's stdout the number of live nodes for each level of the DD heap that contains at least one live node. It also prints a summary containing: <ul> <li> total number of tables; <li> number of tables with live nodes; <li> table with the largest number of live nodes; <li> number of nodes in that table. </ul> If more than one table contains the maximum number of live nodes, only the one of lowest index is reported. Returns 1 in case of success and 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+ <i></i>
+<a name="cuddIZ"><b>cuddIZ</b></a>(
+   <b>dd</b>, <i></i>
+   <b>index</b> <i></i>
+)
+</pre>
+<dd> Finds the current position of ZDD variable index in the order. This macro duplicates the functionality of Cudd_ReadPermZdd, but it does not check for out-of-bounds indices and it is more efficient.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPermZdd">Cudd_ReadPermZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddInitCache"><b>cuddInitCache</b></a>(
+  DdManager * <b>unique</b>, <i>unique table</i>
+  unsigned int  <b>cacheSize</b>, <i>initial size of the cache</i>
+  unsigned int  <b>maxCacheSize</b> <i>cache size beyond which no resizing occurs</i>
+)
+</pre>
+<dd> Initializes the computed table. It is called by Cudd_Init. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Init">Cudd_Init</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddInitInteract"><b>cuddInitInteract</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Initializes the interaction matrix. The interaction matrix is implemented as a bit vector storing the upper triangle of the symmetric interaction matrix. The bit vector is kept in an array of long integers. The computation is based on a series of depth-first searches, one for each root of the DAG. Two flags are needed: The local visited flag uses the LSB of the then pointer. The global visited flag uses the LSB of the next pointer. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddInitLinear"><b>cuddInitLinear</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Initializes the linear transform matrix. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+DdManager * <i></i>
+<a name="cuddInitTable"><b>cuddInitTable</b></a>(
+  unsigned int  <b>numVars</b>, <i>Initial number of BDD variables (and subtables)</i>
+  unsigned int  <b>numVarsZ</b>, <i>Initial number of ZDD variables (and subtables)</i>
+  unsigned int  <b>numSlots</b>, <i>Initial size of the BDD subtables</i>
+  unsigned int  <b>looseUpTo</b> <i>Limit for fast table growth</i>
+)
+</pre>
+<dd> Creates and initializes the unique table. Returns a pointer to the table if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Init">Cudd_Init</a>
+<a href="cuddAllDet.html#cuddFreeTable">cuddFreeTable</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddInsertSubtables"><b>cuddInsertSubtables</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  int  <b>level</b> <i></i>
+)
+</pre>
+<dd> Inserts n new subtables in a unique table at level. The number n should be positive, and level should be an existing level. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddDestroySubtables">cuddDestroySubtables</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddIsConstant"><b>cuddIsConstant</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the node is a constant node (rather than an internal node). All constant nodes have the same index (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_IsConstant">Cudd_IsConstant</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddIsInDeathRow"><b>cuddIsInDeathRow</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Checks whether a node is in the death row. Returns the position of the first occurrence if the node is present; -1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DelayedDerefBdd">Cudd_DelayedDerefBdd</a>
+<a href="cuddAllDet.html#cuddClearDeathRow">cuddClearDeathRow</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddI"><b>cuddI</b></a>(
+   <b>dd</b>, <i></i>
+   <b>index</b> <i></i>
+)
+</pre>
+<dd> Finds the current position of variable index in the order. This macro duplicates the functionality of Cudd_ReadPerm, but it does not check for out-of-bounds indices and it is more efficient.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddLevelQueueDequeue"><b>cuddLevelQueueDequeue</b></a>(
+  DdLevelQueue * <b>queue</b>, <i></i>
+  int  <b>level</b> <i></i>
+)
+</pre>
+<dd> Remove an item from the front of a level queue.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddLevelQueueEnqueue">cuddLevelQueueEnqueue</a>
+</code>
+
+<dt><pre>
+void * <i></i>
+<a name="cuddLevelQueueEnqueue"><b>cuddLevelQueueEnqueue</b></a>(
+  DdLevelQueue * <b>queue</b>, <i>level queue</i>
+  void * <b>key</b>, <i>key to be enqueued</i>
+  int  <b>level</b> <i>level at which to insert</i>
+)
+</pre>
+<dd> Inserts a new key in a level queue. A new entry is created in the queue only if the node is not already enqueued. Returns a pointer to the queue item if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddLevelQueueInit">cuddLevelQueueInit</a>
+<a href="cuddAllDet.html#cuddLevelQueueDequeue">cuddLevelQueueDequeue</a>
+</code>
+
+<dt><pre>
+DdLevelQueue * <i></i>
+<a name="cuddLevelQueueInit"><b>cuddLevelQueueInit</b></a>(
+  int  <b>levels</b>, <i>number of levels</i>
+  int  <b>itemSize</b>, <i>size of the item</i>
+  int  <b>numBuckets</b> <i>initial number of hash buckets</i>
+)
+</pre>
+<dd> Initializes a level queue. A level queue is a queue where inserts are based on the levels of the nodes. Within each level the policy is FIFO. Level queues are useful in traversing a BDD top-down. Queue items are kept in a free list when dequeued for efficiency. Returns a pointer to the new queue if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddLevelQueueQuit">cuddLevelQueueQuit</a>
+<a href="cuddAllDet.html#cuddLevelQueueEnqueue">cuddLevelQueueEnqueue</a>
+<a href="cuddAllDet.html#cuddLevelQueueDequeue">cuddLevelQueueDequeue</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddLevelQueueQuit"><b>cuddLevelQueueQuit</b></a>(
+  DdLevelQueue * <b>queue</b> <i></i>
+)
+</pre>
+<dd> Shuts down a level queue and releases all the associated memory.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddLevelQueueInit">cuddLevelQueueInit</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddLinearAndSifting"><b>cuddLinearAndSifting</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> BDD reduction based on combination of sifting and linear transformations. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique table. <li> Sift the variable up and down, remembering each time the total size of the DD heap. At each position, linear transformation of the two adjacent variables is tried and is accepted if it reduces the size of the DD. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. </ol> Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddLinearInPlace"><b>cuddLinearInPlace</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Linearly combines two adjacent variables. Specifically, replaces the top variable with the exclusive nor of the two variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddLinearInPlace assumes that x &lt; y. Returns the number of keys in the table if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The two subtables corrresponding to variables x and y are modified. The global counters of the unique table are also affected.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddSwapInPlace">cuddSwapInPlace</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddLocalCacheClearAll"><b>cuddLocalCacheClearAll</b></a>(
+  DdManager * <b>manager</b> <i></i>
+)
+</pre>
+<dd> Clears the local caches of a manager. Used before reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddLocalCacheClearDead"><b>cuddLocalCacheClearDead</b></a>(
+  DdManager * <b>manager</b> <i></i>
+)
+</pre>
+<dd> Clears the dead entries of the local caches of a manager. Used during garbage collection.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdLocalCache * <i></i>
+<a name="cuddLocalCacheInit"><b>cuddLocalCacheInit</b></a>(
+  DdManager * <b>manager</b>, <i>manager</i>
+  unsigned int  <b>keySize</b>, <i>size of the key (number of operands)</i>
+  unsigned int  <b>cacheSize</b>, <i>Initial size of the cache</i>
+  unsigned int  <b>maxCacheSize</b> <i>Size of the cache beyond which no resizing occurs</i>
+)
+</pre>
+<dd> Initializes a computed table. Returns a pointer the the new local cache in case of success; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddInitCache">cuddInitCache</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddLocalCacheInsert"><b>cuddLocalCacheInsert</b></a>(
+  DdLocalCache * <b>cache</b>, <i></i>
+  DdNodePtr * <b>key</b>, <i></i>
+  DdNode * <b>value</b> <i></i>
+)
+</pre>
+<dd> Inserts a result in a local cache.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddLocalCacheLookup"><b>cuddLocalCacheLookup</b></a>(
+  DdLocalCache * <b>cache</b>, <i></i>
+  DdNodePtr * <b>key</b> <i></i>
+)
+</pre>
+<dd> Looks up in a local cache. Returns the result if found; it returns NULL if no result is found.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddLocalCacheProfile"><b>cuddLocalCacheProfile</b></a>(
+  DdLocalCache * <b>cache</b> <i></i>
+)
+</pre>
+<dd> Computes and prints a profile of a local cache usage. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddLocalCacheQuit"><b>cuddLocalCacheQuit</b></a>(
+  DdLocalCache * <b>cache</b> <i>cache to be shut down</i>
+)
+</pre>
+<dd> Initializes the computed table. It is called by Cudd_Init. Returns a pointer the the new local cache in case of success; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddLocalCacheInit">cuddLocalCacheInit</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddMakeBddFromZddCover"><b>cuddMakeBddFromZddCover</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, otherwise it returns NULL. It is a recursive algorithm as the following. First computes 3 cofactors of a ZDD cover; f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd. Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v is the variable which has the index of the top node of the ZDD cover. In this case, since the index of v can be larger than either one of T or one of E, cuddUniqueInterIVO is called, here IVO stands for independent variable ordering.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_MakeBddFromZddCover">Cudd_MakeBddFromZddCover</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddNextHigh"><b>cuddNextHigh</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b> <i></i>
+)
+</pre>
+<dd> Finds the next subtable with a larger index. Returns the index.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddNextLow">cuddNextLow</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddNextLow"><b>cuddNextLow</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b> <i></i>
+)
+</pre>
+<dd> Finds the next subtable with a smaller index. Returns the index.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddNextHigh">cuddNextHigh</a>
+</code>
+
+<dt><pre>
+DdNodePtr * <i></i>
+<a name="cuddNodeArray"><b>cuddNodeArray</b></a>(
+  DdNode * <b>f</b>, <i></i>
+  int * <b>n</b> <i></i>
+)
+</pre>
+<dd> Traverses the DD f and collects all its nodes in an array. The caller should free the array returned by cuddNodeArray. Returns a pointer to the array of nodes in case of success; NULL otherwise. The nodes are collected in reverse topological order, so that a node is always preceded in the array by all its descendants.
+<p>
+
+<dd> <b>Side Effects</b> The number of nodes is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddPrintNode"><b>cuddPrintNode</b></a>(
+  DdNode * <b>f</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints out information on a node.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddPrintVarGroups"><b>cuddPrintVarGroups</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  MtrNode * <b>root</b>, <i>root of the group tree</i>
+  int  <b>zdd</b>, <i>0: BDD; 1: ZDD</i>
+  int  <b>silent</b> <i>flag to check tree syntax only</i>
+)
+</pre>
+<dd> Prints the variable groups as a parenthesized list. For each group the level range that it represents is printed. After each group, the group's flags are printed, preceded by a `|'. For each flag (except MTR_TERMINAL) a character is printed. <ul> <li>F: MTR_FIXED <li>N: MTR_NEWNODE <li>S: MTR_SOFT </ul> The second argument, silent, if different from 0, causes Cudd_PrintVarGroups to only check the syntax of the group tree.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddP"><b>cuddP</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Prints a DD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddReclaimZdd"><b>cuddReclaimZdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Brings children of a dead ZDD node back.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddReclaim">cuddReclaim</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddReclaim"><b>cuddReclaim</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Brings children of a dead node back.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddReclaimZdd">cuddReclaimZdd</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddRef"><b>cuddRef</b></a>(
+   <b>n</b> <i></i>
+)
+</pre>
+<dd> Increases the reference count of a node, if it is not saturated. This being a macro, it is faster than Cudd_Ref, but it cannot be used in constructs like cuddRef(a = b()).
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Ref">Cudd_Ref</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddRehash"><b>cuddRehash</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Doubles the size of a unique subtable and rehashes its contents.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddRemapUnderApprox"><b>cuddRemapUnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode * <b>f</b>, <i>current DD</i>
+  int  <b>numVars</b>, <i>maximum number of variables</i>
+  int  <b>threshold</b>, <i>threshold under which approximation stops</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Applies the remapping underappoximation algorithm. Proceeds in three phases: <ul> <li> collect information on each node in the BDD; this is done via DFS. <li> traverse the BDD in top-down fashion and compute for each node whether remapping increases density. <li> traverse the BDD via DFS and actually perform the elimination. </ul> Returns the approximated BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RemapUnderApprox">Cudd_RemapUnderApprox</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddResizeLinear"><b>cuddResizeLinear</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Resizes the linear transform matrix. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddResizeTableZdd"><b>cuddResizeTableZdd</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Increases the number of ZDD subtables in a unique table so that it meets or exceeds index. When new ZDD variables are created, it is possible to preserve the functions unchanged, or it is possible to preserve the covers unchanged, but not both. cuddResizeTableZdd preserves the covers. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddResizeTable">ddResizeTable</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddSatDec"><b>cuddSatDec</b></a>(
+   <b>x</b> <i></i>
+)
+</pre>
+<dd> Saturating decrement operator.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddSatInc">cuddSatInc</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddSatInc"><b>cuddSatInc</b></a>(
+   <b>x</b> <i></i>
+)
+</pre>
+<dd> Saturating increment operator.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddSatDec">cuddSatDec</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddSetInteract"><b>cuddSetInteract</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Given a pair of variables 0 <= x < y < table->size, sets the corresponding bit of the interaction matrix to 1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddShrinkDeathRow"><b>cuddShrinkDeathRow</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Shrinks the death row by a factor of four.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddClearDeathRow">cuddClearDeathRow</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddShrinkSubtable"><b>cuddShrinkSubtable</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Shrinks a subtable.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddRehash">cuddRehash</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddSifting"><b>cuddSifting</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique table. <li> Sift the variable up and down, remembering each time the total size of the DD heap. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. </ol> Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="cuddSlowTableGrowth"><b>cuddSlowTableGrowth</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Adjusts parameters of a table to slow down its growth.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddSolveEqnRecur"><b>cuddSolveEqnRecur</b></a>(
+  DdManager * <b>bdd</b>, <i></i>
+  DdNode * <b>F</b>, <i>the left-hand side of the equation</i>
+  DdNode * <b>Y</b>, <i>the cube of remaining y variables</i>
+  DdNode ** <b>G</b>, <i>the array of solutions</i>
+  int  <b>n</b>, <i>number of unknowns</i>
+  int * <b>yIndex</b>, <i>array holding the y variable indices</i>
+  int  <b>i</b> <i>level of recursion</i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_SolveEqn. Returns NULL if the intermediate solution blows up or reordering occurs. The parametric solutions are stored in the array G.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SolveEqn">Cudd_SolveEqn</a>
+<a href="cuddAllDet.html#Cudd_VerifySol">Cudd_VerifySol</a>
+</code>
+
+<dt><pre>
+DdNode* <i></i>
+<a name="cuddSplitSetRecur"><b>cuddSplitSetRecur</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  st_table * <b>mtable</b>, <i></i>
+  int * <b>varSeen</b>, <i></i>
+  DdNode * <b>p</b>, <i></i>
+  double  <b>n</b>, <i></i>
+  double  <b>max</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_SplitSet. The procedure recursively traverses the BDD and checks to see if any node satisfies the minterm requirements as specified by 'n'. At any node X, n is compared to the number of minterms in the onset of X's children. If either of the child nodes have exactly n minterms, then that node is returned; else, if n is greater than the onset of one of the child nodes, that node is retained and the difference in the number of minterms is extracted from the other child. In case n minterms can be extracted from constant 1, the algorithm returns the result with at most log(n) nodes.
+<p>
+
+<dd> <b>Side Effects</b> The array 'varSeen' is updated at every recursive call to set the variables traversed by the procedure.
+<p>
+
+<dt><pre>
+enum st_retval <i></i>
+<a name="cuddStCountfree"><b>cuddStCountfree</b></a>(
+  char * <b>key</b>, <i></i>
+  char * <b>value</b>, <i></i>
+  char * <b>arg</b> <i></i>
+)
+</pre>
+<dd> Frees the memory used to store the minterm counts recorded in the visited table. Returns ST_CONTINUE.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddSubsetHeavyBranch"><b>cuddSubsetHeavyBranch</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode * <b>f</b>, <i>current DD</i>
+  int  <b>numVars</b>, <i>maximum number of variables</i>
+  int  <b>threshold</b> <i>threshold size for the subset</i>
+)
+</pre>
+<dd> Here a subset BDD is built by throwing away one of the children. Starting at root, annotate each node with the number of minterms (in terms of the total number of variables specified - numVars), number of nodes taken by the DAG rooted at this node and number of additional nodes taken by the child that has the lesser minterms. The child with the lower number of minterms is thrown away and a dyanmic count of the nodes of the subset is kept. Once the threshold is reached the subset is returned to the calling procedure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddSubsetShortPaths"><b>cuddSubsetShortPaths</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>total number of variables in consideration</i>
+  int  <b>threshold</b>, <i>maximum number of nodes allowed in the subset</i>
+  int  <b>hardlimit</b> <i>flag determining whether thershold should be respected strictly</i>
+)
+</pre>
+<dd> The outermost procedure to return a subset of the given BDD with the largest cubes. The path lengths are calculated, the maximum allowable path length is determined and the number of nodes of this path length that can be used to build a subset. If the threshold is larger than the size of the original BDD, the original BDD is returned.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddSwapInPlace"><b>cuddSwapInPlace</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Swaps two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddSwapInPlace assumes that x &lt; y. Returns the number of keys in the table if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddSwapping"><b>cuddSwapping</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b>, <i></i>
+  Cudd_ReorderingType  <b>heuristic</b> <i></i>
+)
+</pre>
+<dd> Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps. <ol> <li> Select two variables (RANDOM or HEURISTIC). <li> Permute these variables. <li> If the nodes have decreased accept the permutation. <li> Otherwise reconstruct the original heap. <li> Loop. </ol> Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddSymmCheck"><b>cuddSymmCheck</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddSymmSiftingConv"><b>cuddSymmSiftingConv</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Symmetric sifting to convergence algorithm. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique subtable. <li> Sift the variable up and down, remembering each time the total size of the DD heap and grouping variables that are symmetric. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. <li> Repeat 1-4 until no further improvement. </ol> Returns 1 plus the number of symmetric variables if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddSymmSifting">cuddSymmSifting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddSymmSifting"><b>cuddSymmSifting</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Symmetric sifting algorithm. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique subtable. <li> Sift the variable up and down, remembering each time the total size of the DD heap and grouping variables that are symmetric. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. </ol> Returns 1 plus the number of symmetric variables if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddSymmSiftingConv">cuddSymmSiftingConv</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddTestInteract"><b>cuddTestInteract</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Given a pair of variables 0 <= x < y < table->size, tests whether the corresponding bit of the interaction matrix is 1. Returns the value of the bit.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddTimesInDeathRow"><b>cuddTimesInDeathRow</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Counts how many times a node is in the death row.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DelayedDerefBdd">Cudd_DelayedDerefBdd</a>
+<a href="cuddAllDet.html#cuddClearDeathRow">cuddClearDeathRow</a>
+<a href="cuddAllDet.html#cuddIsInDeathRow">cuddIsInDeathRow</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddTreeSifting"><b>cuddTreeSifting</b></a>(
+  DdManager * <b>table</b>, <i>DD table</i>
+  Cudd_ReorderingType  <b>method</b> <i>reordering method for the groups of leaves</i>
+)
+</pre>
+<dd> Tree sifting algorithm. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling ddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+ <i></i>
+<a name="cuddT"><b>cuddT</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the then child of an internal node. If <code>node</code> is a constant node, the result is unpredictable. The pointer passed to cuddT must be regular.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_T">Cudd_T</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddUnderApprox"><b>cuddUnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode * <b>f</b>, <i>current DD</i>
+  int  <b>numVars</b>, <i>maximum number of variables</i>
+  int  <b>threshold</b>, <i>threshold under which approximation stops</i>
+  int  <b>safe</b>, <i>enforce safe approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Applies Tom Shiple's underappoximation algorithm. Proceeds in three phases: <ul> <li> collect information on each node in the BDD; this is done via DFS. <li> traverse the BDD in top-down fashion and compute for each node whether its elimination increases density. <li> traverse the BDD via DFS and actually perform the elimination. </ul> Returns the approximated BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_UnderApprox">Cudd_UnderApprox</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddUniqueConst"><b>cuddUniqueConst</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>value</b> <i></i>
+)
+</pre>
+<dd> Checks the unique table for the existence of a constant node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. Returns a pointer to the new node.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddUniqueInterIVO"><b>cuddUniqueInterIVO</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>index</b>, <i></i>
+  DdNode * <b>T</b>, <i></i>
+  DdNode * <b>E</b> <i></i>
+)
+</pre>
+<dd> Wrapper for cuddUniqueInter that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of T and E in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddUniqueInter">cuddUniqueInter</a>
+<a href="cuddAllDet.html#Cudd_MakeBddFromZddCover">Cudd_MakeBddFromZddCover</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddUniqueInterZdd"><b>cuddUniqueInterZdd</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>index</b>, <i></i>
+  DdNode * <b>T</b>, <i></i>
+  DdNode * <b>E</b> <i></i>
+)
+</pre>
+<dd> Checks the unique table for the existence of an internal ZDD node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddUniqueInter">cuddUniqueInter</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddUniqueInter"><b>cuddUniqueInter</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  int  <b>index</b>, <i></i>
+  DdNode * <b>T</b>, <i></i>
+  DdNode * <b>E</b> <i></i>
+)
+</pre>
+<dd> Checks the unique table for the existence of an internal node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddUniqueInterZdd">cuddUniqueInterZdd</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddUpdateInteractionMatrix"><b>cuddUpdateInteractionMatrix</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>xindex</b>, <i></i>
+  int  <b>yindex</b> <i></i>
+)
+</pre>
+<dd> Updates the interaction matrix.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddVerifySol"><b>cuddVerifySol</b></a>(
+  DdManager * <b>bdd</b>, <i></i>
+  DdNode * <b>F</b>, <i>the left-hand side of the equation</i>
+  DdNode ** <b>G</b>, <i>the array of solutions</i>
+  int * <b>yIndex</b>, <i>array holding the y variable indices</i>
+  int  <b>n</b> <i>number of unknowns</i>
+)
+</pre>
+<dd> Implements the recursive step of Cudd_VerifySol.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_VerifySol">Cudd_VerifySol</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="cuddV"><b>cuddV</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the value of a constant node. If <code>node</code> is an internal node, the result is unpredictable. The pointer passed to cuddV must be regular.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_V">Cudd_V</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddWindowReorder"><b>cuddWindowReorder</b></a>(
+  DdManager * <b>table</b>, <i>DD table</i>
+  int  <b>low</b>, <i>lowest index to reorder</i>
+  int  <b>high</b>, <i>highest index to reorder</i>
+  Cudd_ReorderingType  <b>submethod</b> <i>window reordering option</i>
+)
+</pre>
+<dd> Reorders by applying the method of the sliding window. Tries all possible permutations to the variables in a window that slides from low to high. The size of the window is determined by submethod. Assumes that no dead nodes are present. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddAlignToBdd"><b>cuddZddAlignToBdd</b></a>(
+  DdManager * <b>table</b> <i>DD manager</i>
+)
+</pre>
+<dd> Reorders ZDD variables according to the order of the BDD variables. This function can be called at the end of BDD reordering to insure that the order of the ZDD variables is consistent with the order of the BDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let <code>M</code> be the ratio of the two numbers. cuddZddAlignToBdd then considers the ZDD variables from <code>M*i</code> to <code>(M+1)*i-1</code> as corresponding to BDD variable <code>i</code>. This function should be normally called from Cudd_ReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Changes the ZDD variable order for all diagrams and performs garbage collection of the ZDD unique table.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddShuffleHeap">Cudd_zddShuffleHeap</a>
+<a href="cuddAllDet.html#Cudd_ReduceHeap">Cudd_ReduceHeap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddChangeAux"><b>cuddZddChangeAux</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>zvar</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddChange.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddChange"><b>cuddZddChange</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Substitutes a variable with its complement in a ZDD. returns a pointer to the result if successful; NULL otherwise. cuddZddChange performs the same function as Cudd_zddChange, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddChange">Cudd_zddChange</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddComplement"><b>cuddZddComplement</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Computes the complement of a ZDD node. So far, since we couldn't find a direct way to get the complement of a ZDD cover, we first convert a ZDD cover to a BDD, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP.
+<p>
+
+<dd> <b>Side Effects</b> The result depends on current variable order.
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddDiff"><b>cuddZddDiff</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddDiff.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddDivideF"><b>cuddZddDivideF</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddDivideF.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDivideF">Cudd_zddDivideF</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddDivide"><b>cuddZddDivide</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddDivide.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDivide">Cudd_zddDivide</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="cuddZddFreeUniv"><b>cuddZddFreeUniv</b></a>(
+  DdManager * <b>zdd</b> <i></i>
+)
+</pre>
+<dd> Frees the ZDD universe.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddInitUniv">cuddZddInitUniv</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddGetCofactors2"><b>cuddZddGetCofactors2</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>v</b>, <i></i>
+  DdNode ** <b>f1</b>, <i></i>
+  DdNode ** <b>f0</b> <i></i>
+)
+</pre>
+<dd> Computes the two-way decomposition of f w.r.t. v.
+<p>
+
+<dd> <b>Side Effects</b> The results are returned in f1 and f0.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddGetCofactors3">cuddZddGetCofactors3</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddGetCofactors3"><b>cuddZddGetCofactors3</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>v</b>, <i></i>
+  DdNode ** <b>f1</b>, <i></i>
+  DdNode ** <b>f0</b>, <i></i>
+  DdNode ** <b>fd</b> <i></i>
+)
+</pre>
+<dd> Computes the three-way decomposition of function f (represented by a ZDD) wit respect to variable v.
+<p>
+
+<dd> <b>Side Effects</b> The results are returned in f1, f0, and fd.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddGetCofactors2">cuddZddGetCofactors2</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddGetNegVarIndex"><b>cuddZddGetNegVarIndex</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the index of negative ZDD variable.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddGetNegVarLevel"><b>cuddZddGetNegVarLevel</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the level of negative ZDD variable.
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddGetNodeIVO"><b>cuddZddGetNodeIVO</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Wrapper for cuddUniqueInterZdd that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of g and h in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddGetNode">cuddZddGetNode</a>
+<a href="cuddAllDet.html#cuddZddIsop">cuddZddIsop</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddGetNode"><b>cuddZddGetNode</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  int  <b>id</b>, <i></i>
+  DdNode * <b>T</b>, <i></i>
+  DdNode * <b>E</b> <i></i>
+)
+</pre>
+<dd> Wrapper for cuddUniqueInterZdd, which applies the ZDD reduction rule. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddUniqueInterZdd">cuddUniqueInterZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddGetPosVarIndex"><b>cuddZddGetPosVarIndex</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the index of positive ZDD variable.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddGetPosVarLevel"><b>cuddZddGetPosVarLevel</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the level of positive ZDD variable.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddInitUniv"><b>cuddZddInitUniv</b></a>(
+  DdManager * <b>zdd</b> <i></i>
+)
+</pre>
+<dd> Initializes the ZDD universe. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddFreeUniv">cuddZddFreeUniv</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddIntersect"><b>cuddZddIntersect</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddIntersect.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddIsop"><b>cuddZddIsop</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>L</b>, <i></i>
+  DdNode * <b>U</b>, <i></i>
+  DdNode ** <b>zdd_I</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddIsop.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddIsop">Cudd_zddIsop</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddIte"><b>cuddZddIte</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddIte.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddLinearSifting"><b>cuddZddLinearSifting</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Implementation of the linear sifting algorithm for ZDDs. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique table. <li> Sift the variable up and down and applies the XOR transformation, remembering each time the total size of the DD heap. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. </ol> Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddNextHigh"><b>cuddZddNextHigh</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b> <i></i>
+)
+</pre>
+<dd> Finds the next subtable with a larger index. Returns the index.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddNextLow"><b>cuddZddNextLow</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b> <i></i>
+)
+</pre>
+<dd> Finds the next subtable with a smaller index. Returns the index.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddProduct"><b>cuddZddProduct</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddProduct.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddProduct">Cudd_zddProduct</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddP"><b>cuddZddP</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Prints a ZDD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddPrintDebug">Cudd_zddPrintDebug</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddSifting"><b>cuddZddSifting</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique table. <li> Sift the variable up and down, remembering each time the total size of the DD heap. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. </ol> Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddSubset0"><b>cuddZddSubset0</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Computes the negative cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is negated. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset0 performs the same function as Cudd_zddSubset0, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddSubset1">cuddZddSubset1</a>
+<a href="cuddAllDet.html#Cudd_zddSubset0">Cudd_zddSubset0</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddSubset1"><b>cuddZddSubset1</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Computes the positive cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is asserted. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset1 performs the same function as Cudd_zddSubset1, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddSubset0">cuddZddSubset0</a>
+<a href="cuddAllDet.html#Cudd_zddSubset1">Cudd_zddSubset1</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddSwapInPlace"><b>cuddZddSwapInPlace</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Swaps two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddZddSwapInPlace assumes that x &lt; y. Returns the number of keys in the table if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddSwapping"><b>cuddZddSwapping</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b>, <i></i>
+  Cudd_ReorderingType  <b>heuristic</b> <i></i>
+)
+</pre>
+<dd> Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps. <ol> <li> Select two variables (RANDOM or HEURISTIC). <li> Permute these variables. <li> If the nodes have decreased accept the permutation. <li> Otherwise reconstruct the original heap. <li> Loop. </ol> Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddSymmCheck"><b>cuddZddSymmCheck</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>x</b>, <i></i>
+  int  <b>y</b> <i></i>
+)
+</pre>
+<dd> Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddSymmSiftingConv"><b>cuddZddSymmSiftingConv</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Symmetric sifting to convergence algorithm for ZDDs. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique subtable. <li> Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. <li> Repeat 1-4 until no further improvement. </ol> Returns 1 plus the number of symmetric variables if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddSymmSifting">cuddZddSymmSifting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddSymmSifting"><b>cuddZddSymmSifting</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Symmetric sifting algorithm. Assumes that no dead nodes are present. <ol> <li> Order all the variables according to the number of entries in each unique subtable. <li> Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric. <li> Select the best permutation. <li> Repeat 3 and 4 for all variables. </ol> Returns 1 plus the number of symmetric variables if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddZddSymmSiftingConv">cuddZddSymmSiftingConv</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddTreeSifting"><b>cuddZddTreeSifting</b></a>(
+  DdManager * <b>table</b>, <i>DD table</i>
+  Cudd_ReorderingType  <b>method</b> <i>reordering method for the groups of leaves</i>
+)
+</pre>
+<dd> Tree sifting algorithm for ZDDs. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling zddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddUnateProduct"><b>cuddZddUnateProduct</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddUnateProduct.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddUnateProduct">Cudd_zddUnateProduct</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="cuddZddUnion"><b>cuddZddUnion</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddUnion.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="cuddZddUniqueCompare"><b>cuddZddUniqueCompare</b></a>(
+  int * <b>ptr_x</b>, <i></i>
+  int * <b>ptr_y</b> <i></i>
+)
+</pre>
+<dd> Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddWeakDivF"><b>cuddZddWeakDivF</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddWeakDivF.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddWeakDivF">Cudd_zddWeakDivF</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="cuddZddWeakDiv"><b>cuddZddWeakDiv</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Performs the recursive step of Cudd_zddWeakDiv.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddWeakDiv">Cudd_zddWeakDiv</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="ddAbs"><b>ddAbs</b></a>(
+   <b>x</b> <i></i>
+)
+</pre>
+<dd> Computes the absolute value of a number.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+ <i></i>
+<a name="ddCHash2"><b>ddCHash2</b></a>(
+   <b>o</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>g</b>, <i></i>
+   <b>s</b> <i></i>
+)
+</pre>
+<dd> Hash function for the cache for functions with two operands.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddHash">ddHash</a>
+<a href="ddAllDet.html#ddCHash">ddCHash</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="ddCHash"><b>ddCHash</b></a>(
+   <b>o</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>g</b>, <i></i>
+   <b>h</b>, <i></i>
+   <b>s</b> <i></i>
+)
+</pre>
+<dd> Hash function for the cache.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddHash">ddHash</a>
+<a href="ddAllDet.html#ddCHash2">ddCHash2</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="ddEqualVal"><b>ddEqualVal</b></a>(
+   <b>x</b>, <i></i>
+   <b>y</b>, <i></i>
+   <b>e</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the absolute value of the difference of the two arguments x and y is less than e.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+ <i></i>
+<a name="ddHash"><b>ddHash</b></a>(
+   <b>f</b>, <i></i>
+   <b>g</b>, <i></i>
+   <b>s</b> <i></i>
+)
+</pre>
+<dd> Hash function for the unique table.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddCHash">ddCHash</a>
+<a href="ddAllDet.html#ddCHash2">ddCHash2</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="ddLCHash2"><b>ddLCHash2</b></a>(
+   <b>f</b>, <i></i>
+   <b>g</b>, <i></i>
+   <b>shift</b> <i></i>
+)
+</pre>
+<dd> Computes hash function for keys of two operands.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddLCHash3">ddLCHash3</a>
+<a href="ddAllDet.html#ddLCHash">ddLCHash</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="ddLCHash3"><b>ddLCHash3</b></a>(
+   <b>f</b>, <i></i>
+   <b>g</b>, <i></i>
+   <b>h</b>, <i></i>
+   <b>shift</b> <i></i>
+)
+</pre>
+<dd> Computes hash function for keys of three operands.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddLCHash2">ddLCHash2</a>
+<a href="ddAllDet.html#ddLCHash">ddLCHash</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="ddMax"><b>ddMax</b></a>(
+   <b>x</b>, <i></i>
+   <b>y</b> <i></i>
+)
+</pre>
+<dd> Computes the maximum of two numbers.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddMin">ddMin</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="ddMin"><b>ddMin</b></a>(
+   <b>x</b>, <i></i>
+   <b>y</b> <i></i>
+)
+</pre>
+<dd> Computes the minimum of two numbers.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="ddAllDet.html#ddMax">ddMax</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="lqHash"><b>lqHash</b></a>(
+   <b>key</b>, <i></i>
+   <b>shift</b> <i></i>
+)
+</pre>
+<dd> Hash function for the table of a level queue.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="hashAllDet.html#hashInsert">hashInsert</a>
+<a href="hashAllDet.html#hashLookup">hashLookup</a>
+<a href="hashAllDet.html#hashDelete">hashDelete</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="statLine"><b>statLine</b></a>(
+   <b>dd</b> <i></i>
+)
+</pre>
+<dd> Outputs a line of stats if DD_COUNT and DD_STATS are defined. Increments the number of recursive calls if DD_COUNT is defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+
+</dl>
+
+<hr>
+
+Generated automatically by <code>extdoc</code> on 20050517
+
+</body></html>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/cuddExtAbs.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/cuddExtAbs.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/cuddExtAbs.html	(revision 8)
@@ -0,0 +1,1296 @@
+<html>
+<head><title>cudd package abstract</title></head>
+<body>
+
+<h1>cudd package abstract</h1>
+<h2>The University of Colorado decision diagram package.</h2>
+<hr>
+
+<!-- Function Abstracts -->
+
+<dl>
+<dt> <a href="cuddExtDet.html#Cudd_AddHook"><code>Cudd_AddHook()</code></a>
+<dd> Adds a function to a hook.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaAdd"><code>Cudd_ApaAdd()</code></a>
+<dd> Adds two arbitrary precision integers.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaCompareRatios"><code>Cudd_ApaCompareRatios()</code></a>
+<dd> Compares the ratios of two arbitrary precision integers to two unsigned ints.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaCompare"><code>Cudd_ApaCompare()</code></a>
+<dd> Compares two arbitrary precision integers.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaCopy"><code>Cudd_ApaCopy()</code></a>
+<dd> Makes a copy of an arbitrary precision integer.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaCountMinterm"><code>Cudd_ApaCountMinterm()</code></a>
+<dd> Counts the number of minterms of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaIntDivision"><code>Cudd_ApaIntDivision()</code></a>
+<dd> Divides an arbitrary precision integer by an integer.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaNumberOfDigits"><code>Cudd_ApaNumberOfDigits()</code></a>
+<dd> Finds the number of digits for an arbitrary precision integer.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaPowerOfTwo"><code>Cudd_ApaPowerOfTwo()</code></a>
+<dd> Sets an arbitrary precision integer to a power of two.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaPrintDecimal"><code>Cudd_ApaPrintDecimal()</code></a>
+<dd> Prints an arbitrary precision integer in decimal format.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaPrintDensity"><code>Cudd_ApaPrintDensity()</code></a>
+<dd> Prints the density of a BDD or ADD using arbitrary precision arithmetic.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaPrintExponential"><code>Cudd_ApaPrintExponential()</code></a>
+<dd> Prints an arbitrary precision integer in exponential format.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaPrintHex"><code>Cudd_ApaPrintHex()</code></a>
+<dd> Prints an arbitrary precision integer in hexadecimal format.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaPrintMintermExp"><code>Cudd_ApaPrintMintermExp()</code></a>
+<dd> Prints the number of minterms of a BDD or ADD in exponential format using arbitrary precision arithmetic.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaPrintMinterm"><code>Cudd_ApaPrintMinterm()</code></a>
+<dd> Prints the number of minterms of a BDD or ADD using arbitrary precision arithmetic.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaSetToLiteral"><code>Cudd_ApaSetToLiteral()</code></a>
+<dd> Sets an arbitrary precision integer to a one-digit literal.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaShiftRight"><code>Cudd_ApaShiftRight()</code></a>
+<dd> Shifts right an arbitrary precision integer by one binary place.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaShortDivision"><code>Cudd_ApaShortDivision()</code></a>
+<dd> Divides an arbitrary precision integer by a digit.
+
+<dt> <a href="cuddExtDet.html#Cudd_ApaSubtract"><code>Cudd_ApaSubtract()</code></a>
+<dd> Subtracts two arbitrary precision integers.
+
+<dt> <a href="cuddExtDet.html#Cudd_AutodynDisableZdd"><code>Cudd_AutodynDisableZdd()</code></a>
+<dd> Disables automatic dynamic reordering of ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_AutodynDisable"><code>Cudd_AutodynDisable()</code></a>
+<dd> Disables automatic dynamic reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_AutodynEnableZdd"><code>Cudd_AutodynEnableZdd()</code></a>
+<dd> Enables automatic dynamic reordering of ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_AutodynEnable"><code>Cudd_AutodynEnable()</code></a>
+<dd> Enables automatic dynamic reordering of BDDs and ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_AverageDistance"><code>Cudd_AverageDistance()</code></a>
+<dd> Computes the average distance between adjacent nodes.
+
+<dt> <a href="cuddExtDet.html#Cudd_BddToAdd"><code>Cudd_BddToAdd()</code></a>
+<dd> Converts a BDD to a 0-1 ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_BddToCubeArray"><code>Cudd_BddToCubeArray()</code></a>
+<dd> Builds a positional array from the BDD of a cube.
+
+<dt> <a href="cuddExtDet.html#Cudd_BiasedOverApprox"><code>Cudd_BiasedOverApprox()</code></a>
+<dd> Extracts a dense superset from a BDD with the biased underapproximation method.
+
+<dt> <a href="cuddExtDet.html#Cudd_BiasedUnderApprox"><code>Cudd_BiasedUnderApprox()</code></a>
+<dd> Extracts a dense subset from a BDD with the biased underapproximation method.
+
+<dt> <a href="cuddExtDet.html#Cudd_CProjection"><code>Cudd_CProjection()</code></a>
+<dd> Computes the compatible projection of R w.r.t. cube Y.
+
+<dt> <a href="cuddExtDet.html#Cudd_CheckKeys"><code>Cudd_CheckKeys()</code></a>
+<dd> Checks for several conditions that should not occur.
+
+<dt> <a href="cuddExtDet.html#Cudd_CheckZeroRef"><code>Cudd_CheckZeroRef()</code></a>
+<dd> Checks the unique table for nodes with non-zero reference counts.
+
+<dt> <a href="cuddExtDet.html#Cudd_ClassifySupport"><code>Cudd_ClassifySupport()</code></a>
+<dd> Classifies the variables in the support of two DDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_ClearErrorCode"><code>Cudd_ClearErrorCode()</code></a>
+<dd> Clear the error code of a manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_CofMinterm"><code>Cudd_CofMinterm()</code></a>
+<dd> Computes the fraction of minterms in the on-set of all the positive cofactors of a BDD or ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_Cofactor"><code>Cudd_Cofactor()</code></a>
+<dd> Computes the cofactor of f with respect to g.
+
+<dt> <a href="cuddExtDet.html#Cudd_Complement"><code>Cudd_Complement()</code></a>
+<dd> Returns the complemented version of a pointer.
+
+<dt> <a href="cuddExtDet.html#Cudd_CountLeaves"><code>Cudd_CountLeaves()</code></a>
+<dd> Counts the number of leaves in a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_CountMinterm"><code>Cudd_CountMinterm()</code></a>
+<dd> Counts the number of minterms of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_CountPathsToNonZero"><code>Cudd_CountPathsToNonZero()</code></a>
+<dd> Counts the number of paths to a non-zero terminal of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_CountPath"><code>Cudd_CountPath()</code></a>
+<dd> Counts the number of paths of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_CubeArrayToBdd"><code>Cudd_CubeArrayToBdd()</code></a>
+<dd> Builds the BDD of a cube from a positional array.
+
+<dt> <a href="cuddExtDet.html#Cudd_DagSize"><code>Cudd_DagSize()</code></a>
+<dd> Counts the number of nodes in a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_DeadAreCounted"><code>Cudd_DeadAreCounted()</code></a>
+<dd> Tells whether dead nodes are counted towards triggering reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_DebugCheck"><code>Cudd_DebugCheck()</code></a>
+<dd> Checks for inconsistencies in the DD heap.
+
+<dt> <a href="cuddExtDet.html#Cudd_Decreasing"><code>Cudd_Decreasing()</code></a>
+<dd> Determines whether a BDD is negative unate in a variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_DelayedDerefBdd"><code>Cudd_DelayedDerefBdd()</code></a>
+<dd> Decreases the reference count of BDD node n.
+
+<dt> <a href="cuddExtDet.html#Cudd_Density"><code>Cudd_Density()</code></a>
+<dd> Computes the density of a BDD or ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_Deref"><code>Cudd_Deref()</code></a>
+<dd> Decreases the reference count of node.
+
+<dt> <a href="cuddExtDet.html#Cudd_DisableGarbageCollection"><code>Cudd_DisableGarbageCollection()</code></a>
+<dd> Disables garbage collection.
+
+<dt> <a href="cuddExtDet.html#Cudd_DisableReorderingReporting"><code>Cudd_DisableReorderingReporting()</code></a>
+<dd> Disables reporting of reordering stats.
+
+<dt> <a href="cuddExtDet.html#Cudd_DumpBlifBody"><code>Cudd_DumpBlifBody()</code></a>
+<dd> Writes a blif body representing the argument BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_DumpBlif"><code>Cudd_DumpBlif()</code></a>
+<dd> Writes a blif file representing the argument BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_DumpDDcal"><code>Cudd_DumpDDcal()</code></a>
+<dd> Writes a DDcal file representing the argument BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_DumpDaVinci"><code>Cudd_DumpDaVinci()</code></a>
+<dd> Writes a daVinci file representing the argument BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_DumpDot"><code>Cudd_DumpDot()</code></a>
+<dd> Writes a dot file representing the argument DDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_DumpFactoredForm"><code>Cudd_DumpFactoredForm()</code></a>
+<dd> Writes factored forms representing the argument BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_Dxygtdxz"><code>Cudd_Dxygtdxz()</code></a>
+<dd> Generates a BDD for the function d(x,y) &gt; d(x,z).
+
+<dt> <a href="cuddExtDet.html#Cudd_Dxygtdyz"><code>Cudd_Dxygtdyz()</code></a>
+<dd> Generates a BDD for the function d(x,y) &gt; d(y,z).
+
+<dt> <a href="cuddExtDet.html#Cudd_EnableGarbageCollection"><code>Cudd_EnableGarbageCollection()</code></a>
+<dd> Enables garbage collection.
+
+<dt> <a href="cuddExtDet.html#Cudd_EnableReorderingReporting"><code>Cudd_EnableReorderingReporting()</code></a>
+<dd> Enables reporting of reordering stats.
+
+<dt> <a href="cuddExtDet.html#Cudd_EpdCountMinterm"><code>Cudd_EpdCountMinterm()</code></a>
+<dd> Counts the number of minterms of a DD with extended precision.
+
+<dt> <a href="cuddExtDet.html#Cudd_EqualSupNorm"><code>Cudd_EqualSupNorm()</code></a>
+<dd> Compares two ADDs for equality within tolerance.
+
+<dt> <a href="cuddExtDet.html#Cudd_EquivDC"><code>Cudd_EquivDC()</code></a>
+<dd> Tells whether F and G are identical wherever D is 0.
+
+<dt> <a href="cuddExtDet.html#Cudd_EstimateCofactorSimple"><code>Cudd_EstimateCofactorSimple()</code></a>
+<dd> Estimates the number of nodes in a cofactor of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_EstimateCofactor"><code>Cudd_EstimateCofactor()</code></a>
+<dd> Estimates the number of nodes in a cofactor of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_Eval"><code>Cudd_Eval()</code></a>
+<dd> Returns the value of a DD for a given variable assignment.
+
+<dt> <a href="cuddExtDet.html#Cudd_ExpectedUsedSlots"><code>Cudd_ExpectedUsedSlots()</code></a>
+<dd> Computes the expected fraction of used slots in the unique table.
+
+<dt> <a href="cuddExtDet.html#Cudd_E"><code>Cudd_E()</code></a>
+<dd> Returns the else child of an internal node.
+
+<dt> <a href="cuddExtDet.html#Cudd_FindEssential"><code>Cudd_FindEssential()</code></a>
+<dd> Finds the essential variables of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_FindTwoLiteralClauses"><code>Cudd_FindTwoLiteralClauses()</code></a>
+<dd> Finds the two literal clauses of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_FirstCube"><code>Cudd_FirstCube()</code></a>
+<dd> Finds the first cube of a decision diagram.
+
+<dt> <a href="cuddExtDet.html#Cudd_FirstNode"><code>Cudd_FirstNode()</code></a>
+<dd> Finds the first node of a decision diagram.
+
+<dt> <a href="cuddExtDet.html#Cudd_FirstPrime"><code>Cudd_FirstPrime()</code></a>
+<dd> Finds the first prime of a Boolean function.
+
+<dt> <a href="cuddExtDet.html#Cudd_ForeachCube"><code>Cudd_ForeachCube()</code></a>
+<dd> Iterates over the cubes of a decision diagram.
+
+<dt> <a href="cuddExtDet.html#Cudd_ForeachNode"><code>Cudd_ForeachNode()</code></a>
+<dd> Iterates over the nodes of a decision diagram.
+
+<dt> <a href="cuddExtDet.html#Cudd_ForeachPrime"><code>Cudd_ForeachPrime()</code></a>
+<dd> Iterates over the primes of a Boolean function.
+
+<dt> <a href="cuddExtDet.html#Cudd_FreeTree"><code>Cudd_FreeTree()</code></a>
+<dd> Frees the variable group tree of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_FreeZddTree"><code>Cudd_FreeZddTree()</code></a>
+<dd> Frees the variable group tree of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_GarbageCollectionEnabled"><code>Cudd_GarbageCollectionEnabled()</code></a>
+<dd> Tells whether garbage collection is enabled.
+
+<dt> <a href="cuddExtDet.html#Cudd_GenFree"><code>Cudd_GenFree()</code></a>
+<dd> Frees a CUDD generator.
+
+<dt> <a href="cuddExtDet.html#Cudd_Increasing"><code>Cudd_Increasing()</code></a>
+<dd> Determines whether a BDD is positive unate in a variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_IndicesToCube"><code>Cudd_IndicesToCube()</code></a>
+<dd> Builds a cube of BDD variables from an array of indices.
+
+<dt> <a href="cuddExtDet.html#Cudd_Init"><code>Cudd_Init()</code></a>
+<dd> Creates a new DD manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_IsComplement"><code>Cudd_IsComplement()</code></a>
+<dd> Returns 1 if a pointer is complemented.
+
+<dt> <a href="cuddExtDet.html#Cudd_IsConstant"><code>Cudd_IsConstant()</code></a>
+<dd> Returns 1 if the node is a constant node.
+
+<dt> <a href="cuddExtDet.html#Cudd_IsGenEmpty"><code>Cudd_IsGenEmpty()</code></a>
+<dd> Queries the status of a generator.
+
+<dt> <a href="cuddExtDet.html#Cudd_IsInHook"><code>Cudd_IsInHook()</code></a>
+<dd> Checks whether a function is in a hook.
+
+<dt> <a href="cuddExtDet.html#Cudd_IsNonConstant"><code>Cudd_IsNonConstant()</code></a>
+<dd> Returns 1 if a DD node is not constant.
+
+<dt> <a href="cuddExtDet.html#Cudd_IterDerefBdd"><code>Cudd_IterDerefBdd()</code></a>
+<dd> Decreases the reference count of BDD node n.
+
+<dt> <a href="cuddExtDet.html#Cudd_LargestCube"><code>Cudd_LargestCube()</code></a>
+<dd> Finds a largest cube in a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_MakeBddFromZddCover"><code>Cudd_MakeBddFromZddCover()</code></a>
+<dd> Converts a ZDD cover to a BDD graph.
+
+<dt> <a href="cuddExtDet.html#Cudd_MakeTreeNode"><code>Cudd_MakeTreeNode()</code></a>
+<dd> Creates a new variable group.
+
+<dt> <a href="cuddExtDet.html#Cudd_MakeZddTreeNode"><code>Cudd_MakeZddTreeNode()</code></a>
+<dd> Creates a new ZDD variable group.
+
+<dt> <a href="cuddExtDet.html#Cudd_MinHammingDist"><code>Cudd_MinHammingDist()</code></a>
+<dd> Returns the minimum Hamming distance between f and minterm.
+
+<dt> <a href="cuddExtDet.html#Cudd_NewApaNumber"><code>Cudd_NewApaNumber()</code></a>
+<dd> Allocates memory for an arbitrary precision integer.
+
+<dt> <a href="cuddExtDet.html#Cudd_NextCube"><code>Cudd_NextCube()</code></a>
+<dd> Generates the next cube of a decision diagram onset.
+
+<dt> <a href="cuddExtDet.html#Cudd_NextNode"><code>Cudd_NextNode()</code></a>
+<dd> Finds the next node of a decision diagram.
+
+<dt> <a href="cuddExtDet.html#Cudd_NextPrime"><code>Cudd_NextPrime()</code></a>
+<dd> Generates the next prime of a Boolean function.
+
+<dt> <a href="cuddExtDet.html#Cudd_NodeReadIndex"><code>Cudd_NodeReadIndex()</code></a>
+<dd> Returns the index of the node.
+
+<dt> <a href="cuddExtDet.html#Cudd_NotCond"><code>Cudd_NotCond()</code></a>
+<dd> Complements a DD if a condition is true.
+
+<dt> <a href="cuddExtDet.html#Cudd_Not"><code>Cudd_Not()</code></a>
+<dd> Complements a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_OutOfMem"><code>Cudd_OutOfMem()</code></a>
+<dd> Warns that a memory allocation failed.
+
+<dt> <a href="cuddExtDet.html#Cudd_OverApprox"><code>Cudd_OverApprox()</code></a>
+<dd> Extracts a dense superset from a BDD with Shiple's underapproximation method.
+
+<dt> <a href="cuddExtDet.html#Cudd_Prime"><code>Cudd_Prime()</code></a>
+<dd> Returns the next prime &gt;= p.
+
+<dt> <a href="cuddExtDet.html#Cudd_PrintDebug"><code>Cudd_PrintDebug()</code></a>
+<dd> Prints to the standard output a DD and its statistics.
+
+<dt> <a href="cuddExtDet.html#Cudd_PrintInfo"><code>Cudd_PrintInfo()</code></a>
+<dd> Prints out statistics and settings for a CUDD manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_PrintLinear"><code>Cudd_PrintLinear()</code></a>
+<dd> Prints the linear transform matrix.
+
+<dt> <a href="cuddExtDet.html#Cudd_PrintMinterm"><code>Cudd_PrintMinterm()</code></a>
+<dd> Prints a disjoint sum of products.
+
+<dt> <a href="cuddExtDet.html#Cudd_PrintTwoLiteralClauses"><code>Cudd_PrintTwoLiteralClauses()</code></a>
+<dd> Prints the two literal clauses of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_PrintVersion"><code>Cudd_PrintVersion()</code></a>
+<dd> Prints the package version number.
+
+<dt> <a href="cuddExtDet.html#Cudd_PrioritySelect"><code>Cudd_PrioritySelect()</code></a>
+<dd> Selects pairs from R using a priority function.
+
+<dt> <a href="cuddExtDet.html#Cudd_Quit"><code>Cudd_Quit()</code></a>
+<dd> Deletes resources associated with a DD manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_Random"><code>Cudd_Random()</code></a>
+<dd> Portable random number generator.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadArcviolation"><code>Cudd_ReadArcviolation()</code></a>
+<dd> Returns the current value of the arcviolation parameter used in group sifting.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadBackground"><code>Cudd_ReadBackground()</code></a>
+<dd> Reads the background constant of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadCacheHits"><code>Cudd_ReadCacheHits()</code></a>
+<dd> Returns the number of cache hits.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadCacheLookUps"><code>Cudd_ReadCacheLookUps()</code></a>
+<dd> Returns the number of cache look-ups.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadCacheSlots"><code>Cudd_ReadCacheSlots()</code></a>
+<dd> Reads the number of slots in the cache.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadCacheUsedSlots"><code>Cudd_ReadCacheUsedSlots()</code></a>
+<dd> Reads the fraction of used slots in the cache.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadDead"><code>Cudd_ReadDead()</code></a>
+<dd> Returns the number of dead nodes in the unique table.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadEpsilon"><code>Cudd_ReadEpsilon()</code></a>
+<dd> Reads the epsilon parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadErrorCode"><code>Cudd_ReadErrorCode()</code></a>
+<dd> Returns the code of the last error.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadGarbageCollectionTime"><code>Cudd_ReadGarbageCollectionTime()</code></a>
+<dd> Returns the time spent in garbage collection.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadGarbageCollections"><code>Cudd_ReadGarbageCollections()</code></a>
+<dd> Returns the number of times garbage collection has occurred.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadGroupcheck"><code>Cudd_ReadGroupcheck()</code></a>
+<dd> Reads the groupcheck parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadIndex"><code>Cudd_ReadIndex()</code></a>
+<dd> Returns the current position in the order of variable index.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadInvPermZdd"><code>Cudd_ReadInvPermZdd()</code></a>
+<dd> Returns the index of the ZDD variable currently in the i-th position of the order.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadInvPerm"><code>Cudd_ReadInvPerm()</code></a>
+<dd> Returns the index of the variable currently in the i-th position of the order.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadIthClause"><code>Cudd_ReadIthClause()</code></a>
+<dd> Accesses the i-th clause of a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadKeys"><code>Cudd_ReadKeys()</code></a>
+<dd> Returns the number of nodes in the unique table.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadLinear"><code>Cudd_ReadLinear()</code></a>
+<dd> Reads an entry of the linear transform matrix.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadLogicZero"><code>Cudd_ReadLogicZero()</code></a>
+<dd> Returns the logic zero constant of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadLooseUpTo"><code>Cudd_ReadLooseUpTo()</code></a>
+<dd> Reads the looseUpTo parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMaxCacheHard"><code>Cudd_ReadMaxCacheHard()</code></a>
+<dd> Reads the maxCacheHard parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMaxCache"><code>Cudd_ReadMaxCache()</code></a>
+<dd> Returns the soft limit for the cache size.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMaxGrowthAlternate"><code>Cudd_ReadMaxGrowthAlternate()</code></a>
+<dd> Reads the maxGrowthAlt parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMaxGrowth"><code>Cudd_ReadMaxGrowth()</code></a>
+<dd> Reads the maxGrowth parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMaxLive"><code>Cudd_ReadMaxLive()</code></a>
+<dd> Reads the maximum allowed number of live nodes.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMaxMemory"><code>Cudd_ReadMaxMemory()</code></a>
+<dd> Reads the maximum allowed memory.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMemoryInUse"><code>Cudd_ReadMemoryInUse()</code></a>
+<dd> Returns the memory in use by the manager measured in bytes.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMinDead"><code>Cudd_ReadMinDead()</code></a>
+<dd> Reads the minDead parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMinHit"><code>Cudd_ReadMinHit()</code></a>
+<dd> Reads the hit rate that causes resizinig of the computed table.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadMinusInfinity"><code>Cudd_ReadMinusInfinity()</code></a>
+<dd> Reads the minus-infinity constant from the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadNextReordering"><code>Cudd_ReadNextReordering()</code></a>
+<dd> Returns the threshold for the next dynamic reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadNodeCount"><code>Cudd_ReadNodeCount()</code></a>
+<dd> Reports the number of nodes in BDDs and ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadNodesDropped"><code>Cudd_ReadNodesDropped()</code></a>
+<dd> Returns the number of nodes dropped.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadNodesFreed"><code>Cudd_ReadNodesFreed()</code></a>
+<dd> Returns the number of nodes freed.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadNumberXovers"><code>Cudd_ReadNumberXovers()</code></a>
+<dd> Reads the current number of crossovers used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadOne"><code>Cudd_ReadOne()</code></a>
+<dd> Returns the one constant of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadPeakLiveNodeCount"><code>Cudd_ReadPeakLiveNodeCount()</code></a>
+<dd> Reports the peak number of live nodes.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadPeakNodeCount"><code>Cudd_ReadPeakNodeCount()</code></a>
+<dd> Reports the peak number of nodes.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadPermZdd"><code>Cudd_ReadPermZdd()</code></a>
+<dd> Returns the current position of the i-th ZDD variable in the order.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadPerm"><code>Cudd_ReadPerm()</code></a>
+<dd> Returns the current position of the i-th variable in the order.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadPlusInfinity"><code>Cudd_ReadPlusInfinity()</code></a>
+<dd> Reads the plus-infinity constant from the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadPopulationSize"><code>Cudd_ReadPopulationSize()</code></a>
+<dd> Reads the current size of the population used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadRecomb"><code>Cudd_ReadRecomb()</code></a>
+<dd> Returns the current value of the recombination parameter used in group sifting.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadRecursiveCalls"><code>Cudd_ReadRecursiveCalls()</code></a>
+<dd> Returns the number of recursive calls.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadReorderingCycle"><code>Cudd_ReadReorderingCycle()</code></a>
+<dd> Reads the reordCycle parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadReorderingTime"><code>Cudd_ReadReorderingTime()</code></a>
+<dd> Returns the time spent in reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadReorderings"><code>Cudd_ReadReorderings()</code></a>
+<dd> Returns the number of times reordering has occurred.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadSiftMaxSwap"><code>Cudd_ReadSiftMaxSwap()</code></a>
+<dd> Reads the siftMaxSwap parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadSiftMaxVar"><code>Cudd_ReadSiftMaxVar()</code></a>
+<dd> Reads the siftMaxVar parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadSize"><code>Cudd_ReadSize()</code></a>
+<dd> Returns the number of BDD variables in existance.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadSlots"><code>Cudd_ReadSlots()</code></a>
+<dd> Returns the total number of slots of the unique table.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadStderr"><code>Cudd_ReadStderr()</code></a>
+<dd> Reads the stderr of a manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadStdout"><code>Cudd_ReadStdout()</code></a>
+<dd> Reads the stdout of a manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadSwapSteps"><code>Cudd_ReadSwapSteps()</code></a>
+<dd> Reads the number of elementary reordering steps.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadSymmviolation"><code>Cudd_ReadSymmviolation()</code></a>
+<dd> Returns the current value of the symmviolation parameter used in group sifting.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadTree"><code>Cudd_ReadTree()</code></a>
+<dd> Returns the variable group tree of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadUniqueLinks"><code>Cudd_ReadUniqueLinks()</code></a>
+<dd> Returns the number of links followed in the unique table.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadUniqueLookUps"><code>Cudd_ReadUniqueLookUps()</code></a>
+<dd> Returns the number of look-ups in the unique table.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadUsedSlots"><code>Cudd_ReadUsedSlots()</code></a>
+<dd> Reads the fraction of used slots in the unique table.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadVars"><code>Cudd_ReadVars()</code></a>
+<dd> Returns the i-th element of the vars array.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadZddOne"><code>Cudd_ReadZddOne()</code></a>
+<dd> Returns the ZDD for the constant 1 function.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadZddSize"><code>Cudd_ReadZddSize()</code></a>
+<dd> Returns the number of ZDD variables in existance.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadZddTree"><code>Cudd_ReadZddTree()</code></a>
+<dd> Returns the variable group tree of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReadZero"><code>Cudd_ReadZero()</code></a>
+<dd> Returns the zero constant of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_RecursiveDerefZdd"><code>Cudd_RecursiveDerefZdd()</code></a>
+<dd> Decreases the reference count of ZDD node n.
+
+<dt> <a href="cuddExtDet.html#Cudd_RecursiveDeref"><code>Cudd_RecursiveDeref()</code></a>
+<dd> Decreases the reference count of node n.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReduceHeap"><code>Cudd_ReduceHeap()</code></a>
+<dd> Main dynamic reordering routine.
+
+<dt> <a href="cuddExtDet.html#Cudd_Ref"><code>Cudd_Ref()</code></a>
+<dd> Increases the reference count of a node, if it is not saturated.
+
+<dt> <a href="cuddExtDet.html#Cudd_Regular"><code>Cudd_Regular()</code></a>
+<dd> Returns the regular version of a pointer.
+
+<dt> <a href="cuddExtDet.html#Cudd_RemapOverApprox"><code>Cudd_RemapOverApprox()</code></a>
+<dd> Extracts a dense superset from a BDD with the remapping underapproximation method.
+
+<dt> <a href="cuddExtDet.html#Cudd_RemapUnderApprox"><code>Cudd_RemapUnderApprox()</code></a>
+<dd> Extracts a dense subset from a BDD with the remapping underapproximation method.
+
+<dt> <a href="cuddExtDet.html#Cudd_RemoveHook"><code>Cudd_RemoveHook()</code></a>
+<dd> Removes a function from a hook.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReorderingReporting"><code>Cudd_ReorderingReporting()</code></a>
+<dd> Returns 1 if reporting of reordering stats is enabled.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReorderingStatusZdd"><code>Cudd_ReorderingStatusZdd()</code></a>
+<dd> Reports the status of automatic dynamic reordering of ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_ReorderingStatus"><code>Cudd_ReorderingStatus()</code></a>
+<dd> Reports the status of automatic dynamic reordering of BDDs and ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetArcviolation"><code>Cudd_SetArcviolation()</code></a>
+<dd> Sets the value of the arcviolation parameter used in group sifting.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetBackground"><code>Cudd_SetBackground()</code></a>
+<dd> Sets the background constant of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetEpsilon"><code>Cudd_SetEpsilon()</code></a>
+<dd> Sets the epsilon parameter of the manager to ep.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetGroupcheck"><code>Cudd_SetGroupcheck()</code></a>
+<dd> Sets the parameter groupcheck of the manager to gc.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetLooseUpTo"><code>Cudd_SetLooseUpTo()</code></a>
+<dd> Sets the looseUpTo parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetMaxCacheHard"><code>Cudd_SetMaxCacheHard()</code></a>
+<dd> Sets the maxCacheHard parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetMaxGrowthAlternate"><code>Cudd_SetMaxGrowthAlternate()</code></a>
+<dd> Sets the maxGrowthAlt parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetMaxGrowth"><code>Cudd_SetMaxGrowth()</code></a>
+<dd> Sets the maxGrowth parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetMaxLive"><code>Cudd_SetMaxLive()</code></a>
+<dd> Sets the maximum allowed number of live nodes.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetMaxMemory"><code>Cudd_SetMaxMemory()</code></a>
+<dd> Sets the maximum allowed memory.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetMinHit"><code>Cudd_SetMinHit()</code></a>
+<dd> Sets the hit rate that causes resizinig of the computed table.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetNextReordering"><code>Cudd_SetNextReordering()</code></a>
+<dd> Sets the threshold for the next dynamic reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetNumberXovers"><code>Cudd_SetNumberXovers()</code></a>
+<dd> Sets the number of crossovers used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetPopulationSize"><code>Cudd_SetPopulationSize()</code></a>
+<dd> Sets the size of the population used by the genetic algorithm for reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetRecomb"><code>Cudd_SetRecomb()</code></a>
+<dd> Sets the value of the recombination parameter used in group sifting.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetReorderingCycle"><code>Cudd_SetReorderingCycle()</code></a>
+<dd> Sets the reordCycle parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetSiftMaxSwap"><code>Cudd_SetSiftMaxSwap()</code></a>
+<dd> Sets the siftMaxSwap parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetSiftMaxVar"><code>Cudd_SetSiftMaxVar()</code></a>
+<dd> Sets the siftMaxVar parameter of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetStderr"><code>Cudd_SetStderr()</code></a>
+<dd> Sets the stderr of a manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetStdout"><code>Cudd_SetStdout()</code></a>
+<dd> Sets the stdout of a manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetSymmviolation"><code>Cudd_SetSymmviolation()</code></a>
+<dd> Sets the value of the symmviolation parameter used in group sifting.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetTree"><code>Cudd_SetTree()</code></a>
+<dd> Sets the variable group tree of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetVarMap"><code>Cudd_SetVarMap()</code></a>
+<dd> Registers a variable mapping with the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SetZddTree"><code>Cudd_SetZddTree()</code></a>
+<dd> Sets the ZDD variable group tree of the manager.
+
+<dt> <a href="cuddExtDet.html#Cudd_SharingSize"><code>Cudd_SharingSize()</code></a>
+<dd> Counts the number of nodes in an array of DDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_ShortestLength"><code>Cudd_ShortestLength()</code></a>
+<dd> Find the length of the shortest path(s) in a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_ShortestPath"><code>Cudd_ShortestPath()</code></a>
+<dd> Finds a shortest path in a DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_ShuffleHeap"><code>Cudd_ShuffleHeap()</code></a>
+<dd> Reorders variables according to given permutation.
+
+<dt> <a href="cuddExtDet.html#Cudd_SolveEqn"><code>Cudd_SolveEqn()</code></a>
+<dd> Implements the solution of F(x,y) = 0.
+
+<dt> <a href="cuddExtDet.html#Cudd_SplitSet"><code>Cudd_SplitSet()</code></a>
+<dd> Returns m minterms from a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_Srandom"><code>Cudd_Srandom()</code></a>
+<dd> Initializer for the portable random number generator.
+
+<dt> <a href="cuddExtDet.html#Cudd_StdPostReordHook"><code>Cudd_StdPostReordHook()</code></a>
+<dd> Sample hook function to call after reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_StdPreReordHook"><code>Cudd_StdPreReordHook()</code></a>
+<dd> Sample hook function to call before reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_SubsetCompress"><code>Cudd_SubsetCompress()</code></a>
+<dd> Find a dense subset of BDD <code>f</code>.
+
+<dt> <a href="cuddExtDet.html#Cudd_SubsetHeavyBranch"><code>Cudd_SubsetHeavyBranch()</code></a>
+<dd> Extracts a dense subset from a BDD with the heavy branch heuristic.
+
+<dt> <a href="cuddExtDet.html#Cudd_SubsetShortPaths"><code>Cudd_SubsetShortPaths()</code></a>
+<dd> Extracts a dense subset from a BDD with the shortest paths heuristic.
+
+<dt> <a href="cuddExtDet.html#Cudd_SubsetWithMaskVars"><code>Cudd_SubsetWithMaskVars()</code></a>
+<dd> Extracts a subset from a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_SupersetCompress"><code>Cudd_SupersetCompress()</code></a>
+<dd> Find a dense superset of BDD <code>f</code>.
+
+<dt> <a href="cuddExtDet.html#Cudd_SupersetHeavyBranch"><code>Cudd_SupersetHeavyBranch()</code></a>
+<dd> Extracts a dense superset from a BDD with the heavy branch heuristic.
+
+<dt> <a href="cuddExtDet.html#Cudd_SupersetShortPaths"><code>Cudd_SupersetShortPaths()</code></a>
+<dd> Extracts a dense superset from a BDD with the shortest paths heuristic.
+
+<dt> <a href="cuddExtDet.html#Cudd_SupportIndex"><code>Cudd_SupportIndex()</code></a>
+<dd> Finds the variables on which a DD depends.
+
+<dt> <a href="cuddExtDet.html#Cudd_SupportSize"><code>Cudd_SupportSize()</code></a>
+<dd> Counts the variables on which a DD depends.
+
+<dt> <a href="cuddExtDet.html#Cudd_Support"><code>Cudd_Support()</code></a>
+<dd> Finds the variables on which a DD depends.
+
+<dt> <a href="cuddExtDet.html#Cudd_SymmProfile"><code>Cudd_SymmProfile()</code></a>
+<dd> Prints statistics on symmetric variables.
+
+<dt> <a href="cuddExtDet.html#Cudd_TurnOffCountDead"><code>Cudd_TurnOffCountDead()</code></a>
+<dd> Causes the dead nodes not to be counted towards triggering reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_TurnOnCountDead"><code>Cudd_TurnOnCountDead()</code></a>
+<dd> Causes the dead nodes to be counted towards triggering reordering.
+
+<dt> <a href="cuddExtDet.html#Cudd_T"><code>Cudd_T()</code></a>
+<dd> Returns the then child of an internal node.
+
+<dt> <a href="cuddExtDet.html#Cudd_UnderApprox"><code>Cudd_UnderApprox()</code></a>
+<dd> Extracts a dense subset from a BDD with Shiple's underapproximation method.
+
+<dt> <a href="cuddExtDet.html#Cudd_VectorSupportIndex"><code>Cudd_VectorSupportIndex()</code></a>
+<dd> Finds the variables on which a set of DDs depends.
+
+<dt> <a href="cuddExtDet.html#Cudd_VectorSupportSize"><code>Cudd_VectorSupportSize()</code></a>
+<dd> Counts the variables on which a set of DDs depends.
+
+<dt> <a href="cuddExtDet.html#Cudd_VectorSupport"><code>Cudd_VectorSupport()</code></a>
+<dd> Finds the variables on which a set of DDs depends.
+
+<dt> <a href="cuddExtDet.html#Cudd_VerifySol"><code>Cudd_VerifySol()</code></a>
+<dd> Checks the solution of F(x,y) = 0.
+
+<dt> <a href="cuddExtDet.html#Cudd_V"><code>Cudd_V()</code></a>
+<dd> Returns the value of a constant node.
+
+<dt> <a href="cuddExtDet.html#Cudd_Xeqy"><code>Cudd_Xeqy()</code></a>
+<dd> Generates a BDD for the function x==y.
+
+<dt> <a href="cuddExtDet.html#Cudd_Xgty"><code>Cudd_Xgty()</code></a>
+<dd> Generates a BDD for the function x &gt; y.
+
+<dt> <a href="cuddExtDet.html#Cudd_addAgreement"><code>Cudd_addAgreement()</code></a>
+<dd> f if f==g; background if f!=g.
+
+<dt> <a href="cuddExtDet.html#Cudd_addApply"><code>Cudd_addApply()</code></a>
+<dd> Applies op to the corresponding discriminants of f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_addBddInterval"><code>Cudd_addBddInterval()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addBddIthBit"><code>Cudd_addBddIthBit()</code></a>
+<dd> Converts an ADD to a BDD by extracting the i-th bit from the leaves.
+
+<dt> <a href="cuddExtDet.html#Cudd_addBddPattern"><code>Cudd_addBddPattern()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addBddStrictThreshold"><code>Cudd_addBddStrictThreshold()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addBddThreshold"><code>Cudd_addBddThreshold()</code></a>
+<dd> Converts an ADD to a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addCmpl"><code>Cudd_addCmpl()</code></a>
+<dd> Computes the complement of an ADD a la C language.
+
+<dt> <a href="cuddExtDet.html#Cudd_addCompose"><code>Cudd_addCompose()</code></a>
+<dd> Substitutes g for x_v in the ADD for f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addComputeCube"><code>Cudd_addComputeCube()</code></a>
+<dd> Computes the cube of an array of ADD variables.
+
+<dt> <a href="cuddExtDet.html#Cudd_addConstrain"><code>Cudd_addConstrain()</code></a>
+<dd> Computes f constrain c for ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addConst"><code>Cudd_addConst()</code></a>
+<dd> Returns the ADD for constant c.
+
+<dt> <a href="cuddExtDet.html#Cudd_addDiff"><code>Cudd_addDiff()</code></a>
+<dd> Returns plusinfinity if f=g; returns min(f,g) if f!=g.
+
+<dt> <a href="cuddExtDet.html#Cudd_addDivide"><code>Cudd_addDivide()</code></a>
+<dd> Integer and floating point division.
+
+<dt> <a href="cuddExtDet.html#Cudd_addEvalConst"><code>Cudd_addEvalConst()</code></a>
+<dd> Checks whether ADD g is constant whenever ADD f is 1.
+
+<dt> <a href="cuddExtDet.html#Cudd_addExistAbstract"><code>Cudd_addExistAbstract()</code></a>
+<dd> Existentially Abstracts all the variables in cube from f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addFindMax"><code>Cudd_addFindMax()</code></a>
+<dd> Finds the maximum discriminant of f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addFindMin"><code>Cudd_addFindMin()</code></a>
+<dd> Finds the minimum discriminant of f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addGeneralVectorCompose"><code>Cudd_addGeneralVectorCompose()</code></a>
+<dd> Composes an ADD with a vector of ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addHamming"><code>Cudd_addHamming()</code></a>
+<dd> Computes the Hamming distance ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addHarwell"><code>Cudd_addHarwell()</code></a>
+<dd> Reads in a matrix in the format of the Harwell-Boeing benchmark suite.
+
+<dt> <a href="cuddExtDet.html#Cudd_addIteConstant"><code>Cudd_addIteConstant()</code></a>
+<dd> Implements ITEconstant for ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addIte"><code>Cudd_addIte()</code></a>
+<dd> Implements ITE(f,g,h).
+
+<dt> <a href="cuddExtDet.html#Cudd_addIthBit"><code>Cudd_addIthBit()</code></a>
+<dd> Extracts the i-th bit from an ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addIthVar"><code>Cudd_addIthVar()</code></a>
+<dd> Returns the ADD variable with index i.
+
+<dt> <a href="cuddExtDet.html#Cudd_addLeq"><code>Cudd_addLeq()</code></a>
+<dd> Determines whether f is less than or equal to g.
+
+<dt> <a href="cuddExtDet.html#Cudd_addLog"><code>Cudd_addLog()</code></a>
+<dd> Natural logarithm of an ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addMatrixMultiply"><code>Cudd_addMatrixMultiply()</code></a>
+<dd> Calculates the product of two matrices represented as ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addMaximum"><code>Cudd_addMaximum()</code></a>
+<dd> Integer and floating point max.
+
+<dt> <a href="cuddExtDet.html#Cudd_addMinimum"><code>Cudd_addMinimum()</code></a>
+<dd> Integer and floating point min.
+
+<dt> <a href="cuddExtDet.html#Cudd_addMinus"><code>Cudd_addMinus()</code></a>
+<dd> Integer and floating point subtraction.
+
+<dt> <a href="cuddExtDet.html#Cudd_addMonadicApply"><code>Cudd_addMonadicApply()</code></a>
+<dd> Applies op to the discriminants of f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addNand"><code>Cudd_addNand()</code></a>
+<dd> NAND of two 0-1 ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addNegate"><code>Cudd_addNegate()</code></a>
+<dd> Computes the additive inverse of an ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addNewVarAtLevel"><code>Cudd_addNewVarAtLevel()</code></a>
+<dd> Returns a new ADD variable at a specified level.
+
+<dt> <a href="cuddExtDet.html#Cudd_addNewVar"><code>Cudd_addNewVar()</code></a>
+<dd> Returns a new ADD variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_addNonSimCompose"><code>Cudd_addNonSimCompose()</code></a>
+<dd> Composes an ADD with a vector of 0-1 ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addNor"><code>Cudd_addNor()</code></a>
+<dd> NOR of two 0-1 ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addOneZeroMaximum"><code>Cudd_addOneZeroMaximum()</code></a>
+<dd> Returns 1 if f &gt; g and 0 otherwise.
+
+<dt> <a href="cuddExtDet.html#Cudd_addOrAbstract"><code>Cudd_addOrAbstract()</code></a>
+<dd> Disjunctively abstracts all the variables in cube from the 0-1 ADD f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addOr"><code>Cudd_addOr()</code></a>
+<dd> Disjunction of two 0-1 ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addOuterSum"><code>Cudd_addOuterSum()</code></a>
+<dd> Takes the minimum of a matrix and the outer sum of two vectors.
+
+<dt> <a href="cuddExtDet.html#Cudd_addPermute"><code>Cudd_addPermute()</code></a>
+<dd> Permutes the variables of an ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addPlus"><code>Cudd_addPlus()</code></a>
+<dd> Integer and floating point addition.
+
+<dt> <a href="cuddExtDet.html#Cudd_addRead"><code>Cudd_addRead()</code></a>
+<dd> Reads in a sparse matrix.
+
+<dt> <a href="cuddExtDet.html#Cudd_addResidue"><code>Cudd_addResidue()</code></a>
+<dd> Builds an ADD for the residue modulo m of an n-bit number.
+
+<dt> <a href="cuddExtDet.html#Cudd_addRestrict"><code>Cudd_addRestrict()</code></a>
+<dd> ADD restrict according to Coudert and Madre's algorithm (ICCAD90).
+
+<dt> <a href="cuddExtDet.html#Cudd_addRoundOff"><code>Cudd_addRoundOff()</code></a>
+<dd> Rounds off the discriminants of an ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addScalarInverse"><code>Cudd_addScalarInverse()</code></a>
+<dd> Computes the scalar inverse of an ADD.
+
+<dt> <a href="cuddExtDet.html#Cudd_addSetNZ"><code>Cudd_addSetNZ()</code></a>
+<dd> This operator sets f to the value of g wherever g != 0.
+
+<dt> <a href="cuddExtDet.html#Cudd_addSwapVariables"><code>Cudd_addSwapVariables()</code></a>
+<dd> Swaps two sets of variables of the same size (x and y) in the ADD f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addThreshold"><code>Cudd_addThreshold()</code></a>
+<dd> f if f&gt;=g; 0 if f&lt;g.
+
+<dt> <a href="cuddExtDet.html#Cudd_addTimesPlus"><code>Cudd_addTimesPlus()</code></a>
+<dd> Calculates the product of two matrices represented as ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addTimes"><code>Cudd_addTimes()</code></a>
+<dd> Integer and floating point multiplication.
+
+<dt> <a href="cuddExtDet.html#Cudd_addTriangle"><code>Cudd_addTriangle()</code></a>
+<dd> Performs the triangulation step for the shortest path computation.
+
+<dt> <a href="cuddExtDet.html#Cudd_addUnivAbstract"><code>Cudd_addUnivAbstract()</code></a>
+<dd> Universally Abstracts all the variables in cube from f.
+
+<dt> <a href="cuddExtDet.html#Cudd_addVectorCompose"><code>Cudd_addVectorCompose()</code></a>
+<dd> Composes an ADD with a vector of 0-1 ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addWalsh"><code>Cudd_addWalsh()</code></a>
+<dd> Generates a Walsh matrix in ADD form.
+
+<dt> <a href="cuddExtDet.html#Cudd_addXeqy"><code>Cudd_addXeqy()</code></a>
+<dd> Generates an ADD for the function x==y.
+
+<dt> <a href="cuddExtDet.html#Cudd_addXnor"><code>Cudd_addXnor()</code></a>
+<dd> XNOR of two 0-1 ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_addXor"><code>Cudd_addXor()</code></a>
+<dd> XOR of two 0-1 ADDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddAdjPermuteX"><code>Cudd_bddAdjPermuteX()</code></a>
+<dd> Rearranges a set of variables in the BDD B.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddAndAbstractLimit"><code>Cudd_bddAndAbstractLimit()</code></a>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube. Returns NULL if too many nodes are required.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddAndAbstract"><code>Cudd_bddAndAbstract()</code></a>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddAndLimit"><code>Cudd_bddAndLimit()</code></a>
+<dd> Computes the conjunction of two BDDs f and g. Returns NULL if too many nodes are required.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddAnd"><code>Cudd_bddAnd()</code></a>
+<dd> Computes the conjunction of two BDDs f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddApproxConjDecomp"><code>Cudd_bddApproxConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddApproxDisjDecomp"><code>Cudd_bddApproxDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddBindVar"><code>Cudd_bddBindVar()</code></a>
+<dd> Prevents sifting of a variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddBooleanDiff"><code>Cudd_bddBooleanDiff()</code></a>
+<dd> Computes the boolean difference of f with respect to x.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddCharToVect"><code>Cudd_bddCharToVect()</code></a>
+<dd> Computes a vector whose image equals a non-zero function.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddClippingAndAbstract"><code>Cudd_bddClippingAndAbstract()</code></a>
+<dd> Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddClippingAnd"><code>Cudd_bddClippingAnd()</code></a>
+<dd> Approximates the conjunction of two BDDs f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddClosestCube"><code>Cudd_bddClosestCube()</code></a>
+<dd> Finds a cube of f at minimum Hamming distance from g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddCompose"><code>Cudd_bddCompose()</code></a>
+<dd> Substitutes g for x_v in the BDD for f.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddComputeCube"><code>Cudd_bddComputeCube()</code></a>
+<dd> Computes the cube of an array of BDD variables.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddConstrainDecomp"><code>Cudd_bddConstrainDecomp()</code></a>
+<dd> BDD conjunctive decomposition as in McMillan's CAV96 paper.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddConstrain"><code>Cudd_bddConstrain()</code></a>
+<dd> Computes f constrain c.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddCorrelationWeights"><code>Cudd_bddCorrelationWeights()</code></a>
+<dd> Computes the correlation of f and g for given input probabilities.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddCorrelation"><code>Cudd_bddCorrelation()</code></a>
+<dd> Computes the correlation of f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddExistAbstract"><code>Cudd_bddExistAbstract()</code></a>
+<dd> Existentially abstracts all the variables in cube from f.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddGenConjDecomp"><code>Cudd_bddGenConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddGenDisjDecomp"><code>Cudd_bddGenDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIntersect"><code>Cudd_bddIntersect()</code></a>
+<dd> Returns a function included in the intersection of f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsNsVar"><code>Cudd_bddIsNsVar()</code></a>
+<dd> Checks whether a variable is next state.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsPiVar"><code>Cudd_bddIsPiVar()</code></a>
+<dd> Checks whether a variable is primary input.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsPsVar"><code>Cudd_bddIsPsVar()</code></a>
+<dd> Checks whether a variable is present state.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsVarEssential"><code>Cudd_bddIsVarEssential()</code></a>
+<dd> Determines whether a given variable is essential with a given phase in a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsVarHardGroup"><code>Cudd_bddIsVarHardGroup()</code></a>
+<dd> Checks whether a variable is set to be in a hard group.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsVarToBeGrouped"><code>Cudd_bddIsVarToBeGrouped()</code></a>
+<dd> Checks whether a variable is set to be grouped.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsVarToBeUngrouped"><code>Cudd_bddIsVarToBeUngrouped()</code></a>
+<dd> Checks whether a variable is set to be ungrouped.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIsop"><code>Cudd_bddIsop()</code></a>
+<dd> Computes a BDD in the interval between L and U with a simple sum-of-produuct cover.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIteConstant"><code>Cudd_bddIteConstant()</code></a>
+<dd> Implements ITEconstant(f,g,h).
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIterConjDecomp"><code>Cudd_bddIterConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIterDisjDecomp"><code>Cudd_bddIterDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIte"><code>Cudd_bddIte()</code></a>
+<dd> Implements ITE(f,g,h).
+
+<dt> <a href="cuddExtDet.html#Cudd_bddIthVar"><code>Cudd_bddIthVar()</code></a>
+<dd> Returns the BDD variable with index i.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddLICompaction"><code>Cudd_bddLICompaction()</code></a>
+<dd> Performs safe minimization of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddLeqUnless"><code>Cudd_bddLeqUnless()</code></a>
+<dd> Tells whether f is less than of equal to G unless D is 1.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddLeq"><code>Cudd_bddLeq()</code></a>
+<dd> Determines whether f is less than or equal to g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddLiteralSetIntersection"><code>Cudd_bddLiteralSetIntersection()</code></a>
+<dd> Computes the intesection of two sets of literals represented as BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddMakePrime"><code>Cudd_bddMakePrime()</code></a>
+<dd> Expands cube to a prime implicant of f.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddMinimize"><code>Cudd_bddMinimize()</code></a>
+<dd> Finds a small BDD that agrees with <code>f</code> over <code>c</code>.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddNPAnd"><code>Cudd_bddNPAnd()</code></a>
+<dd> Computes f non-polluting-and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddNand"><code>Cudd_bddNand()</code></a>
+<dd> Computes the NAND of two BDDs f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddNewVarAtLevel"><code>Cudd_bddNewVarAtLevel()</code></a>
+<dd> Returns a new BDD variable at a specified level.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddNewVar"><code>Cudd_bddNewVar()</code></a>
+<dd> Returns a new BDD variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddNor"><code>Cudd_bddNor()</code></a>
+<dd> Computes the NOR of two BDDs f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddOr"><code>Cudd_bddOr()</code></a>
+<dd> Computes the disjunction of two BDDs f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddPermute"><code>Cudd_bddPermute()</code></a>
+<dd> Permutes the variables of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddPickArbitraryMinterms"><code>Cudd_bddPickArbitraryMinterms()</code></a>
+<dd> Picks k on-set minterms evenly distributed from given DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddPickOneCube"><code>Cudd_bddPickOneCube()</code></a>
+<dd> Picks one on-set cube randomly from the given DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddPickOneMinterm"><code>Cudd_bddPickOneMinterm()</code></a>
+<dd> Picks one on-set minterm randomly from the given DD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddPrintCover"><code>Cudd_bddPrintCover()</code></a>
+<dd> Prints a sum of prime implicants of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddReadPairIndex"><code>Cudd_bddReadPairIndex()</code></a>
+<dd> Reads a corresponding pair index for a given index.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddRead"><code>Cudd_bddRead()</code></a>
+<dd> Reads in a graph (without labels) given as a list of arcs.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddRealignDisable"><code>Cudd_bddRealignDisable()</code></a>
+<dd> Disables realignment of ZDD order to BDD order.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddRealignEnable"><code>Cudd_bddRealignEnable()</code></a>
+<dd> Enables realignment of BDD order to ZDD order.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddRealignmentEnabled"><code>Cudd_bddRealignmentEnabled()</code></a>
+<dd> Tells whether the realignment of BDD order to ZDD order is enabled.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddResetVarToBeGrouped"><code>Cudd_bddResetVarToBeGrouped()</code></a>
+<dd> Resets a variable not to be grouped.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddRestrict"><code>Cudd_bddRestrict()</code></a>
+<dd> BDD restrict according to Coudert and Madre's algorithm (ICCAD90).
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSetNsVar"><code>Cudd_bddSetNsVar()</code></a>
+<dd> Sets a variable type to next state.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSetPairIndex"><code>Cudd_bddSetPairIndex()</code></a>
+<dd> Sets a corresponding pair index for a given index.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSetPiVar"><code>Cudd_bddSetPiVar()</code></a>
+<dd> Sets a variable type to primary input.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSetPsVar"><code>Cudd_bddSetPsVar()</code></a>
+<dd> Sets a variable type to present state.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSetVarHardGroup"><code>Cudd_bddSetVarHardGroup()</code></a>
+<dd> Sets a variable to be a hard group.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSetVarToBeGrouped"><code>Cudd_bddSetVarToBeGrouped()</code></a>
+<dd> Sets a variable to be grouped.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSetVarToBeUngrouped"><code>Cudd_bddSetVarToBeUngrouped()</code></a>
+<dd> Sets a variable to be ungrouped.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSqueeze"><code>Cudd_bddSqueeze()</code></a>
+<dd> Finds a small BDD in a function interval.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddSwapVariables"><code>Cudd_bddSwapVariables()</code></a>
+<dd> Swaps two sets of variables of the same size (x and y) in the BDD f.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddTransfer"><code>Cudd_bddTransfer()</code></a>
+<dd> Convert a BDD from a manager to another one.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddUnbindVar"><code>Cudd_bddUnbindVar()</code></a>
+<dd> Allows the sifting of a variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddUnivAbstract"><code>Cudd_bddUnivAbstract()</code></a>
+<dd> Universally abstracts all the variables in cube from f.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddVarConjDecomp"><code>Cudd_bddVarConjDecomp()</code></a>
+<dd> Performs two-way conjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddVarDisjDecomp"><code>Cudd_bddVarDisjDecomp()</code></a>
+<dd> Performs two-way disjunctive decomposition of a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddVarIsBound"><code>Cudd_bddVarIsBound()</code></a>
+<dd> Tells whether a variable can be sifted.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddVarIsDependent"><code>Cudd_bddVarIsDependent()</code></a>
+<dd> Checks whether a variable is dependent on others in a function.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddVarMap"><code>Cudd_bddVarMap()</code></a>
+<dd> Remaps the variables of a BDD using the default variable map.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddVectorCompose"><code>Cudd_bddVectorCompose()</code></a>
+<dd> Composes a BDD with a vector of BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddXnor"><code>Cudd_bddXnor()</code></a>
+<dd> Computes the exclusive NOR of two BDDs f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddXorExistAbstract"><code>Cudd_bddXorExistAbstract()</code></a>
+<dd> Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube.
+
+<dt> <a href="cuddExtDet.html#Cudd_bddXor"><code>Cudd_bddXor()</code></a>
+<dd> Computes the exclusive OR of two BDDs f and g.
+
+<dt> <a href="cuddExtDet.html#Cudd_tlcInfoFree"><code>Cudd_tlcInfoFree()</code></a>
+<dd> Frees a DdTlcInfo Structure.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddChange"><code>Cudd_zddChange()</code></a>
+<dd> Substitutes a variable with its complement in a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddComplement"><code>Cudd_zddComplement()</code></a>
+<dd> Computes a complement cover for a ZDD node.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddCountDouble"><code>Cudd_zddCountDouble()</code></a>
+<dd> Counts the number of minterms of a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddCountMinterm"><code>Cudd_zddCountMinterm()</code></a>
+<dd> Counts the number of minterms of a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddCount"><code>Cudd_zddCount()</code></a>
+<dd> Counts the number of minterms in a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddCoverPathToString"><code>Cudd_zddCoverPathToString()</code></a>
+<dd> Converts a path of a ZDD representing a cover to a string.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddDagSize"><code>Cudd_zddDagSize()</code></a>
+<dd> Counts the number of nodes in a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddDiffConst"><code>Cudd_zddDiffConst()</code></a>
+<dd> Performs the inclusion test for ZDDs (P implies Q).
+
+<dt> <a href="cuddExtDet.html#Cudd_zddDiff"><code>Cudd_zddDiff()</code></a>
+<dd> Computes the difference of two ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddDivideF"><code>Cudd_zddDivideF()</code></a>
+<dd> Modified version of Cudd_zddDivide.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddDivide"><code>Cudd_zddDivide()</code></a>
+<dd> Computes the quotient of two unate covers.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddDumpDot"><code>Cudd_zddDumpDot()</code></a>
+<dd> Writes a dot file representing the argument ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddFirstPath"><code>Cudd_zddFirstPath()</code></a>
+<dd> Finds the first path of a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddForeachPath"><code>Cudd_zddForeachPath()</code></a>
+<dd> Iterates over the paths of a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddIntersect"><code>Cudd_zddIntersect()</code></a>
+<dd> Computes the intersection of two ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddIsop"><code>Cudd_zddIsop()</code></a>
+<dd> Computes an ISOP in ZDD form from BDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddIte"><code>Cudd_zddIte()</code></a>
+<dd> Computes the ITE of three ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddIthVar"><code>Cudd_zddIthVar()</code></a>
+<dd> Returns the ZDD variable with index i.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddNextPath"><code>Cudd_zddNextPath()</code></a>
+<dd> Generates the next path of a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddPortFromBdd"><code>Cudd_zddPortFromBdd()</code></a>
+<dd> Converts a BDD into a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddPortToBdd"><code>Cudd_zddPortToBdd()</code></a>
+<dd> Converts a ZDD into a BDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddPrintCover"><code>Cudd_zddPrintCover()</code></a>
+<dd> Prints a sum of products from a ZDD representing a cover.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddPrintDebug"><code>Cudd_zddPrintDebug()</code></a>
+<dd> Prints to the standard output a ZDD and its statistics.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddPrintMinterm"><code>Cudd_zddPrintMinterm()</code></a>
+<dd> Prints a disjoint sum of product form for a ZDD.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddPrintSubtable"><code>Cudd_zddPrintSubtable()</code></a>
+<dd> Prints the ZDD table.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddProduct"><code>Cudd_zddProduct()</code></a>
+<dd> Computes the product of two covers represented by ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddReadNodeCount"><code>Cudd_zddReadNodeCount()</code></a>
+<dd> Reports the number of nodes in ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddRealignDisable"><code>Cudd_zddRealignDisable()</code></a>
+<dd> Disables realignment of ZDD order to BDD order.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddRealignEnable"><code>Cudd_zddRealignEnable()</code></a>
+<dd> Enables realignment of ZDD order to BDD order.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddRealignmentEnabled"><code>Cudd_zddRealignmentEnabled()</code></a>
+<dd> Tells whether the realignment of ZDD order to BDD order is enabled.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddReduceHeap"><code>Cudd_zddReduceHeap()</code></a>
+<dd> Main dynamic reordering routine for ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddShuffleHeap"><code>Cudd_zddShuffleHeap()</code></a>
+<dd> Reorders ZDD variables according to given permutation.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddSubset0"><code>Cudd_zddSubset0()</code></a>
+<dd> Computes the negative cofactor of a ZDD w.r.t. a variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddSubset1"><code>Cudd_zddSubset1()</code></a>
+<dd> Computes the positive cofactor of a ZDD w.r.t. a variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddSymmProfile"><code>Cudd_zddSymmProfile()</code></a>
+<dd> Prints statistics on symmetric ZDD variables.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddUnateProduct"><code>Cudd_zddUnateProduct()</code></a>
+<dd> Computes the product of two unate covers.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddUnion"><code>Cudd_zddUnion()</code></a>
+<dd> Computes the union of two ZDDs.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddVarsFromBddVars"><code>Cudd_zddVarsFromBddVars()</code></a>
+<dd> Creates one or more ZDD variables for each BDD variable.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddWeakDivF"><code>Cudd_zddWeakDivF()</code></a>
+<dd> Modified version of Cudd_zddWeakDiv.
+
+<dt> <a href="cuddExtDet.html#Cudd_zddWeakDiv"><code>Cudd_zddWeakDiv()</code></a>
+<dd> Applies weak division to two covers.
+
+</dl>
+
+<hr>
+
+Generated automatically by <code>extdoc</code> on 20050517
+
+</body></html>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/cuddExtDet.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/cuddExtDet.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/cuddExtDet.html	(revision 8)
@@ -0,0 +1,7456 @@
+<html>
+<head><title>The cudd package</title></head>
+<body>
+
+<h1>The cudd package</h1>
+<h2>The University of Colorado decision diagram package.</h2>
+<h3></h3>
+<hr>
+<ul>
+<li><a href="cuddExtAbs.html"><h3>External abstracts</h3></a>
+<li><a href="cuddAllAbs.html"><h3>All abstracts</h3></a>
+<li><a href="cuddExtDet.html#prototypes"><h3>External functions</h3></a>
+<li><a href="cuddAllDet.html#prototypes"><h3>All functions</h3></a>
+</ul>
+
+<hr>
+
+<a name="description">
+External functions and data strucures of the CUDD package.
+  <ul>
+  <li> To turn on the gathering of statistics, define DD_STATS.
+  <li> To link with mis, define DD_MIS.
+  </ul>
+  Modified by Abelardo Pardo to interface it to VIS.
+</a>
+
+<hr>
+<!-- Function Prototypes and description -->
+
+<dl>
+<a name="prototypes"></a>
+<dt><pre>
+int <i></i>
+<a name="Cudd_AddHook"><b>Cudd_AddHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_HFP  <b>f</b>, <i></i>
+  Cudd_HookType  <b>where</b> <i></i>
+)
+</pre>
+<dd> Adds a function to a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if the function is successfully added; 2 if the function was already in the list; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RemoveHook">Cudd_RemoveHook</a>
+</code>
+
+<dt><pre>
+DdApaDigit <i></i>
+<a name="Cudd_ApaAdd"><b>Cudd_ApaAdd</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>a</b>, <i></i>
+  DdApaNumber  <b>b</b>, <i></i>
+  DdApaNumber  <b>sum</b> <i></i>
+)
+</pre>
+<dd> Adds two arbitrary precision integers. Returns the carry out of the most significant digit.
+<p>
+
+<dd> <b>Side Effects</b> The result of the sum is stored in parameter <code>sum</code>.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaCompareRatios"><b>Cudd_ApaCompareRatios</b></a>(
+  int  <b>digitsFirst</b>, <i></i>
+  DdApaNumber  <b>firstNum</b>, <i></i>
+  unsigned int  <b>firstDen</b>, <i></i>
+  int  <b>digitsSecond</b>, <i></i>
+  DdApaNumber  <b>secondNum</b>, <i></i>
+  unsigned int  <b>secondDen</b> <i></i>
+)
+</pre>
+<dd> Compares the ratios of two arbitrary precision integers to two unsigned ints. Returns 1 if the first number is larger; 0 if they are equal; -1 if the second number is larger.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaCompare"><b>Cudd_ApaCompare</b></a>(
+  int  <b>digitsFirst</b>, <i></i>
+  DdApaNumber  <b>first</b>, <i></i>
+  int  <b>digitsSecond</b>, <i></i>
+  DdApaNumber  <b>second</b> <i></i>
+)
+</pre>
+<dd> Compares two arbitrary precision integers. Returns 1 if the first number is larger; 0 if they are equal; -1 if the second number is larger.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaCopy"><b>Cudd_ApaCopy</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>source</b>, <i></i>
+  DdApaNumber  <b>dest</b> <i></i>
+)
+</pre>
+<dd> Makes a copy of an arbitrary precision integer.
+<p>
+
+<dd> <b>Side Effects</b> Changes parameter <code>dest</code>.
+<p>
+
+<dt><pre>
+DdApaNumber <i></i>
+<a name="Cudd_ApaCountMinterm"><b>Cudd_ApaCountMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b>, <i></i>
+  int * <b>digits</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a DD. The function is assumed to depend on nvars variables. The minterm count is represented as an arbitrary precision unsigned integer, to allow for any number of variables CUDD supports. Returns a pointer to the array representing the number of minterms of the function rooted at node if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The number of digits of the result is returned in parameter <code>digits</code>.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ApaIntDivision"><b>Cudd_ApaIntDivision</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>dividend</b>, <i></i>
+  unsigned int  <b>divisor</b>, <i></i>
+  DdApaNumber  <b>quotient</b> <i></i>
+)
+</pre>
+<dd> Divides an arbitrary precision integer by a 32-bit unsigned integer. Returns the remainder of the division. This procedure relies on the assumption that the number of bits of a DdApaDigit plus the number of bits of an unsigned int is less the number of bits of the mantissa of a double. This guarantees that the product of a DdApaDigit and an unsigned int can be represented without loss of precision by a double. On machines where this assumption is not satisfied, this procedure will malfunction.
+<p>
+
+<dd> <b>Side Effects</b> The quotient is returned in parameter <code>quotient</code>.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaShortDivision">Cudd_ApaShortDivision</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaNumberOfDigits"><b>Cudd_ApaNumberOfDigits</b></a>(
+  int  <b>binaryDigits</b> <i></i>
+)
+</pre>
+<dd> Finds the number of digits for an arbitrary precision integer given the maximum number of binary digits. The number of binary digits should be positive. Returns the number of digits if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaPowerOfTwo"><b>Cudd_ApaPowerOfTwo</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b>, <i></i>
+  int  <b>power</b> <i></i>
+)
+</pre>
+<dd> Sets an arbitrary precision integer to a power of two. If the power of two is too large to be represented, the number is set to 0.
+<p>
+
+<dd> <b>Side Effects</b> The result is returned in parameter <code>number</code>.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintDecimal"><b>Cudd_ApaPrintDecimal</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b> <i></i>
+)
+</pre>
+<dd> Prints an arbitrary precision integer in decimal format. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintHex">Cudd_ApaPrintHex</a>
+<a href="cuddAllDet.html#Cudd_ApaPrintExponential">Cudd_ApaPrintExponential</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintDensity"><b>Cudd_ApaPrintDensity</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b> <i></i>
+)
+</pre>
+<dd> Prints the density of a BDD or ADD using arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintExponential"><b>Cudd_ApaPrintExponential</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b>, <i></i>
+  int  <b>precision</b> <i></i>
+)
+</pre>
+<dd> Prints an arbitrary precision integer in exponential format. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintHex">Cudd_ApaPrintHex</a>
+<a href="cuddAllDet.html#Cudd_ApaPrintDecimal">Cudd_ApaPrintDecimal</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintHex"><b>Cudd_ApaPrintHex</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b> <i></i>
+)
+</pre>
+<dd> Prints an arbitrary precision integer in hexadecimal format. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintDecimal">Cudd_ApaPrintDecimal</a>
+<a href="cuddAllDet.html#Cudd_ApaPrintExponential">Cudd_ApaPrintExponential</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintMintermExp"><b>Cudd_ApaPrintMintermExp</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b>, <i></i>
+  int  <b>precision</b> <i></i>
+)
+</pre>
+<dd> Prints the number of minterms of a BDD or ADD in exponential format using arbitrary precision arithmetic. Parameter precision controls the number of signficant digits printed. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintMinterm">Cudd_ApaPrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ApaPrintMinterm"><b>Cudd_ApaPrintMinterm</b></a>(
+  FILE * <b>fp</b>, <i></i>
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b> <i></i>
+)
+</pre>
+<dd> Prints the number of minterms of a BDD or ADD using arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ApaPrintMintermExp">Cudd_ApaPrintMintermExp</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaSetToLiteral"><b>Cudd_ApaSetToLiteral</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>number</b>, <i></i>
+  DdApaDigit  <b>literal</b> <i></i>
+)
+</pre>
+<dd> Sets an arbitrary precision integer to a one-digit literal.
+<p>
+
+<dd> <b>Side Effects</b> The result is returned in parameter <code>number</code>.
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ApaShiftRight"><b>Cudd_ApaShiftRight</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaDigit  <b>in</b>, <i></i>
+  DdApaNumber  <b>a</b>, <i></i>
+  DdApaNumber  <b>b</b> <i></i>
+)
+</pre>
+<dd> Shifts right an arbitrary precision integer by one binary place. The most significant binary digit of the result is taken from parameter <code>in</code>.
+<p>
+
+<dd> <b>Side Effects</b> The result is returned in parameter <code>b</code>.
+<p>
+
+<dt><pre>
+DdApaDigit <i></i>
+<a name="Cudd_ApaShortDivision"><b>Cudd_ApaShortDivision</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>dividend</b>, <i></i>
+  DdApaDigit  <b>divisor</b>, <i></i>
+  DdApaNumber  <b>quotient</b> <i></i>
+)
+</pre>
+<dd> Divides an arbitrary precision integer by a digit.
+<p>
+
+<dd> <b>Side Effects</b> The quotient is returned in parameter <code>quotient</code>.
+<p>
+
+<dt><pre>
+DdApaDigit <i></i>
+<a name="Cudd_ApaSubtract"><b>Cudd_ApaSubtract</b></a>(
+  int  <b>digits</b>, <i></i>
+  DdApaNumber  <b>a</b>, <i></i>
+  DdApaNumber  <b>b</b>, <i></i>
+  DdApaNumber  <b>diff</b> <i></i>
+)
+</pre>
+<dd> Subtracts two arbitrary precision integers. Returns the borrow out of the most significant digit.
+<p>
+
+<dd> <b>Side Effects</b> The result of the subtraction is stored in parameter <code>diff</code>.
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynDisableZdd"><b>Cudd_AutodynDisableZdd</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables automatic dynamic reordering of ZDDs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnableZdd">Cudd_AutodynEnableZdd</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatusZdd">Cudd_ReorderingStatusZdd</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynDisable"><b>Cudd_AutodynDisable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables automatic dynamic reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnable">Cudd_AutodynEnable</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatus">Cudd_ReorderingStatus</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisableZdd">Cudd_AutodynDisableZdd</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynEnableZdd"><b>Cudd_AutodynEnableZdd</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType  <b>method</b> <i></i>
+)
+</pre>
+<dd> Enables automatic dynamic reordering of ZDDs. Parameter method is used to determine the method used for reordering ZDDs. If CUDD_REORDER_SAME is passed, the method is unchanged.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynDisableZdd">Cudd_AutodynDisableZdd</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatusZdd">Cudd_ReorderingStatusZdd</a>
+<a href="cuddAllDet.html#Cudd_AutodynEnable">Cudd_AutodynEnable</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_AutodynEnable"><b>Cudd_AutodynEnable</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType  <b>method</b> <i></i>
+)
+</pre>
+<dd> Enables automatic dynamic reordering of BDDs and ADDs. Parameter method is used to determine the method used for reordering. If CUDD_REORDER_SAME is passed, the method is unchanged.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatus">Cudd_ReorderingStatus</a>
+<a href="cuddAllDet.html#Cudd_AutodynEnableZdd">Cudd_AutodynEnableZdd</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_AverageDistance"><b>Cudd_AverageDistance</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Computes the average distance between adjacent nodes in the manager. Adjacent nodes are node pairs such that the second node is the then child, else child, or next node in the collision list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_BddToAdd"><b>Cudd_BddToAdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>B</b> <i></i>
+)
+</pre>
+<dd> Converts a BDD to a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_BddToCubeArray"><b>Cudd_BddToCubeArray</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>cube</b>, <i></i>
+  int * <b>array</b> <i></i>
+)
+</pre>
+<dd> Builds a positional array from the BDD of a cube. Array must have one entry for each BDD variable. The positional array has 1 in i-th position if the variable of index i appears in true form in the cube; it has 0 in i-th position if the variable of index i appears in complemented form in the cube; finally, it has 2 in i-th position if the variable of index i does not appear in the cube. Returns 1 if successful (the BDD is indeed a cube); 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The result is in the array passed by reference.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CubeArrayToBdd">Cudd_CubeArrayToBdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_BiasedOverApprox"><b>Cudd_BiasedOverApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  DdNode * <b>b</b>, <i>bias function</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality1</b>, <i>minimum improvement for accepted changes when b=1</i>
+  double  <b>quality0</b> <i>minimum improvement for accepted changes when b=0</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_RemapOverApprox">Cudd_RemapOverApprox</a>
+<a href="cuddAllDet.html#Cudd_BiasedUnderApprox">Cudd_BiasedUnderApprox</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_BiasedUnderApprox"><b>Cudd_BiasedUnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  DdNode * <b>b</b>, <i>bias function</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality1</b>, <i>minimum improvement for accepted changes when b=1</i>
+  double  <b>quality0</b> <i>minimum improvement for accepted changes when b=0</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure uses a biased remapping technique and density as the cost function. The bias is a function. This procedure tries to approximate where the bias is 0 and preserve the given function where the bias is 1. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_UnderApprox">Cudd_UnderApprox</a>
+<a href="cuddAllDet.html#Cudd_RemapUnderApprox">Cudd_RemapUnderApprox</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_CProjection"><b>Cudd_CProjection</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>R</b>, <i></i>
+  DdNode * <b>Y</b> <i></i>
+)
+</pre>
+<dd> Computes the compatible projection of relation R with respect to cube Y. Returns a pointer to the c-projection if successful; NULL otherwise. For a comparison between Cudd_CProjection and Cudd_PrioritySelect, see the documentation of the latter.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_CheckKeys"><b>Cudd_CheckKeys</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Checks for the following conditions: <ul> <li>Wrong sizes of subtables. <li>Wrong number of keys found in unique subtable. <li>Wrong number of dead found in unique subtable. <li>Wrong number of keys found in the constant table <li>Wrong number of dead found in the constant table <li>Wrong number of total slots found <li>Wrong number of maximum keys found <li>Wrong number of total dead found </ul> Reports the average length of non-empty lists. Returns the number of subtables for which the number of keys is wrong.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DebugCheck">Cudd_DebugCheck</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_CheckZeroRef"><b>Cudd_CheckZeroRef</b></a>(
+  DdManager * <b>manager</b> <i></i>
+)
+</pre>
+<dd> Checks the unique table for nodes with non-zero reference counts. It is normally called before Cudd_Quit to make sure that there are no memory leaks due to missing Cudd_RecursiveDeref's. Takes into account that reference counts may saturate and that the basic constants and the projection functions are referenced by the manager. Returns the number of nodes with non-zero reference count. (Except for the cases mentioned above.)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ClassifySupport"><b>Cudd_ClassifySupport</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first DD</i>
+  DdNode * <b>g</b>, <i>second DD</i>
+  DdNode ** <b>common</b>, <i>cube of shared variables</i>
+  DdNode ** <b>onlyF</b>, <i>cube of variables only in f</i>
+  DdNode ** <b>onlyG</b> <i>cube of variables only in g</i>
+)
+</pre>
+<dd> Classifies the variables in the support of two DDs <code>f</code> and <code>g</code>, depending on whther they appear in both DDs, only in <code>f</code>, or only in <code>g</code>. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The cubes of the three classes of variables are returned as side effects.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+<a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_ClearErrorCode"><b>Cudd_ClearErrorCode</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Clear the error code of a manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadErrorCode">Cudd_ReadErrorCode</a>
+</code>
+
+<dt><pre>
+double * <i></i>
+<a name="Cudd_CofMinterm"><b>Cudd_CofMinterm</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Computes the fraction of minterms in the on-set of all the positive cofactors of DD. Returns the pointer to an array of doubles if successful; NULL otherwise. The array has as many positions as there are BDD variables in the manager plus one. The last position of the array contains the fraction of the minterms in the ON-set of the function represented by the BDD or ADD. The other positions of the array hold the variable signatures.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Cofactor"><b>Cudd_Cofactor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the cofactor of f with respect to g; g must be the BDD or the ADD of a cube. Returns a pointer to the cofactor if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_Complement"><b>Cudd_Complement</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the complemented version of a pointer.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Regular">Cudd_Regular</a>
+<a href="cuddAllDet.html#Cudd_IsComplement">Cudd_IsComplement</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_CountLeaves"><b>Cudd_CountLeaves</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of leaves in a DD. Returns the number of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_CountMinterm"><b>Cudd_CountMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a DD. The function is assumed to depend on nvars variables. The minterm count is represented as a double, to allow for a larger number of variables. Returns the number of minterms of the function rooted at node if successful; (double) CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_CountPath">Cudd_CountPath</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_CountPathsToNonZero"><b>Cudd_CountPathsToNonZero</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of paths to a non-zero terminal of a DD. The path count is represented as a double, to allow for a larger number of variables. Returns the number of paths of the function rooted at node.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+<a href="cuddAllDet.html#Cudd_CountPath">Cudd_CountPath</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_CountPath"><b>Cudd_CountPath</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of paths of a DD. Paths to all terminal nodes are counted. The path count is represented as a double, to allow for a larger number of variables. Returns the number of paths of the function rooted at node if successful; (double) CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_CubeArrayToBdd"><b>Cudd_CubeArrayToBdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int * <b>array</b> <i></i>
+)
+</pre>
+<dd> Builds a cube from a positional array. The array must have one integer entry for each BDD variable. If the i-th entry is 1, the variable of index i appears in true form in the cube; If the i-th entry is 0, the variable of index i appears complemented in the cube; otherwise the variable does not appear in the cube. Returns a pointer to the BDD for the cube if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddComputeCube">Cudd_bddComputeCube</a>
+<a href="cuddAllDet.html#Cudd_IndicesToCube">Cudd_IndicesToCube</a>
+<a href="cuddAllDet.html#Cudd_BddToCubeArray">Cudd_BddToCubeArray</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DagSize"><b>Cudd_DagSize</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of nodes in a DD. Returns the number of nodes in the graph rooted at node.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SharingSize">Cudd_SharingSize</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DeadAreCounted"><b>Cudd_DeadAreCounted</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Tells whether dead nodes are counted towards triggering reordering. Returns 1 if dead nodes are counted; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_TurnOnCountDead">Cudd_TurnOnCountDead</a>
+<a href="cuddAllDet.html#Cudd_TurnOffCountDead">Cudd_TurnOffCountDead</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DebugCheck"><b>Cudd_DebugCheck</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Checks for inconsistencies in the DD heap: <ul> <li> node has illegal index <li> live node has dead children <li> node has illegal Then or Else pointers <li> BDD/ADD node has identical children <li> ZDD node has zero then child <li> wrong number of total nodes <li> wrong number of dead nodes <li> ref count error at node </ul> Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is not enough memory; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CheckKeys">Cudd_CheckKeys</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Decreasing"><b>Cudd_Decreasing</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Determines whether the function represented by BDD f is negative unate (monotonic decreasing) in variable i. Returns the constant one is f is unate and the (logical) constant zero if it is not. This function does not generate any new nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Increasing">Cudd_Increasing</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_DelayedDerefBdd"><b>Cudd_DelayedDerefBdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Enqueues node n for later dereferencing. If the queue is full decreases the reference count of the oldest node N to make room for n. If N dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is currently not needed, but may be useful again in the near future. The dereferencing proper is done as in Cudd_IterDerefBdd.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_IterDerefBdd">Cudd_IterDerefBdd</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_Density"><b>Cudd_Density</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function whose density is sought</i>
+  int  <b>nvars</b> <i>size of the support of f</i>
+)
+</pre>
+<dd> Computes the density of a BDD or ADD. The density is the ratio of the number of minterms to the number of nodes. If 0 is passed as number of variables, the number of variables existing in the manager is used. Returns the density if successful; (double) CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+<a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Deref"><b>Cudd_Deref</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous Cudd_Ref.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_RecursiveDerefZdd">Cudd_RecursiveDerefZdd</a>
+<a href="cuddAllDet.html#Cudd_Ref">Cudd_Ref</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_DisableGarbageCollection"><b>Cudd_DisableGarbageCollection</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Disables garbage collection. Garbage collection is initially enabled. This function may be called to disable it. However, garbage collection will still occur when a new node must be created and no memory is left, or when garbage collection is required for correctness. (E.g., before reordering.)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableGarbageCollection">Cudd_EnableGarbageCollection</a>
+<a href="cuddAllDet.html#Cudd_GarbageCollectionEnabled">Cudd_GarbageCollectionEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DisableReorderingReporting"><b>Cudd_DisableReorderingReporting</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Disables reporting of reordering stats. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Removes functions from the pre-reordering and post-reordering hooks.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableReorderingReporting">Cudd_EnableReorderingReporting</a>
+<a href="cuddAllDet.html#Cudd_ReorderingReporting">Cudd_ReorderingReporting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpBlifBody"><b>Cudd_DumpBlifBody</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a blif body representing the argument BDDs as a network of multiplexers. No header (.model, .inputs, and .outputs) and footer (.end) are produced by this function. One multiplexer is written for each BDD node. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full, or an ADD with constants different from 0 and 1). Cudd_DumpBlifBody does not close the file: This is the caller responsibility. Cudd_DumpBlifBody uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. This function prints out only .names part.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpBlif"><b>Cudd_DumpBlif</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  char * <b>mname</b>, <i>model name (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a blif file representing the argument BDDs as a network of multiplexers. One multiplexer is written for each BDD node. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full, or an ADD with constants different from 0 and 1). Cudd_DumpBlif does not close the file: This is the caller responsibility. Cudd_DumpBlif uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpBlifBody">Cudd_DumpBlifBody</a>
+<a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpDDcal"><b>Cudd_DumpDDcal</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a DDcal file representing the argument BDDs. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or file system full). Cudd_DumpDDcal does not close the file: This is the caller responsibility. Cudd_DumpDDcal uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpDaVinci"><b>Cudd_DumpDaVinci</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a daVinci file representing the argument BDDs. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or file system full). Cudd_DumpDaVinci does not close the file: This is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpDot"><b>Cudd_DumpDot</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a file representing the argument DDs in a format suitable for the graph drawing program dot. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full). Cudd_DumpDot does not close the file: This is the caller responsibility. Cudd_DumpDot uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. Cudd_DumpDot uses the following convention to draw arcs: <ul> <li> solid line: THEN arcs; <li> dotted line: complement arcs; <li> dashed line: regular ELSE arcs. </ul> The dot options are chosen so that the drawing fits on a letter-size sheet.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpFactoredForm">Cudd_DumpFactoredForm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_DumpFactoredForm"><b>Cudd_DumpFactoredForm</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes factored forms representing the argument BDDs. The format of the factored form is the one used in the genlib files for technology mapping in sis. It returns 1 in case of success; 0 otherwise (e.g., file system full). Cudd_DumpFactoredForm does not close the file: This is the caller responsibility. Caution must be exercised because a factored form may be exponentially larger than the argument BDD. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_DumpBlif">Cudd_DumpBlif</a>
+<a href="cuddAllDet.html#Cudd_DumpDaVinci">Cudd_DumpDaVinci</a>
+<a href="cuddAllDet.html#Cudd_DumpDDcal">Cudd_DumpDDcal</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Dxygtdxz"><b>Cudd_Dxygtdxz</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x, y, and z variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b>, <i>array of y variables</i>
+  DdNode ** <b>z</b> <i>array of z variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function d(x,y) &gt; d(x,z); x, y, and z are N-bit numbers, x[0] x[1] ... x[N-1], y[0] y[1] ... y[N-1], and z[0] z[1] ... z[N-1], with 0 the most significant bit. The distance d(x,y) is defined as: sum_{i=0}^{N-1}(|x_i - y_i| cdot 2^{N-i-1}). The BDD is built bottom-up. It has 7*N-3 internal nodes, if the variables are ordered as follows: x[0] y[0] z[0] x[1] y[1] z[1] ... x[N-1] y[N-1] z[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+<a href="cuddAllDet.html#Cudd_Xgty">Cudd_Xgty</a>
+<a href="cuddAllDet.html#Cudd_bddAdjPermuteX">Cudd_bddAdjPermuteX</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Dxygtdyz"><b>Cudd_Dxygtdyz</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x, y, and z variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b>, <i>array of y variables</i>
+  DdNode ** <b>z</b> <i>array of z variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function d(x,y) &gt; d(y,z); x, y, and z are N-bit numbers, x[0] x[1] ... x[N-1], y[0] y[1] ... y[N-1], and z[0] z[1] ... z[N-1], with 0 the most significant bit. The distance d(x,y) is defined as: sum_{i=0}^{N-1}(|x_i - y_i| cdot 2^{N-i-1}). The BDD is built bottom-up. It has 7*N-3 internal nodes, if the variables are ordered as follows: x[0] y[0] z[0] x[1] y[1] z[1] ... x[N-1] y[N-1] z[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Xgty">Cudd_Xgty</a>
+<a href="cuddAllDet.html#Cudd_bddAdjPermuteX">Cudd_bddAdjPermuteX</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_EnableGarbageCollection"><b>Cudd_EnableGarbageCollection</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Enables garbage collection. Garbage collection is initially enabled. Therefore it is necessary to call this function only if garbage collection has been explicitly disabled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DisableGarbageCollection">Cudd_DisableGarbageCollection</a>
+<a href="cuddAllDet.html#Cudd_GarbageCollectionEnabled">Cudd_GarbageCollectionEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EnableReorderingReporting"><b>Cudd_EnableReorderingReporting</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Enables reporting of reordering stats. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Installs functions in the pre-reordering and post-reordering hooks.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DisableReorderingReporting">Cudd_DisableReorderingReporting</a>
+<a href="cuddAllDet.html#Cudd_ReorderingReporting">Cudd_ReorderingReporting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EpdCountMinterm"><b>Cudd_EpdCountMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>nvars</b>, <i></i>
+  EpDouble * <b>epd</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a DD with extended precision. The function is assumed to depend on nvars variables. The minterm count is represented as an EpDouble, to allow any number of variables. Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_CountPath">Cudd_CountPath</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EqualSupNorm"><b>Cudd_EqualSupNorm</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first ADD</i>
+  DdNode * <b>g</b>, <i>second ADD</i>
+  CUDD_VALUE_TYPE  <b>tolerance</b>, <i>maximum allowed difference</i>
+  int  <b>pr</b> <i>verbosity level</i>
+)
+</pre>
+<dd> Compares two ADDs for equality within tolerance. Two ADDs are reported to be equal if the maximum difference between them (the sup norm of their difference) is less than or equal to the tolerance parameter. Returns 1 if the two ADDs are equal (within tolerance); 0 otherwise. If parameter <code>pr</code> is positive the first failure is reported to the standard output.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EquivDC"><b>Cudd_EquivDC</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>F</b>, <i></i>
+  DdNode * <b>G</b>, <i></i>
+  DdNode * <b>D</b> <i></i>
+)
+</pre>
+<dd> Tells whether F and G are identical wherever D is 0. F and G are either two ADDs or two BDDs. D is either a 0-1 ADD or a BDD. The function returns 1 if F and G are equivalent, and 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddLeqUnless">Cudd_bddLeqUnless</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EstimateCofactorSimple"><b>Cudd_EstimateCofactorSimple</b></a>(
+  DdNode * <b>node</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Estimates the number of nodes in a cofactor of a DD. Returns an estimate of the number of nodes in the positive cofactor of the graph rooted at node with respect to the variable whose index is i. This procedure implements with minor changes the algorithm of Cabodi et al. (ICCAD96). It does not allocate any memory, it does not change the state of the manager, and it is fast. However, it has been observed to overestimate the size of the cofactor by as much as a factor of 2.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_EstimateCofactor"><b>Cudd_EstimateCofactor</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function</i>
+  int  <b>i</b>, <i>index of variable</i>
+  int  <b>phase</b> <i>1: positive; 0: negative</i>
+)
+</pre>
+<dd> Estimates the number of nodes in a cofactor of a DD. Returns an estimate of the number of nodes in a cofactor of the graph rooted at node with respect to the variable whose index is i. In case of failure, returns CUDD_OUT_OF_MEM. This function uses a refinement of the algorithm of Cabodi et al. (ICCAD96). The refinement allows the procedure to account for part of the recombination that may occur in the part of the cofactor above the cofactoring variable. This procedure does no create any new node. It does keep a small table of results; therefore it may run out of memory. If this is a concern, one should use Cudd_EstimateCofactorSimple, which is faster, does not allocate any memory, but is less accurate.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+<a href="cuddAllDet.html#Cudd_EstimateCofactorSimple">Cudd_EstimateCofactorSimple</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Eval"><b>Cudd_Eval</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>inputs</b> <i></i>
+)
+</pre>
+<dd> Finds the value of a DD for a given variable assignment. The variable assignment is passed in an array of int's, that should specify a zero or a one for each variable in the support of the function. Returns a pointer to a constant node. No new nodes are produced.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ExpectedUsedSlots"><b>Cudd_ExpectedUsedSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Computes the fraction of slots in the unique table that should be in use. This expected value is based on the assumption that the hash function distributes the keys randomly; it can be compared with the result of Cudd_ReadUsedSlots to monitor the performance of the unique table hash function.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSlots">Cudd_ReadSlots</a>
+<a href="cuddAllDet.html#Cudd_ReadUsedSlots">Cudd_ReadUsedSlots</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_E"><b>Cudd_E</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the else child of an internal node. If <code>node</code> is a constant node, the result is unpredictable.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_T">Cudd_T</a>
+<a href="cuddAllDet.html#Cudd_V">Cudd_V</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_FindEssential"><b>Cudd_FindEssential</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns the cube of the essential variables. A positive literal means that the variable must be set to 1 for the function to be 1. A negative literal means that the variable must be set to 0 for the function to be 1. Returns a pointer to the cube BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIsVarEssential">Cudd_bddIsVarEssential</a>
+</code>
+
+<dt><pre>
+DdTlcInfo * <i></i>
+<a name="Cudd_FindTwoLiteralClauses"><b>Cudd_FindTwoLiteralClauses</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns the one- and two-literal clauses of a DD. Returns a pointer to the structure holding the clauses if successful; NULL otherwise. For a constant DD, the empty set of clauses is returned. This is obviously correct for a non-zero constant. For the constant zero, it is based on the assumption that only those clauses containing variables in the support of the function are considered. Since the support of a constant function is empty, no clauses are returned.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindEssential">Cudd_FindEssential</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_FirstCube"><b>Cudd_FirstCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int ** <b>cube</b>, <i></i>
+  CUDD_VALUE_TYPE * <b>value</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on the onset of a decision diagram and finds its first cube. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.<p> A cube is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents a complemented literal, 1 represents an uncomplemented literal, and 2 stands for don't care. The enumeration produces a disjoint cover of the function associated with the diagram. The size of the array equals the number of variables in the manager at the time Cudd_FirstCube is called.<p> For each cube, a value is also returned. This value is always 1 for a BDD, while it may be different from 1 for an ADD. For BDDs, the offset is the set of cubes whose value is the logical zero. For ADDs, the offset is the set of cubes whose value is the background value. The cubes of the offset are not enumerated.
+<p>
+
+<dd> <b>Side Effects</b> The first cube and its value are returned as side effects.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_FirstNode"><b>Cudd_FirstNode</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>node</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on the nodes of a decision diagram and finds its first node. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise. The nodes are enumerated in a reverse topological order, so that a node is always preceded in the enumeration by its descendants.
+<p>
+
+<dd> <b>Side Effects</b> The first node is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_FirstPrime"><b>Cudd_FirstPrime</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>l</b>, <i></i>
+  DdNode * <b>u</b>, <i></i>
+  int ** <b>cube</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on a pair of BDDs describing a (possibly incompletely specified) Boolean functions and finds the first cube of a cover of the function. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.<p> The two argument BDDs are the lower and upper bounds of an interval. It is a mistake to call this function with a lower bound that is not less than or equal to the upper bound.<p> A cube is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents a complemented literal, 1 represents an uncomplemented literal, and 2 stands for don't care. The enumeration produces a prime and irredundant cover of the function associated with the two BDDs. The size of the array equals the number of variables in the manager at the time Cudd_FirstCube is called.<p> This iterator can only be used on BDDs.
+<p>
+
+<dd> <b>Side Effects</b> The first cube is returned as side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachPrime">Cudd_ForeachPrime</a>
+<a href="cuddAllDet.html#Cudd_NextPrime">Cudd_NextPrime</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ForeachCube"><b>Cudd_ForeachCube</b></a>(
+   <b>manager</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>cube</b>, <i></i>
+   <b>value</b> <i></i>
+)
+</pre>
+<dd> Iterates over the cubes of a decision diagram f. <ul> <li> DdManager *manager; <li> DdNode *f; <li> DdGen *gen; <li> int *cube; <li> CUDD_VALUE_TYPE value; </ul> Cudd_ForeachCube allocates and frees the generator. Therefore the application should not try to do that. Also, the cube is freed at the end of Cudd_ForeachCube and hence is not available outside of the loop.<p> CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ForeachNode"><b>Cudd_ForeachNode</b></a>(
+   <b>manager</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Iterates over the nodes of a decision diagram f. <ul> <li> DdManager *manager; <li> DdNode *f; <li> DdGen *gen; <li> DdNode *node; </ul> The nodes are returned in a seemingly random order. Cudd_ForeachNode allocates and frees the generator. Therefore the application should not try to do that.<p> CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ForeachPrime"><b>Cudd_ForeachPrime</b></a>(
+   <b>manager</b>, <i></i>
+   <b>l</b>, <i></i>
+   <b>u</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>cube</b> <i></i>
+)
+</pre>
+<dd> Iterates over the primes of a Boolean function producing a prime and irredundant cover. <ul> <li> DdManager *manager; <li> DdNode *l; <li> DdNode *u; <li> DdGen *gen; <li> int *cube; </ul> The Boolean function is described by an upper bound and a lower bound. If the function is completely specified, the two bounds coincide. Cudd_ForeachPrime allocates and frees the generator. Therefore the application should not try to do that. Also, the cube is freed at the end of Cudd_ForeachPrime and hence is not available outside of the loop.<p> CAUTION: It is a mistake to change a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_FirstPrime">Cudd_FirstPrime</a>
+<a href="cuddAllDet.html#Cudd_NextPrime">Cudd_NextPrime</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_FreeTree"><b>Cudd_FreeTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Frees the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetTree">Cudd_SetTree</a>
+<a href="cuddAllDet.html#Cudd_ReadTree">Cudd_ReadTree</a>
+<a href="cuddAllDet.html#Cudd_FreeZddTree">Cudd_FreeZddTree</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_FreeZddTree"><b>Cudd_FreeZddTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Frees the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetZddTree">Cudd_SetZddTree</a>
+<a href="cuddAllDet.html#Cudd_ReadZddTree">Cudd_ReadZddTree</a>
+<a href="cuddAllDet.html#Cudd_FreeTree">Cudd_FreeTree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_GarbageCollectionEnabled"><b>Cudd_GarbageCollectionEnabled</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if garbage collection is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableGarbageCollection">Cudd_EnableGarbageCollection</a>
+<a href="cuddAllDet.html#Cudd_DisableGarbageCollection">Cudd_DisableGarbageCollection</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_GenFree"><b>Cudd_GenFree</b></a>(
+  DdGen * <b>gen</b> <i></i>
+)
+</pre>
+<dd> Frees a CUDD generator. Always returns 0, so that it can be used in mis-like foreach constructs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Increasing"><b>Cudd_Increasing</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Determines whether the function represented by BDD f is positive unate (monotonic increasing) in variable i. It is based on Cudd_Decreasing and the fact that f is monotonic increasing in i if and only if its complement is monotonic decreasing in i.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Decreasing">Cudd_Decreasing</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_IndicesToCube"><b>Cudd_IndicesToCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int * <b>array</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Builds a cube of BDD variables from an array of indices. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddComputeCube">Cudd_bddComputeCube</a>
+<a href="cuddAllDet.html#Cudd_CubeArrayToBdd">Cudd_CubeArrayToBdd</a>
+</code>
+
+<dt><pre>
+DdManager * <i></i>
+<a name="Cudd_Init"><b>Cudd_Init</b></a>(
+  unsigned int  <b>numVars</b>, <i>initial number of BDD variables (i.e., subtables)</i>
+  unsigned int  <b>numVarsZ</b>, <i>initial number of ZDD variables (i.e., subtables)</i>
+  unsigned int  <b>numSlots</b>, <i>initial size of the unique tables</i>
+  unsigned int  <b>cacheSize</b>, <i>initial size of the cache</i>
+  unsigned long  <b>maxMemory</b> <i>target maximum memory occupation</i>
+)
+</pre>
+<dd> Creates a new DD manager, initializes the table, the basic constants and the projection functions. If maxMemory is 0, Cudd_Init decides suitable values for the maximum size of the cache and for the limit for fast unique table growth based on the available memory. Returns a pointer to the manager if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Quit">Cudd_Quit</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_IsComplement"><b>Cudd_IsComplement</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if a pointer is complemented.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Regular">Cudd_Regular</a>
+<a href="cuddAllDet.html#Cudd_Complement">Cudd_Complement</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_IsConstant"><b>Cudd_IsConstant</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the node is a constant node (rather than an internal node). All constant nodes have the same index (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either regular or complemented.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_IsGenEmpty"><b>Cudd_IsGenEmpty</b></a>(
+  DdGen * <b>gen</b> <i></i>
+)
+</pre>
+<dd> Queries the status of a generator. Returns 1 if the generator is empty or NULL; 0 otherswise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_IsInHook"><b>Cudd_IsInHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_HFP  <b>f</b>, <i></i>
+  Cudd_HookType  <b>where</b> <i></i>
+)
+</pre>
+<dd> Checks whether a function is in a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if the function is found; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AddHook">Cudd_AddHook</a>
+<a href="cuddAllDet.html#Cudd_RemoveHook">Cudd_RemoveHook</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_IsNonConstant"><b>Cudd_IsNonConstant</b></a>(
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if a DD node is not constant. This function is useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant, Cudd_addEvalConst. These results may be a special value signifying non-constant. In the other cases the macro Cudd_IsConstant can be used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_IsConstant">Cudd_IsConstant</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_IterDerefBdd"><b>Cudd_IterDerefBdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is no longer needed. It is more efficient than Cudd_RecursiveDeref, but it cannot be used on ADDs. The greater efficiency comes from being able to assume that no constant node will ever die as a result of a call to this procedure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_DelayedDerefBdd">Cudd_DelayedDerefBdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_LargestCube"><b>Cudd_LargestCube</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>length</b> <i></i>
+)
+</pre>
+<dd> Finds a largest cube in a DD. f is the DD we want to get the largest cube for. The problem is translated into the one of finding a shortest path in f, when both THEN and ELSE arcs are assumed to have unit length. This yields a largest cube in the disjoint cover corresponding to the DD. Therefore, it is not necessarily the largest implicant of f. Returns the largest cube as a BDD.
+<p>
+
+<dd> <b>Side Effects</b> The number of literals of the cube is returned in length.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ShortestPath">Cudd_ShortestPath</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_MakeBddFromZddCover"><b>Cudd_MakeBddFromZddCover</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, otherwise it returns NULL.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#cuddMakeBddFromZddCover">cuddMakeBddFromZddCover</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_MakeTreeNode"><b>Cudd_MakeTreeNode</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  unsigned int  <b>low</b>, <i>index of the first group variable</i>
+  unsigned int  <b>size</b>, <i>number of variables in the group</i>
+  unsigned int  <b>type</b> <i>MTR_DEFAULT or MTR_FIXED</i>
+)
+</pre>
+<dd> Creates a new variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The variable tree is changed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_MakeZddTreeNode">Cudd_MakeZddTreeNode</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_MakeZddTreeNode"><b>Cudd_MakeZddTreeNode</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  unsigned int  <b>low</b>, <i>index of the first group variable</i>
+  unsigned int  <b>size</b>, <i>number of variables in the group</i>
+  unsigned int  <b>type</b> <i>MTR_DEFAULT or MTR_FIXED</i>
+)
+</pre>
+<dd> Creates a new ZDD variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The ZDD variable tree is changed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_MakeTreeNode">Cudd_MakeTreeNode</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_MinHammingDist"><b>Cudd_MinHammingDist</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode * <b>f</b>, <i>function to examine</i>
+  int * <b>minterm</b>, <i>reference minterm</i>
+  int  <b>upperBound</b> <i>distance above which an approximate answer is OK</i>
+)
+</pre>
+<dd> Returns the minimum Hamming distance between the minterms of a function f and a reference minterm. The function is given as a BDD; the minterm is given as an array of integers, one for each variable in the manager. Returns the minimum distance if it is less than the upper bound; the upper bound if the minimum distance is at least as large; CUDD_OUT_OF_MEM in case of failure.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addHamming">Cudd_addHamming</a>
+<a href="cuddAllDet.html#Cudd_bddClosestCube">Cudd_bddClosestCube</a>
+</code>
+
+<dt><pre>
+DdApaNumber <i></i>
+<a name="Cudd_NewApaNumber"><b>Cudd_NewApaNumber</b></a>(
+  int  <b>digits</b> <i></i>
+)
+</pre>
+<dd> Allocates memory for an arbitrary precision integer. Returns a pointer to the allocated memory if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_NextCube"><b>Cudd_NextCube</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  int ** <b>cube</b>, <i></i>
+  CUDD_VALUE_TYPE * <b>value</b> <i></i>
+)
+</pre>
+<dd> Generates the next cube of a decision diagram onset, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The cube and its value are returned as side effects. The generator is modified.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachCube">Cudd_ForeachCube</a>
+<a href="cuddAllDet.html#Cudd_FirstCube">Cudd_FirstCube</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_NextNode"><b>Cudd_NextNode</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  DdNode ** <b>node</b> <i></i>
+)
+</pre>
+<dd> Finds the node of a decision diagram, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The next node is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachNode">Cudd_ForeachNode</a>
+<a href="cuddAllDet.html#Cudd_FirstNode">Cudd_FirstNode</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_NextPrime"><b>Cudd_NextPrime</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  int ** <b>cube</b> <i></i>
+)
+</pre>
+<dd> Generates the next cube of a Boolean function, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The cube and is returned as side effects. The generator is modified.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ForeachPrime">Cudd_ForeachPrime</a>
+<a href="cuddAllDet.html#Cudd_FirstPrime">Cudd_FirstPrime</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_NextCube">Cudd_NextCube</a>
+<a href="cuddAllDet.html#Cudd_NextNode">Cudd_NextNode</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_NodeReadIndex"><b>Cudd_NodeReadIndex</b></a>(
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the node. The node pointer can be either regular or complemented.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadIndex">Cudd_ReadIndex</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_NotCond"><b>Cudd_NotCond</b></a>(
+   <b>node</b>, <i></i>
+   <b>c</b> <i></i>
+)
+</pre>
+<dd> Complements a DD if condition c is true; c should be either 0 or 1, because it is used directly (for efficiency). If in doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Not">Cudd_Not</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_Not"><b>Cudd_Not</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Complements a DD by flipping the complement attribute of the pointer (the least significant bit).
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_NotCond">Cudd_NotCond</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_OutOfMem"><b>Cudd_OutOfMem</b></a>(
+  long  <b>size</b> <i>size of the allocation that failed</i>
+)
+</pre>
+<dd> Warns that a memory allocation failed. This function can be used as replacement of MMout_of_memory to prevent the safe_mem functions of the util package from exiting when malloc returns NULL. One possible use is in case of discretionary allocations; for instance, the allocation of memory to enlarge the computed table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_OverApprox"><b>Cudd_OverApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  int  <b>safe</b>, <i>enforce safe approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_Prime"><b>Cudd_Prime</b></a>(
+  unsigned int  <b>p</b> <i></i>
+)
+</pre>
+<dd> Returns the next prime &gt;= p.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintDebug"><b>Cudd_PrintDebug</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  int  <b>pr</b> <i></i>
+)
+</pre>
+<dd> Prints to the standard output a DD and its statistics. The statistics include the number of nodes, the number of leaves, and the number of minterms. (The number of minterms is the number of assignments to the variables that cause the function to be different from the logical zero (for BDDs) and from the background value (for ADDs.) The statistics are printed if pr &gt; 0. Specifically: <ul> <li> pr = 0 : prints nothing <li> pr = 1 : prints counts of nodes and minterms <li> pr = 2 : prints counts + disjoint sum of product <li> pr = 3 : prints counts + list of nodes <li> pr &gt; 3 : prints counts + disjoint sum of product + list of nodes </ul> For the purpose of counting the number of minterms, the function is supposed to depend on n variables. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+<a href="cuddAllDet.html#Cudd_CountLeaves">Cudd_CountLeaves</a>
+<a href="cuddAllDet.html#Cudd_CountMinterm">Cudd_CountMinterm</a>
+<a href="cuddAllDet.html#Cudd_PrintMinterm">Cudd_PrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintInfo"><b>Cudd_PrintInfo</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints out statistics and settings for a CUDD manager. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintLinear"><b>Cudd_PrintLinear</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Prints the linear transform matrix. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintMinterm"><b>Cudd_PrintMinterm</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Prints a disjoint sum of product cover for the function rooted at node. Each product corresponds to a path from node to a leaf node different from the logical zero, and different from the background value. Uses the package default output file. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintDebug">Cudd_PrintDebug</a>
+<a href="cuddAllDet.html#Cudd_bddPrintCover">Cudd_bddPrintCover</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_PrintTwoLiteralClauses"><b>Cudd_PrintTwoLiteralClauses</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  char ** <b>names</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints the one- and two-literal clauses. Returns 1 if successful; 0 otherwise. The argument "names" can be NULL, in which case the variable indices are printed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindTwoLiteralClauses">Cudd_FindTwoLiteralClauses</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_PrintVersion"><b>Cudd_PrintVersion</b></a>(
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Prints the package version number.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_PrioritySelect"><b>Cudd_PrioritySelect</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>R</b>, <i>BDD of the relation</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b>, <i>array of y variables</i>
+  DdNode ** <b>z</b>, <i>array of z variables (optional: may be NULL)</i>
+  DdNode * <b>Pi</b>, <i>BDD of the priority function (optional: may be NULL)</i>
+  int  <b>n</b>, <i>size of x, y, and z</i>
+  DD_PRFP  <b>Pifunc</b> <i>function used to build Pi if it is NULL</i>
+)
+</pre>
+<dd> Selects pairs from a relation R(x,y) (given as a BDD) in such a way that a given x appears in one pair only. Uses a priority function to determine which y should be paired to a given x. Cudd_PrioritySelect returns a pointer to the selected function if successful; NULL otherwise. Three of the arguments--x, y, and z--are vectors of BDD variables. The first two are the variables on which R depends. The third vectore is a vector of auxiliary variables, used during the computation. This vector is optional. If a NULL value is passed instead, Cudd_PrioritySelect will create the working variables on the fly. The sizes of x and y (and z if it is not NULL) should equal n. The priority function Pi can be passed as a BDD, or can be built by Cudd_PrioritySelect. If NULL is passed instead of a DdNode *, parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the priority function. (Pifunc is a pointer to a C function.) If Pi is not NULL, then Pifunc is ignored. Pifunc should have the same interface as the standard priority functions (e.g., Cudd_Dxygtdxz). Cudd_PrioritySelect and Cudd_CProjection can sometimes be used interchangeably. Specifically, calling Cudd_PrioritySelect with Cudd_Xgty as Pifunc produces the same result as calling Cudd_CProjection with the all-zero minterm as reference minterm. However, depending on the application, one or the other may be preferable: <ul> <li> When extracting representatives from an equivalence relation, Cudd_CProjection has the advantage of nor requiring the auxiliary variables. <li> When computing matchings in general bipartite graphs, Cudd_PrioritySelect normally obtains better results because it can use more powerful matching schemes (e.g., Cudd_Dxygtdxz). </ul>
+<p>
+
+<dd> <b>Side Effects</b> If called with z == NULL, will create new variables in the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+<a href="cuddAllDet.html#Cudd_Xgty">Cudd_Xgty</a>
+<a href="cuddAllDet.html#Cudd_bddAdjPermuteX">Cudd_bddAdjPermuteX</a>
+<a href="cuddAllDet.html#Cudd_CProjection">Cudd_CProjection</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Quit"><b>Cudd_Quit</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Deletes resources associated with a DD manager and resets the global statistical counters. (Otherwise, another manaqger subsequently created would inherit the stats of this one.)
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Init">Cudd_Init</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_Random"><b>Cudd_Random</b></a>(
+   <b></b> <i></i>
+)
+</pre>
+<dd> Portable number generator based on ran2 from "Numerical Recipes in C." It is a long period (> 2 * 10^18) random number generator of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly distributed between 0 and 2147483561 (inclusive of the endpoint values). The random generator can be explicitly initialized by calling Cudd_Srandom. If no explicit initialization is performed, then the seed 1 is assumed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Srandom">Cudd_Srandom</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadArcviolation"><b>Cudd_ReadArcviolation</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the current value of the arcviolation parameter. This parameter is used in group sifting to decide how many arcs into <code>y</code> not coming from <code>x</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetArcviolation">Cudd_SetArcviolation</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadBackground"><b>Cudd_ReadBackground</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the background constant of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadCacheHits"><b>Cudd_ReadCacheHits</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of cache hits.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheLookUps">Cudd_ReadCacheLookUps</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadCacheLookUps"><b>Cudd_ReadCacheLookUps</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of cache look-ups.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheHits">Cudd_ReadCacheHits</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadCacheSlots"><b>Cudd_ReadCacheSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the number of slots in the cache.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheUsedSlots">Cudd_ReadCacheUsedSlots</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadCacheUsedSlots"><b>Cudd_ReadCacheUsedSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the fraction of used slots in the cache. The unused slots are those in which no valid data is stored. Garbage collection, variable reordering, and cache resizing may cause used slots to become unused.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadCacheSlots">Cudd_ReadCacheSlots</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadDead"><b>Cudd_ReadDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of dead nodes in the unique table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadKeys">Cudd_ReadKeys</a>
+</code>
+
+<dt><pre>
+CUDD_VALUE_TYPE <i></i>
+<a name="Cudd_ReadEpsilon"><b>Cudd_ReadEpsilon</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the epsilon parameter of the manager. The epsilon parameter control the comparison between floating point numbers.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetEpsilon">Cudd_SetEpsilon</a>
+</code>
+
+<dt><pre>
+Cudd_ErrorType <i></i>
+<a name="Cudd_ReadErrorCode"><b>Cudd_ReadErrorCode</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the code of the last error. The error codes are defined in cudd.h.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ClearErrorCode">Cudd_ClearErrorCode</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadGarbageCollectionTime"><b>Cudd_ReadGarbageCollectionTime</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of milliseconds spent doing garbage collection since the manager was initialized.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadGarbageCollections">Cudd_ReadGarbageCollections</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadGarbageCollections"><b>Cudd_ReadGarbageCollections</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of times garbage collection has occurred in the manager. The number includes both the calls from reordering procedures and those caused by requests to create new nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadGarbageCollectionTime">Cudd_ReadGarbageCollectionTime</a>
+</code>
+
+<dt><pre>
+Cudd_AggregationType <i></i>
+<a name="Cudd_ReadGroupcheck"><b>Cudd_ReadGroupcheck</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the groupcheck parameter of the manager. The groupcheck parameter determines the aggregation criterion in group sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetGroupcheck">Cudd_SetGroupcheck</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_ReadIndex"><b>Cudd_ReadIndex</b></a>(
+   <b>dd</b>, <i></i>
+   <b>index</b> <i></i>
+)
+</pre>
+<dd> Returns the current position in the order of variable index. This macro is obsolete and is kept for compatibility. New applications should use Cudd_ReadPerm instead.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadInvPermZdd"><b>Cudd_ReadInvPermZdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the ZDD variable currently in the i-th position of the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+<a href="cuddAllDet.html#Cudd_ReadInvPermZdd">Cudd_ReadInvPermZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadInvPerm"><b>Cudd_ReadInvPerm</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the index of the variable currently in the i-th position of the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+<a href="cuddAllDet.html#Cudd_ReadInvPermZdd">Cudd_ReadInvPermZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadIthClause"><b>Cudd_ReadIthClause</b></a>(
+  DdTlcInfo * <b>tlc</b>, <i></i>
+  int  <b>i</b>, <i></i>
+  DdHalfWord * <b>var1</b>, <i></i>
+  DdHalfWord * <b>var2</b>, <i></i>
+  int * <b>phase1</b>, <i></i>
+  int * <b>phase2</b> <i></i>
+)
+</pre>
+<dd> Accesses the i-th clause of a DD given the clause set which must be already computed. Returns 1 if successful; 0 if i is out of range, or in case of error.
+<p>
+
+<dd> <b>Side Effects</b> the four components of a clause are returned as side effects.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindTwoLiteralClauses">Cudd_FindTwoLiteralClauses</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadKeys"><b>Cudd_ReadKeys</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the total number of nodes currently in the unique table, including the dead nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadDead">Cudd_ReadDead</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadLinear"><b>Cudd_ReadLinear</b></a>(
+  DdManager * <b>table</b>, <i>CUDD manager</i>
+  int  <b>x</b>, <i>row index</i>
+  int  <b>y</b> <i>column index</i>
+)
+</pre>
+<dd> Reads an entry of the linear transform matrix.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadLogicZero"><b>Cudd_ReadLogicZero</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the zero constant of the manager. The logic zero constant is the complement of the one constant, and is distinct from the arithmetic zero.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadOne">Cudd_ReadOne</a>
+<a href="cuddAllDet.html#Cudd_ReadZero">Cudd_ReadZero</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadLooseUpTo"><b>Cudd_ReadLooseUpTo</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the looseUpTo parameter of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetLooseUpTo">Cudd_SetLooseUpTo</a>
+<a href="cuddAllDet.html#Cudd_ReadMinHit">Cudd_ReadMinHit</a>
+<a href="cuddAllDet.html#Cudd_ReadMinDead">Cudd_ReadMinDead</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMaxCacheHard"><b>Cudd_ReadMaxCacheHard</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maxCacheHard parameter of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxCacheHard">Cudd_SetMaxCacheHard</a>
+<a href="cuddAllDet.html#Cudd_ReadMaxCache">Cudd_ReadMaxCache</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMaxCache"><b>Cudd_ReadMaxCache</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the soft limit for the cache size. The soft limit
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxCache">Cudd_ReadMaxCache</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadMaxGrowthAlternate"><b>Cudd_ReadMaxGrowthAlternate</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maxGrowthAlt parameter of the manager. This parameter is analogous to the maxGrowth paramter, and is used every given number of reorderings instead of maxGrowth. The number of reorderings is set with Cudd_SetReorderingCycle. If the number of reorderings is 0 (default) maxGrowthAlt is never used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowth">Cudd_ReadMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetReorderingCycle">Cudd_SetReorderingCycle</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingCycle">Cudd_ReadReorderingCycle</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadMaxGrowth"><b>Cudd_ReadMaxGrowth</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maxGrowth parameter of the manager. This parameter determines how much the number of nodes can grow during sifting of a variable. Overall, sifting never increases the size of the decision diagrams. This parameter only refers to intermediate results. A lower value will speed up sifting, possibly at the expense of quality.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxGrowth">Cudd_SetMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMaxLive"><b>Cudd_ReadMaxLive</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maximum allowed number of live nodes. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxLive">Cudd_SetMaxLive</a>
+</code>
+
+<dt><pre>
+unsigned long <i></i>
+<a name="Cudd_ReadMaxMemory"><b>Cudd_ReadMaxMemory</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the maximum allowed memory. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMaxMemory">Cudd_SetMaxMemory</a>
+</code>
+
+<dt><pre>
+unsigned long <i></i>
+<a name="Cudd_ReadMemoryInUse"><b>Cudd_ReadMemoryInUse</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the memory in use by the manager measured in bytes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMinDead"><b>Cudd_ReadMinDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the minDead parameter of the manager. The minDead parameter is used by the package to decide whether to collect garbage or resize a subtable of the unique table when the subtable becomes too full. The application can indirectly control the value of minDead by setting the looseUpTo parameter.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadDead">Cudd_ReadDead</a>
+<a href="cuddAllDet.html#Cudd_ReadLooseUpTo">Cudd_ReadLooseUpTo</a>
+<a href="cuddAllDet.html#Cudd_SetLooseUpTo">Cudd_SetLooseUpTo</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadMinHit"><b>Cudd_ReadMinHit</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the hit rate that causes resizinig of the computed table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetMinHit">Cudd_SetMinHit</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadMinusInfinity"><b>Cudd_ReadMinusInfinity</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the minus-infinity constant from the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadNextReordering"><b>Cudd_ReadNextReordering</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the threshold for the next dynamic reordering. The threshold is in terms of number of nodes and is in effect only if reordering is enabled. The count does not include the dead nodes, unless the countDead parameter of the manager has been changed from its default setting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetNextReordering">Cudd_SetNextReordering</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadNodeCount"><b>Cudd_ReadNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the number of live nodes in BDDs and ADDs. This number does not include the isolated projection functions and the unused constants. These nodes that are not counted are not part of the DDs manipulated by the application.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPeakNodeCount">Cudd_ReadPeakNodeCount</a>
+<a href="cuddAllDet.html#Cudd_zddReadNodeCount">Cudd_zddReadNodeCount</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadNodesDropped"><b>Cudd_ReadNodesDropped</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of nodes killed by dereferencing if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_STATS defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodesFreed">Cudd_ReadNodesFreed</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadNodesFreed"><b>Cudd_ReadNodesFreed</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of nodes returned to the free list if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_STATS defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodesDropped">Cudd_ReadNodesDropped</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadNumberXovers"><b>Cudd_ReadNumberXovers</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the current number of crossovers used by the genetic algorithm for variable reordering. A larger number of crossovers will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as number of crossovers, with a maximum of 60.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetNumberXovers">Cudd_SetNumberXovers</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadOne"><b>Cudd_ReadOne</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the one constant of the manager. The one constant is common to ADDs and BDDs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadZero">Cudd_ReadZero</a>
+<a href="cuddAllDet.html#Cudd_ReadLogicZero">Cudd_ReadLogicZero</a>
+<a href="cuddAllDet.html#Cudd_ReadZddOne">Cudd_ReadZddOne</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPeakLiveNodeCount"><b>Cudd_ReadPeakLiveNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the peak number of live nodes. This count is kept only if CUDD is compiled with DD_STATS defined. If DD_STATS is not defined, this function returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodeCount">Cudd_ReadNodeCount</a>
+<a href="cuddAllDet.html#Cudd_PrintInfo">Cudd_PrintInfo</a>
+<a href="cuddAllDet.html#Cudd_ReadPeakNodeCount">Cudd_ReadPeakNodeCount</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadPeakNodeCount"><b>Cudd_ReadPeakNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the peak number of nodes. This number includes node on the free list. At the peak, the number of nodes on the free list is guaranteed to be less than DD_MEM_CHUNK.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNodeCount">Cudd_ReadNodeCount</a>
+<a href="cuddAllDet.html#Cudd_PrintInfo">Cudd_PrintInfo</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPermZdd"><b>Cudd_ReadPermZdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the current position of the i-th ZDD variable in the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadInvPermZdd">Cudd_ReadInvPermZdd</a>
+<a href="cuddAllDet.html#Cudd_ReadPerm">Cudd_ReadPerm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPerm"><b>Cudd_ReadPerm</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the current position of the i-th variable in the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadInvPerm">Cudd_ReadInvPerm</a>
+<a href="cuddAllDet.html#Cudd_ReadPermZdd">Cudd_ReadPermZdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadPlusInfinity"><b>Cudd_ReadPlusInfinity</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the plus-infinity constant from the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadPopulationSize"><b>Cudd_ReadPopulationSize</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the current size of the population used by the genetic algorithm for variable reordering. A larger population size will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as population size, with a maximum of 120.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetPopulationSize">Cudd_SetPopulationSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadRecomb"><b>Cudd_ReadRecomb</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the current value of the recombination parameter used in group sifting. A larger (positive) value makes the aggregation of variables due to the second difference criterion more likely. A smaller (negative) value makes aggregation less likely.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetRecomb">Cudd_SetRecomb</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadRecursiveCalls"><b>Cudd_ReadRecursiveCalls</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of recursive calls if the package is compiled with DD_COUNT defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadReorderingCycle"><b>Cudd_ReadReorderingCycle</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the reordCycle parameter of the manager. This parameter determines how often the alternate threshold on maximum growth is used in reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetReorderingCycle">Cudd_SetReorderingCycle</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_ReadReorderingTime"><b>Cudd_ReadReorderingTime</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of milliseconds spent reordering variables since the manager was initialized. The time spent in collecting garbage before reordering is included.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadReorderings">Cudd_ReadReorderings</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadReorderings"><b>Cudd_ReadReorderings</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of times reordering has occurred in the manager. The number includes both the calls to Cudd_ReduceHeap from the application program and those automatically performed by the package. However, calls that do not even initiate reordering are not counted. A call may not initiate reordering if there are fewer than minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified as reordering method. The calls to Cudd_ShuffleHeap are not counted.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReduceHeap">Cudd_ReduceHeap</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingTime">Cudd_ReadReorderingTime</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSiftMaxSwap"><b>Cudd_ReadSiftMaxSwap</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the siftMaxSwap parameter of the manager. This parameter gives the maximum number of swaps that will be attempted for each invocation of sifting. The real number of swaps may exceed the set limit because the package will always complete the sifting of the variable that causes the limit to be reached.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSiftMaxVar">Cudd_ReadSiftMaxVar</a>
+<a href="cuddAllDet.html#Cudd_SetSiftMaxSwap">Cudd_SetSiftMaxSwap</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSiftMaxVar"><b>Cudd_ReadSiftMaxVar</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the siftMaxVar parameter of the manager. This parameter gives the maximum number of variables that will be sifted for each invocation of sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSiftMaxSwap">Cudd_ReadSiftMaxSwap</a>
+<a href="cuddAllDet.html#Cudd_SetSiftMaxVar">Cudd_SetSiftMaxVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSize"><b>Cudd_ReadSize</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of BDD variables in existance.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadZddSize">Cudd_ReadZddSize</a>
+</code>
+
+<dt><pre>
+unsigned int <i></i>
+<a name="Cudd_ReadSlots"><b>Cudd_ReadSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the total number of slots of the unique table. This number ismainly for diagnostic purposes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+FILE * <i></i>
+<a name="Cudd_ReadStderr"><b>Cudd_ReadStderr</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the stderr of a manager. This is the file pointer to which messages normally going to stderr are written. It is initialized to stderr. Cudd_SetStderr allows the application to redirect it.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetStderr">Cudd_SetStderr</a>
+<a href="cuddAllDet.html#Cudd_ReadStdout">Cudd_ReadStdout</a>
+</code>
+
+<dt><pre>
+FILE * <i></i>
+<a name="Cudd_ReadStdout"><b>Cudd_ReadStdout</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the stdout of a manager. This is the file pointer to which messages normally going to stdout are written. It is initialized to stdout. Cudd_SetStdout allows the application to redirect it.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetStdout">Cudd_SetStdout</a>
+<a href="cuddAllDet.html#Cudd_ReadStderr">Cudd_ReadStderr</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadSwapSteps"><b>Cudd_ReadSwapSteps</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the number of elementary reordering steps.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadSymmviolation"><b>Cudd_ReadSymmviolation</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the current value of the symmviolation parameter. This parameter is used in group sifting to decide how many violations to the symmetry conditions <code>f10 = f01</code> or <code>f11 = f00</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetSymmviolation">Cudd_SetSymmviolation</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_ReadTree"><b>Cudd_ReadTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetTree">Cudd_SetTree</a>
+<a href="cuddAllDet.html#Cudd_FreeTree">Cudd_FreeTree</a>
+<a href="cuddAllDet.html#Cudd_ReadZddTree">Cudd_ReadZddTree</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadUniqueLinks"><b>Cudd_ReadUniqueLinks</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of links followed during look-ups in the unique table if the keeping of this statistic is enabled; -1 otherwise. If an item is found in the first position of its collision list, the number of links followed is taken to be 0. If it is in second position, the number of links is 1, and so on. This statistic is enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadUniqueLookUps">Cudd_ReadUniqueLookUps</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadUniqueLookUps"><b>Cudd_ReadUniqueLookUps</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of look-ups in the unique table if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadUniqueLinks">Cudd_ReadUniqueLinks</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_ReadUsedSlots"><b>Cudd_ReadUsedSlots</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reads the fraction of used slots in the unique table. The unused slots are those in which no valid data is stored. Garbage collection, variable reordering, and subtable resizing may cause used slots to become unused.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSlots">Cudd_ReadSlots</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadVars"><b>Cudd_ReadVars</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the i-th element of the vars array if it falls within the array bounds; NULL otherwise. If i is the index of an existing variable, this function produces the same result as Cudd_bddIthVar. However, if the i-th var does not exist yet, Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadZddOne"><b>Cudd_ReadZddOne</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Returns the ZDD for the constant 1 function. The representation of the constant 1 function as a ZDD depends on how many variables it (nominally) depends on. The index of the topmost variable in the support is given as argument <code>i</code>.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadOne">Cudd_ReadOne</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReadZddSize"><b>Cudd_ReadZddSize</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the number of ZDD variables in existance.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+MtrNode * <i></i>
+<a name="Cudd_ReadZddTree"><b>Cudd_ReadZddTree</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetZddTree">Cudd_SetZddTree</a>
+<a href="cuddAllDet.html#Cudd_FreeZddTree">Cudd_FreeZddTree</a>
+<a href="cuddAllDet.html#Cudd_ReadTree">Cudd_ReadTree</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ReadZero"><b>Cudd_ReadZero</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns the zero constant of the manager. The zero constant is the arithmetic zero, rather than the logic zero. The latter is the complement of the one constant.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadOne">Cudd_ReadOne</a>
+<a href="cuddAllDet.html#Cudd_ReadLogicZero">Cudd_ReadLogicZero</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_RecursiveDerefZdd"><b>Cudd_RecursiveDerefZdd</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of ZDD node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a ZDD that is no longer needed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Deref">Cudd_Deref</a>
+<a href="cuddAllDet.html#Cudd_Ref">Cudd_Ref</a>
+<a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_RecursiveDeref"><b>Cudd_RecursiveDeref</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a DD that is no longer needed.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Deref">Cudd_Deref</a>
+<a href="cuddAllDet.html#Cudd_Ref">Cudd_Ref</a>
+<a href="cuddAllDet.html#Cudd_RecursiveDerefZdd">Cudd_RecursiveDerefZdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReduceHeap"><b>Cudd_ReduceHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  Cudd_ReorderingType  <b>heuristic</b>, <i>method used for reordering</i>
+  int  <b>minsize</b> <i>bound below which no reordering occurs</i>
+)
+</pre>
+<dd> Main dynamic reordering routine. Calls one of the possible reordering procedures: <ul> <li>Swapping <li>Sifting <li>Symmetric Sifting <li>Group Sifting <li>Window Permutation <li>Simulated Annealing <li>Genetic Algorithm <li>Dynamic Programming (exact) </ul> For sifting, symmetric sifting, group sifting, and window permutation it is possible to request reordering to convergence.<p> The core of all methods is the reordering procedure cuddSwapInPlace() which swaps two adjacent variables and is based on Rudell's paper. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.
+<p>
+
+<dd> <b>Side Effects</b> Changes the variable order for all diagrams and clears the cache.
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Ref"><b>Cudd_Ref</b></a>(
+  DdNode * <b>n</b> <i></i>
+)
+</pre>
+<dd> Increases the reference count of a node, if it is not saturated.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_RecursiveDeref">Cudd_RecursiveDeref</a>
+<a href="cuddAllDet.html#Cudd_Deref">Cudd_Deref</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_Regular"><b>Cudd_Regular</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the regular version of a pointer.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Complement">Cudd_Complement</a>
+<a href="cuddAllDet.html#Cudd_IsComplement">Cudd_IsComplement</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_RemapOverApprox"><b>Cudd_RemapOverApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_RemapUnderApprox"><b>Cudd_RemapUnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure uses a remapping technique and density as the cost function. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_UnderApprox">Cudd_UnderApprox</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_RemoveHook"><b>Cudd_RemoveHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_HFP  <b>f</b>, <i></i>
+  Cudd_HookType  <b>where</b> <i></i>
+)
+</pre>
+<dd> Removes a function from a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if successful; 0 the function was not in the list.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AddHook">Cudd_AddHook</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReorderingReporting"><b>Cudd_ReorderingReporting</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if reporting of reordering stats is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EnableReorderingReporting">Cudd_EnableReorderingReporting</a>
+<a href="cuddAllDet.html#Cudd_DisableReorderingReporting">Cudd_DisableReorderingReporting</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReorderingStatusZdd"><b>Cudd_ReorderingStatusZdd</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType * <b>method</b> <i></i>
+)
+</pre>
+<dd> Reports the status of automatic dynamic reordering of ZDDs. Parameter method is set to the ZDD reordering method currently selected. Returns 1 if automatic reordering is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Parameter method is set to the ZDD reordering method currently selected.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnableZdd">Cudd_AutodynEnableZdd</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisableZdd">Cudd_AutodynDisableZdd</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatus">Cudd_ReorderingStatus</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ReorderingStatus"><b>Cudd_ReorderingStatus</b></a>(
+  DdManager * <b>unique</b>, <i></i>
+  Cudd_ReorderingType * <b>method</b> <i></i>
+)
+</pre>
+<dd> Reports the status of automatic dynamic reordering of BDDs and ADDs. Parameter method is set to the reordering method currently selected. Returns 1 if automatic reordering is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Parameter method is set to the reordering method currently selected.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_AutodynEnable">Cudd_AutodynEnable</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+<a href="cuddAllDet.html#Cudd_ReorderingStatusZdd">Cudd_ReorderingStatusZdd</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetArcviolation"><b>Cudd_SetArcviolation</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>arcviolation</b> <i></i>
+)
+</pre>
+<dd> Sets the value of the arcviolation parameter. This parameter is used in group sifting to decide how many arcs into <code>y</code> not coming from <code>x</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadArcviolation">Cudd_ReadArcviolation</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetBackground"><b>Cudd_SetBackground</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>bck</b> <i></i>
+)
+</pre>
+<dd> Sets the background constant of the manager. It assumes that the DdNode pointer bck is already referenced.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetEpsilon"><b>Cudd_SetEpsilon</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>ep</b> <i></i>
+)
+</pre>
+<dd> Sets the epsilon parameter of the manager to ep. The epsilon parameter control the comparison between floating point numbers.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadEpsilon">Cudd_ReadEpsilon</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetGroupcheck"><b>Cudd_SetGroupcheck</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  Cudd_AggregationType  <b>gc</b> <i></i>
+)
+</pre>
+<dd> Sets the parameter groupcheck of the manager to gc. The groupcheck parameter determines the aggregation criterion in group sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadGroupCheck">Cudd_ReadGroupCheck</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetLooseUpTo"><b>Cudd_SetLooseUpTo</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>lut</b> <i></i>
+)
+</pre>
+<dd> Sets the looseUpTo parameter of the manager. This parameter of the manager controls the threshold beyond which no fast growth of the unique table is allowed. The threshold is given as a number of slots. If the value passed to this function is 0, the function determines a suitable value based on the available memory.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadLooseUpTo">Cudd_ReadLooseUpTo</a>
+<a href="cuddAllDet.html#Cudd_SetMinHit">Cudd_SetMinHit</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxCacheHard"><b>Cudd_SetMaxCacheHard</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>mc</b> <i></i>
+)
+</pre>
+<dd> Sets the maxCacheHard parameter of the manager. The cache cannot grow larger than maxCacheHard entries. This parameter allows an application to control the trade-off of memory versus speed. If the value passed to this function is 0, the function determines a suitable maximum cache size based on the available memory.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxCacheHard">Cudd_ReadMaxCacheHard</a>
+<a href="cuddAllDet.html#Cudd_SetMaxCache">Cudd_SetMaxCache</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxGrowthAlternate"><b>Cudd_SetMaxGrowthAlternate</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  double  <b>mg</b> <i></i>
+)
+</pre>
+<dd> Sets the maxGrowthAlt parameter of the manager. This parameter is analogous to the maxGrowth paramter, and is used every given number of reorderings instead of maxGrowth. The number of reorderings is set with Cudd_SetReorderingCycle. If the number of reorderings is 0 (default) maxGrowthAlt is never used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowth">Cudd_SetMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_SetReorderingCycle">Cudd_SetReorderingCycle</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingCycle">Cudd_ReadReorderingCycle</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxGrowth"><b>Cudd_SetMaxGrowth</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  double  <b>mg</b> <i></i>
+)
+</pre>
+<dd> Sets the maxGrowth parameter of the manager. This parameter determines how much the number of nodes can grow during sifting of a variable. Overall, sifting never increases the size of the decision diagrams. This parameter only refers to intermediate results. A lower value will speed up sifting, possibly at the expense of quality.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowth">Cudd_ReadMaxGrowth</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxLive"><b>Cudd_SetMaxLive</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>maxLive</b> <i></i>
+)
+</pre>
+<dd> Sets the maximum allowed number of live nodes. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxLive">Cudd_ReadMaxLive</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMaxMemory"><b>Cudd_SetMaxMemory</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned long  <b>maxMemory</b> <i></i>
+)
+</pre>
+<dd> Sets the maximum allowed memory. When this number is exceeded, the package returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxMemory">Cudd_ReadMaxMemory</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetMinHit"><b>Cudd_SetMinHit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>hr</b> <i></i>
+)
+</pre>
+<dd> Sets the minHit parameter of the manager. This parameter controls the resizing of the computed table. If the hit rate is larger than the specified value, and the cache is not already too large, then its size is doubled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMinHit">Cudd_ReadMinHit</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetNextReordering"><b>Cudd_SetNextReordering</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  unsigned int  <b>next</b> <i></i>
+)
+</pre>
+<dd> Sets the threshold for the next dynamic reordering. The threshold is in terms of number of nodes and is in effect only if reordering is enabled. The count does not include the dead nodes, unless the countDead parameter of the manager has been changed from its default setting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNextReordering">Cudd_ReadNextReordering</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetNumberXovers"><b>Cudd_SetNumberXovers</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>numberXovers</b> <i></i>
+)
+</pre>
+<dd> Sets the number of crossovers used by the genetic algorithm for variable reordering. A larger number of crossovers will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as number of crossovers, with a maximum of 60.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadNumberXovers">Cudd_ReadNumberXovers</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetPopulationSize"><b>Cudd_SetPopulationSize</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>populationSize</b> <i></i>
+)
+</pre>
+<dd> Sets the size of the population used by the genetic algorithm for variable reordering. A larger population size will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as population size, with a maximum of 120.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPopulationSize">Cudd_ReadPopulationSize</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetRecomb"><b>Cudd_SetRecomb</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>recomb</b> <i></i>
+)
+</pre>
+<dd> Sets the value of the recombination parameter used in group sifting. A larger (positive) value makes the aggregation of variables due to the second difference criterion more likely. A smaller (negative) value makes aggregation less likely. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadRecomb">Cudd_ReadRecomb</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetReorderingCycle"><b>Cudd_SetReorderingCycle</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>cycle</b> <i></i>
+)
+</pre>
+<dd> Sets the reordCycle parameter of the manager. This parameter determines how often the alternate threshold on maximum growth is used in reordering.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadMaxGrowthAlternate">Cudd_ReadMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_SetMaxGrowthAlternate">Cudd_SetMaxGrowthAlternate</a>
+<a href="cuddAllDet.html#Cudd_ReadReorderingCycle">Cudd_ReadReorderingCycle</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetSiftMaxSwap"><b>Cudd_SetSiftMaxSwap</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>sms</b> <i></i>
+)
+</pre>
+<dd> Sets the siftMaxSwap parameter of the manager. This parameter gives the maximum number of swaps that will be attempted for each invocation of sifting. The real number of swaps may exceed the set limit because the package will always complete the sifting of the variable that causes the limit to be reached.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetSiftMaxVar">Cudd_SetSiftMaxVar</a>
+<a href="cuddAllDet.html#Cudd_ReadSiftMaxSwap">Cudd_ReadSiftMaxSwap</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetSiftMaxVar"><b>Cudd_SetSiftMaxVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>smv</b> <i></i>
+)
+</pre>
+<dd> Sets the siftMaxVar parameter of the manager. This parameter gives the maximum number of variables that will be sifted for each invocation of sifting.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SetSiftMaxSwap">Cudd_SetSiftMaxSwap</a>
+<a href="cuddAllDet.html#Cudd_ReadSiftMaxVar">Cudd_ReadSiftMaxVar</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetStderr"><b>Cudd_SetStderr</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Sets the stderr of a manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadStderr">Cudd_ReadStderr</a>
+<a href="cuddAllDet.html#Cudd_SetStdout">Cudd_SetStdout</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetStdout"><b>Cudd_SetStdout</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  FILE * <b>fp</b> <i></i>
+)
+</pre>
+<dd> Sets the stdout of a manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadStdout">Cudd_ReadStdout</a>
+<a href="cuddAllDet.html#Cudd_SetStderr">Cudd_SetStderr</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetSymmviolation"><b>Cudd_SetSymmviolation</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>symmviolation</b> <i></i>
+)
+</pre>
+<dd> Sets the value of the symmviolation parameter. This parameter is used in group sifting to decide how many violations to the symmetry conditions <code>f10 = f01</code> or <code>f11 = f00</code> are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadSymmviolation">Cudd_ReadSymmviolation</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetTree"><b>Cudd_SetTree</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  MtrNode * <b>tree</b> <i></i>
+)
+</pre>
+<dd> Sets the variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FreeTree">Cudd_FreeTree</a>
+<a href="cuddAllDet.html#Cudd_ReadTree">Cudd_ReadTree</a>
+<a href="cuddAllDet.html#Cudd_SetZddTree">Cudd_SetZddTree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_SetVarMap"><b>Cudd_SetVarMap</b></a>(
+  DdManager * <b>manager</b>, <i>DD manager</i>
+  DdNode ** <b>x</b>, <i>first array of variables</i>
+  DdNode ** <b>y</b>, <i>second array of variables</i>
+  int  <b>n</b> <i>length of both arrays</i>
+)
+</pre>
+<dd> Registers with the manager a variable mapping described by two sets of variables. This variable mapping is then used by functions like Cudd_bddVarMap. This function is convenient for those applications that perform the same mapping several times. However, if several different permutations are used, it may be more efficient not to rely on the registered mapping, because changing mapping causes the cache to be cleared. (The initial setting, however, does not clear the cache.) The two sets of variables (x and y) must have the same size (x and y). The size is given by n. The two sets of variables are normally disjoint, but this restriction is not imposeded by the function. When new variables are created, the map is automatically extended (each new variable maps to itself). The typical use, however, is to wait until all variables are created, and then create the map. Returns 1 if the mapping is successfully registered with the manager; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Modifies the manager. May clear the cache.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddVarMap">Cudd_bddVarMap</a>
+<a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SetZddTree"><b>Cudd_SetZddTree</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  MtrNode * <b>tree</b> <i></i>
+)
+</pre>
+<dd> Sets the ZDD variable group tree of the manager.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FreeZddTree">Cudd_FreeZddTree</a>
+<a href="cuddAllDet.html#Cudd_ReadZddTree">Cudd_ReadZddTree</a>
+<a href="cuddAllDet.html#Cudd_SetTree">Cudd_SetTree</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_SharingSize"><b>Cudd_SharingSize</b></a>(
+  DdNode ** <b>nodeArray</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Counts the number of nodes in an array of DDs. Shared nodes are counted only once. Returns the total number of nodes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ShortestLength"><b>Cudd_ShortestLength</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>weight</b> <i></i>
+)
+</pre>
+<dd> Find the length of the shortest path(s) in a DD. f is the DD we want to get the shortest path for; weight[i] is the weight of the THEN edge coming from the node whose index is i. All ELSE edges have 0 weight. Returns the length of the shortest path(s) if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ShortestPath">Cudd_ShortestPath</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_ShortestPath"><b>Cudd_ShortestPath</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int * <b>weight</b>, <i></i>
+  int * <b>support</b>, <i></i>
+  int * <b>length</b> <i></i>
+)
+</pre>
+<dd> Finds a shortest path in a DD. f is the DD we want to get the shortest path for; weight[i] is the weight of the THEN arc coming from the node whose index is i. If weight is NULL, then unit weights are assumed for all THEN arcs. All ELSE arcs have 0 weight. If non-NULL, both weight and support should point to arrays with at least as many entries as there are variables in the manager. Returns the shortest path as the BDD of a cube.
+<p>
+
+<dd> <b>Side Effects</b> support contains on return the true support of f. If support is NULL on entry, then Cudd_ShortestPath does not compute the true support info. length contains the length of the path.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ShortestLength">Cudd_ShortestLength</a>
+<a href="cuddAllDet.html#Cudd_LargestCube">Cudd_LargestCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_ShuffleHeap"><b>Cudd_ShuffleHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  int * <b>permutation</b> <i>required variable permutation</i>
+)
+</pre>
+<dd> Reorders variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Changes the variable order for all diagrams and clears the cache.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReduceHeap">Cudd_ReduceHeap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SolveEqn"><b>Cudd_SolveEqn</b></a>(
+  DdManager * <b>bdd</b>, <i></i>
+  DdNode * <b>F</b>, <i>the left-hand side of the equation</i>
+  DdNode * <b>Y</b>, <i>the cube of the y variables</i>
+  DdNode ** <b>G</b>, <i>the array of solutions (return parameter)</i>
+  int ** <b>yIndex</b>, <i>index of y variables</i>
+  int  <b>n</b> <i>numbers of unknowns</i>
+)
+</pre>
+<dd> Implements the solution for F(x,y) = 0. The return value is the consistency condition. The y variables are the unknowns and the remaining variables are the parameters. Returns the consistency condition if successful; NULL otherwise. Cudd_SolveEqn allocates an array and fills it with the indices of the unknowns. This array is used by Cudd_VerifySol.
+<p>
+
+<dd> <b>Side Effects</b> The solution is returned in G; the indices of the y variables are returned in yIndex.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_VerifySol">Cudd_VerifySol</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SplitSet"><b>Cudd_SplitSet</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>S</b>, <i></i>
+  DdNode ** <b>xVars</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  double  <b>m</b> <i></i>
+)
+</pre>
+<dd> Returns <code>m</code> minterms from a BDD whose support has <code>n</code> variables at most. The procedure tries to create as few extra nodes as possible. The function represented by <code>S</code> depends on at most <code>n</code> of the variables in <code>xVars</code>. Returns a BDD with <code>m</code> minterms of the on-set of S if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_Srandom"><b>Cudd_Srandom</b></a>(
+  long  <b>seed</b> <i></i>
+)
+</pre>
+<dd> Initializer for the portable number generator based on ran2 in "Numerical Recipes in C." The input is the seed for the generator. If it is negative, its absolute value is taken as seed. If it is 0, then 1 is taken as seed. The initialized sets up the two recurrences used to generate a long-period stream, and sets up the shuffle table.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Random">Cudd_Random</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_StdPostReordHook"><b>Cudd_StdPostReordHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  const char * <b>str</b>, <i></i>
+  void * <b>data</b> <i></i>
+)
+</pre>
+<dd> Sample hook function to call after reordering. Prints on the manager's stdout final size and reordering time. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_StdPreReordHook">Cudd_StdPreReordHook</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_StdPreReordHook"><b>Cudd_StdPreReordHook</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  const char * <b>str</b>, <i></i>
+  void * <b>data</b> <i></i>
+)
+</pre>
+<dd> Sample hook function to call before reordering. Prints on the manager's stdout reordering method and initial size. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_StdPostReordHook">Cudd_StdPostReordHook</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetCompress"><b>Cudd_SubsetCompress</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>BDD whose subset is sought</i>
+  int  <b>nvars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the subset</i>
+)
+</pre>
+<dd> Finds a dense subset of BDD <code>f</code>. Density is the ratio of number of minterms to number of nodes. Uses several techniques in series. It is more expensive than other subsetting procedures, but often produces better results. See Cudd_SubsetShortPaths for a description of the threshold and nvars parameters. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetRemap">Cudd_SubsetRemap</a>
+<a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetHeavyBranch"><b>Cudd_SubsetHeavyBranch</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the subset</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure builds a subset by throwing away one of the children of each node, starting from the root, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetShortPaths"><b>Cudd_SubsetShortPaths</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>maximum number of nodes in the subset</i>
+  int  <b>hardlimit</b> <i>flag: 1 if threshold is a hard limit</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure tries to preserve the shortest paths of the input BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the subset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the subset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVars. If 0 is passed, then the value returned by Cudd_ReadSize is used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SubsetWithMaskVars"><b>Cudd_SubsetWithMaskVars</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function from which to pick a cube</i>
+  DdNode ** <b>vars</b>, <i>array of variables</i>
+  int  <b>nvars</b>, <i>size of <code>vars</code></i>
+  DdNode ** <b>maskVars</b>, <i>array of variables</i>
+  int  <b>mvars</b> <i>size of <code>maskVars</code></i>
+)
+</pre>
+<dd> Extracts a subset from a BDD in the following procedure. 1. Compute the weight for each mask variable by counting the number of minterms for both positive and negative cofactors of the BDD with respect to each mask variable. (weight = #positive - #negative) 2. Find a representative cube of the BDD by using the weight. From the top variable of the BDD, for each variable, if the weight is greater than 0.0, choose THEN branch, othereise ELSE branch, until meeting the constant 1. 3. Quantify out the variables not in maskVars from the representative cube and if a variable in maskVars is don't care, replace the variable with a constant(1 or 0) depending on the weight. 4. Make a subset of the BDD by multiplying with the modified cube.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SupersetCompress"><b>Cudd_SupersetCompress</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>BDD whose superset is sought</i>
+  int  <b>nvars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the superset</i>
+)
+</pre>
+<dd> Finds a dense superset of BDD <code>f</code>. Density is the ratio of number of minterms to number of nodes. Uses several techniques in series. It is more expensive than other supersetting procedures, but often produces better results. See Cudd_SupersetShortPaths for a description of the threshold and nvars parameters. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetCompress">Cudd_SubsetCompress</a>
+<a href="cuddAllDet.html#Cudd_SupersetRemap">Cudd_SupersetRemap</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SupersetHeavyBranch"><b>Cudd_SupersetHeavyBranch</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b> <i>maximum number of nodes in the superset</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure builds a superset by throwing away one of the children of each node starting from the root of the complement function, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_SupersetShortPaths">Cudd_SupersetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_SupersetShortPaths"><b>Cudd_SupersetShortPaths</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be superset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>maximum number of nodes in the subset</i>
+  int  <b>hardlimit</b> <i>flag: 1 if threshold is a hard limit</i>
+)
+</pre>
+<dd> Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure tries to preserve the shortest paths of the complement BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the superset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the superset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVar. If 0 is passed, then the value returned by Cudd_ReadSize is used.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SupersetHeavyBranch">Cudd_SupersetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+int * <i></i>
+<a name="Cudd_SupportIndex"><b>Cudd_SupportIndex</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b> <i>DD whose support is sought</i>
+)
+</pre>
+<dd> Finds the variables on which a DD depends. Returns an index array of the variables if successful; NULL otherwise. The size of the array equals the number of variables in the manager. Each entry of the array is 1 if the corresponding variable is in the support of the DD and 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+<a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_SupportSize"><b>Cudd_SupportSize</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b> <i>DD whose support size is sought</i>
+)
+</pre>
+<dd> Counts the variables on which a DD depends. Returns the number of the variables if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Support"><b>Cudd_Support</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b> <i>DD whose support is sought</i>
+)
+</pre>
+<dd> Finds the variables on which a DD depends. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_SymmProfile"><b>Cudd_SymmProfile</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Prints statistics on symmetric variables.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_TurnOffCountDead"><b>Cudd_TurnOffCountDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Causes the dead nodes not to be counted towards triggering reordering. This causes less frequent reorderings. By default dead nodes are not counted. Therefore there is no need to call this function unless Cudd_TurnOnCountDead has been previously called.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_TurnOnCountDead">Cudd_TurnOnCountDead</a>
+<a href="cuddAllDet.html#Cudd_DeadAreCounted">Cudd_DeadAreCounted</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_TurnOnCountDead"><b>Cudd_TurnOnCountDead</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Causes the dead nodes to be counted towards triggering reordering. This causes more frequent reorderings. By default dead nodes are not counted.
+<p>
+
+<dd> <b>Side Effects</b> Changes the manager.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_TurnOffCountDead">Cudd_TurnOffCountDead</a>
+<a href="cuddAllDet.html#Cudd_DeadAreCounted">Cudd_DeadAreCounted</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_T"><b>Cudd_T</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the then child of an internal node. If <code>node</code> is a constant node, the result is unpredictable.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_E">Cudd_E</a>
+<a href="cuddAllDet.html#Cudd_V">Cudd_V</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_UnderApprox"><b>Cudd_UnderApprox</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be subset</i>
+  int  <b>numVars</b>, <i>number of variables in the support of f</i>
+  int  <b>threshold</b>, <i>when to stop approximation</i>
+  int  <b>safe</b>, <i>enforce safe approximation</i>
+  double  <b>quality</b> <i>minimum improvement for accepted changes</i>
+)
+</pre>
+<dd> Extracts a dense subset from a BDD. This procedure uses a variant of Tom Shiple's underapproximation method. The main difference from the original method is that density is used as cost function. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SubsetShortPaths">Cudd_SubsetShortPaths</a>
+<a href="cuddAllDet.html#Cudd_SubsetHeavyBranch">Cudd_SubsetHeavyBranch</a>
+<a href="cuddAllDet.html#Cudd_ReadSize">Cudd_ReadSize</a>
+</code>
+
+<dt><pre>
+int * <i></i>
+<a name="Cudd_VectorSupportIndex"><b>Cudd_VectorSupportIndex</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode ** <b>F</b>, <i>array of DDs whose support is sought</i>
+  int  <b>n</b> <i>size of the array</i>
+)
+</pre>
+<dd> Finds the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns an index array of the variables if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SupportIndex">Cudd_SupportIndex</a>
+<a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_VectorSupportSize"><b>Cudd_VectorSupportSize</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode ** <b>F</b>, <i>array of DDs whose support is sought</i>
+  int  <b>n</b> <i>size of the array</i>
+)
+</pre>
+<dd> Counts the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns the number of the variables if successful; CUDD_OUT_OF_MEM otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_VectorSupport">Cudd_VectorSupport</a>
+<a href="cuddAllDet.html#Cudd_SupportSize">Cudd_SupportSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_VectorSupport"><b>Cudd_VectorSupport</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode ** <b>F</b>, <i>array of DDs whose support is sought</i>
+  int  <b>n</b> <i>size of the array</i>
+)
+</pre>
+<dd> Finds the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Support">Cudd_Support</a>
+<a href="cuddAllDet.html#Cudd_ClassifySupport">Cudd_ClassifySupport</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_VerifySol"><b>Cudd_VerifySol</b></a>(
+  DdManager * <b>bdd</b>, <i></i>
+  DdNode * <b>F</b>, <i>the left-hand side of the equation</i>
+  DdNode ** <b>G</b>, <i>the array of solutions</i>
+  int * <b>yIndex</b>, <i>index of y variables</i>
+  int  <b>n</b> <i>numbers of unknowns</i>
+)
+</pre>
+<dd> Checks the solution of F(x,y) = 0. This procedure substitutes the solution components for the unknowns of F and returns the resulting BDD for F.
+<p>
+
+<dd> <b>Side Effects</b> Frees the memory pointed by yIndex.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_SolveEqn">Cudd_SolveEqn</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_V"><b>Cudd_V</b></a>(
+   <b>node</b> <i></i>
+)
+</pre>
+<dd> Returns the value of a constant node. If <code>node</code> is an internal node, the result is unpredictable.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_T">Cudd_T</a>
+<a href="cuddAllDet.html#Cudd_E">Cudd_E</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Xeqy"><b>Cudd_Xeqy</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x and y variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b> <i>array of y variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function x==y. Both x and y are N-bit numbers, x[0] x[1] ... x[N-1] and y[0] y[1] ... y[N-1], with 0 the most significant bit. The BDD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x[0] y[0] x[1] y[1] ... x[N-1] y[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addXeqy">Cudd_addXeqy</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_Xgty"><b>Cudd_Xgty</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x and y variables</i>
+  DdNode ** <b>z</b>, <i>array of z variables: unused</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b> <i>array of y variables</i>
+)
+</pre>
+<dd> This function generates a BDD for the function x &gt; y. Both x and y are N-bit numbers, x[0] x[1] ... x[N-1] and y[0] y[1] ... y[N-1], with 0 the most significant bit. The BDD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x[0] y[0] x[1] y[1] ... x[N-1] y[N-1]. Argument z is not used by Cudd_Xgty: it is included to make it call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addAgreement"><b>Cudd_addAgreement</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns NULL if not a terminal case; f op g otherwise, where f op g is f if f==g; background if f!=g.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addApply"><b>Cudd_addApply</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_AOP  <b>op</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Applies op to the corresponding discriminants of f and g. Returns a pointer to the result if succssful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMonadicApply">Cudd_addMonadicApply</a>
+<a href="cuddAllDet.html#Cudd_addPlus">Cudd_addPlus</a>
+<a href="cuddAllDet.html#Cudd_addTimes">Cudd_addTimes</a>
+<a href="cuddAllDet.html#Cudd_addThreshold">Cudd_addThreshold</a>
+<a href="cuddAllDet.html#Cudd_addSetNZ">Cudd_addSetNZ</a>
+<a href="cuddAllDet.html#Cudd_addDivide">Cudd_addDivide</a>
+<a href="cuddAllDet.html#Cudd_addMinus">Cudd_addMinus</a>
+<a href="cuddAllDet.html#Cudd_addMinimum">Cudd_addMinimum</a>
+<a href="cuddAllDet.html#Cudd_addMaximum">Cudd_addMaximum</a>
+<a href="cuddAllDet.html#Cudd_addOneZeroMaximum">Cudd_addOneZeroMaximum</a>
+<a href="cuddAllDet.html#Cudd_addDiff">Cudd_addDiff</a>
+<a href="cuddAllDet.html#Cudd_addAgreement">Cudd_addAgreement</a>
+<a href="cuddAllDet.html#Cudd_addOr">Cudd_addOr</a>
+<a href="cuddAllDet.html#Cudd_addNand">Cudd_addNand</a>
+<a href="cuddAllDet.html#Cudd_addNor">Cudd_addNor</a>
+<a href="cuddAllDet.html#Cudd_addXor">Cudd_addXor</a>
+<a href="cuddAllDet.html#Cudd_addXnor">Cudd_addXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddInterval"><b>Cudd_addBddInterval</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>lower</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants greater than or equal to lower and less than or equal to upper with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddIthBit"><b>Cudd_addBddIthBit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>bit</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants whose i-th bit is equal to 1 with 1, and all other discriminants with 0. The i-th bit refers to the integer representation of the leaf value. If the value is has a fractional part, it is ignored. Repeated calls to this procedure allow one to transform an integer-valued ADD into an array of BDDs, one for each bit of the leaf values. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddPattern"><b>Cudd_addBddPattern</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants different from 0 with 1. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+<a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+<a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddStrictThreshold"><b>Cudd_addBddStrictThreshold</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>value</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants STRICTLY greater than value with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+<a href="cuddAllDet.html#Cudd_addBddThreshold">Cudd_addBddThreshold</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addBddThreshold"><b>Cudd_addBddThreshold</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>value</b> <i></i>
+)
+</pre>
+<dd> Converts an ADD to a BDD by replacing all discriminants greater than or equal to value with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddInterval">Cudd_addBddInterval</a>
+<a href="cuddAllDet.html#Cudd_addBddPattern">Cudd_addBddPattern</a>
+<a href="cuddAllDet.html#Cudd_BddToAdd">Cudd_BddToAdd</a>
+<a href="cuddAllDet.html#Cudd_addBddStrictThreshold">Cudd_addBddStrictThreshold</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addCmpl"><b>Cudd_addCmpl</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Computes the complement of an ADD a la C language: The complement of 0 is 1 and the complement of everything else is 0. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNegate">Cudd_addNegate</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addCompose"><b>Cudd_addCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  int  <b>v</b> <i></i>
+)
+</pre>
+<dd> Substitutes g for x_v in the ADD for f. v is the index of the variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes the corresponding projection function to the recursive procedure, so that the cache may be used. Returns the composed ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddCompose">Cudd_bddCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addComputeCube"><b>Cudd_addComputeCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>vars</b>, <i></i>
+  int * <b>phase</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Computes the cube of an array of ADD variables. If non-null, the phase argument indicates which literal of each variable should appear in the cube. If phase[i] is nonzero, then the positive literal is used. If phase is NULL, the cube is positive unate. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddComputeCube">Cudd_bddComputeCube</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addConstrain"><b>Cudd_addConstrain</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Computes f constrain c (f @ c), for f an ADD and c a 0-1 ADD. List of special cases: <ul> <li> F @ 0 = 0 <li> F @ 1 = F <li> 0 @ c = 0 <li> 1 @ c = 1 <li> F @ F = 1 </ul> Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addConst"><b>Cudd_addConst</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  CUDD_VALUE_TYPE  <b>c</b> <i></i>
+)
+</pre>
+<dd> Retrieves the ADD for constant c if it already exists, or creates a new ADD. Returns a pointer to the ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addDiff"><b>Cudd_addDiff</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns NULL if not a terminal case; f op g otherwise, where f op g is plusinfinity if f=g; min(f,g) if f!=g.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addDivide"><b>Cudd_addDivide</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point division. Returns NULL if not a terminal case; f / g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addEvalConst"><b>Cudd_addEvalConst</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Checks whether ADD g is constant whenever ADD f is 1. f must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may or may not be constant) or DD_NON_CONSTANT. If f is identically 0, the check is assumed to be successful, and the background value is returned. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addLeq">Cudd_addLeq</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addExistAbstract"><b>Cudd_addExistAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Abstracts all the variables in cube from f by summing over all possible values taken by the variables. Returns the abstracted ADD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addUnivAbstract">Cudd_addUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_addOrAbstract">Cudd_addOrAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addFindMax"><b>Cudd_addFindMax</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns a pointer to a constant ADD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addFindMin"><b>Cudd_addFindMin</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Returns a pointer to a constant ADD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addGeneralVectorCompose"><b>Cudd_addGeneralVectorCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vectorOn</b>, <i></i>
+  DdNode ** <b>vectorOff</b> <i></i>
+)
+</pre>
+<dd> Given a vector of ADDs, creates a new ADD by substituting the ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted for the x_v and vectorOff the ADDs to be substituted for x_v'. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addVectorCompose">Cudd_addVectorCompose</a>
+<a href="cuddAllDet.html#Cudd_addNonSimCompose">Cudd_addNonSimCompose</a>
+<a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+<a href="cuddAllDet.html#Cudd_bddVectorCompose">Cudd_bddVectorCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addHamming"><b>Cudd_addHamming</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>xVars</b>, <i></i>
+  DdNode ** <b>yVars</b>, <i></i>
+  int  <b>nVars</b> <i></i>
+)
+</pre>
+<dd> Computes the Hamming distance ADD. Returns an ADD that gives the Hamming distance between its two arguments if successful; NULL otherwise. The two vectors xVars and yVars identify the variables that form the two arguments.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_addHarwell"><b>Cudd_addHarwell</b></a>(
+  FILE * <b>fp</b>, <i>pointer to the input file</i>
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode ** <b>E</b>, <i>characteristic function of the graph</i>
+  DdNode *** <b>x</b>, <i>array of row variables</i>
+  DdNode *** <b>y</b>, <i>array of column variables</i>
+  DdNode *** <b>xn</b>, <i>array of complemented row variables</i>
+  DdNode *** <b>yn_</b>, <i>array of complemented column variables</i>
+  int * <b>nx</b>, <i>number or row variables</i>
+  int * <b>ny</b>, <i>number or column variables</i>
+  int * <b>m</b>, <i>number of rows</i>
+  int * <b>n</b>, <i>number of columns</i>
+  int  <b>bx</b>, <i>first index of row variables</i>
+  int  <b>sx</b>, <i>step of row variables</i>
+  int  <b>by</b>, <i>first index of column variables</i>
+  int  <b>sy</b>, <i>step of column variables</i>
+  int  <b>pr</b> <i>verbosity level</i>
+)
+</pre>
+<dd> Reads in a matrix in the format of the Harwell-Boeing benchmark suite. The variables are ordered as follows: <blockquote> x[0] y[0] x[1] y[1] ... </blockquote> 0 is the most significant bit. On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. Returns 1 on success; 0 otherwise. The ADD for the sparse matrix is returned in E, and its reference count is > 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addRead">Cudd_addRead</a>
+<a href="cuddAllDet.html#Cudd_bddRead">Cudd_bddRead</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIteConstant"><b>Cudd_addIteConstant</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITEconstant for ADDs. f must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may or may not be constant) or DD_NON_CONSTANT. No new nodes are created. This function can be used, for instance, to check that g has a constant value (specified by h) whenever f is 1. If the constant value is unknown, then one should use Cudd_addEvalConst.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIte">Cudd_addIte</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIte"><b>Cudd_addIte</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITE(f,g,h). This procedure assumes that f is a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIthBit"><b>Cudd_addIthBit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>bit</b> <i></i>
+)
+</pre>
+<dd> Produces an ADD from another ADD by replacing all discriminants whose i-th bit is equal to 1 with 1, and all other discriminants with 0. The i-th bit refers to the integer representation of the leaf value. If the value is has a fractional part, it is ignored. Repeated calls to this procedure allow one to transform an integer-valued ADD into an array of ADDs, one for each bit of the leaf values. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addBddIthBit">Cudd_addBddIthBit</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addIthVar"><b>Cudd_addIthVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Retrieves the ADD variable with index i if it already exists, or creates a new ADD variable. Returns a pointer to the variable if successful; NULL otherwise. An ADD variable differs from a BDD variable because it points to the arithmetic zero, instead of having a complement pointer to 1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_addConst">Cudd_addConst</a>
+<a href="cuddAllDet.html#Cudd_addNewVarAtLevel">Cudd_addNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_addLeq"><b>Cudd_addLeq</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created. This procedure works for arbitrary ADDs. For 0-1 ADDs Cudd_addEvalConst is more efficient.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+<a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addLog"><b>Cudd_addLog</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Natural logarithm of an ADDs. Returns NULL if not a terminal case; log(f) otherwise. The discriminants of f must be positive double's.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMonadicApply">Cudd_addMonadicApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMatrixMultiply"><b>Cudd_addMatrixMultiply</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>A</b>, <i></i>
+  DdNode * <b>B</b>, <i></i>
+  DdNode ** <b>z</b>, <i></i>
+  int  <b>nz</b> <i></i>
+)
+</pre>
+<dd> Calculates the product of two matrices, A and B, represented as ADDs. This procedure implements the quasiring multiplication algorithm. A is assumed to depend on variables x (rows) and z (columns). B is assumed to depend on variables z (rows) and y (columns). The product of A and B then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "summation" variables. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addTimesPlus">Cudd_addTimesPlus</a>
+<a href="cuddAllDet.html#Cudd_addTriangle">Cudd_addTriangle</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMaximum"><b>Cudd_addMaximum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point max for Cudd_addApply. Returns NULL if not a terminal case; max(f,g) otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMinimum"><b>Cudd_addMinimum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point min for Cudd_addApply. Returns NULL if not a terminal case; min(f,g) otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMinus"><b>Cudd_addMinus</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point subtraction. Returns NULL if not a terminal case; f - g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addMonadicApply"><b>Cudd_addMonadicApply</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DD_MAOP  <b>op</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Applies op to the discriminants of f. Returns a pointer to the result if succssful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_addLog">Cudd_addLog</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNand"><b>Cudd_addNand</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> NAND of two 0-1 ADDs. Returns NULL if not a terminal case; f NAND g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNegate"><b>Cudd_addNegate</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Computes the additive inverse of an ADD. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addCmpl">Cudd_addCmpl</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNewVarAtLevel"><b>Cudd_addNewVarAtLevel</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>level</b> <i></i>
+)
+</pre>
+<dd> Creates a new ADD variable. The new variable has an index equal to the largest previous index plus 1 and is positioned at the specified level in the order. Returns a pointer to the new variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNewVar"><b>Cudd_addNewVar</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Creates a new ADD variable. The new variable has an index equal to the largest previous index plus 1. Returns a pointer to the new variable if successful; NULL otherwise. An ADD variable differs from a BDD variable because it points to the arithmetic zero, instead of having a complement pointer to 1.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+<a href="cuddAllDet.html#Cudd_addConst">Cudd_addConst</a>
+<a href="cuddAllDet.html#Cudd_addNewVarAtLevel">Cudd_addNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNonSimCompose"><b>Cudd_addNonSimCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vector</b> <i></i>
+)
+</pre>
+<dd> Given a vector of 0-1 ADDs, creates a new ADD by substituting the 0-1 ADDs for the variables of the ADD f. There should be an entry in vector for each variable in the manager. This function implements non-simultaneous composition. If any of the functions being composed depends on any of the variables being substituted, then the result depends on the order of composition, which in turn depends on the variable order: The variables farther from the roots in the order are substituted first. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addVectorCompose">Cudd_addVectorCompose</a>
+<a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addNor"><b>Cudd_addNor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> NOR of two 0-1 ADDs. Returns NULL if not a terminal case; f NOR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOneZeroMaximum"><b>Cudd_addOneZeroMaximum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f &gt; g and 0 otherwise. Used in conjunction with Cudd_addApply. Returns NULL if not a terminal case.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOrAbstract"><b>Cudd_addOrAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Abstracts all the variables in cube from the 0-1 ADD f by taking the disjunction over all possible values taken by the variables. Returns the abstracted ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addUnivAbstract">Cudd_addUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_addExistAbstract">Cudd_addExistAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOr"><b>Cudd_addOr</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Disjunction of two 0-1 ADDs. Returns NULL if not a terminal case; f OR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addOuterSum"><b>Cudd_addOuterSum</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>M</b>, <i></i>
+  DdNode * <b>r</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Takes the pointwise minimum of a matrix and the outer sum of two vectors. This procedure is used in the Floyd-Warshall all-pair shortest path algorithm. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addPermute"><b>Cudd_addPermute</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int * <b>permut</b> <i></i>
+)
+</pre>
+<dd> Given a permutation in array permut, creates a new ADD with permuted variables. There should be an entry in array permut for each variable in the manager. The i-th entry of permut holds the index of the variable that is to substitute the i-th variable. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_addSwapVariables">Cudd_addSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addPlus"><b>Cudd_addPlus</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point addition. Returns NULL if not a terminal case; f+g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_addRead"><b>Cudd_addRead</b></a>(
+  FILE * <b>fp</b>, <i>input file pointer</i>
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode ** <b>E</b>, <i>characteristic function of the graph</i>
+  DdNode *** <b>x</b>, <i>array of row variables</i>
+  DdNode *** <b>y</b>, <i>array of column variables</i>
+  DdNode *** <b>xn</b>, <i>array of complemented row variables</i>
+  DdNode *** <b>yn_</b>, <i>array of complemented column variables</i>
+  int * <b>nx</b>, <i>number or row variables</i>
+  int * <b>ny</b>, <i>number or column variables</i>
+  int * <b>m</b>, <i>number of rows</i>
+  int * <b>n</b>, <i>number of columns</i>
+  int  <b>bx</b>, <i>first index of row variables</i>
+  int  <b>sx</b>, <i>step of row variables</i>
+  int  <b>by</b>, <i>first index of column variables</i>
+  int  <b>sy</b> <i>step of column variables</i>
+)
+</pre>
+<dd> Reads in a sparse matrix specified in a simple format. The first line of the input contains the numbers of rows and columns. The remaining lines contain the elements of the matrix, one per line. Given a background value (specified by the background field of the manager), only the values different from it are explicitly listed. Each foreground element is described by two integers, i.e., the row and column number, and a real number, i.e., the value.<p> Cudd_addRead produces an ADD that depends on two sets of variables: x and y. The x variables (x[0] ... x[nx-1]) encode the row index and the y variables (y[0] ... y[ny-1]) encode the column index. x[0] and y[0] are the most significant bits in the indices. The variables may already exist or may be created by the function. The index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy.<p> On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. When Cudd_addRead creates the variable arrays, the index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy. When some variables already exist Cudd_addRead expects the indices of the existing x variables to be bx+i*sx, and the indices of the existing y variables to be by+i*sy.<p> m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. The ADD for the sparse matrix is returned in E, and its reference count is > 0. Cudd_addRead returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> nx and ny are set to the numbers of row and column variables. m and n are set to the numbers of rows and columns. x and y are possibly extended to represent the array of row and column variables. Similarly for xn and yn_, which hold on return from Cudd_addRead the complements of the row and column variables.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addHarwell">Cudd_addHarwell</a>
+<a href="cuddAllDet.html#Cudd_bddRead">Cudd_bddRead</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addResidue"><b>Cudd_addResidue</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of bits</i>
+  int  <b>m</b>, <i>modulus</i>
+  int  <b>options</b>, <i>options</i>
+  int  <b>top</b> <i>index of top variable</i>
+)
+</pre>
+<dd> Builds an ADD for the residue modulo m of an n-bit number. The modulus must be at least 2, and the number of bits at least 1. Parameter options specifies whether the MSB should be on top or the LSB; and whther the number whose residue is computed is in two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's complement residue. To request MSB on top and two's complement residue simultaneously, one can OR the two macros: CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC. Cudd_addResidue returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addRestrict"><b>Cudd_addRestrict</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> ADD restrict according to Coudert and Madre's algorithm (ICCAD90). Returns the restricted ADD if successful; otherwise NULL. If application of restrict results in an ADD larger than the input ADD, the input ADD is returned.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addConstrain">Cudd_addConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addRoundOff"><b>Cudd_addRoundOff</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>N</b> <i></i>
+)
+</pre>
+<dd> Rounds off the discriminants of an ADD. The discriminants are rounded off to N digits after the decimal. Returns a pointer to the result ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addScalarInverse"><b>Cudd_addScalarInverse</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>epsilon</b> <i></i>
+)
+</pre>
+<dd> Computes an n ADD where the discriminants are the multiplicative inverses of the corresponding discriminants of the argument ADD. Returns a pointer to the resulting ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addSetNZ"><b>Cudd_addSetNZ</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> This operator sets f to the value of g wherever g != 0. Returns NULL if not a terminal case; f op g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addSwapVariables"><b>Cudd_addSwapVariables</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  DdNode ** <b>y</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Swaps two sets of variables of the same size (x and y) in the ADD f. The size is given by n. The two sets of variables are assumed to be disjoint. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addThreshold"><b>Cudd_addThreshold</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g). Returns NULL if not a terminal case; f op g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addTimesPlus"><b>Cudd_addTimesPlus</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>A</b>, <i></i>
+  DdNode * <b>B</b>, <i></i>
+  DdNode ** <b>z</b>, <i></i>
+  int  <b>nz</b> <i></i>
+)
+</pre>
+<dd> Calculates the product of two matrices, A and B, represented as ADDs, using the CMU matrix by matrix multiplication procedure by Clarke et al.. Matrix A has x's as row variables and z's as column variables, while matrix B has z's as row variables and y's as column variables. Returns the pointer to the result if successful; NULL otherwise. The resulting matrix has x's as row variables and y's as column variables.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMatrixMultiply">Cudd_addMatrixMultiply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addTimes"><b>Cudd_addTimes</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> Integer and floating point multiplication. Returns NULL if not a terminal case; f * g otherwise. This function can be used also to take the AND of two 0-1 ADDs.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addTriangle"><b>Cudd_addTriangle</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode ** <b>z</b>, <i></i>
+  int  <b>nz</b> <i></i>
+)
+</pre>
+<dd> Implements the semiring multiplication algorithm used in the triangulation step for the shortest path computation. f is assumed to depend on variables x (rows) and z (columns). g is assumed to depend on variables z (rows) and y (columns). The product of f and g then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "abstraction" variables. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMatrixMultiply">Cudd_addMatrixMultiply</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addUnivAbstract"><b>Cudd_addUnivAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Abstracts all the variables in cube from f by taking the product over all possible values taken by the variable. Returns the abstracted ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addExistAbstract">Cudd_addExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddUnivAbstract">Cudd_bddUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_addOrAbstract">Cudd_addOrAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addVectorCompose"><b>Cudd_addVectorCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vector</b> <i></i>
+)
+</pre>
+<dd> Given a vector of 0-1 ADDs, creates a new ADD by substituting the 0-1 ADDs for the variables of the ADD f. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting ADD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNonSimCompose">Cudd_addNonSimCompose</a>
+<a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+<a href="cuddAllDet.html#Cudd_bddVectorCompose">Cudd_bddVectorCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addWalsh"><b>Cudd_addWalsh</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  DdNode ** <b>y</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Generates a Walsh matrix in ADD form. Returns a pointer to the matrixi if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addXeqy"><b>Cudd_addXeqy</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>N</b>, <i>number of x and y variables</i>
+  DdNode ** <b>x</b>, <i>array of x variables</i>
+  DdNode ** <b>y</b> <i>array of y variables</i>
+)
+</pre>
+<dd> This function generates an ADD for the function x==y. Both x and y are N-bit numbers, x[0] x[1] ... x[N-1] and y[0] y[1] ... y[N-1], with 0 the most significant bit. The ADD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x[0] y[0] x[1] y[1] ... x[N-1] y[N-1].
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_Xeqy">Cudd_Xeqy</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addXnor"><b>Cudd_addXnor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> XNOR of two 0-1 ADDs. Returns NULL if not a terminal case; f XNOR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_addXor"><b>Cudd_addXor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>f</b>, <i></i>
+  DdNode ** <b>g</b> <i></i>
+)
+</pre>
+<dd> XOR of two 0-1 ADDs. Returns NULL if not a terminal case; f XOR g otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAdjPermuteX"><b>Cudd_bddAdjPermuteX</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>B</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Rearranges a set of variables in the BDD B. The size of the set is given by n. This procedure is intended for the `randomization' of the priority functions. Returns a pointer to the BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdxz">Cudd_Dxygtdxz</a>
+<a href="cuddAllDet.html#Cudd_Dxygtdyz">Cudd_Dxygtdyz</a>
+<a href="cuddAllDet.html#Cudd_PrioritySelect">Cudd_PrioritySelect</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAndAbstractLimit"><b>Cudd_bddAndAbstractLimit</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b>, <i></i>
+  unsigned int  <b>limit</b> <i></i>
+)
+</pre>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise. In particular, if the number of new nodes created exceeds <code>limit</code>, this function returns NULL.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAndAbstract"><b>Cudd_bddAndAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise. Cudd_bddAndAbstract implements the semiring matrix multiplication algorithm for the boolean semiring.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addMatrixMultiply">Cudd_addMatrixMultiply</a>
+<a href="cuddAllDet.html#Cudd_addTriangle">Cudd_addTriangle</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAndLimit"><b>Cudd_bddAndLimit</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  unsigned int  <b>limit</b> <i></i>
+)
+</pre>
+<dd> Computes the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up or more new nodes than <code>limit</code> are required.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddAnd"><b>Cudd_bddAnd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddIntersect">Cudd_bddIntersect</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddApproxConjDecomp"><b>Cudd_bddApproxConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the first factor</i>
+)
+</pre>
+<dd> Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the use of supersetting to obtain an initial factor of the given function. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_RemapOverApprox">Cudd_RemapOverApprox</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddApproxDisjDecomp"><b>Cudd_bddApproxDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddBindVar"><b>Cudd_bddBindVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> This function sets a flag to prevent sifting of a variable. Returns 1 if successful; 0 otherwise (i.e., invalid variable index).
+<p>
+
+<dd> <b>Side Effects</b> Changes the "bindVar" flag in DdSubtable.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddUnbindVar">Cudd_bddUnbindVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddBooleanDiff"><b>Cudd_bddBooleanDiff</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>x</b> <i></i>
+)
+</pre>
+<dd> Computes the boolean difference of f with respect to the variable with index x. Returns the BDD of the boolean difference if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode ** <i></i>
+<a name="Cudd_bddCharToVect"><b>Cudd_bddCharToVect</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Computes a vector of BDDs whose image equals a non-zero function. The result depends on the variable order. The i-th component of the vector depends only on the first i variables in the order. Each BDD in the vector is not larger than the BDD of the given characteristic function. This function is based on the description of char-to-vect in "Verification of Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C. Berthet and J. C. Madre. Returns a pointer to an array containing the result if successful; NULL otherwise. The size of the array equals the number of variables in the manager. The components of the solution have their reference counts already incremented (unlike the results of most other functions in the package).
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddClippingAndAbstract"><b>Cudd_bddClippingAndAbstract</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first conjunct</i>
+  DdNode * <b>g</b>, <i>second conjunct</i>
+  DdNode * <b>cube</b>, <i>cube of variables to be abstracted</i>
+  int  <b>maxDepth</b>, <i>maximum recursion depth</i>
+  int  <b>direction</b> <i>under (0) or over (1) approximation</i>
+)
+</pre>
+<dd> Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddClippingAnd">Cudd_bddClippingAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddClippingAnd"><b>Cudd_bddClippingAnd</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first conjunct</i>
+  DdNode * <b>g</b>, <i>second conjunct</i>
+  int  <b>maxDepth</b>, <i>maximum recursion depth</i>
+  int  <b>direction</b> <i>under (0) or over (1) approximation</i>
+)
+</pre>
+<dd> Approximates the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddClosestCube"><b>Cudd_bddClosestCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  int * <b>distance</b> <i></i>
+)
+</pre>
+<dd> Finds a cube of f at minimum Hamming distance from the minterms of g. All the minterms of the cube are at the minimum distance. If the distance is 0, the cube belongs to the intersection of f and g. Returns the cube if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The distance is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_MinHammingDist">Cudd_MinHammingDist</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddCompose"><b>Cudd_bddCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  int  <b>v</b> <i></i>
+)
+</pre>
+<dd> Substitutes g for x_v in the BDD for f. v is the index of the variable to be substituted. Cudd_bddCompose passes the corresponding projection function to the recursive procedure, so that the cache may be used. Returns the composed BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addCompose">Cudd_addCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddComputeCube"><b>Cudd_bddComputeCube</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode ** <b>vars</b>, <i></i>
+  int * <b>phase</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Computes the cube of an array of BDD variables. If non-null, the phase argument indicates which literal of each variable should appear in the cube. If phase[i] is nonzero, then the positive literal is used. If phase is NULL, the cube is positive unate. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addComputeCube">Cudd_addComputeCube</a>
+<a href="cuddAllDet.html#Cudd_IndicesToCube">Cudd_IndicesToCube</a>
+<a href="cuddAllDet.html#Cudd_CubeArrayToBdd">Cudd_CubeArrayToBdd</a>
+</code>
+
+<dt><pre>
+DdNode ** <i></i>
+<a name="Cudd_bddConstrainDecomp"><b>Cudd_bddConstrainDecomp</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> BDD conjunctive decomposition as in McMillan's CAV96 paper. The decomposition is canonical only for a given variable order. If canonicity is required, variable ordering must be disabled after the decomposition has been computed. Returns an array with one entry for each BDD variable in the manager if successful; otherwise NULL. The components of the solution have their reference counts already incremented (unlike the results of most other functions in the package.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddConstrain"><b>Cudd_bddConstrain</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Computes f constrain c (f @ c). Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true for c.) List of special cases: <ul> <li> f @ 0 = 0 <li> f @ 1 = f <li> 0 @ c = 0 <li> 1 @ c = 1 <li> f @ f = 1 <li> f @ f'= 0 </ul> Returns a pointer to the result if successful; NULL otherwise. Note that if F=(f1,...,fn) and reordering takes place while computing F @ c, then the image restriction property (Img(F,c) = Img(F @ c)) is lost.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+<a href="cuddAllDet.html#Cudd_addConstrain">Cudd_addConstrain</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_bddCorrelationWeights"><b>Cudd_bddCorrelationWeights</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  double * <b>prob</b> <i></i>
+)
+</pre>
+<dd> Computes the correlation of f and g for given input probabilities. On input, prob[i] is supposed to contain the probability of the i-th input variable to be 1. If f == g, their correlation is 1. If f == g', their correlation is 0. Returns the probability that f and g have the same value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The correlation of f and the constant one gives the probability of f.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddCorrelation">Cudd_bddCorrelation</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_bddCorrelation"><b>Cudd_bddCorrelation</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the correlation of f and g. If f == g, their correlation is 1. If f == g', their correlation is 0. Returns the fraction of minterms in the ON-set of the EXNOR of f and g. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddCorrelationWeights">Cudd_bddCorrelationWeights</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddExistAbstract"><b>Cudd_bddExistAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Existentially abstracts all the variables in cube from f. Returns the abstracted BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddUnivAbstract">Cudd_bddUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_addExistAbstract">Cudd_addExistAbstract</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddGenConjDecomp"><b>Cudd_bddGenConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the array of conjuncts</i>
+)
+</pre>
+<dd> Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the fact tht it generalizes the decomposition based on the cofactors with respect to one variable. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be balanced.
+<p>
+
+<dd> <b>Side Effects</b> The two factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddGenDisjDecomp"><b>Cudd_bddGenDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be balanced.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIntersect"><b>Cudd_bddIntersect</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>first operand</i>
+  DdNode * <b>g</b> <i>second operand</i>
+)
+</pre>
+<dd> Computes a function included in the intersection of f and g. (That is, a witness that the intersection is not empty.) Cudd_bddIntersect tries to build as few new nodes as possible. If the only result of interest is whether f and g intersect, Cudd_bddLeq should be used instead.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsNsVar"><b>Cudd_bddIsNsVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is next state. Returns 1 if the variable's type is present state; 0 if the variable exists but is not a present state; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetNsVar">Cudd_bddSetNsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPiVar">Cudd_bddIsPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPsVar">Cudd_bddIsPsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsPiVar"><b>Cudd_bddIsPiVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Checks whether a variable is primary input. Returns 1 if the variable's type is primary input; 0 if the variable exists but is not a primary input; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPiVar">Cudd_bddSetPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPsVar">Cudd_bddIsPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsNsVar">Cudd_bddIsNsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsPsVar"><b>Cudd_bddIsPsVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is present state. Returns 1 if the variable's type is present state; 0 if the variable exists but is not a present state; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPsVar">Cudd_bddSetPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPiVar">Cudd_bddIsPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsNsVar">Cudd_bddIsNsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarEssential"><b>Cudd_bddIsVarEssential</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>id</b>, <i></i>
+  int  <b>phase</b> <i></i>
+)
+</pre>
+<dd> Determines whether a given variable is essential with a given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1 and f-->x_id, or if phase == 0 and f-->x_id'.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_FindEssential">Cudd_FindEssential</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarHardGroup"><b>Cudd_bddIsVarHardGroup</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is set to be in a hard group. This function is used for lazy sifting. Returns 1 if the variable is marked to be in a hard group; 0 if the variable exists, but it is not marked to be in a hard group; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarHardGroup">Cudd_bddSetVarHardGroup</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarToBeGrouped"><b>Cudd_bddIsVarToBeGrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is set to be grouped. This function is used for lazy sifting.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIsVarToBeUngrouped"><b>Cudd_bddIsVarToBeUngrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Checks whether a variable is set to be ungrouped. This function is used for lazy sifting. Returns 1 if the variable is marked to be ungrouped; 0 if the variable exists, but it is not marked to be ungrouped; -1 if the variable does not exist.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarToBeUngrouped">Cudd_bddSetVarToBeUngrouped</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_bddIsop"><b>Cudd_bddIsop</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>L</b>, <i></i>
+  DdNode * <b>U</b> <i></i>
+)
+</pre>
+<dd> Computes a BDD in the interval between L and U with a simple sum-of-produuct cover. This procedure is similar to Cudd_zddIsop, but it does not return the ZDD for the cover. Returns a pointer to the BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddIsop">Cudd_zddIsop</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIteConstant"><b>Cudd_bddIteConstant</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITEconstant(f,g,h). Returns a pointer to the resulting BDD (which may or may not be constant) or DD_NON_CONSTANT. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_bddIntersect">Cudd_bddIntersect</a>
+<a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_addIteConstant">Cudd_addIteConstant</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIterConjDecomp"><b>Cudd_bddIterConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the array of conjuncts</i>
+)
+</pre>
+<dd> Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the iterated use of supersetting to obtain a factor of the given function. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_RemapOverApprox">Cudd_RemapOverApprox</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddIterDisjDecomp"><b>Cudd_bddIterDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be imbalanced.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIte"><b>Cudd_bddIte</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Implements ITE(f,g,h). Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addIte">Cudd_addIte</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+<a href="cuddAllDet.html#Cudd_bddIntersect">Cudd_bddIntersect</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddIthVar"><b>Cudd_bddIthVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Retrieves the BDD variable with index i if it already exists, or creates a new BDD variable. Returns a pointer to the variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+<a href="cuddAllDet.html#Cudd_ReadVars">Cudd_ReadVars</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddLICompaction"><b>Cudd_bddLICompaction</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be minimized</i>
+  DdNode * <b>c</b> <i>constraint (care set)</i>
+)
+</pre>
+<dd> Performs safe minimization of a BDD. Given the BDD <code>f</code> of a function to be minimized and a BDD <code>c</code> representing the care set, Cudd_bddLICompaction produces the BDD of a function that agrees with <code>f</code> wherever <code>c</code> is 1. Safe minimization means that the size of the result is guaranteed not to exceed the size of <code>f</code>. This function is based on the DAC97 paper by Hong et al.. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddLeqUnless"><b>Cudd_bddLeqUnless</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>D</b> <i></i>
+)
+</pre>
+<dd> Tells whether f is less than of equal to G unless D is 1. f, g, and D are BDDs. The function returns 1 if f is less than of equal to G, and 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_EquivDC">Cudd_EquivDC</a>
+<a href="cuddAllDet.html#Cudd_bddLeq">Cudd_bddLeq</a>
+<a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddLeq"><b>Cudd_bddLeq</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIteConstant">Cudd_bddIteConstant</a>
+<a href="cuddAllDet.html#Cudd_addEvalConst">Cudd_addEvalConst</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddLiteralSetIntersection"><b>Cudd_bddLiteralSetIntersection</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the intesection of two sets of literals represented as BDDs. Each set is represented as a cube of the literals in the set. The empty set is represented by the constant 1. No variable can be simultaneously present in both phases in a set. Returns a pointer to the BDD representing the intersected sets, if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddMakePrime"><b>Cudd_bddMakePrime</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>cube</b>, <i>cube to be expanded</i>
+  DdNode * <b>f</b> <i>function of which the cube is to be made a prime</i>
+)
+</pre>
+<dd> Expands cube to a prime implicant of f. Returns the prime if successful; NULL otherwise. In particular, NULL is returned if cube is not a real cube or is not an implicant of f.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddMinimize"><b>Cudd_bddMinimize</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> Finds a small BDD that agrees with <code>f</code> over <code>c</code>. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+<a href="cuddAllDet.html#Cudd_bddSqueeze">Cudd_bddSqueeze</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNPAnd"><b>Cudd_bddNPAnd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes f non-polluting-and g. The non-polluting AND of f and g is a hybrid of AND and Restrict. From Restrict, this operation takes the idea of existentially quantifying the top variable of the second operand if it does not appear in the first. Therefore, the variables that appear in the result also appear in f. For the rest, the function behaves like AND. Since the two operands play different roles, non-polluting AND is not commutative. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNand"><b>Cudd_bddNand</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the NAND of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNewVarAtLevel"><b>Cudd_bddNewVarAtLevel</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>level</b> <i></i>
+)
+</pre>
+<dd> Creates a new BDD variable. The new variable has an index equal to the largest previous index plus 1 and is positioned at the specified level in the order. Returns a pointer to the new variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_addNewVarAtLevel">Cudd_addNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNewVar"><b>Cudd_bddNewVar</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Creates a new BDD variable. The new variable has an index equal to the largest previous index plus 1. Returns a pointer to the new variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addNewVar">Cudd_addNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddNor"><b>Cudd_bddNor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the NOR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddOr"><b>Cudd_bddOr</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the disjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddPermute"><b>Cudd_bddPermute</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int * <b>permut</b> <i></i>
+)
+</pre>
+<dd> Given a permutation in array permut, creates a new BDD with permuted variables. There should be an entry in array permut for each variable in the manager. The i-th entry of permut holds the index of the variable that is to substitute the i-th variable. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addPermute">Cudd_addPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode ** <i></i>
+<a name="Cudd_bddPickArbitraryMinterms"><b>Cudd_bddPickArbitraryMinterms</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function from which to pick k minterms</i>
+  DdNode ** <b>vars</b>, <i>array of variables</i>
+  int  <b>n</b>, <i>size of <code>vars</code></i>
+  int  <b>k</b> <i>number of minterms to find</i>
+)
+</pre>
+<dd> Picks k on-set minterms evenly distributed from given DD. The minterms are in terms of <code>vars</code>. The array <code>vars</code> should contain at least all variables in the support of <code>f</code>; if this condition is not met the minterms built by this procedure may not be contained in <code>f</code>. Builds an array of BDDs for the minterms and returns a pointer to it if successful; NULL otherwise. There are three reasons why the procedure may fail: <ul> <li> It may run out of memory; <li> the function <code>f</code> may be the constant 0; <li> the minterms may not be contained in <code>f</code>. </ul>
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPickOneMinterm">Cudd_bddPickOneMinterm</a>
+<a href="cuddAllDet.html#Cudd_bddPickOneCube">Cudd_bddPickOneCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddPickOneCube"><b>Cudd_bddPickOneCube</b></a>(
+  DdManager * <b>ddm</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  char * <b>string</b> <i></i>
+)
+</pre>
+<dd> Picks one on-set cube randomly from the given DD. The cube is written into an array of characters. The array must have at least as many entries as there are variables. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPickOneMinterm">Cudd_bddPickOneMinterm</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddPickOneMinterm"><b>Cudd_bddPickOneMinterm</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function from which to pick one minterm</i>
+  DdNode ** <b>vars</b>, <i>array of variables</i>
+  int  <b>n</b> <i>size of <code>vars</code></i>
+)
+</pre>
+<dd> Picks one on-set minterm randomly from the given DD. The minterm is in terms of <code>vars</code>. The array <code>vars</code> should contain at least all variables in the support of <code>f</code>; if this condition is not met the minterm built by this procedure may not be contained in <code>f</code>. Builds a BDD for the minterm and returns a pointer to it if successful; NULL otherwise. There are three reasons why the procedure may fail: <ul> <li> It may run out of memory; <li> the function <code>f</code> may be the constant 0; <li> the minterm may not be contained in <code>f</code>. </ul>
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPickOneCube">Cudd_bddPickOneCube</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddPrintCover"><b>Cudd_bddPrintCover</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>l</b>, <i></i>
+  DdNode * <b>u</b> <i></i>
+)
+</pre>
+<dd> Prints a sum of product cover for an incompletely specified function given by a lower bound and an upper bound. Each product is a prime implicant obtained by expanding the product corresponding to a path from node to the constant one. Uses the package default output file. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_PrintMinterm">Cudd_PrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddReadPairIndex"><b>Cudd_bddReadPairIndex</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Reads a corresponding pair index for a given index. These pair indices are present and next state variable. Returns the corresponding variable index if the variable exists; -1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPairIndex">Cudd_bddSetPairIndex</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddRead"><b>Cudd_bddRead</b></a>(
+  FILE * <b>fp</b>, <i>input file pointer</i>
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  DdNode ** <b>E</b>, <i>characteristic function of the graph</i>
+  DdNode *** <b>x</b>, <i>array of row variables</i>
+  DdNode *** <b>y</b>, <i>array of column variables</i>
+  int * <b>nx</b>, <i>number or row variables</i>
+  int * <b>ny</b>, <i>number or column variables</i>
+  int * <b>m</b>, <i>number of rows</i>
+  int * <b>n</b>, <i>number of columns</i>
+  int  <b>bx</b>, <i>first index of row variables</i>
+  int  <b>sx</b>, <i>step of row variables</i>
+  int  <b>by</b>, <i>first index of column variables</i>
+  int  <b>sy</b> <i>step of column variables</i>
+)
+</pre>
+<dd> Reads in a graph (without labels) given as an adjacency matrix. The first line of the input contains the numbers of rows and columns of the adjacency matrix. The remaining lines contain the arcs of the graph, one per line. Each arc is described by two integers, i.e., the row and column number, or the indices of the two endpoints. Cudd_bddRead produces a BDD that depends on two sets of variables: x and y. The x variables (x[0] ... x[nx-1]) encode the row index and the y variables (y[0] ... y[ny-1]) encode the column index. x[0] and y[0] are the most significant bits in the indices. The variables may already exist or may be created by the function. The index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy.<p> On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. When Cudd_bddRead creates the variable arrays, the index of x[i] is bx+i*sx, and the index of y[i] is by+i*sy. When some variables already exist, Cudd_bddRead expects the indices of the existing x variables to be bx+i*sx, and the indices of the existing y variables to be by+i*sy.<p> m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. The BDD for the graph is returned in E, and its reference count is > 0. Cudd_bddRead returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> nx and ny are set to the numbers of row and column variables. m and n are set to the numbers of rows and columns. x and y are possibly extended to represent the array of row and column variables.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_addHarwell">Cudd_addHarwell</a>
+<a href="cuddAllDet.html#Cudd_addRead">Cudd_addRead</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_bddRealignDisable"><b>Cudd_bddRealignDisable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables realignment of ZDD order to BDD order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_bddRealignEnable"><b>Cudd_bddRealignEnable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Enables realignment of the BDD variable order to the ZDD variable order after the ZDDs have been reordered. The number of ZDD variables must be a multiple of the number of BDD variables for realignment to make sense. If this condition is not met, Cudd_zddReduceHeap will return 0. Let <code>M</code> be the ratio of the two numbers. For the purpose of realignment, the ZDD variables from <code>M*i</code> to <code>(M+1)*i-1</code> are reagarded as corresponding to BDD variable <code>i</code>. Realignment is initially disabled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddReduceHeap">Cudd_zddReduceHeap</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddRealignmentEnabled"><b>Cudd_bddRealignmentEnabled</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the realignment of BDD order to ZDD order is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddResetVarToBeGrouped"><b>Cudd_bddResetVarToBeGrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Resets a variable not to be grouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarToBeGrouped">Cudd_bddSetVarToBeGrouped</a>
+<a href="cuddAllDet.html#Cudd_bddSetVarHardGroup">Cudd_bddSetVarHardGroup</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddRestrict"><b>Cudd_bddRestrict</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>c</b> <i></i>
+)
+</pre>
+<dd> BDD restrict according to Coudert and Madre's algorithm (ICCAD90). Returns the restricted BDD if successful; otherwise NULL. If application of restrict results in a BDD larger than the input BDD, the input BDD is returned.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddConstrain">Cudd_bddConstrain</a>
+<a href="cuddAllDet.html#Cudd_addRestrict">Cudd_addRestrict</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetNsVar"><b>Cudd_bddSetNsVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Sets a variable type to next state. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPiVar">Cudd_bddSetPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddSetPsVar">Cudd_bddSetPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsNsVar">Cudd_bddIsNsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetPairIndex"><b>Cudd_bddSetPairIndex</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b>, <i>variable index</i>
+  int  <b>pairIndex</b> <i>corresponding variable index</i>
+)
+</pre>
+<dd> Sets a corresponding pair index for a given index. These pair indices are present and next state variable. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddReadPairIndex">Cudd_bddReadPairIndex</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetPiVar"><b>Cudd_bddSetPiVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Sets a variable type to primary input. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPsVar">Cudd_bddSetPsVar</a>
+<a href="cuddAllDet.html#Cudd_bddSetNsVar">Cudd_bddSetNsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPiVar">Cudd_bddIsPiVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetPsVar"><b>Cudd_bddSetPsVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> Sets a variable type to present state. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetPiVar">Cudd_bddSetPiVar</a>
+<a href="cuddAllDet.html#Cudd_bddSetNsVar">Cudd_bddSetNsVar</a>
+<a href="cuddAllDet.html#Cudd_bddIsPsVar">Cudd_bddIsPsVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetVarHardGroup"><b>Cudd_bddSetVarHardGroup</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Sets a variable to be a hard group. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarToBeGrouped">Cudd_bddSetVarToBeGrouped</a>
+<a href="cuddAllDet.html#Cudd_bddResetVarToBeGrouped">Cudd_bddResetVarToBeGrouped</a>
+<a href="cuddAllDet.html#Cudd_bddIsVarHardGroup">Cudd_bddIsVarHardGroup</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetVarToBeGrouped"><b>Cudd_bddSetVarToBeGrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Sets a variable to be grouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddSetVarHardGroup">Cudd_bddSetVarHardGroup</a>
+<a href="cuddAllDet.html#Cudd_bddResetVarToBeGrouped">Cudd_bddResetVarToBeGrouped</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddSetVarToBeUngrouped"><b>Cudd_bddSetVarToBeUngrouped</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>index</b> <i></i>
+)
+</pre>
+<dd> Sets a variable to be ungrouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> modifies the manager
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIsVarToBeUngrouped">Cudd_bddIsVarToBeUngrouped</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddSqueeze"><b>Cudd_bddSqueeze</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>l</b>, <i>lower bound</i>
+  DdNode * <b>u</b> <i>upper bound</i>
+)
+</pre>
+<dd> Finds a small BDD in a function interval. Given BDDs <code>l</code> and <code>u</code>, representing the lower bound and upper bound of a function interval, Cudd_bddSqueeze produces the BDD of a function within the interval with a small BDD. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddRestrict">Cudd_bddRestrict</a>
+<a href="cuddAllDet.html#Cudd_bddLICompaction">Cudd_bddLICompaction</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddSwapVariables"><b>Cudd_bddSwapVariables</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>x</b>, <i></i>
+  DdNode ** <b>y</b>, <i></i>
+  int  <b>n</b> <i></i>
+)
+</pre>
+<dd> Swaps two sets of variables of the same size (x and y) in the BDD f. The size is given by n. The two sets of variables are assumed to be disjoint. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_addSwapVariables">Cudd_addSwapVariables</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddTransfer"><b>Cudd_bddTransfer</b></a>(
+  DdManager * <b>ddSource</b>, <i></i>
+  DdManager * <b>ddDestination</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Convert a BDD from a manager to another one. The orders of the variables in the two managers may be different. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddUnbindVar"><b>Cudd_bddUnbindVar</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> This function resets the flag that prevents the sifting of a variable. In successive variable reorderings, the variable will NOT be skipped, that is, sifted. Initially all variables can be sifted. It is necessary to call this function only to re-enable sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0 otherwise (i.e., invalid variable index).
+<p>
+
+<dd> <b>Side Effects</b> Changes the "bindVar" flag in DdSubtable.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddBindVar">Cudd_bddBindVar</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddUnivAbstract"><b>Cudd_bddUnivAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Universally abstracts all the variables in cube from f. Returns the abstracted BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_addUnivAbstract">Cudd_addUnivAbstract</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarConjDecomp"><b>Cudd_bddVarConjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>conjuncts</b> <i>address of the array of conjuncts</i>
+)
+</pre>
+<dd> Conjunctively decomposes one BDD according to a variable. If <code>f</code> is the function of the BDD and <code>x</code> is the variable, the decomposition is <code>(f+x)(f+x')</code>. The variable is chosen so as to balance the sizes of the two conjuncts and to keep them small. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The two factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddVarDisjDecomp">Cudd_bddVarDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenConjDecomp">Cudd_bddGenConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxConjDecomp">Cudd_bddApproxConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterConjDecomp">Cudd_bddIterConjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarDisjDecomp"><b>Cudd_bddVarDisjDecomp</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  DdNode * <b>f</b>, <i>function to be decomposed</i>
+  DdNode *** <b>disjuncts</b> <i>address of the array of the disjuncts</i>
+)
+</pre>
+<dd> Performs two-way disjunctive decomposition of a BDD according to a variable. If <code>f</code> is the function of the BDD and <code>x</code> is the variable, the decomposition is <code>f*x + f*x'</code>. The variable is chosen so as to balance the sizes of the two disjuncts and to keep them small. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddVarConjDecomp">Cudd_bddVarConjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddApproxDisjDecomp">Cudd_bddApproxDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddIterDisjDecomp">Cudd_bddIterDisjDecomp</a>
+<a href="cuddAllDet.html#Cudd_bddGenDisjDecomp">Cudd_bddGenDisjDecomp</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarIsBound"><b>Cudd_bddVarIsBound</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>index</b> <i>variable index</i>
+)
+</pre>
+<dd> This function returns 1 if a variable is enabled for sifting. Initially all variables can be sifted. This function returns 0 only if there has been a previous call to Cudd_bddBindVar for that variable not followed by a call to Cudd_bddUnbindVar. The function returns 0 also in the case in which the index of the variable is out of bounds.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddBindVar">Cudd_bddBindVar</a>
+<a href="cuddAllDet.html#Cudd_bddUnbindVar">Cudd_bddUnbindVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_bddVarIsDependent"><b>Cudd_bddVarIsDependent</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>var</b> <i>variable</i>
+)
+</pre>
+<dd> Checks whether a variable is dependent on others in a function. Returns 1 if the variable is dependent; 0 otherwise. No new nodes are created.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddVarMap"><b>Cudd_bddVarMap</b></a>(
+  DdManager * <b>manager</b>, <i>DD manager</i>
+  DdNode * <b>f</b> <i>function in which to remap variables</i>
+)
+</pre>
+<dd> Remaps the variables of a BDD using the default variable map. A typical use of this function is to swap two sets of variables. The variable map must be registered with Cudd_SetVarMap. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddSwapVariables">Cudd_bddSwapVariables</a>
+<a href="cuddAllDet.html#Cudd_SetVarMap">Cudd_SetVarMap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddVectorCompose"><b>Cudd_bddVectorCompose</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode ** <b>vector</b> <i></i>
+)
+</pre>
+<dd> Given a vector of BDDs, creates a new BDD by substituting the BDDs for the variables of the BDD f. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting BDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddPermute">Cudd_bddPermute</a>
+<a href="cuddAllDet.html#Cudd_bddCompose">Cudd_bddCompose</a>
+<a href="cuddAllDet.html#Cudd_addVectorCompose">Cudd_addVectorCompose</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddXnor"><b>Cudd_bddXnor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the exclusive NOR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXor">Cudd_bddXor</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddXorExistAbstract"><b>Cudd_bddXorExistAbstract</b></a>(
+  DdManager * <b>manager</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>cube</b> <i></i>
+)
+</pre>
+<dd> Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddUnivAbstract">Cudd_bddUnivAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddExistAbstract">Cudd_bddExistAbstract</a>
+<a href="cuddAllDet.html#Cudd_bddAndAbstract">Cudd_bddAndAbstract</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_bddXor"><b>Cudd_bddXor</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the exclusive OR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIte">Cudd_bddIte</a>
+<a href="cuddAllDet.html#Cudd_addApply">Cudd_addApply</a>
+<a href="cuddAllDet.html#Cudd_bddAnd">Cudd_bddAnd</a>
+<a href="cuddAllDet.html#Cudd_bddOr">Cudd_bddOr</a>
+<a href="cuddAllDet.html#Cudd_bddNand">Cudd_bddNand</a>
+<a href="cuddAllDet.html#Cudd_bddNor">Cudd_bddNor</a>
+<a href="cuddAllDet.html#Cudd_bddXnor">Cudd_bddXnor</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_tlcInfoFree"><b>Cudd_tlcInfoFree</b></a>(
+  DdTlcInfo * <b>t</b> <i></i>
+)
+</pre>
+<dd> Frees a DdTlcInfo Structure as well as the memory pointed by it.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddChange"><b>Cudd_zddChange</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Substitutes a variable with its complement in a ZDD. returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddComplement"><b>Cudd_zddComplement</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Computes a complement cover for a ZDD node. For lack of a better method, we first extract the function BDD from the ZDD cover, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP. Returns a pointer to the resulting cover if successful; NULL otherwise. The result depends on current variable order.
+<p>
+
+<dd> <b>Side Effects</b> The result depends on current variable order.
+<p>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_zddCountDouble"><b>Cudd_zddCountDouble</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of a ZDD. The result is returned as a double. If the procedure runs out of memory, it returns (double) CUDD_OUT_OF_MEM. This procedure is used in Cudd_zddCountMinterm.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddCountMinterm">Cudd_zddCountMinterm</a>
+<a href="cuddAllDet.html#Cudd_zddCount">Cudd_zddCount</a>
+</code>
+
+<dt><pre>
+double <i></i>
+<a name="Cudd_zddCountMinterm"><b>Cudd_zddCountMinterm</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>node</b>, <i></i>
+  int  <b>path</b> <i></i>
+)
+</pre>
+<dd> Counts the number of minterms of the ZDD rooted at <code>node</code>. This procedure takes a parameter <code>path</code> that specifies how many variables are in the support of the function. If the procedure runs out of memory, it returns (double) CUDD_OUT_OF_MEM.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddCountDouble">Cudd_zddCountDouble</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddCount"><b>Cudd_zddCount</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b> <i></i>
+)
+</pre>
+<dd> Returns an integer representing the number of minterms in a ZDD.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddCountDouble">Cudd_zddCountDouble</a>
+</code>
+
+<dt><pre>
+char * <i></i>
+<a name="Cudd_zddCoverPathToString"><b>Cudd_zddCoverPathToString</b></a>(
+  DdManager * <b>zdd</b>, <i>DD manager</i>
+  int * <b>path</b>, <i>path of ZDD representing a cover</i>
+  char * <b>str</b> <i>pointer to string to use if != NULL</i>
+)
+</pre>
+<dd> Converts a path of a ZDD representing a cover to a string. The string represents an implicant of the cover. The path is typically produced by Cudd_zddForeachPath. Returns a pointer to the string if successful; NULL otherwise. If the str input is NULL, it allocates a new string. The string passed to this function must have enough room for all variables and for the terminator.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddForeachPath">Cudd_zddForeachPath</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddDagSize"><b>Cudd_zddDagSize</b></a>(
+  DdNode * <b>p_node</b> <i></i>
+)
+</pre>
+<dd> Counts the number of nodes in a ZDD. This function duplicates Cudd_DagSize and is only retained for compatibility.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DagSize">Cudd_DagSize</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddDiffConst"><b>Cudd_zddDiffConst</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Inclusion test for ZDDs (P implies Q). No new nodes are generated by this procedure. Returns empty if true; a valid pointer different from empty or DD_NON_CONSTANT otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDiff">Cudd_zddDiff</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddDiff"><b>Cudd_zddDiff</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Computes the difference of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDiffConst">Cudd_zddDiffConst</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddDivideF"><b>Cudd_zddDivideF</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Modified version of Cudd_zddDivide. This function may disappear in future releases.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddDivide"><b>Cudd_zddDivide</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the quotient of two unate covers represented by ZDDs. Unate covers use one ZDD variable for each BDD variable. Returns a pointer to the resulting ZDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddWeakDiv">Cudd_zddWeakDiv</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddDumpDot"><b>Cudd_zddDumpDot</b></a>(
+  DdManager * <b>dd</b>, <i>manager</i>
+  int  <b>n</b>, <i>number of output nodes to be dumped</i>
+  DdNode ** <b>f</b>, <i>array of output nodes to be dumped</i>
+  char ** <b>inames</b>, <i>array of input names (or NULL)</i>
+  char ** <b>onames</b>, <i>array of output names (or NULL)</i>
+  FILE * <b>fp</b> <i>pointer to the dump file</i>
+)
+</pre>
+<dd> Writes a file representing the argument ZDDs in a format suitable for the graph drawing program dot. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full). Cudd_zddDumpDot does not close the file: This is the caller responsibility. Cudd_zddDumpDot uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. Cudd_zddDumpDot uses the following convention to draw arcs: <ul> <li> solid line: THEN arcs; <li> dashed line: ELSE arcs. </ul> The dot options are chosen so that the drawing fits on a letter-size sheet.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_DumpDot">Cudd_DumpDot</a>
+<a href="cuddAllDet.html#Cudd_zddPrintDebug">Cudd_zddPrintDebug</a>
+</code>
+
+<dt><pre>
+DdGen * <i></i>
+<a name="Cudd_zddFirstPath"><b>Cudd_zddFirstPath</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int ** <b>path</b> <i></i>
+)
+</pre>
+<dd> Defines an iterator on the paths of a ZDD and finds its first path. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.<p> A path is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc out of a node, and 2 stands for the absence of a node. The size of the array equals the number of variables in the manager at the time Cudd_zddFirstCube is called.<p> The paths that end in the empty terminal are not enumerated.
+<p>
+
+<dd> <b>Side Effects</b> The first path is returned as a side effect.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddForeachPath">Cudd_zddForeachPath</a>
+<a href="cuddAllDet.html#Cudd_zddNextPath">Cudd_zddNextPath</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+ <i></i>
+<a name="Cudd_zddForeachPath"><b>Cudd_zddForeachPath</b></a>(
+   <b>manager</b>, <i></i>
+   <b>f</b>, <i></i>
+   <b>gen</b>, <i></i>
+   <b>path</b> <i></i>
+)
+</pre>
+<dd> Iterates over the paths of a ZDD f. <ul> <li> DdManager *manager; <li> DdNode *f; <li> DdGen *gen; <li> int *path; </ul> Cudd_zddForeachPath allocates and frees the generator. Therefore the application should not try to do that. Also, the path is freed at the end of Cudd_zddForeachPath and hence is not available outside of the loop.<p> CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.
+<p>
+
+<dd> <b>Side Effects</b> none
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddFirstPath">Cudd_zddFirstPath</a>
+<a href="cuddAllDet.html#Cudd_zddNextPath">Cudd_zddNextPath</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+<a href="cuddAllDet.html#Cudd_AutodynDisable">Cudd_AutodynDisable</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddIntersect"><b>Cudd_zddIntersect</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Computes the intersection of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddIsop"><b>Cudd_zddIsop</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>L</b>, <i></i>
+  DdNode * <b>U</b>, <i></i>
+  DdNode ** <b>zdd_I</b> <i></i>
+)
+</pre>
+<dd> Computes an irredundant sum of products (ISOP) in ZDD form from BDDs. The two BDDs L and U represent the lower bound and the upper bound, respectively, of the function. The ISOP uses two ZDD variables for each BDD variable: One for the positive literal, and one for the negative literal. These two variables should be adjacent in the ZDD order. The two ZDD variables corresponding to BDD variable <code>i</code> should have indices <code>2i</code> and <code>2i+1</code>. The result of this procedure depends on the variable order. If successful, Cudd_zddIsop returns the BDD for the function chosen from the interval. The ZDD representing the irredundant cover is returned as a side effect in zdd_I. In case of failure, NULL is returned.
+<p>
+
+<dd> <b>Side Effects</b> zdd_I holds the pointer to the ZDD for the ISOP on successful return.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIsop">Cudd_bddIsop</a>
+<a href="cuddAllDet.html#Cudd_zddVarsFromBddVars">Cudd_zddVarsFromBddVars</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddIte"><b>Cudd_zddIte</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b>, <i></i>
+  DdNode * <b>h</b> <i></i>
+)
+</pre>
+<dd> Computes the ITE of three ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddIthVar"><b>Cudd_zddIthVar</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  int  <b>i</b> <i></i>
+)
+</pre>
+<dd> Retrieves the ZDD variable with index i if it already exists, or creates a new ZDD variable. Returns a pointer to the variable if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_addIthVar">Cudd_addIthVar</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddNextPath"><b>Cudd_zddNextPath</b></a>(
+  DdGen * <b>gen</b>, <i></i>
+  int ** <b>path</b> <i></i>
+)
+</pre>
+<dd> Generates the next path of a ZDD onset, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> The path is returned as a side effect. The generator is modified.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddForeachPath">Cudd_zddForeachPath</a>
+<a href="cuddAllDet.html#Cudd_zddFirstPath">Cudd_zddFirstPath</a>
+<a href="cuddAllDet.html#Cudd_GenFree">Cudd_GenFree</a>
+<a href="cuddAllDet.html#Cudd_IsGenEmpty">Cudd_IsGenEmpty</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddPortFromBdd"><b>Cudd_zddPortFromBdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>B</b> <i></i>
+)
+</pre>
+<dd> Converts a BDD into a ZDD. This function assumes that there is a one-to-one correspondence between the BDD variables and the ZDD variables, and that the variable order is the same for both types of variables. These conditions are established if the ZDD variables are created by one call to Cudd_zddVarsFromBddVars with multiplicity = 1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddVarsFromBddVars">Cudd_zddVarsFromBddVars</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddPortToBdd"><b>Cudd_zddPortToBdd</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b> <i></i>
+)
+</pre>
+<dd> Converts a ZDD into a BDD. Returns a pointer to the resulting ZDD if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddPortFromBdd">Cudd_zddPortFromBdd</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddPrintCover"><b>Cudd_zddPrintCover</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Prints a sum of products from a ZDD representing a cover. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddPrintMinterm">Cudd_zddPrintMinterm</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddPrintDebug"><b>Cudd_zddPrintDebug</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  int  <b>n</b>, <i></i>
+  int  <b>pr</b> <i></i>
+)
+</pre>
+<dd> Prints to the standard output a DD and its statistics. The statistics include the number of nodes and the number of minterms. (The number of minterms is also the number of combinations in the set.) The statistics are printed if pr &gt; 0. Specifically: <ul> <li> pr = 0 : prints nothing <li> pr = 1 : prints counts of nodes and minterms <li> pr = 2 : prints counts + disjoint sum of products <li> pr = 3 : prints counts + list of nodes <li> pr &gt; 3 : prints counts + disjoint sum of products + list of nodes </ul> Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddPrintMinterm"><b>Cudd_zddPrintMinterm</b></a>(
+  DdManager * <b>zdd</b>, <i></i>
+  DdNode * <b>node</b> <i></i>
+)
+</pre>
+<dd> Prints a disjoint sum of product form for a ZDD. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddPrintDebug">Cudd_zddPrintDebug</a>
+<a href="cuddAllDet.html#Cudd_zddPrintCover">Cudd_zddPrintCover</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddPrintSubtable"><b>Cudd_zddPrintSubtable</b></a>(
+  DdManager * <b>table</b> <i></i>
+)
+</pre>
+<dd> Prints the ZDD table for debugging purposes.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddProduct"><b>Cudd_zddProduct</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the product of two covers represented by ZDDs. The result is also a ZDD. Returns a pointer to the result if successful; NULL otherwise. The covers on which Cudd_zddProduct operates use two ZDD variables for each function variable (one ZDD variable for each literal of the variable). Those two ZDD variables should be adjacent in the order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddUnateProduct">Cudd_zddUnateProduct</a>
+</code>
+
+<dt><pre>
+long <i></i>
+<a name="Cudd_zddReadNodeCount"><b>Cudd_zddReadNodeCount</b></a>(
+  DdManager * <b>dd</b> <i></i>
+)
+</pre>
+<dd> Reports the number of nodes in ZDDs. This number always includes the two constants 1 and 0.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReadPeakNodeCount">Cudd_ReadPeakNodeCount</a>
+<a href="cuddAllDet.html#Cudd_ReadNodeCount">Cudd_ReadNodeCount</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddRealignDisable"><b>Cudd_zddRealignDisable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Disables realignment of ZDD order to BDD order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddRealignEnable"><b>Cudd_zddRealignEnable</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Enables realignment of the ZDD variable order to the BDD variable order after the BDDs and ADDs have been reordered. The number of ZDD variables must be a multiple of the number of BDD variables for realignment to make sense. If this condition is not met, Cudd_ReduceHeap will return 0. Let <code>M</code> be the ratio of the two numbers. For the purpose of realignment, the ZDD variables from <code>M*i</code> to <code>(M+1)*i-1</code> are reagarded as corresponding to BDD variable <code>i</code>. Realignment is initially disabled.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_ReduceHeap">Cudd_ReduceHeap</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignmentEnabled">Cudd_zddRealignmentEnabled</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignmentEnabled">Cudd_bddRealignmentEnabled</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddRealignmentEnabled"><b>Cudd_zddRealignmentEnabled</b></a>(
+  DdManager * <b>unique</b> <i></i>
+)
+</pre>
+<dd> Returns 1 if the realignment of ZDD order to BDD order is enabled; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddRealignEnable">Cudd_zddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_zddRealignDisable">Cudd_zddRealignDisable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignEnable">Cudd_bddRealignEnable</a>
+<a href="cuddAllDet.html#Cudd_bddRealignDisable">Cudd_bddRealignDisable</a>
+</code>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddReduceHeap"><b>Cudd_zddReduceHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  Cudd_ReorderingType  <b>heuristic</b>, <i>method used for reordering</i>
+  int  <b>minsize</b> <i>bound below which no reordering occurs</i>
+)
+</pre>
+<dd> Main dynamic reordering routine for ZDDs. Calls one of the possible reordering procedures: <ul> <li>Swapping <li>Sifting <li>Symmetric Sifting </ul> For sifting and symmetric sifting it is possible to request reordering to convergence.<p> The core of all methods is the reordering procedure cuddZddSwapInPlace() which swaps two adjacent variables. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.
+<p>
+
+<dd> <b>Side Effects</b> Changes the variable order for all ZDDs and clears the cache.
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddShuffleHeap"><b>Cudd_zddShuffleHeap</b></a>(
+  DdManager * <b>table</b>, <i>DD manager</i>
+  int * <b>permutation</b> <i>required variable permutation</i>
+)
+</pre>
+<dd> Reorders ZDD variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> Changes the ZDD variable order for all diagrams and clears the cache.
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddReduceHeap">Cudd_zddReduceHeap</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddSubset0"><b>Cudd_zddSubset0</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Computes the negative cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is negated. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddSubset1">Cudd_zddSubset1</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddSubset1"><b>Cudd_zddSubset1</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  int  <b>var</b> <i></i>
+)
+</pre>
+<dd> Computes the positive cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is asserted. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddSubset0">Cudd_zddSubset0</a>
+</code>
+
+<dt><pre>
+void <i></i>
+<a name="Cudd_zddSymmProfile"><b>Cudd_zddSymmProfile</b></a>(
+  DdManager * <b>table</b>, <i></i>
+  int  <b>lower</b>, <i></i>
+  int  <b>upper</b> <i></i>
+)
+</pre>
+<dd> Prints statistics on symmetric ZDD variables.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddUnateProduct"><b>Cudd_zddUnateProduct</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Computes the product of two unate covers represented as ZDDs. Unate covers use one ZDD variable for each BDD variable. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddProduct">Cudd_zddProduct</a>
+</code>
+
+<dt><pre>
+DdNode * <i></i>
+<a name="Cudd_zddUnion"><b>Cudd_zddUnion</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>P</b>, <i></i>
+  DdNode * <b>Q</b> <i></i>
+)
+</pre>
+<dd> Computes the union of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dt><pre>
+int <i></i>
+<a name="Cudd_zddVarsFromBddVars"><b>Cudd_zddVarsFromBddVars</b></a>(
+  DdManager * <b>dd</b>, <i>DD manager</i>
+  int  <b>multiplicity</b> <i>how many ZDD variables are created for each BDD variable</i>
+)
+</pre>
+<dd> Creates one or more ZDD variables for each BDD variable. If some ZDD variables already exist, only the missing variables are created. Parameter multiplicity allows the caller to control how many variables are created for each BDD variable in existence. For instance, if ZDDs are used to represent covers, two ZDD variables are required for each BDD variable. The order of the BDD variables is transferred to the ZDD variables. If a variable group tree exists for the BDD variables, a corresponding ZDD variable group tree is created by expanding the BDD variable tree. In any case, the ZDD variables derived from the same BDD variable are merged in a ZDD variable group. If a ZDD variable group tree exists, it is freed. Returns 1 if successful; 0 otherwise.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_bddNewVar">Cudd_bddNewVar</a>
+<a href="cuddAllDet.html#Cudd_bddIthVar">Cudd_bddIthVar</a>
+<a href="cuddAllDet.html#Cudd_bddNewVarAtLevel">Cudd_bddNewVarAtLevel</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddWeakDivF"><b>Cudd_zddWeakDivF</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Modified version of Cudd_zddWeakDiv. This function may disappear in future releases.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddWeakDiv">Cudd_zddWeakDiv</a>
+</code>
+
+<dt><pre>
+DdNode	* <i></i>
+<a name="Cudd_zddWeakDiv"><b>Cudd_zddWeakDiv</b></a>(
+  DdManager * <b>dd</b>, <i></i>
+  DdNode * <b>f</b>, <i></i>
+  DdNode * <b>g</b> <i></i>
+)
+</pre>
+<dd> Applies weak division to two ZDDs representing two covers. Returns a pointer to the ZDD representing the result if successful; NULL otherwise. The result of weak division depends on the variable order. The covers on which Cudd_zddWeakDiv operates use two ZDD variables for each function variable (one ZDD variable for each literal of the variable). Those two ZDD variables should be adjacent in the order.
+<p>
+
+<dd> <b>Side Effects</b> None
+<p>
+
+<dd> <b>See Also</b> <code><a href="cuddAllDet.html#Cudd_zddDivide">Cudd_zddDivide</a>
+</code>
+
+
+</dl>
+
+<hr>
+
+Generated automatically by <code>extdoc</code> on 20050517
+
+</body></html>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/cuddIntro.css
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/cuddIntro.css	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/cuddIntro.css	(revision 8)
@@ -0,0 +1,30 @@
+/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */
+.MATH    { font-family: "Century Schoolbook", serif; }
+.MATH I  { font-family: "Century Schoolbook", serif; font-shape: italic }
+.BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold }
+
+/* implement both fixed-size and relative sizes */
+SMALL.XTINY		{ font-size : xx-small }
+SMALL.TINY		{ font-size : x-small  }
+SMALL.SCRIPTSIZE	{ font-size : smaller  }
+SMALL.FOOTNOTESIZE	{ font-size : small    }
+SMALL.SMALL		{  }
+BIG.LARGE		{  }
+BIG.XLARGE		{ font-size : large    }
+BIG.XXLARGE		{ font-size : x-large  }
+BIG.HUGE		{ font-size : larger   }
+BIG.XHUGE		{ font-size : xx-large }
+
+/* heading styles */
+H1		{  }
+H2		{  }
+H3		{  }
+H4		{  }
+H5		{  }
+
+/* mathematics styles */
+DIV.displaymath		{ }	/* math displays */
+TD.eqno			{ }	/* equation-number cells */
+
+
+/* document-specific styles come next */
Index: /vis_dev/glu-2.1/src/cuBdd/doc/cuddIntro.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/cuddIntro.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/cuddIntro.html	(revision 8)
@@ -0,0 +1,224 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>CUDD: CU Decision Diagram Package
+Release 2.4.1</TITLE>
+<META NAME="description" CONTENT="CUDD: CU Decision Diagram Package
+Release 2.4.1">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node1.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html175"
+  HREF="node1.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up_g.png"> 
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev_g.png">  
+<A NAME="tex2html173"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html176"
+  HREF="node1.html">Introduction</A>
+ &nbsp <B>  <A NAME="tex2html174"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+
+<H1 ALIGN="CENTER">CUDD: CU Decision Diagram Package
+<BR>
+Release 2.4.1</H1>
+<P ALIGN="CENTER"><STRONG>Fabio Somenzi
+<BR>
+Department of Electrical and Computer Engineering
+<BR>
+University of Colorado at Boulder
+<BR><IMG
+ WIDTH="20" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img1.png"
+ ALT="$&lt;$">Fabio@Colorado.EDU<IMG
+ WIDTH="20" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img2.png"
+ ALT="$&gt;$"></STRONG></P>
+
+<P>
+<BR><HR>
+<!--Table of Child-Links-->
+<A NAME="CHILD_LINKS"></A>
+
+<UL>
+<LI><A NAME="tex2html177"
+  HREF="node1.html">Introduction</A>
+<LI><A NAME="tex2html178"
+  HREF="node2.html">How to Get CUDD</A>
+<UL>
+<LI><A NAME="tex2html179"
+  HREF="node2.html#SECTION00021000000000000000">The CUDD Package</A>
+<LI><A NAME="tex2html180"
+  HREF="node2.html#SECTION00022000000000000000">CUDD Friends</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html181"
+  HREF="node3.html">User's Manual</A>
+<UL>
+<LI><A NAME="tex2html182"
+  HREF="node3.html#SECTION00031000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html183"
+  HREF="node3.html#SECTION00032000000000000000">Basic Data Structures</A>
+<UL>
+<LI><A NAME="tex2html184"
+  HREF="node3.html#SECTION00032100000000000000">Nodes</A>
+<LI><A NAME="tex2html185"
+  HREF="node3.html#SECTION00032200000000000000">The Manager</A>
+<LI><A NAME="tex2html186"
+  HREF="node3.html#SECTION00032300000000000000">Cache</A>
+</UL>
+<LI><A NAME="tex2html187"
+  HREF="node3.html#SECTION00033000000000000000">Initializing and Shutting Down a DdManager</A>
+<LI><A NAME="tex2html188"
+  HREF="node3.html#SECTION00034000000000000000">Setting Parameters</A>
+<LI><A NAME="tex2html189"
+  HREF="node3.html#SECTION00035000000000000000">Constant Functions</A>
+<UL>
+<LI><A NAME="tex2html190"
+  HREF="node3.html#SECTION00035100000000000000">One, Logic Zero, and Arithmetic Zero</A>
+<LI><A NAME="tex2html191"
+  HREF="node3.html#SECTION00035200000000000000">Predefined Constants</A>
+<LI><A NAME="tex2html192"
+  HREF="node3.html#SECTION00035300000000000000">Background</A>
+<LI><A NAME="tex2html193"
+  HREF="node3.html#SECTION00035400000000000000">New Constants</A>
+</UL>
+<LI><A NAME="tex2html194"
+  HREF="node3.html#SECTION00036000000000000000">Creating Variables</A>
+<UL>
+<LI><A NAME="tex2html195"
+  HREF="node3.html#SECTION00036100000000000000">New BDD and ADD Variables</A>
+<LI><A NAME="tex2html196"
+  HREF="node3.html#SECTION00036200000000000000">New ZDD Variables</A>
+</UL>
+<LI><A NAME="tex2html197"
+  HREF="node3.html#SECTION00037000000000000000">Basic BDD Manipulation</A>
+<LI><A NAME="tex2html198"
+  HREF="node3.html#SECTION00038000000000000000">Basic ADD Manipulation</A>
+<LI><A NAME="tex2html199"
+  HREF="node3.html#SECTION00039000000000000000">Basic ZDD Manipulation</A>
+<LI><A NAME="tex2html200"
+  HREF="node3.html#SECTION000310000000000000000">Converting ADDs to BDDs and Vice Versa</A>
+<LI><A NAME="tex2html201"
+  HREF="node3.html#SECTION000311000000000000000">Converting BDDs to ZDDs and Vice Versa</A>
+<LI><A NAME="tex2html202"
+  HREF="node3.html#SECTION000312000000000000000">Variable Reordering for BDDs and ADDs</A>
+<LI><A NAME="tex2html203"
+  HREF="node3.html#SECTION000313000000000000000">Grouping Variables</A>
+<LI><A NAME="tex2html204"
+  HREF="node3.html#SECTION000314000000000000000">Variable Reordering for ZDDs</A>
+<LI><A NAME="tex2html205"
+  HREF="node3.html#SECTION000315000000000000000">Keeping Consistent Variable Orders for BDDs and ZDDs</A>
+<LI><A NAME="tex2html206"
+  HREF="node3.html#SECTION000316000000000000000">Hooks</A>
+<LI><A NAME="tex2html207"
+  HREF="node3.html#SECTION000317000000000000000">The SIS/VIS Interface</A>
+<UL>
+<LI><A NAME="tex2html208"
+  HREF="node3.html#SECTION000317100000000000000">Using the CUDD Package in SIS</A>
+</UL>
+<LI><A NAME="tex2html209"
+  HREF="node3.html#SECTION000318000000000000000">Writing Decision Diagrams to a File</A>
+<LI><A NAME="tex2html210"
+  HREF="node3.html#SECTION000319000000000000000">Saving and Restoring BDDs</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html211"
+  HREF="node4.html">Programmer's Manual</A>
+<UL>
+<LI><A NAME="tex2html212"
+  HREF="node4.html#SECTION00041000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html213"
+  HREF="node4.html#SECTION00042000000000000000">Reference Counts</A>
+<UL>
+<LI><A NAME="tex2html214"
+  HREF="node4.html#SECTION00042100000000000000">NULL Return Values</A>
+<LI><A NAME="tex2html215"
+  HREF="node4.html#SECTION00042200000000000000"><EM>Cudd_RecursiveDeref</EM> vs. <EM>Cudd_Deref</EM></A>
+<LI><A NAME="tex2html216"
+  HREF="node4.html#SECTION00042300000000000000">When Increasing the Reference Count is Unnecessary</A>
+<LI><A NAME="tex2html217"
+  HREF="node4.html#SECTION00042400000000000000">Saturating Increments and Decrements</A>
+</UL>
+<LI><A NAME="tex2html218"
+  HREF="node4.html#SECTION00043000000000000000">Complement Arcs</A>
+<LI><A NAME="tex2html219"
+  HREF="node4.html#SECTION00044000000000000000">The Cache</A>
+<UL>
+<LI><A NAME="tex2html220"
+  HREF="node4.html#SECTION00044100000000000000">Cache Sizing</A>
+<LI><A NAME="tex2html221"
+  HREF="node4.html#SECTION00044200000000000000">Local Caches</A>
+</UL>
+<LI><A NAME="tex2html222"
+  HREF="node4.html#SECTION00045000000000000000">The Unique Table</A>
+<LI><A NAME="tex2html223"
+  HREF="node4.html#SECTION00046000000000000000">Allowing Asynchronous Reordering</A>
+<LI><A NAME="tex2html224"
+  HREF="node4.html#SECTION00047000000000000000">Debugging</A>
+<LI><A NAME="tex2html225"
+  HREF="node4.html#SECTION00048000000000000000">Gathering and Interpreting Statistics</A>
+<UL>
+<LI><A NAME="tex2html226"
+  HREF="node4.html#SECTION00048100000000000000">Non Modifiable Parameters</A>
+<LI><A NAME="tex2html227"
+  HREF="node4.html#SECTION00048200000000000000">Modifiable Parameters</A>
+<LI><A NAME="tex2html228"
+  HREF="node4.html#SECTION00048300000000000000">Extended Statistics and Reporting</A>
+</UL>
+<LI><A NAME="tex2html229"
+  HREF="node4.html#SECTION00049000000000000000">Guidelines for Documentation</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html230"
+  HREF="node5.html">The C++ Interface</A>
+<UL>
+<LI><A NAME="tex2html231"
+  HREF="node5.html#SECTION00051000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html232"
+  HREF="node5.html#SECTION00052000000000000000">Basic Manipulation</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html233"
+  HREF="node6.html">Acknowledgments</A>
+<LI><A NAME="tex2html234"
+  HREF="node7.html">Bibliography</A>
+<LI><A NAME="tex2html235"
+  HREF="node8.html">Index</A>
+</UL>
+<!--End of Table of Child-Links-->
+<BR><HR>
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/footnode.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/footnode.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/footnode.html	(revision 8)
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>Footnotes</TITLE>
+<META NAME="description" CONTENT="Footnotes">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="previous" HREF="node7.html">
+<LINK REL="up" HREF="cuddIntro.html">
+</HEAD>
+
+<BODY >
+
+<DL>
+<DT><A NAME="foot145">... application.</A><A NAME="foot145"
+ HREF="node3.html#tex2html10"><SUP>1</SUP></A>
+<DD>The
+  global statistical counters are used locally; hence they are
+  compatible with the use of multiple managers.
+<PRE>.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+</PRE>
+<DT><A NAME="foot1315">...
+node.</A><A NAME="foot1315"
+ HREF="node3.html#tex2html80"><SUP>2</SUP></A>
+<DD>When the variables in a group are reordered, the
+  association between the <EM>low</EM> field and the index of the first
+  variable in the group is lost. The package updates the tree to keep
+  track of the changes. However, the application cannot rely on <EM>low</EM> to determine the position of variables.
+<PRE>.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+</PRE>
+</DL>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/index.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/index.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/index.html	(revision 8)
@@ -0,0 +1,224 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>CUDD: CU Decision Diagram Package
+Release 2.4.1</TITLE>
+<META NAME="description" CONTENT="CUDD: CU Decision Diagram Package
+Release 2.4.1">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node1.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html175"
+  HREF="node1.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up_g.png"> 
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev_g.png">  
+<A NAME="tex2html173"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html176"
+  HREF="node1.html">Introduction</A>
+ &nbsp <B>  <A NAME="tex2html174"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+
+<H1 ALIGN="CENTER">CUDD: CU Decision Diagram Package
+<BR>
+Release 2.4.1</H1>
+<P ALIGN="CENTER"><STRONG>Fabio Somenzi
+<BR>
+Department of Electrical and Computer Engineering
+<BR>
+University of Colorado at Boulder
+<BR><IMG
+ WIDTH="20" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img1.png"
+ ALT="$&lt;$">Fabio@Colorado.EDU<IMG
+ WIDTH="20" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img2.png"
+ ALT="$&gt;$"></STRONG></P>
+
+<P>
+<BR><HR>
+<!--Table of Child-Links-->
+<A NAME="CHILD_LINKS"></A>
+
+<UL>
+<LI><A NAME="tex2html177"
+  HREF="node1.html">Introduction</A>
+<LI><A NAME="tex2html178"
+  HREF="node2.html">How to Get CUDD</A>
+<UL>
+<LI><A NAME="tex2html179"
+  HREF="node2.html#SECTION00021000000000000000">The CUDD Package</A>
+<LI><A NAME="tex2html180"
+  HREF="node2.html#SECTION00022000000000000000">CUDD Friends</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html181"
+  HREF="node3.html">User's Manual</A>
+<UL>
+<LI><A NAME="tex2html182"
+  HREF="node3.html#SECTION00031000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html183"
+  HREF="node3.html#SECTION00032000000000000000">Basic Data Structures</A>
+<UL>
+<LI><A NAME="tex2html184"
+  HREF="node3.html#SECTION00032100000000000000">Nodes</A>
+<LI><A NAME="tex2html185"
+  HREF="node3.html#SECTION00032200000000000000">The Manager</A>
+<LI><A NAME="tex2html186"
+  HREF="node3.html#SECTION00032300000000000000">Cache</A>
+</UL>
+<LI><A NAME="tex2html187"
+  HREF="node3.html#SECTION00033000000000000000">Initializing and Shutting Down a DdManager</A>
+<LI><A NAME="tex2html188"
+  HREF="node3.html#SECTION00034000000000000000">Setting Parameters</A>
+<LI><A NAME="tex2html189"
+  HREF="node3.html#SECTION00035000000000000000">Constant Functions</A>
+<UL>
+<LI><A NAME="tex2html190"
+  HREF="node3.html#SECTION00035100000000000000">One, Logic Zero, and Arithmetic Zero</A>
+<LI><A NAME="tex2html191"
+  HREF="node3.html#SECTION00035200000000000000">Predefined Constants</A>
+<LI><A NAME="tex2html192"
+  HREF="node3.html#SECTION00035300000000000000">Background</A>
+<LI><A NAME="tex2html193"
+  HREF="node3.html#SECTION00035400000000000000">New Constants</A>
+</UL>
+<LI><A NAME="tex2html194"
+  HREF="node3.html#SECTION00036000000000000000">Creating Variables</A>
+<UL>
+<LI><A NAME="tex2html195"
+  HREF="node3.html#SECTION00036100000000000000">New BDD and ADD Variables</A>
+<LI><A NAME="tex2html196"
+  HREF="node3.html#SECTION00036200000000000000">New ZDD Variables</A>
+</UL>
+<LI><A NAME="tex2html197"
+  HREF="node3.html#SECTION00037000000000000000">Basic BDD Manipulation</A>
+<LI><A NAME="tex2html198"
+  HREF="node3.html#SECTION00038000000000000000">Basic ADD Manipulation</A>
+<LI><A NAME="tex2html199"
+  HREF="node3.html#SECTION00039000000000000000">Basic ZDD Manipulation</A>
+<LI><A NAME="tex2html200"
+  HREF="node3.html#SECTION000310000000000000000">Converting ADDs to BDDs and Vice Versa</A>
+<LI><A NAME="tex2html201"
+  HREF="node3.html#SECTION000311000000000000000">Converting BDDs to ZDDs and Vice Versa</A>
+<LI><A NAME="tex2html202"
+  HREF="node3.html#SECTION000312000000000000000">Variable Reordering for BDDs and ADDs</A>
+<LI><A NAME="tex2html203"
+  HREF="node3.html#SECTION000313000000000000000">Grouping Variables</A>
+<LI><A NAME="tex2html204"
+  HREF="node3.html#SECTION000314000000000000000">Variable Reordering for ZDDs</A>
+<LI><A NAME="tex2html205"
+  HREF="node3.html#SECTION000315000000000000000">Keeping Consistent Variable Orders for BDDs and ZDDs</A>
+<LI><A NAME="tex2html206"
+  HREF="node3.html#SECTION000316000000000000000">Hooks</A>
+<LI><A NAME="tex2html207"
+  HREF="node3.html#SECTION000317000000000000000">The SIS/VIS Interface</A>
+<UL>
+<LI><A NAME="tex2html208"
+  HREF="node3.html#SECTION000317100000000000000">Using the CUDD Package in SIS</A>
+</UL>
+<LI><A NAME="tex2html209"
+  HREF="node3.html#SECTION000318000000000000000">Writing Decision Diagrams to a File</A>
+<LI><A NAME="tex2html210"
+  HREF="node3.html#SECTION000319000000000000000">Saving and Restoring BDDs</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html211"
+  HREF="node4.html">Programmer's Manual</A>
+<UL>
+<LI><A NAME="tex2html212"
+  HREF="node4.html#SECTION00041000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html213"
+  HREF="node4.html#SECTION00042000000000000000">Reference Counts</A>
+<UL>
+<LI><A NAME="tex2html214"
+  HREF="node4.html#SECTION00042100000000000000">NULL Return Values</A>
+<LI><A NAME="tex2html215"
+  HREF="node4.html#SECTION00042200000000000000"><EM>Cudd_RecursiveDeref</EM> vs. <EM>Cudd_Deref</EM></A>
+<LI><A NAME="tex2html216"
+  HREF="node4.html#SECTION00042300000000000000">When Increasing the Reference Count is Unnecessary</A>
+<LI><A NAME="tex2html217"
+  HREF="node4.html#SECTION00042400000000000000">Saturating Increments and Decrements</A>
+</UL>
+<LI><A NAME="tex2html218"
+  HREF="node4.html#SECTION00043000000000000000">Complement Arcs</A>
+<LI><A NAME="tex2html219"
+  HREF="node4.html#SECTION00044000000000000000">The Cache</A>
+<UL>
+<LI><A NAME="tex2html220"
+  HREF="node4.html#SECTION00044100000000000000">Cache Sizing</A>
+<LI><A NAME="tex2html221"
+  HREF="node4.html#SECTION00044200000000000000">Local Caches</A>
+</UL>
+<LI><A NAME="tex2html222"
+  HREF="node4.html#SECTION00045000000000000000">The Unique Table</A>
+<LI><A NAME="tex2html223"
+  HREF="node4.html#SECTION00046000000000000000">Allowing Asynchronous Reordering</A>
+<LI><A NAME="tex2html224"
+  HREF="node4.html#SECTION00047000000000000000">Debugging</A>
+<LI><A NAME="tex2html225"
+  HREF="node4.html#SECTION00048000000000000000">Gathering and Interpreting Statistics</A>
+<UL>
+<LI><A NAME="tex2html226"
+  HREF="node4.html#SECTION00048100000000000000">Non Modifiable Parameters</A>
+<LI><A NAME="tex2html227"
+  HREF="node4.html#SECTION00048200000000000000">Modifiable Parameters</A>
+<LI><A NAME="tex2html228"
+  HREF="node4.html#SECTION00048300000000000000">Extended Statistics and Reporting</A>
+</UL>
+<LI><A NAME="tex2html229"
+  HREF="node4.html#SECTION00049000000000000000">Guidelines for Documentation</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html230"
+  HREF="node5.html">The C++ Interface</A>
+<UL>
+<LI><A NAME="tex2html231"
+  HREF="node5.html#SECTION00051000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html232"
+  HREF="node5.html#SECTION00052000000000000000">Basic Manipulation</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html233"
+  HREF="node6.html">Acknowledgments</A>
+<LI><A NAME="tex2html234"
+  HREF="node7.html">Bibliography</A>
+<LI><A NAME="tex2html235"
+  HREF="node8.html">Index</A>
+</UL>
+<!--End of Table of Child-Links-->
+<BR><HR>
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node1.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node1.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node1.html	(revision 8)
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>Introduction</TITLE>
+<META NAME="description" CONTENT="Introduction">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node2.html">
+<LINK REL="previous" HREF="cuddIntro.html">
+<LINK REL="up" HREF="cuddIntro.html">
+<LINK REL="next" HREF="node2.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html246"
+  HREF="node2.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html242"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html236"
+  HREF="cuddIntro.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html244"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html247"
+  HREF="node2.html">How to Get CUDD</A>
+<B> Up:</B> <A NAME="tex2html243"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html237"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+ &nbsp <B>  <A NAME="tex2html245"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+
+<H1><A NAME="SECTION00010000000000000000"></A>
+<A NAME="sec:intro"></A>
+<BR>
+Introduction
+</H1>
+
+<P>
+The CUDD package provides functions to manipulate Binary Decision
+Diagrams<A NAME="13"></A> (BDDs) [<A
+ HREF="node7.html#BDD">5</A>,<A
+ HREF="node7.html#BBR">3</A>],
+Algebraic Decision Diagrams<A NAME="15"></A> (ADDs)
+[<A
+ HREF="node7.html#Bahar93">1</A>], and Zero-suppressed Binary Decision
+Diagrams<A NAME="17"></A> (ZDDs)
+[<A
+ HREF="node7.html#Minato93">12</A>]. BDDs are used to represent
+switching<A NAME="19"></A> functions; ADDs are used to
+represent function from <IMG
+ WIDTH="58" HEIGHT="37" ALIGN="MIDDLE" BORDER="0"
+ SRC="img3.png"
+ ALT="$\{0,1\}^n$"> to an arbitrary set.  ZDDs
+represent switching<A NAME="20"></A> functions like BDDs;
+however, they are much more efficient than BDDs when the functions to
+be represented are characteristic<A NAME="21"></A>
+functions of cube<A NAME="22"></A> sets, or in general, when the
+ON-set<A NAME="23"></A> of the function to be represented is
+very sparse. They are inferior to BDDs in other cases.
+
+<P>
+The package provides a large set of operations on BDDs, ADDs, and
+ZDDs, functions to convert BDDs into ADDs or ZDDs and vice versa, and
+a large assortment of variable reordering<A NAME="24"></A> methods.
+
+<P>
+The CUDD package can be used in three ways:
+
+<UL>
+<LI>As a black box<A NAME="26"></A>.  In this case, the application
+  program that needs to manipulate decision diagrams only uses the
+  exported functions of the package. The rich set of functions
+  included in the CUDD package allows many applications to be written
+  in this way.  Section&nbsp;<A HREF="node3.html#sec:user">3</A> describes how to use the
+  exported functions of the package. An application written in terms
+  of the exported functions of the package needs not concern itself
+  with the details of variable reordering<A NAME="28"></A>, which may
+  take place behind the scenes.
+Click <A NAME="tex2html1"
+  HREF="cuddExtAbs.html">here</A>
+for a list of the
+  exported functions.
+</LI>
+<LI>As a clear box<A NAME="31"></A>. When writing a sophisticated
+  application based on decision diagrams, efficiency often dictates
+  that some functions be implemented as direct recursive manipulation
+  of the diagrams, instead of being written in terms of existing
+  primitive functions.  Section&nbsp;<A HREF="node4.html#sec:prog">4</A> explains how to add new
+  functions to the CUDD package. It also details how to write a
+  recursive function that can be interrupted by
+  dynamic<A NAME="33"></A> variable reordering.
+Click <A NAME="tex2html2"
+  HREF="cuddAllAbs.html">here</A>
+for a list of the
+  exported and internal functions.
+</LI>
+<LI>Through an interface. Object-oriented languages like C++ and
+  Perl5 can free the programmer from the burden of memory management.
+  A C++ interface is included in the distribution of CUDD. It
+  automatically frees decision diagrams that are no longer used by the
+  application and overloads operators. Almost all the functionality
+  provided by the CUDD exported functions is available through the C++
+  interface, which is especially recommended for fast prototyping.
+  Section&nbsp;<A HREF="node5.html#sec:cpp">5</A> explains how to use the interface. A Perl5
+  interface also exists and is ditributed separately. (See
+  Section&nbsp;<A HREF="node2.html#sec:getFriends">2.2</A>.) Some applications define their own
+  interfaces. See for example Section&nbsp;<A HREF="node3.html#sec:sis-vis">3.17</A>.
+</LI>
+</UL>
+In the following, the reader is supposed to be familiar with the basic
+ideas about decision diagrams, as found, for instance, in [<A
+ HREF="node7.html#BBR">3</A>].
+
+<P>
+<HR>
+<!--Navigation Panel-->
+<A NAME="tex2html246"
+  HREF="node2.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html242"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html236"
+  HREF="cuddIntro.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html244"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html247"
+  HREF="node2.html">How to Get CUDD</A>
+<B> Up:</B> <A NAME="tex2html243"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html237"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+ &nbsp <B>  <A NAME="tex2html245"
+  HREF="node8.html">Index</A></B> 
+<!--End of Navigation Panel-->
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node2.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node2.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node2.html	(revision 8)
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>How to Get CUDD</TITLE>
+<META NAME="description" CONTENT="How to Get CUDD">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node3.html">
+<LINK REL="previous" HREF="node1.html">
+<LINK REL="up" HREF="cuddIntro.html">
+<LINK REL="next" HREF="node3.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html258"
+  HREF="node3.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html254"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html248"
+  HREF="node1.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html256"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html259"
+  HREF="node3.html">User's Manual</A>
+<B> Up:</B> <A NAME="tex2html255"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html249"
+  HREF="node1.html">Introduction</A>
+ &nbsp <B>  <A NAME="tex2html257"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+<!--Table of Child-Links-->
+<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></A>
+
+<UL>
+<LI><A NAME="tex2html260"
+  HREF="#SECTION00021000000000000000">The CUDD Package</A>
+<LI><A NAME="tex2html261"
+  HREF="#SECTION00022000000000000000">CUDD Friends</A>
+</UL>
+<!--End of Table of Child-Links-->
+<HR>
+
+<H1><A NAME="SECTION00020000000000000000"></A>
+<A NAME="sec:getting"></A>
+<BR>
+How to Get CUDD
+</H1>
+
+<P>
+
+<H2><A NAME="SECTION00021000000000000000"></A>
+<A NAME="sec:getCUDD"></A>
+<BR>
+The CUDD Package
+</H2>
+
+<P>
+The CUDD package is available via anonymous FTP<A NAME="45"></A> from
+vlsi.Colorado.EDU.  A compressed tar file named <TT>  cudd-2.4.1.tar.gz</TT> can be found in directory <TT>pub</TT>. Once you
+have this file,
+<BLOCKQUOTE>
+<TT>gzip<A NAME="49"></A> -dc cudd-2.4.1.tar.gz | tar xvf -
+
+</TT></BLOCKQUOTE>
+will create directory <TT>cudd-2.4.1</TT> and its subdirectories.
+These directories contain the decision diagram package, a few support
+libraries<A NAME="52"></A>, and a toy application based on the
+decision diagram package.  There is a README<A NAME="53"></A> file
+with instructions on configuration<A NAME="54"></A> and
+installation<A NAME="55"></A> in <TT>cudd-2.4.1</TT>.
+You can use a compiler for either ANSI C or C++.
+
+<P>
+Once you have made the libraries and program, you can type:
+<BLOCKQUOTE>
+<TT>cd nanotrav<A NAME="58"></A> 
+<BR>
+nanotrav -p 1 -autodyn -reordering sifting -trav mult32a.blif
+
+</TT></BLOCKQUOTE>
+This will run a simple-minded FSM traversal program. (On a 200 MHz
+PentiumPro<A NAME="60"></A> (TM), it takes about 6 sec.) The
+output produced by the program can be checked against the contents of
+<TT>cudd-2.4.1/nanotrav/mult32a.out</TT>.  More information on the
+<TT>nanotrav<A NAME="62"></A></TT> program can be found in <TT>  cudd-2.4.1/nanotrav/README<A NAME="63"></A></TT>.
+
+<P>
+If you want to be notified of new releases of the CUDD package, send a
+message to <TT>Fabio@Colorado.EDU</TT>.
+
+<P>
+
+<H2><A NAME="SECTION00022000000000000000"></A>
+<A NAME="sec:getFriends"></A>
+<BR>
+CUDD Friends
+</H2>
+
+<P>
+Two CUDD extensions are available via anonymous FTP<A NAME="67"></A> from
+vlsi.Colorado.EDU.
+
+<UL>
+<LI><EM>PerlDD</EM> is an object-oriented Perl5 interface to CUDD. It
+  is organized as a standard Perl extension module. The Perl interface
+  is at a somewhat higher level than the C++ interface, but it is not
+  as complete.
+</LI>
+<LI><EM>DDcal</EM> is a graphic BDD calculator based on CUDD,
+  Perl-Tk, and dot. (See Section&nbsp;<A HREF="node3.html#sec:dump">3.18</A> for information on <EM>    dot</EM>.)
+
+<P>
+</LI>
+</UL><HR>
+<!--Navigation Panel-->
+<A NAME="tex2html258"
+  HREF="node3.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html254"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html248"
+  HREF="node1.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html256"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html259"
+  HREF="node3.html">User's Manual</A>
+<B> Up:</B> <A NAME="tex2html255"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html249"
+  HREF="node1.html">Introduction</A>
+ &nbsp <B>  <A NAME="tex2html257"
+  HREF="node8.html">Index</A></B> 
+<!--End of Navigation Panel-->
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node3.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node3.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node3.html	(revision 8)
@@ -0,0 +1,1669 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>User's Manual</TITLE>
+<META NAME="description" CONTENT="User's Manual">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node4.html">
+<LINK REL="previous" HREF="node2.html">
+<LINK REL="up" HREF="cuddIntro.html">
+<LINK REL="next" HREF="node4.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html272"
+  HREF="node4.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html268"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html262"
+  HREF="node2.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html270"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html273"
+  HREF="node4.html">Programmer's Manual</A>
+<B> Up:</B> <A NAME="tex2html269"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html263"
+  HREF="node2.html">How to Get CUDD</A>
+ &nbsp <B>  <A NAME="tex2html271"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+<!--Table of Child-Links-->
+<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></A>
+
+<UL>
+<LI><A NAME="tex2html274"
+  HREF="#SECTION00031000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html275"
+  HREF="#SECTION00032000000000000000">Basic Data Structures</A>
+<UL>
+<LI><A NAME="tex2html276"
+  HREF="#SECTION00032100000000000000">Nodes</A>
+<LI><A NAME="tex2html277"
+  HREF="#SECTION00032200000000000000">The Manager</A>
+<LI><A NAME="tex2html278"
+  HREF="#SECTION00032300000000000000">Cache</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html279"
+  HREF="#SECTION00033000000000000000">Initializing and Shutting Down a DdManager</A>
+<LI><A NAME="tex2html280"
+  HREF="#SECTION00034000000000000000">Setting Parameters</A>
+<LI><A NAME="tex2html281"
+  HREF="#SECTION00035000000000000000">Constant Functions</A>
+<UL>
+<LI><A NAME="tex2html282"
+  HREF="#SECTION00035100000000000000">One, Logic Zero, and Arithmetic Zero</A>
+<LI><A NAME="tex2html283"
+  HREF="#SECTION00035200000000000000">Predefined Constants</A>
+<LI><A NAME="tex2html284"
+  HREF="#SECTION00035300000000000000">Background</A>
+<LI><A NAME="tex2html285"
+  HREF="#SECTION00035400000000000000">New Constants</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html286"
+  HREF="#SECTION00036000000000000000">Creating Variables</A>
+<UL>
+<LI><A NAME="tex2html287"
+  HREF="#SECTION00036100000000000000">New BDD and ADD Variables</A>
+<LI><A NAME="tex2html288"
+  HREF="#SECTION00036200000000000000">New ZDD Variables</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html289"
+  HREF="#SECTION00037000000000000000">Basic BDD Manipulation</A>
+<LI><A NAME="tex2html290"
+  HREF="#SECTION00038000000000000000">Basic ADD Manipulation</A>
+<LI><A NAME="tex2html291"
+  HREF="#SECTION00039000000000000000">Basic ZDD Manipulation</A>
+<LI><A NAME="tex2html292"
+  HREF="#SECTION000310000000000000000">Converting ADDs to BDDs and Vice Versa</A>
+<LI><A NAME="tex2html293"
+  HREF="#SECTION000311000000000000000">Converting BDDs to ZDDs and Vice Versa</A>
+<LI><A NAME="tex2html294"
+  HREF="#SECTION000312000000000000000">Variable Reordering for BDDs and ADDs</A>
+<LI><A NAME="tex2html295"
+  HREF="#SECTION000313000000000000000">Grouping Variables</A>
+<LI><A NAME="tex2html296"
+  HREF="#SECTION000314000000000000000">Variable Reordering for ZDDs</A>
+<LI><A NAME="tex2html297"
+  HREF="#SECTION000315000000000000000">Keeping Consistent Variable Orders for BDDs and ZDDs</A>
+<LI><A NAME="tex2html298"
+  HREF="#SECTION000316000000000000000">Hooks</A>
+<LI><A NAME="tex2html299"
+  HREF="#SECTION000317000000000000000">The SIS/VIS Interface</A>
+<UL>
+<LI><A NAME="tex2html300"
+  HREF="#SECTION000317100000000000000">Using the CUDD Package in SIS</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html301"
+  HREF="#SECTION000318000000000000000">Writing Decision Diagrams to a File</A>
+<LI><A NAME="tex2html302"
+  HREF="#SECTION000319000000000000000">Saving and Restoring BDDs</A>
+</UL>
+<!--End of Table of Child-Links-->
+<HR>
+
+<H1><A NAME="SECTION00030000000000000000"></A>
+<A NAME="sec:user"></A>
+<BR>
+User's Manual
+</H1>
+
+<P>
+This section describes the use of the CUDD package as a black box.
+
+<P>
+
+<H2><A NAME="SECTION00031000000000000000"></A>
+<A NAME="sec:compileExt"></A><A NAME="78"></A>
+<BR>
+Compiling and Linking
+</H2>
+
+<P>
+To build an application that uses the CUDD package, you should add
+<PRE>
+#include "util.h"
+#include "cudd.h"
+</PRE>
+<A NAME="81"></A>
+to your source files, and should link
+<code>libcudd.a</code><A NAME="82"></A>,
+<code>libmtr.a</code><A NAME="83"></A>,
+<code>libst.a</code><A NAME="84"></A>, and
+<code>libutil.a</code><A NAME="85"></A> to your executable. (All these
+libraries are part of the distribution.) Some
+platforms require specific compiler and linker flags.  Refer to the
+<TT>Makefile<A NAME="86"></A></TT> in the top level directory of the
+distribution.
+
+<P>
+Keep in mind that whatever flags affect the size of data
+structures--for instance the flags used to use 64-bit pointers where
+available--must be specified when compiling both CUDD and the files
+that include its header files.
+
+<P>
+
+<H2><A NAME="SECTION00032000000000000000"></A>
+<A NAME="sec:struct"></A>
+<BR>
+Basic Data Structures
+</H2>
+
+<P>
+
+<H3><A NAME="SECTION00032100000000000000"></A>
+<A NAME="sec:nodes"></A>
+<BR>
+Nodes
+</H3>
+
+<P>
+BDDs, ADDs, and ZDDs are made of DdNode's. A DdNode<A NAME="91"></A>
+(node<A NAME="92"></A> for short) is a structure with several fields. Those
+that are of interest to the application that uses the CUDD package as
+a black box are the variable index<A NAME="93"></A>, the
+reference<A NAME="94"></A> count, and the value. The
+remaining fields are pointers that connect nodes among themselves and
+that are used to implement the unique<A NAME="95"></A> table. (See
+Section&nbsp;<A HREF="node3.html#sec:manager">3.2.2</A>.)
+
+<P>
+The <EM>index</EM> field holds the name of the variable that labels the
+node. The index of a variable is a permanent attribute that reflects
+the order<A NAME="98"></A> of creation.  Index 0 corresponds to
+the variable created first. On a machine with 32-bit pointers, the
+maximum number of variables is the largest value that can be stored in
+an unsigned short integer minus 1. The largest index is reserved for
+the constant<A NAME="99"></A> nodes. When 64-bit pointers are
+used, the maximum number of variables is the largest value that can be
+stored in an unsigned integer minus 1.
+
+<P>
+When variables are reordered to reduce the size of the decision
+diagrams, the variables may shift in the order, but they retain their
+indices. The package keeps track of the variable
+permutation<A NAME="100"></A> (and its inverse). The
+application is not affected by variable reordering<A NAME="101"></A>,
+except in the following cases.
+
+<UL>
+<LI>If the application uses
+  generators<A NAME="103"></A> (<A NAME="tex2html3"
+  HREF="cuddExtDet.html#Cudd_ForeachCube"><EM>Cudd_ForeachCube</EM></A>
+<A NAME="1423"></A> and <A NAME="tex2html4"
+  HREF="cuddExtDet.html#Cudd_ForeachNode"><EM>Cudd_ForeachNode</EM></A>
+<A NAME="1425"></A>) and reordering is enabled, then it
+  must take care not to call any operation that may create new nodes
+  (and hence possibly trigger reordering). This is because the cubes
+  (i.e., paths) and nodes of a diagram change as a result of reordering.
+</LI>
+<LI>If the application uses <A NAME="tex2html5"
+  HREF="cuddExtDet.html#Cudd_bddConstrain"><EM>    Cudd_bddConstrain</EM></A><A NAME="1427"></A> and reordering
+
+takes place, then the property of <A NAME="tex2html6"
+  HREF="cuddExtDet.html#Cudd_bddConstrain"><EM>Cudd_bddConstrain</EM></A>
+of being an
+  image restrictor is lost.
+</LI>
+</UL>
+
+<P>
+The CUDD package relies on garbage<A NAME="116"></A>
+collection to reclaim the memory used by diagrams that are no longer
+in use. The scheme employed for garbage collection is based on keeping
+a reference<A NAME="117"></A> count for each node.  The
+references that are counted are both the internal references
+(references from other nodes) and external references (typically
+references from the calling environment).  When an application creates
+a new BDD<A NAME="118"></A>, ADD<A NAME="119"></A>, or ZDD<A NAME="120"></A>,
+it must increase its reference count explicitly, through
+a call to <A NAME="tex2html7"
+  HREF="cuddExtDet.html#Cudd_Ref"><EM>Cudd_Ref</EM></A><A NAME="1429"></A>.  Similarly, when a
+diagram is no longer needed, the application must call <A NAME="tex2html8"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1431"></A> (for BDDs
+and ADDs) or <A NAME="tex2html9"
+  HREF="cuddExtDet.html#Cudd_RecursiveDerefZdd"><EM>  Cudd_RecursiveDerefZdd</EM></A><A NAME="1433"></A>
+(for ZDDs) to ``recycle<A NAME="130"></A>" the nodes of the
+diagram.
+
+<P>
+Terminal<A NAME="131"></A> nodes carry a value. This is especially
+important for ADDs.  By default, the value is a double<A NAME="132"></A>.
+To change to something different (e.g., an integer), the
+package must be modified and recompiled.  Support for this process is
+currently very rudimentary.
+
+<P>
+
+<H3><A NAME="SECTION00032200000000000000"></A>
+<A NAME="134"></A><A NAME="sec:manager"></A>
+<BR>
+The Manager
+</H3>
+
+<P>
+All nodes used in BDDs, ADDs, and ZDDs are kept in special
+hash<A NAME="136"></A> tables called the <EM>  unique<A NAME="137"></A> tables</EM>. Specifically, BDDs and ADDs
+share the same unique table, whereas ZDDs have their own table.  As
+the name implies, the main purpose of the unique table is to guarantee
+that each node is unique; that is, there is no other node labeled by
+the same variable and with the same children. This uniqueness property
+makes decision diagrams canonical<A NAME="138"></A>. The
+unique<A NAME="139"></A> tables and some auxiliary data structures
+make up the DdManager<A NAME="140"></A> (manager<A NAME="141"></A> for
+short).  Though the application that uses only the exported functions
+needs not be concerned with most details of the manager, it has to
+deal with the manager in the following sense. The application must
+initialize the manager by calling an appropriate function. (See
+Section&nbsp;<A HREF="node3.html#sec:init">3.3</A>.) Subsequently, it must pass a pointer to the
+manager to all the functions that operate on decision diagrams.
+
+<P>
+With the exception of a few statistical counters<A NAME="143"></A>, there are no global<A NAME="144"></A> variables in
+the CUDD package. Therefore, it is quite possible to have multiple
+managers simultaneously active in the same application.<A NAME="tex2html10"
+  HREF="footnode.html#foot145"><SUP>1</SUP></A> It is the pointers to
+the managers that tell the functions on what data they should operate.
+
+<P>
+
+<H3><A NAME="SECTION00032300000000000000"></A>
+<A NAME="147"></A><A NAME="sec:memoize"></A>
+<BR>
+Cache
+</H3>
+
+<P>
+Efficient recursive manipulation of decision diagrams requires the use
+of a table to store computed results. This table<A NAME="149"></A>
+is called here the <EM>cache<A NAME="150"></A></EM> because it is
+effectively handled like a cache of variable but limited capacity. The
+CUDD package starts by default with a small cache, and increases its
+size until either no further benefit is achieved, or a limit size is
+reached. The user can influence this policy by choosing initial and
+limit values for the cache size.
+
+<P>
+Too small a cache will cause frequent overwriting of useful results.
+Too large a cache will cause overhead, because the whole cache is
+scanned every time garbage<A NAME="151"></A> collection takes
+place. The optimal parameters depend on the specific application. The
+default parameters work reasonably well for a large spectrum of
+applications.
+
+<P>
+The cache<A NAME="152"></A> of the CUDD package is used by most recursive
+functions of the package, and can be used by user-supplied functions
+as well. (See Section&nbsp;<A HREF="node4.html#sec:cache">4.4</A>.)
+
+<P>
+
+<H2><A NAME="SECTION00033000000000000000"></A>
+<A NAME="155"></A><A NAME="sec:init"></A>
+<BR>
+Initializing and Shutting Down a DdManager
+</H2>
+
+<P>
+To use the functions in the CUDD package, one has first to initialize
+the package itself by calling <A NAME="tex2html11"
+  HREF="cuddExtDet.html#Cudd_Init"><EM>  Cudd_Init</EM></A><A NAME="1435"></A>.  This function takes four
+parameters:
+
+<UL>
+<LI>numVars<A NAME="161"></A>: It is the initial number of variables
+  for BDDs and ADDs. If the total number of variables needed by the
+  application is known, then it is slightly more efficient to create a
+  manager with that number of variables. If the number is unknown, it
+  can be set to 0, or to any other lower bound on the number of
+  variables.  Requesting more variables than are actually needed is
+  not incorrect, but is not efficient.
+</LI>
+<LI>numVarsZ<A NAME="162"></A>: It is the initial number of variables
+  for ZDDs. See Sections&nbsp;<A HREF="node3.html#sec:basicZDD">3.9</A> and&nbsp;<A HREF="node3.html#sec:convertZ">3.11</A> for
+  a discussion of the value of this argument.
+</LI>
+<LI>numSlots<A NAME="165"></A>: Determines the initial size of each
+  subtable<A NAME="166"></A> of the unique<A NAME="167"></A> table.
+  There is a subtable for each variable. The size of each subtable is
+  dynamically adjusted to reflect the number of nodes.  It is normally
+  O.K. to use the default value for this parameter, which is
+  CUDD_UNIQUE_SLOTS<A NAME="168"></A>.
+</LI>
+<LI>cacheSize<A NAME="169"></A>: It is the initial size (number of
+  entries) of the cache<A NAME="170"></A>. Its default value is
+  CUDD_CACHE_SLOTS<A NAME="171"></A>.
+</LI>
+<LI>maxMemory<A NAME="172"></A>: It is the target value for the
+  maximum memory occupation (in bytes). The package uses this value to
+  decide two parameters.
+  
+<UL>
+<LI>the maximum size to which the cache will grow, regardless of
+    the hit rate or the size of the unique<A NAME="174"></A> table.
+</LI>
+<LI>the maximum size to which growth of the unique table will be
+    preferred to garbage collection.
+  
+</LI>
+</UL>
+  If maxMemory is set to 0, CUDD tries to guess a good value based on
+  the available memory.
+</LI>
+</UL>
+A typical call to <A NAME="tex2html12"
+  HREF="cuddExtDet.html#Cudd_Init"><EM>Cudd_Init</EM></A><A NAME="1437"></A> may look
+like this:
+<PRE>
+  manager = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0);
+</PRE>
+To reclaim all the memory associated with a manager, an application
+must call <A NAME="tex2html13"
+  HREF="cuddExtDet.html#Cudd_Quit"><EM>Cudd_Quit</EM></A><A NAME="1439"></A>. This is normally
+done before exiting.
+
+<P>
+
+<H2><A NAME="SECTION00034000000000000000"></A>
+<A NAME="sec:params"></A>
+<BR>
+Setting Parameters
+</H2>
+
+<P>
+The package provides several functions to set the parameters that
+control various functions. For instance, the package has an automatic
+way of determining whether a larger unique<A NAME="187"></A> table
+would make the application run faster. In that case, the package
+enters a ``fast growth<A NAME="188"></A>" mode in which resizing of
+the unique subtables is favored over garbage<A NAME="189"></A>
+collection. When the unique table reaches a given size, however, the
+package returns to the normal ``slow growth" mode, even though the
+conditions that caused the transition to fast growth still prevail.
+The limit size for fast growth<A NAME="190"></A> can be read by <A NAME="tex2html14"
+  HREF="cuddExtDet.html#Cudd_ReadLooseUpTo"><EM>  Cudd_ReadLooseUpTo</EM></A><A NAME="1441"></A> and changed
+by <A NAME="tex2html15"
+  HREF="cuddExtDet.html#Cudd_SetLooseUpTo"><EM>Cudd_SetLooseUpTo</EM></A><A NAME="1443"></A>.  Similar
+pairs of functions exist for several other parameters. See also
+Section&nbsp;<A HREF="node4.html#sec:stats">4.8</A>.
+
+<P>
+
+<H2><A NAME="SECTION00035000000000000000"></A>
+<A NAME="199"></A><A NAME="sec:const"></A>
+<BR>
+Constant Functions
+</H2>
+
+<P>
+The CUDD Package defines several constant functions. These functions
+are created when the manager<A NAME="201"></A> is initialized, and are accessible
+through the manager itself.
+
+<P>
+
+<H3><A NAME="SECTION00035100000000000000"></A>
+<A NAME="203"></A><A NAME="204"></A><A NAME="sec:zero"></A>
+<BR>
+One, Logic Zero, and Arithmetic Zero
+</H3>
+
+<P>
+The constant<A NAME="206"></A> 1 (returned by <A NAME="tex2html16"
+  HREF="cuddExtDet.html#Cudd_ReadOne"><EM>  Cudd_ReadOne</EM></A><A NAME="1445"></A>) is common to BDDs,
+ADDs, and ZDDs.  However, its meaning is different for ADDs and BDDs,
+on the one hand, and ZDDs, on the other hand. The diagram consisting
+of the constant 1 node only represents the constant 1 function for
+ADDs and BDDs. For ZDDs, its meaning depends on the number of
+variables: It is the conjunction of the complements of all variables.
+Conversely, the representation of the constant 1 function depends on
+the number of variables. The constant 1 function of <IMG
+ WIDTH="17" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img4.png"
+ ALT="$n$"> variables is
+returned by <A NAME="tex2html17"
+  HREF="cuddExtDet.html#Cudd_ReadZddOne"><EM>Cudd_ReadZddOne</EM></A><A NAME="1447"></A>.
+
+<P>
+The constant 0 is common to ADDs and ZDDs, but not to BDDs.  The
+BDD<A NAME="213"></A> logic 0 is <B>not</B> associated
+with the constant 0 function: It is obtained by complementation (<A NAME="tex2html18"
+  HREF="cuddExtDet.html#Cudd_Not"><EM>  Cudd_Not</EM></A><A NAME="1449"></A>) of the constant 1. (It is also
+returned by <A NAME="tex2html19"
+  HREF="cuddExtDet.html#Cudd_ReadLogicZero"><EM>  Cudd_ReadLogicZero</EM></A><A NAME="1451"></A>.)  All
+other constants are specific to ADDs.
+
+<P>
+
+<H3><A NAME="SECTION00035200000000000000"></A>
+<A NAME="sec:predef-const"></A>
+<BR>
+Predefined Constants
+</H3>
+
+<P>
+Besides 0 (returned by <A NAME="tex2html20"
+  HREF="cuddExtDet.html#Cudd_ReadZero"><EM>Cudd_ReadZero</EM></A><A NAME="1453"></A>)
+and 1, the following constant<A NAME="226"></A> functions are
+created at initialization time.
+
+<OL>
+<LI>PlusInfinity<A NAME="228"></A> and
+  MinusInfinity<A NAME="229"></A>: On computers implementing the
+  IEEE<A NAME="230"></A> standard 754 for
+  floating-point<A NAME="231"></A> arithmetic, these two constants
+  are set to the signed infinities<A NAME="232"></A>. On the DEC
+  Alphas<A NAME="233"></A>, the option <code>-ieee_with_no_inexact</code> or
+  <code>-ieee_with_inexact</code> must be passed to the DEC compiler to get
+  support of the IEEE standard. (The compiler still produces a
+  warning, but it can be ignored.) Compiling<A NAME="234"></A> with
+  those options may cause substantial performance degradation on the
+  Evolution IV CPUs. (Especially if the application does use the
+  infinities.)  The problem is reportedly solved in the Evolution V
+  CPUs.  If <TT>gcc<A NAME="235"></A></TT> is used to compile CUDD on the
+  Alphas, the symbol <TT>HAVE_IEEE_754<A NAME="236"></A></TT> must
+  be undefined. (See the Makefile<A NAME="237"></A> for the details.)
+  The values of these constants are returned by <A NAME="tex2html21"
+  HREF="cuddExtDet.html#Cudd_ReadPlusInfinity"><EM>    Cudd_ReadPlusInfinity</EM></A><A NAME="1455"></A> and <A NAME="tex2html22"
+  HREF="cuddExtDet.html#Cudd_ReadMinusInfinity"><EM>    Cudd_ReadMinusInfinity</EM></A><A NAME="1457"></A>.
+</LI>
+<LI>Epsilon<A NAME="244"></A>: This constant, initially set to
+
+<IMG
+ WIDTH="49" HEIGHT="22" ALIGN="BOTTOM" BORDER="0"
+ SRC="img5.png"
+ ALT="$10^{-12}$">, is used in comparing floating point values for equality.
+  Its value is returned by <A NAME="tex2html23"
+  HREF="cuddExtDet.html#Cudd_ReadEpsilon"><EM>    Cudd_ReadEpsilon</EM></A><A NAME="1459"></A>, and it can be
+
+modified by calling <A NAME="tex2html24"
+  HREF="cuddExtDet.html#Cudd_SetEpsilon"><EM>    Cudd_SetEpsilon</EM></A><A NAME="1461"></A>. Unlike the other
+
+constants, it does not correspond to a node.
+</LI>
+</OL>
+
+<P>
+
+<H3><A NAME="SECTION00035300000000000000"></A>
+<A NAME="254"></A><A NAME="sec:background"></A>
+<BR>
+Background
+</H3>
+
+<P>
+The background value is a constant<A NAME="256"></A> typically used
+to represent non-existing arcs in graphs. Consider a shortest path
+problem. Two nodes that are not connected by an arc can be regarded as
+being joined by an arc<A NAME="257"></A> of infinite length. In
+shortest path problems, it is therefore convenient to set the
+background value to PlusInfinity<A NAME="258"></A>. In network flow
+problems, on the other hand, two nodes not connected by an arc can be
+regarded as joined by an arc<A NAME="259"></A> of 0 capacity.
+For these problems, therefore, it is more convenient to set the
+background value to 0.  In general, when representing
+sparse<A NAME="260"></A> matrices, the background value is the value that
+is assumed implicitly.
+
+<P>
+At initialization, the background value is set to 0. It can be read
+with <A NAME="tex2html25"
+  HREF="cuddExtDet.html#Cudd_ReadBackground"><EM>Cudd_ReadBackground</EM></A><A NAME="1463"></A>,
+and modified with <A NAME="tex2html26"
+  HREF="cuddExtDet.html#Cudd_SetBackground"><EM>Cudd_SetBackground</EM></A>.  The background value
+affects procedures that read sparse matrices/graphs (<A NAME="tex2html27"
+  HREF="cuddExtDet.html#Cudd_addRead"><EM>  Cudd_addRead</EM></A><A NAME="1465"></A> and <A NAME="tex2html28"
+  HREF="cuddExtDet.html#Cudd_addHarwell"><EM>  Cudd_addHarwell</EM></A><A NAME="1467"></A>), procedures that
+print out sum-of-product<A NAME="272"></A> expressions
+for ADDs (<A NAME="tex2html29"
+  HREF="cuddExtDet.html#Cudd_PrintMinterm"><EM>  Cudd_PrintMinterm</EM></A><A NAME="1469"></A>), generators
+of cubes (<A NAME="tex2html30"
+  HREF="cuddExtDet.html#Cudd_ForeachCube"><EM>Cudd_ForeachCube</EM></A><A NAME="1471"></A>),
+and procedures that count minterms<A NAME="279"></A> (<A NAME="tex2html31"
+  HREF="cuddExtDet.html#Cudd_CountMinterm"><EM>  Cudd_CountMinterm</EM></A><A NAME="1473"></A>).
+
+<P>
+
+<H3><A NAME="SECTION00035400000000000000"></A>
+<A NAME="sec:newconst"></A>
+<BR>
+New Constants
+</H3>
+
+<P>
+New constant<A NAME="285"></A> can be created by calling <A NAME="tex2html32"
+  HREF="cuddExtDet.html#Cudd_addConst"><EM>  Cudd_addConst</EM></A><A NAME="1475"></A>. This function will
+retrieve the ADD<A NAME="289"></A> for the desired
+constant, if it already exist, or it will create a new one. Obviously,
+new constants should only be used when manipulating ADDs.
+
+<P>
+
+<H2><A NAME="SECTION00036000000000000000"></A>
+<A NAME="sec:newvar"></A>
+<BR>
+Creating Variables
+</H2>
+
+<P>
+Decision diagrams are typically created by combining simpler decision
+diagrams. The simplest decision diagrams, of course, cannot be created
+in that way.  Constant functions have been discussed in
+Section&nbsp;<A HREF="node3.html#sec:const">3.5</A>. In this section we discuss the simple
+variable functions, also known as <EM>  projection<A NAME="293"></A> functions</EM>.
+
+<P>
+
+<H3><A NAME="SECTION00036100000000000000"></A>
+<A NAME="sec:BDDADDvar"></A>
+<BR>
+New BDD and ADD Variables
+</H3>
+
+<P>
+The projection<A NAME="296"></A> functions are distinct for
+BDDs and ADDs. A projection function for BDDs consists of an internal
+node with both outgoing arcs pointing to the constant 1. The <EM>  else</EM> arc<A NAME="298"></A> is complemented.
+
+<P>
+An ADD projection function, on the other hand, has the <EM>else</EM>
+pointer directed to the arithmetic<A NAME="300"></A> zero
+function. One should never mix the two types of variables. BDD
+variables should be used when manipulating BDDs, and ADD variables
+should be used when manipulating ADDs.  Three functions are provided
+to create BDD variables:
+
+<UL>
+<LI><A NAME="tex2html33"
+  HREF="cuddExtDet.html#Cudd_bddIthVar"><EM>Cudd_bddIthVar</EM></A><A NAME="1477"></A>: Returns
+
+the projection<A NAME="305"></A> function with index <IMG
+ WIDTH="12" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img6.png"
+ ALT="$i$">.
+  If the function does not exist, it is created.
+</LI>
+<LI><A NAME="tex2html34"
+  HREF="cuddExtDet.html#Cudd_bddNewVar"><EM>Cudd_bddNewVar</EM></A><A NAME="1479"></A>: Returns a
+
+new projection<A NAME="309"></A> function, whose index is
+  the largest index in use at the time of the call, plus 1.
+</LI>
+<LI><A NAME="tex2html35"
+  HREF="cuddExtDet.html#Cudd_bddNewVarAtLevel"><EM>    Cudd_bddNewVarAtLevel</EM></A><A NAME="1481"></A>:
+
+Similar to <A NAME="tex2html36"
+  HREF="cuddExtDet.html#Cudd_bddNewVar"><EM>Cudd_bddNewVar</EM></A><A NAME="1483"></A>.  In
+
+addition it allows to specify the position in the variable
+  order<A NAME="316"></A> at which the new variable should be
+  inserted. By contrast, <A NAME="tex2html37"
+  HREF="cuddExtDet.html#Cudd_bddNewVar"><EM>    Cudd_bddNewVar</EM></A><A NAME="1485"></A> adds the new
+
+variable at the end of the order.
+</LI>
+</UL>
+The analogous functions for ADDs are <A NAME="tex2html38"
+  HREF="cuddExtDet.html#Cudd_addIthVar"><EM>  Cudd_addIthVar</EM></A><A NAME="1487"></A>, <A NAME="tex2html39"
+  HREF="cuddExtDet.html#Cudd_addNewVar"><EM>  Cudd_addNewVar</EM></A><A NAME="1489"></A>, and <A NAME="tex2html40"
+  HREF="cuddExtDet.html#Cudd_addNewVarAtLevel"><EM>  Cudd_addNewVarAtLevel</EM></A><A NAME="1491"></A>.
+
+<P>
+
+<H3><A NAME="SECTION00036200000000000000"></A>
+<A NAME="331"></A><A NAME="sec:ZDDvars"></A>
+<BR>
+New ZDD Variables
+</H3>
+
+<P>
+Unlike the projection functions of BDDs and ADDs, the
+projection<A NAME="333"></A> functions of ZDDs have diagrams
+with <IMG
+ WIDTH="47" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img7.png"
+ ALT="$n+1$"> nodes, where <IMG
+ WIDTH="17" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img4.png"
+ ALT="$n$"> is the number of variables. Therefore the
+ZDDs of the projection functions change when new variables are added.
+This will be discussed in Section&nbsp;<A HREF="node3.html#sec:basicZDD">3.9</A>. Here we assume
+that the number of variables is fixed. The ZDD of the <IMG
+ WIDTH="12" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img6.png"
+ ALT="$i$">-th
+projection function is returned by <A NAME="tex2html41"
+  HREF="cuddExtDet.html#Cudd_zddIthVar"><EM>  Cudd_zddIthVar</EM></A><A NAME="1493"></A>.
+
+<P>
+
+<H2><A NAME="SECTION00037000000000000000"></A>
+<A NAME="339"></A><A NAME="sec:basicBDD"></A>
+<BR>
+Basic BDD Manipulation
+</H2>
+
+<P>
+Common manipulations of BDDs can be accomplished by calling <A NAME="tex2html42"
+  HREF="cuddExtDet.html#Cudd_bddIte"><EM>  Cudd_bddIte</EM></A>.  This function takes three BDDs, <IMG
+ WIDTH="17" HEIGHT="35" ALIGN="MIDDLE" BORDER="0"
+ SRC="img8.png"
+ ALT="$f$">, <IMG
+ WIDTH="15" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img9.png"
+ ALT="$g$">, and <IMG
+ WIDTH="17" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img10.png"
+ ALT="$h$">,
+as arguments and computes <!-- MATH
+ $f\cdot g + f'\cdot h$
+ -->
+<IMG
+ WIDTH="97" HEIGHT="37" ALIGN="MIDDLE" BORDER="0"
+ SRC="img11.png"
+ ALT="$f\cdot g + f'\cdot h$">. Like all the
+functions that create new BDDs or ADDs, <A NAME="tex2html43"
+  HREF="cuddExtDet.html#Cudd_bddIte"><EM>  Cudd_bddIte</EM></A><A NAME="1495"></A> returns a result that must
+be explicitly referenced by the caller. <A NAME="tex2html44"
+  HREF="cuddExtDet.html#Cudd_bddIte"><EM>Cudd_bddIte</EM></A>
+can be
+used to implement all two-argument boolean functions. However, the
+package also provides <A NAME="tex2html45"
+  HREF="cuddExtDet.html#Cudd_bddAnd"><EM>Cudd_bddAnd</EM></A><A NAME="1497"></A>
+as well as the other two-operand boolean functions, which are slightly
+more efficient when a two-operand function is called for. The
+following fragment of code illustrates how to build the BDD for the
+function <!-- MATH
+ $f = x_0'x_1'x_2'x_3'$
+ -->
+<IMG
+ WIDTH="110" HEIGHT="37" ALIGN="MIDDLE" BORDER="0"
+ SRC="img12.png"
+ ALT="$f = x_0'x_1'x_2'x_3'$">.
+<PRE>
+        DdManager *manager;
+        DdNode *f, *var, *tmp;
+        int i;
+
+        ...
+
+        f = Cudd_ReadOne(manager);
+        Cudd_Ref(f);
+        for (i = 3; i &gt;= 0; i--) {
+            var = Cudd_bddIthVar(manager,i);
+            tmp = Cudd_bddAnd(manager,Cudd_Not(var),f);
+            Cudd_Ref(tmp);
+            Cudd_RecursiveDeref(manager,f);
+            f = tmp;
+        }
+</PRE>
+This example illustrates the following points:
+
+<UL>
+<LI>Intermediate results must be ``referenced" and ``dereferenced."
+  However, <TT>var</TT> is a projection<A NAME="355"></A>
+  function, and its reference<A NAME="356"></A> count is always
+  greater than 0. Therefore, there is no call to <A NAME="tex2html46"
+  HREF="cuddExtDet.html#Cudd_Ref"><EM>    Cudd_Ref</EM></A><A NAME="1499"></A>.
+</LI>
+<LI>The new <TT>f</TT> must be assigned to a temporary variable (<TT>    tmp</TT> in this example). If the result of <A NAME="tex2html47"
+  HREF="cuddExtDet.html#Cudd_bddAnd"><EM>    Cudd_bddAnd</EM></A><A NAME="1501"></A> were assigned directly
+
+to <TT>f</TT>, the old <TT>f</TT> would be lost, and there would be no way
+  to free its nodes.
+</LI>
+<LI>The statement <TT>f = tmp</TT> has the same effect as:
+<PRE>
+            f = tmp;
+            Cudd_Ref(f);
+            Cudd_RecursiveDeref(manager,tmp);
+</PRE>
+  but is more efficient. The reference<A NAME="370"></A> is
+  ``passed" from <TT>tmp</TT> to <TT>f</TT>, and <TT>tmp</TT> is now ready to
+  be reutilized.
+</LI>
+<LI>It is normally more efficient to build BDDs ``bottom-up." This
+  is why the loop goes from 3 to 0. Notice, however, that after
+  variable reordering, higher index does not necessarily mean ``closer
+  to the bottom." Of course, in this simple example, efficiency is not
+  a concern.
+</LI>
+<LI>Had we wanted to conjoin the variables in a bottom-up fashion
+  even after reordering, we should have used <A NAME="tex2html48"
+  HREF="cuddExtDet.html#Cudd_ReadInvPerm"><EM>    Cudd_ReadInvPerm</EM></A><A NAME="1503"></A>.  One has to be
+
+careful, though, to fix the order of conjunction before entering the
+  loop. Otherwise, if reordering takes place, it is possible to use
+  one variable twice and skip another variable.
+</LI>
+</UL>
+
+<P>
+
+<H2><A NAME="SECTION00038000000000000000"></A>
+<A NAME="379"></A><A NAME="sec:basicADD"></A>
+<BR>
+Basic ADD Manipulation
+</H2>
+
+<P>
+The most common way to manipulate ADDs is via <A NAME="tex2html49"
+  HREF="cuddExtDet.html#Cudd_addApply"><EM>  Cudd_addApply</EM></A><A NAME="1505"></A>.  This function can
+apply a wide variety of operators to a pair of ADDs.  Among the
+available operators are addition, multiplication, division, minimum,
+maximum, and boolean operators that work on ADDs whose leaves are
+restricted to 0 and 1 (0-1 ADDs).
+
+<P>
+The following fragment of code illustrates how to build the ADD for
+the function <!-- MATH
+ $f = 5x_0x_1x_2x_3$
+ -->
+<IMG
+ WIDTH="119" HEIGHT="35" ALIGN="MIDDLE" BORDER="0"
+ SRC="img13.png"
+ ALT="$f = 5x_0x_1x_2x_3$">.
+<PRE>
+        DdManager *manager;
+        DdNode *f, *var, *tmp;
+        int i;
+
+        ...
+
+        f = Cudd_addConst(manager,5);
+        Cudd_Ref(f);
+        for (i = 3; i &gt;= 0; i--) {
+            var = Cudd_addIthVar(manager,i);
+            Cudd_Ref(var);
+            tmp = Cudd_addApply(manager,Cudd_addTimes,var,f);
+            Cudd_Ref(tmp);
+            Cudd_RecursiveDeref(manager,f);
+            Cudd_RecursiveDeref(manager,var);
+            f = tmp;
+        }
+</PRE>
+This example, contrasted to the example of BDD manipulation,
+illustrates the following points:
+
+<UL>
+<LI>The ADD projection<A NAME="387"></A> function are not
+  maintained by the manager.  It is therefore necessary to
+  reference<A NAME="388"></A> and
+  dereference<A NAME="389"></A> them.
+</LI>
+<LI>The product of two ADDs is computed by calling <A NAME="tex2html50"
+  HREF="cuddExtDet.html#Cudd_addApply"><EM>    Cudd_addApply</EM></A><A NAME="1507"></A> with <A NAME="tex2html51"
+  HREF="cuddExtDet.html#Cudd_addTimes"><EM>    Cudd_addTimes</EM></A><A NAME="1509"></A> as parameter.  There
+
+is no ``apply'' function for BDDs, because <A NAME="tex2html52"
+  HREF="cuddExtDet.html#Cudd_bddAnd"><EM>    Cudd_bddAnd</EM></A><A NAME="1511"></A> and <A NAME="tex2html53"
+  HREF="cuddExtDet.html#Cudd_bddXor"><EM>    Cudd_bddXor</EM></A><A NAME="1513"></A> plus complementation are
+
+sufficient to implement all two-argument boolean functions.
+</LI>
+</UL>
+
+<P>
+
+<H2><A NAME="SECTION00039000000000000000"></A>
+<A NAME="404"></A><A NAME="sec:basicZDD"></A>
+<BR>
+Basic ZDD Manipulation
+</H2>
+
+<P>
+ZDDs are often generated by converting<A NAME="406"></A>
+existing BDDs. (See Section&nbsp;<A HREF="node3.html#sec:convertZ">3.11</A>.) However, it is also
+possible to build ZDDs by applying boolean operators to other ZDDs,
+starting from constants and projection<A NAME="408"></A>
+functions.  The following fragment of code illustrates how to build
+the ZDD for the function <!-- MATH
+ $f = x_0'+x_1'+x_2'+x_3'$
+ -->
+<IMG
+ WIDTH="174" HEIGHT="37" ALIGN="MIDDLE" BORDER="0"
+ SRC="img14.png"
+ ALT="$f = x_0'+x_1'+x_2'+x_3'$">. We assume that the
+four variables already exist in the manager when the ZDD for <IMG
+ WIDTH="17" HEIGHT="35" ALIGN="MIDDLE" BORDER="0"
+ SRC="img8.png"
+ ALT="$f$"> is
+built. Note the use of De Morgan's law.
+<PRE>
+        DdManager *manager;
+        DdNode *f, *var, *tmp;
+        int i;
+
+        manager = Cudd_Init(0,4,CUDD_UNIQUE_SLOTS,
+                            CUDD_CACHE_SLOTS,0);
+        ...
+
+        tmp = Cudd_ReadZddOne(manager,0);
+        Cudd_Ref(tmp);
+        for (i = 3; i &gt;= 0; i--) {
+            var = Cudd_zddIthVar(manager,i);
+            Cudd_Ref(var);
+            f = Cudd_zddIntersect(manager,var,tmp);
+            Cudd_Ref(f);
+            Cudd_RecursiveDerefZdd(manager,tmp);
+            Cudd_RecursiveDerefZdd(manager,var);
+            tmp = f;
+        }
+        f = Cudd_zddDiff(manager,Cudd_ReadZddOne(manager,0),tmp);
+        Cudd_Ref(f);
+        Cudd_RecursiveDerefZdd(manager,tmp);
+</PRE>
+This example illustrates the following points:
+
+<UL>
+<LI>The projection<A NAME="412"></A> functions are
+  referenced, because they are not maintained by the manager.
+</LI>
+<LI>Complementation is obtained by subtracting from the constant 1
+  function.
+</LI>
+<LI>The result of <A NAME="tex2html54"
+  HREF="cuddExtDet.html#Cudd_ReadZddOne"><EM>    Cudd_ReadZddOne</EM></A><A NAME="1515"></A> does not
+
+require referencing.
+</LI>
+</UL>
+CUDD provides functions for the manipulation of
+covers<A NAME="417"></A> represented by ZDDs. For instance, <A NAME="tex2html55"
+  HREF="cuddExtDet.html#Cudd_zddIsop"><EM>  Cudd_zddIsop</EM></A><A NAME="1517"></A> builds a ZDD
+representing an irredundant<A NAME="421"></A> sum of
+products for the incompletely specified function defined by the two
+BDDs <IMG
+ WIDTH="18" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img15.png"
+ ALT="$L$"> and <IMG
+ WIDTH="20" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img16.png"
+ ALT="$U$">. <A NAME="tex2html56"
+  HREF="cuddExtDet.html#Cudd_zddWeakDiv"><EM>  Cudd_zddWeakDiv</EM></A><A NAME="1519"></A> performs the weak
+division of two covers given as ZDDs.  These functions expect the two
+ZDD variables corresponding to the two literals of the function variable
+to be adjacent.  One has to create variable groups (see
+Section&nbsp;<A HREF="node3.html#sec:reordZ">3.14</A>) for reordering<A NAME="426"></A> of
+the ZDD variables to work.  BDD automatic reordering is safe even
+without groups: If realignment of ZDD and ADD/BDD variables is requested
+(see Section&nbsp;<A HREF="node3.html#sec:consist">3.15</A>) groups will be kept adjacent.
+
+<P>
+
+<H2><A NAME="SECTION000310000000000000000"></A>
+<A NAME="429"></A>
+<A NAME="430"></A><A NAME="sec:convert"></A>
+<BR>
+Converting ADDs to BDDs and Vice Versa
+</H2>
+
+<P>
+Several procedures are provided to convert ADDs to BDDs, according to
+different criteria. (<A NAME="tex2html57"
+  HREF="cuddExtDet.html#Cudd_addBddPattern"><EM>  Cudd_addBddPattern</EM></A><A NAME="1521"></A>, <A NAME="tex2html58"
+  HREF="cuddExtDet.html#Cudd_addBddInterval"><EM>  Cudd_addBddInterval</EM></A><A NAME="1523"></A>, and <A NAME="tex2html59"
+  HREF="cuddExtDet.html#Cudd_addBddThreshold"><EM>  Cudd_addBddThreshold</EM></A><A NAME="1525"></A>.) The
+conversion from BDDs to ADDs (<A NAME="tex2html60"
+  HREF="cuddExtDet.html#Cudd_BddToAdd"><EM>  Cudd_BddToAdd</EM></A><A NAME="1527"></A>) is based on the
+simple principle of mapping the logical 0<A NAME="444"></A> and 1 on
+the arithmetic<A NAME="445"></A> 0 and 1.  It is also possible to
+convert an ADD with integer values (more precisely, floating point
+numbers with 0 fractional part) to an array of BDDs by repeatedly
+calling <A NAME="tex2html61"
+  HREF="cuddExtDet.html#Cudd_addIthBit"><EM>Cudd_addIthBit</EM></A><A NAME="1529"></A>.
+
+<P>
+
+<H2><A NAME="SECTION000311000000000000000"></A>
+<A NAME="450"></A>
+<A NAME="451"></A><A NAME="sec:convertZ"></A>
+<BR>
+Converting BDDs to ZDDs and Vice Versa
+</H2>
+
+<P>
+Many applications first build a set of BDDs and then derive ZDDs from
+the BDDs. These applications should create the manager with 0
+ZDD<A NAME="453"></A> variables and
+create the BDDs. Then they should call <A NAME="tex2html62"
+  HREF="cuddExtDet.html#Cudd_zddVarsFromBddVars"><EM>  Cudd_zddVarsFromBddVars</EM></A><A NAME="1531"></A> to
+create the necessary ZDD variables--whose number is likely to be
+known once the BDDs are available.  This approach eliminates the
+difficulties that arise when the number of ZDD variables changes while
+ZDDs are being built.
+
+<P>
+The simplest conversion from BDDs to ZDDs is a simple change of
+representation, which preserves the functions. Simply put, given a BDD
+for <IMG
+ WIDTH="17" HEIGHT="35" ALIGN="MIDDLE" BORDER="0"
+ SRC="img8.png"
+ ALT="$f$">, a ZDD for <IMG
+ WIDTH="17" HEIGHT="35" ALIGN="MIDDLE" BORDER="0"
+ SRC="img8.png"
+ ALT="$f$"> is requested. In this case the correspondence
+between the BDD variables and ZDD variables is one-to-one. Hence, <A NAME="tex2html63"
+  HREF="cuddExtDet.html#Cudd_zddVarsFromBddVars"><EM>  Cudd_zddVarsFromBddVars</EM></A>
+should be called with the <EM>  multiplicity</EM> parameter equal to 1. The conversion proper can then
+be performed by calling <A NAME="tex2html64"
+  HREF="cuddExtDet.html#Cudd_zddPortFromBdd"><EM>  Cudd_zddPortFromBdd</EM></A><A NAME="1533"></A>. The
+inverse transformation is performed by <A NAME="tex2html65"
+  HREF="cuddExtDet.html#Cudd_zddPortToBdd"><EM>  Cudd_zddPortToBdd</EM></A><A NAME="1535"></A>.
+
+<P>
+ZDDs are quite often used for the representation of <EM>  covers</EM><A NAME="467"></A>. This is normally done by associating
+two ZDD variables to each variable of the function. (And hence,
+typically, to each BDD variable.) One ZDD variable is associated with
+the positive literal of the BDD variable, while the other ZDD variable
+is associated with the negative literal.  A call to <A NAME="tex2html66"
+  HREF="cuddExtDet.html#Cudd_zddVarsFromBddVars"><EM>  Cudd_zddVarsFromBddVars</EM></A><A NAME="1537"></A>
+with <EM>multiplicity</EM> equal to 2 will associate to BDD variable
+<IMG
+ WIDTH="12" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img6.png"
+ ALT="$i$"> the two ZDD variables <IMG
+ WIDTH="21" HEIGHT="19" ALIGN="BOTTOM" BORDER="0"
+ SRC="img17.png"
+ ALT="$2i$"> and <IMG
+ WIDTH="51" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img18.png"
+ ALT="$2i+1$">.
+
+<P>
+If a BDD variable group tree exists when <A NAME="tex2html67"
+  HREF="cuddExtDet.html#Cudd_zddVarsFromBddVars"><EM>  Cudd_zddVarsFromBddVars</EM></A>
+is called (see Section&nbsp;<A HREF="node3.html#sec:group">3.13</A>)
+the function generates a ZDD variable group tree consistent to it.  In
+any case, all the ZDD variables derived from the same BDD variable are
+clustered into a group.
+
+<P>
+If the ZDD for <IMG
+ WIDTH="17" HEIGHT="35" ALIGN="MIDDLE" BORDER="0"
+ SRC="img8.png"
+ ALT="$f$"> is created and later a new ZDD variable is added to
+the manager, the function represented by the existing ZDD changes.
+Suppose, for instance, that two variables are initially created, and
+that the ZDD for <IMG
+ WIDTH="97" HEIGHT="35" ALIGN="MIDDLE" BORDER="0"
+ SRC="img19.png"
+ ALT="$f = x_0 + x_1$"> is built. If a third variable is
+added, say <IMG
+ WIDTH="24" HEIGHT="34" ALIGN="MIDDLE" BORDER="0"
+ SRC="img20.png"
+ ALT="$x_2$">, then the ZDD represents <!-- MATH
+ $g = (x_0 + x_1) x_2'$
+ -->
+<IMG
+ WIDTH="126" HEIGHT="37" ALIGN="MIDDLE" BORDER="0"
+ SRC="img21.png"
+ ALT="$g = (x_0 + x_1) x_2'$">
+instead.  This change in function obviously applies regardless of what
+use is made of the ZDD. However, if the ZDD is used to represent a
+cover<A NAME="475"></A>, the cover itself is not changed by the
+addition of new variable. (What changes is the
+characteristic<A NAME="476"></A> function of the cover.)
+
+<P>
+
+<H2><A NAME="SECTION000312000000000000000"></A>
+<A NAME="478"></A><A NAME="sec:reorder"></A>
+<BR>
+Variable Reordering for BDDs and ADDs
+</H2>
+
+<P>
+The CUDD package provides a rich set of
+dynamic<A NAME="480"></A> reordering algorithms.  Some of them
+are slight variations of existing techniques
+[<A
+ HREF="node7.html#Rudell93">16</A>,<A
+ HREF="node7.html#Drechs95">6</A>,<A
+ HREF="node7.html#Bollig95">2</A>,<A
+ HREF="node7.html#Ishiur91">10</A>,<A
+ HREF="node7.html#Plessi93">15</A>,<A
+ HREF="node7.html#Jeong93">11</A>]; some
+others have been developed specifically for this package
+[<A
+ HREF="node7.html#Panda94">14</A>,<A
+ HREF="node7.html#Panda95b">13</A>].
+
+<P>
+Reordering affects a unique<A NAME="483"></A> table. This means that
+BDDs and ADDs, which share the same unique table are simultaneously
+reordered. ZDDs, on the other hand, are reordered separately. In the
+following we discuss the reordering of BDDs and ADDs. Reordering for
+ZDDs is the subject of Section&nbsp;<A HREF="node3.html#sec:reordZ">3.14</A>.
+
+<P>
+Reordering of the variables can be invoked directly by the application
+by calling <A NAME="tex2html68"
+  HREF="cuddExtDet.html#Cudd_ReduceHeap"><EM>Cudd_ReduceHeap</EM></A><A NAME="1539"></A>. Or it
+can be automatically triggered by the package when the number of nodes
+has reached a given threshold<A NAME="488"></A>.  (The
+threshold is initialized and automatically adjusted after each
+reordering by the package.) To enable automatic dynamic reordering
+(also called <EM>asynchronous<A NAME="489"></A></EM>
+dynamic reordering in this document) the application must call <A NAME="tex2html69"
+  HREF="cuddExtDet.html#Cudd_AutodynEnable"><EM>  Cudd_AutodynEnable</EM></A><A NAME="1541"></A>.  Automatic
+dynamic reordering can subsequently be disabled by calling <A NAME="tex2html70"
+  HREF="cuddExtDet.html#Cudd_AutodynDisable"><EM>  Cudd_AutodynDisable</EM></A><A NAME="1543"></A>.
+
+<P>
+All reordering methods are available in both the case of direct call
+to <A NAME="tex2html71"
+  HREF="cuddExtDet.html#Cudd_ReduceHeap"><EM>Cudd_ReduceHeap</EM></A><A NAME="1545"></A> and the case of
+automatic invocation. For many methods, the reordering procedure is
+iterated until no further improvement is obtained. We call these
+methods the <EM>converging<A NAME="499"></A></EM> methods.
+When constraints are imposed on the relative position of variables
+(see Section&nbsp;<A HREF="node3.html#sec:group">3.13</A>) the reordering methods apply inside the
+groups. The groups<A NAME="501"></A> themselves are reordered by
+sifting<A NAME="502"></A>.  Each method is identified by a
+constant of the enumerated type <EM>  Cudd_ReorderingType<A NAME="503"></A></EM>
+defined in <EM>cudd.h<A NAME="504"></A></EM> (the external
+header<A NAME="505"></A> file of the CUDD package):
+
+<P>
+<DL>
+<DT><STRONG>CUDD_REORDER_NONE<A NAME="507"></A>:</STRONG></DT>
+<DD>This method
+  causes no reordering.
+</DD>
+<DT><STRONG>CUDD_REORDER_SAME<A NAME="508"></A>:</STRONG></DT>
+<DD>If passed to
+  <A NAME="tex2html72"
+  HREF="cuddExtDet.html#Cudd_AutodynEnable"><EM>Cudd_AutodynEnable</EM></A><A NAME="1547"></A>, this
+
+method leaves the current method for automatic reordering unchanged.
+  If passed to <A NAME="tex2html73"
+  HREF="cuddExtDet.html#Cudd_ReduceHeap"><EM>Cudd_ReduceHeap</EM></A><A NAME="1549"></A>,
+
+this method causes the current method for automatic reordering to be
+  used.
+</DD>
+<DT><STRONG>CUDD_REORDER_RANDOM<A NAME="515"></A>:</STRONG></DT>
+<DD>Pairs of
+  variables are randomly chosen, and swapped in the order. The swap is
+  performed by a series of swaps of adjacent variables. The best order
+  among those obtained by the series of swaps is retained. The number
+  of pairs chosen for swapping<A NAME="516"></A> equals the
+  number of variables in the diagram.
+</DD>
+<DT><STRONG>CUDD_REORDER_RANDOM_PIVOT<A NAME="517"></A>:</STRONG></DT>
+<DD>Same as CUDD_REORDER_RANDOM, but the two variables are chosen so
+  that the first is above the variable with the largest number of
+  nodes, and the second is below that variable.  In case there are
+  several variables tied for the maximum number of nodes, the one
+  closest to the root is used.
+</DD>
+<DT><STRONG>CUDD_REORDER_SIFT<A NAME="518"></A>:</STRONG></DT>
+<DD>This method is
+  an implementation of Rudell's sifting<A NAME="519"></A>
+  algorithm [<A
+ HREF="node7.html#Rudell93">16</A>]. A simplified description of sifting is as
+  follows: Each variable is considered in turn. A variable is moved up
+  and down in the order so that it takes all possible positions. The
+  best position is identified and the variable is returned to that
+  position.
+
+<P>
+In reality, things are a bit more complicated. For instance, there
+  is a limit on the number of variables that will be sifted. This
+  limit can be read with <A NAME="tex2html74"
+  HREF="cuddExtDet.html#Cudd_ReadSiftMaxVar"><EM>    Cudd_ReadSiftMaxVar</EM></A><A NAME="1551"></A> and set
+
+with <A NAME="tex2html75"
+  HREF="cuddExtDet.html#Cudd_SetSiftMaxVar"><EM>Cudd_SetSiftMaxVar</EM></A><A NAME="1553"></A>. In
+
+addition, if the diagram grows too much while moving a variable up
+  or down, that movement is terminated before the variable has reached
+  one end of the order. The maximum ratio by which the diagram is
+  allowed to grow while a variable is being sifted can be read with
+  <A NAME="tex2html76"
+  HREF="cuddExtDet.html#Cudd_ReadMaxGrowth"><EM>Cudd_ReadMaxGrowth</EM></A><A NAME="1555"></A> and
+
+set with <A NAME="tex2html77"
+  HREF="cuddExtDet.html#Cudd_SetMaxGrowth"><EM>Cudd_SetMaxGrowth</EM></A><A NAME="1557"></A>.
+</DD>
+<DT><STRONG>CUDD_REORDER_SIFT_CONVERGE<A NAME="533"></A>:</STRONG></DT>
+<DD>This is the converging<A NAME="534"></A> variant of
+
+CUDD_REORDER_SIFT.
+</DD>
+<DT><STRONG>CUDD_REORDER_SYMM_SIFT<A NAME="535"></A>:</STRONG></DT>
+<DD>This method is an implementation of
+  symmetric<A NAME="536"></A> sifting [<A
+ HREF="node7.html#Panda94">14</A>]. It is
+  similar to sifting, with one addition: Variables that become
+  adjacent during sifting are tested for symmetry<A NAME="538"></A>. If
+  they are symmetric, they are linked in a group.  Sifting then
+  continues with a group being moved, instead of a single variable.
+  After symmetric sifting has been run, <A NAME="tex2html78"
+  HREF="cuddExtDet.html#Cudd_SymmProfile"><EM>    Cudd_SymmProfile</EM></A><A NAME="1559"></A> can be called
+
+to report on the symmetry groups found. (Both positive and negative
+  symmetries are reported.)
+</DD>
+<DT><STRONG>CUDD_REORDER_SYMM_SIFT_CONV<A NAME="542"></A>:</STRONG></DT>
+<DD>This is the converging<A NAME="543"></A> variant of
+  CUDD_REORDER_SYMM_SIFT.
+</DD>
+<DT><STRONG>CUDD_REORDER_GROUP_SIFT<A NAME="544"></A>:</STRONG></DT>
+<DD>This method is an implementation of group<A NAME="545"></A>
+  sifting [<A
+ HREF="node7.html#Panda95b">13</A>]. It is similar to symmetric sifting, but
+  aggregation<A NAME="547"></A> is not restricted to symmetric
+  variables.
+</DD>
+<DT><STRONG>CUDD_REORDER_GROUP_SIFT_CONV<A NAME="548"></A>:</STRONG></DT>
+<DD>This method repeats until convergence the combination of
+  CUDD_REORDER_GROUP_SIFT and CUDD_REORDER_WINDOW4.
+</DD>
+<DT><STRONG>CUDD_REORDER_WINDOW2<A NAME="549"></A>:</STRONG></DT>
+<DD>This
+  method implements the window<A NAME="550"></A> permutation
+  approach of Fujita [<A
+ HREF="node7.html#Fujita91b">8</A>] and Ishiura [<A
+ HREF="node7.html#Ishiur91">10</A>].
+  The size of the window is 2.
+</DD>
+<DT><STRONG>CUDD_REORDER_WINDOW3<A NAME="553"></A>:</STRONG></DT>
+<DD>Similar
+  to CUDD_REORDER_WINDOW2, but with a window of size 3.
+</DD>
+<DT><STRONG>CUDD_REORDER_WINDOW4<A NAME="554"></A>:</STRONG></DT>
+<DD>Similar
+  to CUDD_REORDER_WINDOW2, but with a window of size 4.
+</DD>
+<DT><STRONG>CUDD_REORDER_WINDOW2_CONV<A NAME="555"></A>:</STRONG></DT>
+<DD>This is the converging<A NAME="556"></A> variant of
+  CUDD_REORDER_WINDOW2.
+</DD>
+<DT><STRONG>CUDD_REORDER_WINDOW3_CONV<A NAME="557"></A>:</STRONG></DT>
+<DD>This is the converging variant of CUDD_REORDER_WINDOW3.
+</DD>
+<DT><STRONG>CUDD_REORDER_WINDOW4_CONV<A NAME="558"></A>:</STRONG></DT>
+<DD>This is the converging variant of CUDD_REORDER_WINDOW4.
+</DD>
+<DT><STRONG>CUDD_REORDER_ANNEALING<A NAME="559"></A>:</STRONG></DT>
+<DD>This
+  method is an implementation of simulated
+  annealing<A NAME="560"></A> for variable
+  ordering, vaguely resemblant of the algorithm of [<A
+ HREF="node7.html#Bollig95">2</A>].
+  This method is potentially very slow.
+</DD>
+<DT><STRONG>CUDD_REORDER_GENETIC:<A NAME="562"></A></STRONG></DT>
+<DD>This
+  method is an implementation of a genetic<A NAME="563"></A>
+  algorithm for variable ordering, inspired by the work of Drechsler
+  [<A
+ HREF="node7.html#Drechs95">6</A>]. This method is potentially very slow.
+</DD>
+<DT><STRONG>CUDD_REORDER_EXACT<A NAME="565"></A>:</STRONG></DT>
+<DD>This method
+  implements a dynamic programming approach to
+  exact<A NAME="566"></A> reordering
+  [<A
+ HREF="node7.html#Held62">9</A>,<A
+ HREF="node7.html#Friedman90">7</A>,<A
+ HREF="node7.html#Ishiur91">10</A>], with improvements described in
+  [<A
+ HREF="node7.html#Jeong93">11</A>]. It only stores one BDD at the time. Therefore, it is
+  relatively efficient in terms of memory.  Compared to other
+  reordering strategies, it is very slow, and is not recommended for
+  more than 16 variables.
+</DD>
+</DL>
+So far we have described methods whereby the package selects an order
+automatically. A given order of the variables can also be imposed by
+calling <A NAME="tex2html79"
+  HREF="cuddExtDet.html#Cudd_ShuffleHeap"><EM>Cudd_ShuffleHeap</EM></A><A NAME="1561"></A>.
+
+<P>
+
+<H2><A NAME="SECTION000313000000000000000"></A>
+<A NAME="574"></A><A NAME="sec:group"></A>
+<BR>
+Grouping Variables
+</H2>
+
+<P>
+CUDD allows the application to specify constraints on the positions of
+group of variables. It is possible to request that a group of
+contiguous variables be kept contiguous by the reordering procedures.
+It is also possible to request that the relative order of some groups
+of variables be left unchanged. The constraints on the order are
+specified by means of a tree<A NAME="576"></A>, which is created in
+one of two ways:
+
+<UL>
+<LI>By calling <A NAME="tex2html81"
+  HREF="cuddExtDet.html#Cudd_MakeTreeNode"><EM>Cudd_MakeTreeNode</EM></A><A NAME="1563"></A>.
+</LI>
+<LI>By calling the functions of the MTR<A NAME="581"></A> library
+
+(part of the distribution), and by registering the result with the
+  manager using <A NAME="tex2html82"
+  HREF="cuddExtDet.html#Cudd_SetTree"><EM>Cudd_SetTree</EM></A><A NAME="1565"></A>. The
+
+current tree registered with the manager can be read with <A NAME="tex2html83"
+  HREF="cuddExtDet.html#Cudd_ReadTree"><EM>    Cudd_ReadTree</EM></A><A NAME="1567"></A>.
+</LI>
+</UL>
+
+<P>
+Each node in the tree represents a range of variables. The lower bound
+of the range is given by the <EM>low</EM> field of the node, and the
+size of the group is given by the <EM>size</EM> field of the
+node.<A NAME="tex2html80"
+  HREF="footnode.html#foot1315"><SUP>2</SUP></A>  The variables in
+each range are kept contiguous. Furthermore, if a node is marked with
+the MTR_FIXED<A NAME="593"></A> flag, then the relative order of the
+variable ranges associated to its children is not changed.  As an
+example, suppose the initial variable order is:
+<PRE>
+        x0, y0, z0, x1, y1, z1, ... , x9, y9, z9.
+</PRE>
+Suppose we want to keep each group of three variables with the same
+index (e.g., <code>x3, y3, z3</code>) contiguous, while allowing the package
+to change the order of the groups. We can accomplish this with the
+following code:
+<PRE>
+        for (i = 0; i &lt; 10; i++) {
+            (void) Cudd_MakeTreeNode(manager,i*3,3,MTR_DEFAULT);
+        }
+</PRE>
+If we want to keep the order within each group of variables
+fixed (i.e., <code>x</code> before <code>y</code> before <code>z</code>) we need to
+change MTR_DEFAULT<A NAME="598"></A> into MTR_FIXED.
+
+<P>
+The <EM>low</EM> parameter passed to <A NAME="tex2html84"
+  HREF="cuddExtDet.html#Cudd_MakeTreeNode"><EM>  Cudd_MakeTreeNode</EM></A><A NAME="1569"></A> is the index
+of a variable (as opposed to its level or position in the order).  The
+group tree<A NAME="603"></A> can be created at any time. The result
+obviously depends on the variable order in effect at creation time.
+
+<P>
+It is possible to create a variable group tree also before the
+variables themselves are created. The package assumes in this case
+that the index of the variables not yet in existence will equal their
+position in the order when they are created. Therefore, applications
+that rely on <A NAME="tex2html85"
+  HREF="cuddExtDet.html#Cudd_bddNewVarAtLevel"><EM>  Cudd_bddNewVarAtLevel</EM></A><A NAME="1571"></A> or
+<A NAME="tex2html86"
+  HREF="cuddExtDet.html#Cudd_addNewVarAtLevel"><EM>Cudd_addNewVarAtLevel</EM></A><A NAME="1573"></A> to
+create new variables have to create the variables before they group
+them.
+
+<P>
+The reordering procedure will skip all groups whose variables are not
+yet in existence. For groups that are only partially in existence, the
+reordering procedure will try to reorder the variables already
+instantiated, without violating the adjacency constraints.
+
+<P>
+
+<H2><A NAME="SECTION000314000000000000000"></A>
+<A NAME="611"></A><A NAME="sec:reordZ"></A>
+<BR>
+Variable Reordering for ZDDs
+</H2>
+
+<P>
+Reordering of ZDDs is done in much the same way as the reordering of
+BDDs and ADDs. The functions corresponding to <A NAME="tex2html87"
+  HREF="cuddExtDet.html#Cudd_ReduceHeap"><EM>Cudd_ReduceHeap</EM></A>
+and <A NAME="tex2html88"
+  HREF="cuddExtDet.html#Cudd_ShuffleHeap"><EM>Cudd_ShuffleHeap</EM></A>
+are <A NAME="tex2html89"
+  HREF="cuddExtDet.html#Cudd_zddReduceHeap"><EM>  Cudd_zddReduceHeap</EM></A><A NAME="1575"></A> and <A NAME="tex2html90"
+  HREF="cuddExtDet.html#Cudd_zddShuffleHeap"><EM>  Cudd_zddShuffleHeap</EM></A><A NAME="1577"></A>. To enable
+dynamic<A NAME="623"></A> reordering, the application must
+call <A NAME="tex2html91"
+  HREF="cuddExtDet.html#Cudd_AutodynEnableZdd"><EM>Cudd_AutodynEnableZdd</EM></A><A NAME="1579"></A>,
+and to disable dynamic reordering, it must call <A NAME="tex2html92"
+  HREF="cuddExtDet.html#Cudd_AutodynDisableZdd"><EM>  Cudd_AutodynDisableZdd</EM></A><A NAME="1581"></A>.  In
+the current implementation, however, the choice of reordering methods
+for ZDDs is more limited. Specifically, these methods are available:
+
+<P>
+<DL>
+<DT><STRONG>CUDD_REORDER_NONE<A NAME="631"></A>;</STRONG></DT>
+<DD>
+</DD>
+<DT><STRONG>CUDD_REORDER_SAME<A NAME="632"></A>;</STRONG></DT>
+<DD>
+</DD>
+<DT><STRONG>CUDD_REORDER_RANDOM<A NAME="633"></A>;</STRONG></DT>
+<DD>
+</DD>
+<DT><STRONG>CUDD_REORDER_RANDOM_PIVOT<A NAME="634"></A>;</STRONG></DT>
+<DD>
+</DD>
+<DT><STRONG>CUDD_REORDER_SIFT<A NAME="635"></A>;</STRONG></DT>
+<DD>
+</DD>
+<DT><STRONG>CUDD_REORDER_SIFT_CONVERGE<A NAME="636"></A>;</STRONG></DT>
+<DD>
+</DD>
+<DT><STRONG>CUDD_REORDER_SYMM_SIFT<A NAME="637"></A>;</STRONG></DT>
+<DD>
+</DD>
+<DT><STRONG>CUDD_REORDER_SYMM_SIFT_CONV<A NAME="638"></A>.</STRONG></DT>
+<DD>
+</DD>
+</DL>
+
+<P>
+To create ZDD variable groups, the application calls <A NAME="tex2html93"
+  HREF="cuddExtDet.html#Cudd_MakeZddTreeNode"><EM>  Cudd_MakeZddTreeNode</EM></A><A NAME="1583"></A>.
+
+<P>
+
+<H2><A NAME="SECTION000315000000000000000"></A>
+<A NAME="sec:consist"></A>
+<BR>
+Keeping Consistent Variable Orders for BDDs and ZDDs
+</H2>
+
+<P>
+Several applications that manipulate both BDDs and ZDDs benefit from
+keeping a fixed correspondence between the order of the BDD variables
+and the order of the ZDD variables. If each BDD variable corresponds
+to a group of ZDD variables, then it is often desirable that the
+groups of ZDD variables be in the same order as the corresponding BDD
+variables. CUDD allows the ZDD order to
+track the BDD order and vice versa. To have the ZDD order track
+the BDD order, the application calls <A NAME="tex2html94"
+  HREF="cuddExtDet.html#Cudd_zddRealignEnable"><EM>  Cudd_zddRealignEnable</EM></A><A NAME="1585"></A>. The
+effect of this call can be reversed by calling <A NAME="tex2html95"
+  HREF="cuddExtDet.html#Cudd_zddRealignDisable"><EM>  Cudd_zddRealignDisable</EM></A><A NAME="1587"></A>. When
+ZDD realignment is in effect, automatic reordering of ZDDs should be
+disabled.
+
+<P>
+
+<H2><A NAME="SECTION000316000000000000000"></A>
+<A NAME="652"></A><A NAME="sec:hooks"></A>
+<BR>
+Hooks
+</H2>
+
+<P>
+Hooks in CUDD are lists of application-specified functions to be run on
+certain occasions. Each hook is identified by a constant of the
+enumerated type <A NAME="tex2html96"
+  HREF="cuddExtDet.html#Cudd_HookType"><EM>Cudd_HookType</EM></A><A NAME="1589"></A>. In Version
+2.4.1 hooks are defined for these occasions:
+
+<UL>
+<LI>before garbage collection (CUDD_PRE_GC_HOOK);
+</LI>
+<LI>after garbage collection (CUDD_POST_GC_HOOK);
+</LI>
+<LI>before variable reordering (CUDD_PRE_REORDERING_HOOK);
+</LI>
+<LI>after variable reordering (CUDD_POST_REORDERING_HOOK).
+</LI>
+</UL>
+The current implementation of hooks is experimental. A function added
+to a hook receives a pointer to the manager, a pointer to a constant
+string, and a pointer to void as arguments; it must return 1 if
+successful; 0 otherwise. The second argument is one of ``DD,''
+``BDD,'' and ``ZDD.'' This allows the hook functions to tell the type
+of diagram for which reordering or garbage collection takes place. The
+third argument varies depending on the hook. The hook functions called
+before or after garbage collection<A NAME="659"></A> do
+not use it. The hook functions called before
+reordering<A NAME="660"></A> are passed, in addition to the
+pointer to the manager, also the method used for reordering. The hook
+functions called after reordering are passed the start time. To add a
+function to a hook, one uses <A NAME="tex2html97"
+  HREF="cuddExtDet.html#Cudd_AddHook"><EM>  Cudd_AddHook</EM></A><A NAME="1591"></A>. The function of a given hook
+are called in the order in which they were added to the hook.  For
+sample hook functions, one may look at
+<I>Cudd_StdPreReordHook</I><A NAME="1593"></A> and
+<I>Cudd_StdPostReordHook</I><A NAME="1595"></A>.
+
+<P>
+
+<H2><A NAME="SECTION000317000000000000000"></A>
+<A NAME="669"></A><A NAME="670"></A><A NAME="sec:sis-vis"></A>
+<BR>
+The SIS/VIS Interface
+</H2>
+
+<P>
+The CUDD package contains interface functions that emulate the
+behavior of the original BDD package used in SIS [<A
+ HREF="node7.html#Sentov92">17</A>] and
+in the newer
+<A NAME="tex2html98"
+  HREF="http://vlsi.Colorado.EDU/~vis/">VIS</A>
+[<A
+ HREF="node7.html#VIS">4</A>]. How to build VIS with CUDD is described
+in the installation documents of VIS. (Version 1.1 and later.)
+
+<P>
+
+<H3><A NAME="SECTION000317100000000000000"></A>
+<A NAME="677"></A><A NAME="sec:sis"></A>
+<BR>
+Using the CUDD Package in SIS
+</H3>
+
+<P>
+This section describes how to build SIS with the CUDD package.  Let
+<TT>SISDIR<A NAME="679"></A></TT> designate the root of the directory
+hierarchy where the sources for SIS reside. Let <TT>  CUDDDIR<A NAME="680"></A></TT> be the root of the directory hierarchy where
+the distribution of the CUDD package resides.  To build SIS with the
+CUDD package, follow these steps.
+
+<OL>
+<LI>Create directories <TT>SISDIR/sis/cudd</TT> and <TT>    SISDIR/sis/mtr</TT>.
+</LI>
+<LI>Copy all files from <TT>CUDDDIR/cudd</TT> and <TT>CUDDDIR/sis</TT> to
+  <TT>SISDIR/sis/cudd</TT> and all files from <TT>CUDDDIR/mtr</TT> to <TT>  SISDIR/sis/mtr</TT>.
+</LI>
+<LI>Copy <TT>CUDDDIR/cudd/doc/cudd.doc</TT> to <TT>SISDIR/sis/cudd</TT>;
+  also copy <TT>CUDDDIR/mtr/doc/mtr.doc</TT> to <TT>SISDIR/sis/mtr</TT>.
+</LI>
+<LI>In <TT>SISDIR/sis/cudd</TT> make <TT>bdd.h</TT> a symbolic link to
+  <TT>cuddBdd.h</TT>. (That is: <TT>ln -s cuddBdd.h bdd.h</TT>.)
+</LI>
+<LI>In <TT>SISDIR/sis/cudd</TT> delete <TT>Makefile</TT> and rename <TT>    Makefile.sis</TT> as <TT>Makefile</TT>. Do the same in <TT>    SISDIR/sis/mtr</TT>.
+</LI>
+<LI>Copy <TT>CUDDDIR/sis/st.[ch]</TT> and <TT>CUDDDIR/st/doc/st.doc</TT>
+  to <TT>SISDIR/sis/st</TT>. (This will overwrite the original files: You
+  may want to save them beforehand.)
+</LI>
+<LI>From <TT>CUDDDIR/util</TT> copy <TT>datalimit.c</TT>
+  to <TT>SISDIR/sis/util</TT>. Update <TT>util.h</TT> and <TT>Makefile</TT>
+  in <TT>SISDIR/sis/util</TT>. Specifically, add the declaration
+  <TT>EXTERN long getSoftDataLimit();</TT> to <TT>util.h</TT> and add
+  <TT>datalimit.c</TT> to the list of source files (PSRC) in <TT>Makefile</TT>.
+</LI>
+<LI>In <TT>SISDIR/sis</TT> remove the link from <TT>bdd</TT> to <TT>    bdd_cmu</TT> or <TT>bdd_ucb</TT> (that is, <TT>rm bdd</TT>) and make <TT>    bdd</TT> a symbolic link to <TT>cudd</TT>.  (That is: <TT>ln -s cudd
+    bdd</TT>.)
+</LI>
+<LI>Still in <TT>SISDIR/sis</TT>, edit <TT>Makefile</TT>, <TT>    Makefile.oct</TT>, and <TT>Makefile.nooct</TT>. In all three files add
+  mtr to the list of directories to be made (DIRS).
+</LI>
+<LI>In <TT>SISDIR/sis/include</TT> make <TT>mtr.h</TT> a symbolic link to
+  <TT>../mtr/mtr.h</TT>.
+</LI>
+<LI>In <TT>SISDIR/sis/doc</TT> make <TT>cudd.doc</TT> a symbolic link to
+  <TT>../cudd/cudd.doc</TT> and <TT>mtr.doc</TT> a symbolic link to <TT>    ../mtr/mtr.doc</TT>. (That is: <TT>ln -s ../cudd/cudd.doc .; ln -s
+    ../mtr/mtr.doc .</TT>.)
+</LI>
+<LI>From <TT>SISDIR</TT> do <TT>make clean</TT> followed by <TT>make -i</TT>.
+  This should create a working copy of SIS that uses the CUDD package.
+</LI>
+</OL>
+
+<P>
+The replacement for the <TT>st</TT> library is because the version
+shipped with the CUDD package tests for out-of-memory conditions.
+Notice that the version of the <TT>st</TT> library to be used for
+replacement is not the one used for the normal build, because the
+latter has been modified for C++ compatibility. The above installation
+procedure has been tested on SIS 1.3. SIS can be obtained via
+anonymous FTP<A NAME="742"></A> from <A NAME="tex2html99"
+  HREF="ftp://ic.eecs.berkeley.edu"><TT>    ic.eecs.berkeley.edu</TT></A>.  To build SIS
+1.3, you need <TT>sis-1.2.tar.Z</TT> and <TT>sis-1.2.patch1.Z</TT>. When
+compiling on a DEC Alpha<A NAME="747"></A>, you should add the <TT>  -ieee_with_no_inexact</TT> flag. (See
+Section&nbsp;<A HREF="node3.html#sec:predef-const">3.5.2</A>.) Refer to the <TT>Makefile</TT> in the
+top level directory of the distribution for how to compile with 32-bit
+pointers.
+
+<P>
+
+<H2><A NAME="SECTION000318000000000000000"></A>
+<A NAME="sec:dump"></A>
+<BR>
+Writing Decision Diagrams to a File
+</H2>
+
+<P>
+The CUDD package provides several functions to write decision diagrams
+to a file. <A NAME="tex2html101"
+  HREF="cuddExtDet.html#Cudd_DumpBlif"><EM>Cudd_DumpBlif</EM></A><A NAME="1597"></A> writes a
+file in <EM>blif</EM> format.  It is restricted to BDDs. The diagrams
+are written as a network of multiplexers, one multiplexer for each
+internal node of the BDD.
+
+<P>
+<A NAME="tex2html102"
+  HREF="cuddExtDet.html#Cudd_DumpDot"><EM>Cudd_DumpDot</EM></A><A NAME="1599"></A> produces input suitable to
+the graph-drawing<A NAME="760"></A> program
+<A NAME="tex2html103"
+  HREF="http://www.research.att.com/sw/tools/graphviz"><EM>dot</EM></A>
+written by
+Eleftherios Koutsofios and Stephen C. North. An example of drawing
+produced by dot from the output of <A NAME="tex2html104"
+  HREF="cuddExtDet.html#Cudd_DumpDot"><EM>Cudd_DumpDot</EM></A>
+is shown in
+Figure&nbsp;<A HREF="node3.html#fi:phase">1</A>. It is restricted to BDDs and ADDs.
+
+<P></P>
+<DIV ALIGN="CENTER"><A NAME="fi:phase"></A><A NAME="1339"></A>
+<TABLE>
+<CAPTION ALIGN="BOTTOM"><STRONG>Figure 1:</STRONG>
+A BDD representing a phase constraint for the optimization of
+  fixed-polarity Reed-Muller forms. The label of each node is the
+  unique part of the node address. All nodes on the same level
+  correspond to the same variable, whose name is shown at the left of
+  the diagram. Dotted lines indicate complement<A NAME="768"></A>
+  arcs. Dashed lines indicate regular<A NAME="769"></A> ``else"
+  arcs.</CAPTION>
+<TR><TD><IMG
+ WIDTH="429" HEIGHT="701" BORDER="0"
+ SRC="img22.png"
+ ALT="\begin{figure}\centerline{\epsfig{file=phase.ps,height=15.5cm}}\end{figure}"></TD></TR>
+</TABLE>
+</DIV><P></P>
+
+<A NAME="tex2html105"
+  HREF="cuddExtDet.html#Cudd_zddDumpDot"><EM>Cudd_zddDumpDot</EM></A><A NAME="1601"></A> is the analog of <A NAME="tex2html106"
+  HREF="cuddExtDet.html#Cudd_DumpDot"><EM>  Cudd_DumpDot</EM></A>
+for ZDDs.
+
+<P>
+<A NAME="tex2html107"
+  HREF="cuddExtDet.html#Cudd_DumpDaVinci"><EM>Cudd_DumpDaVinci</EM></A><A NAME="1603"></A> produces input suitable to
+the graph-drawing<A NAME="780"></A> program
+<A NAME="tex2html108"
+  HREF="ftp://ftp.uni-bremen.de/pub/graphics/daVinci"><EM>    daVinci</EM></A>
+developed
+at the University of Bremen. It is  restricted to BDDs and ADDs.
+
+<P>
+Functions are also available to produce the input format of <EM>  DDcal</EM> (see Section&nbsp;<A HREF="node2.html#sec:getFriends">2.2</A>) and factored forms.
+
+<P>
+
+<H2><A NAME="SECTION000319000000000000000"></A>
+<A NAME="sec:save-restore"></A>
+<BR>
+Saving and Restoring BDDs
+</H2>
+
+<P>
+The <A NAME="tex2html109"
+  HREF="ftp://ftp.polito.it/pub/research/dddmp/"><EM>dddmp</EM></A>
+library<A NAME="789"></A> by Gianpiero Cabodi and
+Stefano Quer allows a CUDD application to save BDDs to disk in compact
+form for later retrieval. See the library's own documentation for the
+details.
+
+<P>
+<HR>
+<!--Navigation Panel-->
+<A NAME="tex2html272"
+  HREF="node4.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html268"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html262"
+  HREF="node2.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html270"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html273"
+  HREF="node4.html">Programmer's Manual</A>
+<B> Up:</B> <A NAME="tex2html269"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html263"
+  HREF="node2.html">How to Get CUDD</A>
+ &nbsp <B>  <A NAME="tex2html271"
+  HREF="node8.html">Index</A></B> 
+<!--End of Navigation Panel-->
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node4.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node4.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node4.html	(revision 8)
@@ -0,0 +1,1208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>Programmer's Manual</TITLE>
+<META NAME="description" CONTENT="Programmer's Manual">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node5.html">
+<LINK REL="previous" HREF="node3.html">
+<LINK REL="up" HREF="cuddIntro.html">
+<LINK REL="next" HREF="node5.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html313"
+  HREF="node5.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html309"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html303"
+  HREF="node3.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html311"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html314"
+  HREF="node5.html">The C++ Interface</A>
+<B> Up:</B> <A NAME="tex2html310"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html304"
+  HREF="node3.html">User's Manual</A>
+ &nbsp <B>  <A NAME="tex2html312"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+<!--Table of Child-Links-->
+<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></A>
+
+<UL>
+<LI><A NAME="tex2html315"
+  HREF="#SECTION00041000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html316"
+  HREF="#SECTION00042000000000000000">Reference Counts</A>
+<UL>
+<LI><A NAME="tex2html317"
+  HREF="#SECTION00042100000000000000">NULL Return Values</A>
+<LI><A NAME="tex2html318"
+  HREF="#SECTION00042200000000000000"><EM>Cudd_RecursiveDeref</EM> vs. <EM>Cudd_Deref</EM></A>
+<LI><A NAME="tex2html319"
+  HREF="#SECTION00042300000000000000">When Increasing the Reference Count is Unnecessary</A>
+<LI><A NAME="tex2html320"
+  HREF="#SECTION00042400000000000000">Saturating Increments and Decrements</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html321"
+  HREF="#SECTION00043000000000000000">Complement Arcs</A>
+<LI><A NAME="tex2html322"
+  HREF="#SECTION00044000000000000000">The Cache</A>
+<UL>
+<LI><A NAME="tex2html323"
+  HREF="#SECTION00044100000000000000">Cache Sizing</A>
+<LI><A NAME="tex2html324"
+  HREF="#SECTION00044200000000000000">Local Caches</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html325"
+  HREF="#SECTION00045000000000000000">The Unique Table</A>
+<LI><A NAME="tex2html326"
+  HREF="#SECTION00046000000000000000">Allowing Asynchronous Reordering</A>
+<LI><A NAME="tex2html327"
+  HREF="#SECTION00047000000000000000">Debugging</A>
+<LI><A NAME="tex2html328"
+  HREF="#SECTION00048000000000000000">Gathering and Interpreting Statistics</A>
+<UL>
+<LI><A NAME="tex2html329"
+  HREF="#SECTION00048100000000000000">Non Modifiable Parameters</A>
+<LI><A NAME="tex2html330"
+  HREF="#SECTION00048200000000000000">Modifiable Parameters</A>
+<LI><A NAME="tex2html331"
+  HREF="#SECTION00048300000000000000">Extended Statistics and Reporting</A>
+</UL>
+<BR>
+<LI><A NAME="tex2html332"
+  HREF="#SECTION00049000000000000000">Guidelines for Documentation</A>
+</UL>
+<!--End of Table of Child-Links-->
+<HR>
+
+<H1><A NAME="SECTION00040000000000000000"></A>
+<A NAME="sec:prog"></A>
+<BR>
+Programmer's Manual
+</H1>
+
+<P>
+This section provides additional detail on the working of the CUDD
+package and on the programming conventions followed in its writing.
+The additional detail should help those who want to write procedures
+that directly manipulate the CUDD data structures.
+
+<P>
+
+<H2><A NAME="SECTION00041000000000000000"></A>
+<A NAME="793"></A><A NAME="sec:compileInt"></A>
+<BR>
+Compiling and Linking
+</H2>
+
+<P>
+If you plan to use the CUDD package as a clear box<A NAME="795"></A>
+(for instance, you want to write a procedure that traverses a decision
+diagram) you need to add
+<PRE>
+#include "cuddInt.h"
+</PRE>
+to your source files. In addition, you should link <code>libcudd.a</code> to
+your executable.  Some platforms require specific compiler and linker
+flags.  Refer to the <TT>Makefile</TT> in the top level directory of the
+distribution.
+
+<P>
+
+<H2><A NAME="SECTION00042000000000000000"></A>
+<A NAME="800"></A><A NAME="sec:ref"></A>
+<BR>
+Reference Counts
+</H2>
+
+<P>
+Garbage<A NAME="802"></A> collection in the CUDD package is
+based on reference counts.  Each node stores the sum of the external
+references and internal references. An internal BDD or ADD node is
+created by a call to <A NAME="tex2html110"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>cuddUniqueInter</EM></A><A NAME="1605"></A>, an
+internal ZDD node is created by a call to <A NAME="tex2html111"
+  HREF="cuddAllDet.html#cuddUniqueInterZdd"><EM>  cuddUniqueInterZdd</EM></A><A NAME="1607"></A>, and a
+terminal<A NAME="809"></A> node is created by a call to <A NAME="tex2html112"
+  HREF="cuddAllDet.html#cuddUniqueConst"><EM>  cuddUniqueConst</EM></A><A NAME="1609"></A>. If the node returned by
+these functions is new, its reference count is zero.  The function
+that calls <A NAME="tex2html113"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>cuddUniqueInter</EM></A><A NAME="1611"></A>, <A NAME="tex2html114"
+  HREF="cuddAllDet.html#cuddUniqueInterZdd"><EM>  cuddUniqueInterZdd</EM></A><A NAME="1613"></A>, or <A NAME="tex2html115"
+  HREF="cuddAllDet.html#cuddUniqueConst"><EM>  cuddUniqueConst</EM></A><A NAME="1615"></A> is responsible for
+increasing the reference count of the node. This is accomplished by
+calling <A NAME="tex2html116"
+  HREF="cuddExtDet.html#Cudd_Ref"><EM>Cudd_Ref</EM></A><A NAME="1617"></A>.
+
+<P>
+When a function is no longer needed by an application, the memory used
+by its diagram can be recycled by calling <A NAME="tex2html117"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1619"></A> (BDDs and
+ADDs) or <A NAME="tex2html118"
+  HREF="cuddExtDet.html#Cudd_RecursiveDerefZdd"><EM>  Cudd_RecursiveDerefZdd</EM></A><A NAME="1621"></A>
+(ZDDs).  These functions decrease the reference
+<A NAME="831"></A> count of the node passed to them.
+If the reference count becomes 0, then two things happen:
+
+<OL>
+<LI>The node is declared ``dead<A NAME="833"></A>;" this entails
+  increasing the counters<A NAME="834"></A> of the dead
+  nodes. (One counter for the subtable<A NAME="835"></A> to which the
+  node belongs, and one global counter for the
+  unique<A NAME="836"></A> table to which the node belongs.) The
+  node itself is not affected.
+</LI>
+<LI>The function is recursively called on the two children of the
+  node.
+</LI>
+</OL>
+For instance, if the diagram of a function does not share any nodes
+with other diagrams, then calling <A NAME="tex2html119"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1623"></A> or <A NAME="tex2html120"
+  HREF="cuddExtDet.html#Cudd_RecursiveDerefZdd"><EM>  Cudd_RecursiveDerefZdd</EM></A><A NAME="1625"></A> on
+its root will cause all the nodes of the diagram to become dead.
+
+<P>
+When the number of dead nodes reaches a given level (dynamically
+determined by the package) garbage collection takes place. During
+garbage<A NAME="844"></A> collection dead nodes are returned
+to the node free list<A NAME="845"></A>.
+
+<P>
+When a new node is created, it is important to increase its
+reference<A NAME="846"></A> count before one of the two
+following events occurs:
+
+<OL>
+<LI>A call to <A NAME="tex2html121"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>cuddUniqueInter</EM></A><A NAME="1627"></A>,
+
+to <A NAME="tex2html122"
+  HREF="cuddAllDet.html#cuddUniqueInterZdd"><EM>cuddUniqueInterZdd</EM></A><A NAME="1629"></A>, to
+
+<A NAME="tex2html123"
+  HREF="cuddAllDet.html#cuddUniqueConst"><EM>cuddUniqueConst</EM></A><A NAME="1631"></A>, or to a
+
+function that may eventually cause a call to them.
+</LI>
+<LI>A call to <A NAME="tex2html124"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>    Cudd_RecursiveDeref</EM></A><A NAME="1633"></A>, to <A NAME="tex2html125"
+  HREF="cuddExtDet.html#Cudd_RecursiveDerefZdd"><EM>    Cudd_RecursiveDerefZdd</EM></A><A NAME="1635"></A>, or
+
+to a function that may eventually cause a call to them.
+</LI>
+</OL>
+In practice, it is recommended to increase the reference count as soon
+as the returned pointer has been tested for not being NULL.
+
+<P>
+
+<H3><A NAME="SECTION00042100000000000000"></A>
+<A NAME="sec:null"></A>
+<BR>
+NULL Return Values
+</H3>
+
+<P>
+The interface to the memory management functions (e.g., malloc) used by CUDD
+intercepts NULL return values and calls a handler. The default handler
+exits with an error message. If the application does not install
+another handler, therefore, a NULL return value from an exported
+function of CUDD signals an internal error.
+
+<P>
+If the aplication, however, installs another handler that lets
+execution continue, a NULL pointer returned by an exported function
+typically indicates that the process has run out of memory. <A NAME="tex2html126"
+  HREF="cuddExtDet.html#Cudd_ReadErrorCode"><EM>  Cudd_ReadErrorCode</EM></A><A NAME="1637"></A> can be used to
+ascertain the nature of the problem.
+
+<P>
+An application that tests for the result being NULL can try some
+remedial action, if it runs out of memory.  For instance, it may free
+some memory that is not strictly necessary, or try a slower algorithm
+that takes less space. As an example, CUDD overrides the default
+handler when trying to enlarge the cache or increase the number of
+slots of the unique table. If the allocation fails, the package prints
+out a message and continues without resizing the cache.
+
+<P>
+
+<H3><A NAME="SECTION00042200000000000000"></A>
+<A NAME="sec:deref"></A>
+<BR>
+<EM>Cudd_RecursiveDeref</EM> vs. <EM>Cudd_Deref</EM>
+</H3>
+
+<P>
+It is often the case that a recursive procedure has to protect the
+result it is going to return, while it disposes of intermediate
+results.  (See the previous discussion on when to increase reference
+counts.)  Once the intermediate results have been properly disposed
+of, the final result must be returned to its pristine state, in which
+the root node may have a reference count of 0. One cannot use <A NAME="tex2html127"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1639"></A> (or <A NAME="tex2html128"
+  HREF="cuddExtDet.html#Cudd_RecursiveDerefZdd"><EM>  Cudd_RecursiveDerefZdd</EM></A>) for this purpose, because it may
+erroneously make some nodes dead.  Therefore, the package provides a
+different function: <A NAME="tex2html129"
+  HREF="cuddExtDet.html#Cudd_Deref"><EM>Cudd_Deref</EM></A><A NAME="1641"></A>. This
+function is not recursive, and does not change the dead node counts.
+Its use is almost exclusively the one just described: Decreasing the
+reference count of the root of the final result before returning from
+a recursive procedure.
+
+<P>
+
+<H3><A NAME="SECTION00042300000000000000"></A>
+<A NAME="881"></A><A NAME="sec:noref"></A>
+<BR>
+When Increasing the Reference Count is Unnecessary
+</H3>
+
+<P>
+When a copy of a predefined constant<A NAME="883"></A> or of a
+simple BDD variable is needed for comparison purposes, then calling
+<A NAME="tex2html130"
+  HREF="cuddExtDet.html#Cudd_Ref"><EM>Cudd_Ref</EM></A><A NAME="1643"></A> is not necessary, because
+these simple functions are guaranteed to have reference counts greater
+than 0 at all times. If no call to <A NAME="tex2html131"
+  HREF="cuddExtDet.html#Cudd_Ref"><EM>Cudd_Ref</EM></A>
+is made, then no
+attempt to free the diagram by calling <A NAME="tex2html132"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1645"></A> or <A NAME="tex2html133"
+  HREF="cuddExtDet.html#Cudd_RecursiveDerefZdd"><EM>  Cudd_RecursiveDerefZdd</EM></A><A NAME="1647"></A>
+should be made.
+
+<P>
+
+<H3><A NAME="SECTION00042400000000000000"></A>
+<A NAME="896"></A><A NAME="897"></A><A NAME="sec:satur"></A>
+<BR>
+Saturating Increments and Decrements
+</H3>
+
+<P>
+On 32-bit machines, the CUDD package stores the
+reference<A NAME="899"></A> counts in unsigned short int's.
+For large diagrams, it is possible for some reference counts to exceed
+the capacity of an unsigned short int.  Therefore, increments and
+decrements of reference counts are <EM>saturating</EM>. This means that
+once a reference count has reached the maximum possible value, it is
+no longer changed by calls to <A NAME="tex2html134"
+  HREF="cuddExtDet.html#Cudd_Ref"><EM>Cudd_Ref</EM></A>, <A NAME="tex2html135"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1649"></A>, <A NAME="tex2html136"
+  HREF="cuddExtDet.html#Cudd_RecursiveDerefZdd"><EM>  Cudd_RecursiveDerefZdd</EM></A><A NAME="1651"></A>, or
+<A NAME="tex2html137"
+  HREF="cuddExtDet.html#Cudd_Deref"><EM>Cudd_Deref</EM></A><A NAME="1653"></A>. As a consequence, some
+nodes that have no references may not be declared dead. This may
+result in a small waste of memory, which is normally more than offset
+by the reduction in size of the node structure.
+
+<P>
+When using 64-bit pointers, there is normally no memory advantage from
+using short int's instead of int's in a DdNode. Therefore, increments
+and decrements are not saturating in that case. What option is in
+effect depends on two macros, SIZEOF_VOID_P<A NAME="912"></A>
+and SIZEOF_INT<A NAME="913"></A>, defined in the external
+header<A NAME="914"></A> file (<EM>cudd.h</EM><A NAME="916"></A>). The
+increments and decrements of the reference counts are performed using
+two macros: <A NAME="tex2html138"
+  HREF="cuddAllDet.html#cuddSatInc"><EM>cuddSatInc</EM></A><A NAME="1655"></A> and <A NAME="tex2html139"
+  HREF="cuddAllDet.html#cuddSatDec"><EM>  cuddSatDec</EM></A><A NAME="1657"></A>, whose definitions depend on
+SIZEOF_VOID_P<A NAME="923"></A> and
+SIZEOF_INT<A NAME="924"></A>.
+
+<P>
+
+<H2><A NAME="SECTION00043000000000000000"></A>
+<A NAME="926"></A><A NAME="sec:compl"></A>
+<BR>
+Complement Arcs
+</H2>
+
+<P>
+If ADDs are restricted to use only the constants 0 and 1, they behave
+like BDDs without complement arcs. It is normally easier to write code
+that manipulates 0-1 ADDs, than to write code for BDDs. However,
+complementation is trivial with complement arcs, and is not trivial
+without. As a consequence, with complement arcs it is possible to
+check for more terminal cases and it is possible to apply De Morgan's
+laws to reduce problems that are essentially identical to a standard
+form. This in turn increases the utilization of the cache<A NAME="928"></A>.
+
+<P>
+The complement attribute is stored in the least significant bit of the
+``else" pointer of each node. An external pointer to a function can
+also be complemented. The ``then" pointer to a node, on the other
+hand, is always <EM>regular<A NAME="929"></A></EM>. It is a mistake to
+use a<A NAME="930"></A> pointer as it is to address memory. Instead, it
+is always necessary to obtain a regular version of it. This is
+normally done by calling <A NAME="tex2html140"
+  HREF="cuddExtDet.html#Cudd_Regular"><EM>  Cudd_Regular</EM></A><A NAME="1659"></A>. It is also a mistake to
+call <A NAME="tex2html141"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>cuddUniqueInter</EM></A><A NAME="1661"></A> with a
+complemented ``then" child as argument. The calling procedure must
+apply De Morgan's laws by complementing both pointers passed to <A NAME="tex2html142"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>  cuddUniqueInter</EM></A><A NAME="1663"></A> and then taking the
+complement of the result.
+
+<P>
+
+<H2><A NAME="SECTION00044000000000000000"></A>
+<A NAME="941"></A><A NAME="sec:cache"></A>
+<BR>
+The Cache
+</H2>
+
+<P>
+Each entry of the cache consists of five fields: The operator, three
+pointers to operands and a pointer to the result. The operator and the
+three pointers to the operands are combined to form three words. The
+combination relies on two facts:
+
+<UL>
+<LI>Most operations have one or two operands. A few bits are
+  sufficient to discriminate all three-operands operations.
+</LI>
+<LI>All nodes are aligned to 16-byte boundaries. (32-byte boundaries
+  if 64-bit pointers are used.) Hence, there are a few bits available
+  to distinguish the three-operand operations from te others and to
+  assign unique codes to them.
+</LI>
+</UL>
+
+<P>
+The cache does not contribute to the reference
+<A NAME="945"></A>
+counts of the nodes.  The fact that the cache contains a
+pointer to a node does not imply that the node is alive. Instead, when
+garbage<A NAME="946"></A> collection takes place, all entries
+of the cache pointing to dead<A NAME="947"></A> nodes are cleared.
+
+<P>
+The cache is also cleared (of all entries) when dynamic
+reordering<A NAME="948"></A> takes place. In both cases, the entries
+removed from the cache are about to become invalid.
+
+<P>
+All operands and results in a cache entry must be pointers to
+DdNodes<A NAME="949"></A>.  If a function produces more than one result,
+or uses more than three arguments, there are currently two solutions:
+
+<UL>
+<LI>Build a separate, local, cache<A NAME="951"></A>. (Using, for
+  instance, the <EM>st</EM> library<A NAME="953"></A>.)
+</LI>
+<LI>Combine multiple results, or multiple operands, into a single
+  diagram, by building a ``multiplexing structure" with reserved
+  variables.
+</LI>
+</UL>
+Support of the former solution is under development. (See <TT>  cuddLCache.c</TT>..)  Support for the latter solution may be provided
+in future versions of the package.
+
+<P>
+There are three sets of interface<A NAME="956"></A> functions to
+the cache. The first set is for functions with three operands: <A NAME="tex2html143"
+  HREF="cuddAllDet.html#cuddCacheInsert"><EM>  cuddCacheInsert</EM></A><A NAME="1665"></A> and <A NAME="tex2html144"
+  HREF="cuddAllDet.html#cuddCacheLookup"><EM>  cuddCacheLookup</EM></A><A NAME="1667"></A>. The second set is for
+functions with two operands: <A NAME="tex2html145"
+  HREF="cuddAllDet.html#cuddCacheInsert2"><EM>  cuddCacheInsert2</EM></A><A NAME="1669"></A> and <A NAME="tex2html146"
+  HREF="cuddAllDet.html#cuddCacheLookup2"><EM>  cuddCacheLookup2</EM></A><A NAME="1671"></A>.
+The second set is for
+functions with one operand: <A NAME="tex2html147"
+  HREF="cuddAllDet.html#cuddCacheInsert1"><EM>  cuddCacheInsert1</EM></A><A NAME="1673"></A> and <A NAME="tex2html148"
+  HREF="cuddAllDet.html#cuddCacheLookup1"><EM>  cuddCacheLookup1</EM></A><A NAME="1675"></A>.
+The second set is
+slightly faster than the first, and the third set is slightly faster
+than the second.
+
+<P>
+
+<H3><A NAME="SECTION00044100000000000000"></A>
+<A NAME="976"></A><A NAME="sec:cache-sizing"></A>
+<BR>
+Cache Sizing
+</H3>
+
+<P>
+The size of the cache can increase during the execution of an
+application. (There is currently no way to decrease the size of the
+cache, though it would not be difficult to do it.) When a cache miss
+occurs, the package uses the following criteria to decide whether to
+resize the cache:
+
+<OL>
+<LI>If the cache already exceeds the limit given by the <TT>    maxCache<A NAME="979"></A></TT> field of the manager, no resizing takes
+  place. The limit is the minimum of two values: a value set at
+  initialization time and possibly modified by the application, which
+  constitutes the hard limit beyond which the cache will never grow;
+  and a number that depends on the current total number of slots in
+  the unique<A NAME="980"></A> table.
+</LI>
+<LI>If the cache is not too large already, resizing is decided based
+  on the hit rate. The policy adopted by the CUDD package is
+  ``reward-based<A NAME="981"></A>." If the cache hit
+  rate is high, then it is worthwhile to increase the size of the
+  cache.
+</LI>
+</OL>
+When resizing takes place, the statistical counters <A NAME="983"></A> used to compute the hit rate are reinitialized so as to
+prevent immediate resizing. The number of entries is doubled.
+
+<P>
+The rationale for the ``reward-based<A NAME="984"></A>"
+policy is as follows. In many BDD/ADD applications the hit rate is
+not very sensitive to the size of the cache: It is primarily a
+function of the problem instance at hand.  If a large hit rate is
+observed, chances are that by using a large cache, the results of
+large problems (those that would take longer to solve) will survive in
+the cache without being overwritten long enough to cause a valuable
+cache hit. Notice that when a large problem is solved more than once,
+so are its recursively generated subproblems.  If the hit rate is
+low, the probability of large problems being solved more than once is
+low.
+
+<P>
+The other observation about the cache sizing policy is that there is
+little point in keeping a cache which is much larger than the unique
+table. Every time the unique table ``fills up," garbage collection is
+invoked and the cache is cleared of all dead entries. A cache that is
+much larger than the unique<A NAME="985"></A> table is therefore
+less than fully utilized.
+
+<P>
+
+<H3><A NAME="SECTION00044200000000000000"></A>
+<A NAME="987"></A><A NAME="sec:local-caches"></A>
+<BR>
+Local Caches
+</H3>
+
+<P>
+Sometimes it may be necessary or convenient to use a local cache.  A
+local cache can be lossless<A NAME="989"></A> (no results are ever
+overwritten), or it may store objects for which
+canonical<A NAME="990"></A> representations are not available.  One
+important fact to keep in mind when using a local cache is that local
+caches are not cleared during garbage<A NAME="991"></A>
+collection or before reordering. Therefore, it is necessary to
+increment the reference<A NAME="992"></A> count of all nodes
+pointed by a local cache. (Unless their reference counts are
+guaranteed positive in some other way. One such way is by including
+all partial results in the global result.) Before disposing of the
+local cache, all elements stored in it must be passed to <A NAME="tex2html149"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1677"></A>. As
+consequence of the fact that all results in a local cache are
+referenced, it is generally convenient to store in the local cache
+also the result of trivial problems, which are not usually stored in
+the global cache. Otherwise, after a recursive call, it is difficult
+to tell whether the result is in the cache, and therefore referenced,
+or not in the cache, and therefore not referenced.
+
+<P>
+An alternative approach to referencing the results in the local caches
+is to install hook functions (see Section&nbsp;<A HREF="node3.html#sec:hooks">3.16</A>) to be
+executed before garbage collection.
+
+<P>
+
+<H2><A NAME="SECTION00045000000000000000"></A>
+<A NAME="998"></A><A NAME="sec:unique"></A>
+<BR>
+The Unique Table
+</H2>
+
+<P>
+A recursive procedure typically splits the operands by expanding with
+respect to the topmost variable. Topmost in this context refers to the
+variable that is closest to the roots in the current variable order.
+The nodes, on the other hand, hold the index, which is invariant with
+reordering. Therefore, when splitting, one must use the
+permutation<A NAME="1000"></A> array maintained by the
+package to get the right level. Access to the permutation array is
+provided by the macro <A NAME="tex2html150"
+  HREF="cuddAllDet.html#cuddI"><EM>cuddI</EM></A><A NAME="1679"></A> for BDDs and ADDs,
+and by the macro <A NAME="tex2html151"
+  HREF="cuddAllDet.html#cuddIZ"><EM>cuddIZ</EM></A><A NAME="1681"></A> for ZDDs.
+
+<P>
+The unique table consists of as many hash<A NAME="1007"></A> tables as there are
+variables in use. These has tables are called <EM>unique subtables</EM>.
+The sizes of the unique subtables are determined by two criteria:
+
+<OL>
+<LI>The collision<A NAME="1010"></A> lists should be short
+  to keep access time down.
+</LI>
+<LI>There should be enough room for dead<A NAME="1011"></A> nodes, to
+  prevent too frequent garbage<A NAME="1012"></A> collections.
+</LI>
+</OL>
+While the first criterion is fairly straightforward to implement, the
+second leaves more room to creativity. The CUDD package tries to
+figure out whether more dead node should be allowed to increase
+performance.  (See also Section&nbsp;<A HREF="node3.html#sec:params">3.4</A>.) There are two
+reasons for not doing garbage collection too often. The obvious one is
+that it is expensive.  The second is that dead nodes may be
+reclaimed<A NAME="1015"></A>, if they are the result of a
+successful cache lookup. Hence dead nodes may provide a substantial
+speed-up if they are kept around long enough.  The usefulness of
+keeping many dead nodes around varies from application to application,
+and from problem instance to problem instance. As in the sizing of the
+cache, the CUDD package adopts a
+``reward-based<A NAME="1016"></A>" policy to
+decide how much room should be used for the unique table. If the
+number of dead nodes reclaimed is large compared to the number of
+nodes directly requested from the memory manager, then the CUDD
+package assumes that it will be beneficial to allow more room for the
+subtables, thereby reducing the frequency of garbage collection.  The
+package does so by switching between two modes of operation:
+
+<OL>
+<LI>Fast growth<A NAME="1018"></A>: In this mode, the
+  ratio of dead nodes to total nodes required for garbage collection
+  is higher than in the slow growth mode to favor resizing
+  of the subtables.
+</LI>
+<LI>Slow growth<A NAME="1019"></A>: In this
+  mode keeping many dead nodes around is not as important as
+  keeping memory requirements low.
+</LI>
+</OL>
+Switching from one mode to the other is based on the following
+criteria:
+
+<OL>
+<LI>If the unique table is already large, only slow growth is
+  possible.
+</LI>
+<LI>If the table is small and many dead nodes are being reclaimed,
+  then fast growth is selected.
+</LI>
+</OL>
+This policy is especially effective when the diagrams being
+manipulated have lots of recombination. Notice the interplay of the
+cache sizing and unique sizing: Fast growth normally occurs when the
+cache hit rate is large. The cache and the unique table then grow in
+concert, preserving a healthy balance between their sizes.
+
+<P>
+
+<H2><A NAME="SECTION00046000000000000000"></A>
+<A NAME="1024"></A><A NAME="sec:async"></A>
+<BR>
+Allowing Asynchronous Reordering
+</H2>
+
+<P>
+Asynchronous reordering is the reordering that is triggered
+automatically by the increase of the number of nodes. Asynchronous
+reordering takes place when a new internal node must be created, and
+the number of nodes has reached a given
+threshold<A NAME="1026"></A>. (The threshold is adjusted by
+the package every time reordering takes place.)
+
+<P>
+Those procedures that do not create new nodes (e.g., procedures that
+count the number of nodes or minterms<A NAME="1027"></A>) need
+not worry about asynchronous reordering: No special precaution is
+necessary in writing them.
+
+<P>
+Procedures that only manipulate decision diagrams through the exported
+functions of the CUDD package also need not concern themselves with
+asynchronous reordering. (See Section&nbsp;<A HREF="node3.html#sec:nodes">3.2.1</A> for the
+exceptions.)
+
+<P>
+The remaining class of procedures is composed of functions that visit
+the diagrams and may create new nodes. All such procedures in the CUDD
+package are written so that they can be interrupted by dynamic
+reordering. The general approach followed goes under the name of
+``abort and retry<A NAME="1029"></A>." As the name
+implies, a computation that is interrupted by dynamic reordering is
+aborted and tried again.
+
+<P>
+A recursive procedure that can be interrupted by dynamic reordering
+(an interruptible<A NAME="1030"></A> procedure
+from now on) is composed of two functions.  One is responsible for the
+real computation. The other is a simple
+wrapper<A NAME="1031"></A>, which tests whether
+reordering occurred and restarts the computation if it did.
+
+<P>
+Asynchronous reordering of BDDs and ADDs can only be triggered inside
+<A NAME="tex2html152"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>cuddUniqueInter</EM></A><A NAME="1683"></A>, when a new node
+is about to be created.  Likewise, asynchronous reordering of ZDDs can
+only be triggered inside <A NAME="tex2html153"
+  HREF="cuddAllDet.html#cuddUniqueInterZdd"><EM>  cuddUniqueInterZdd</EM></A><A NAME="1685"></A>.  When
+reordering is triggered, three things happen:
+
+<OL>
+<LI><A NAME="tex2html154"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>cuddUniqueInter</EM></A><A NAME="1687"></A> returns a
+
+NULL value;
+</LI>
+<LI>The flag <EM>reordered</EM> of the manager is set to 1. (0 means
+  no reordering, while 2 indicates an error occurred during
+  reordering.)
+</LI>
+<LI>The counter <EM>reorderings</EM> of the manager is incremented.
+  The counter is initialized to 0 when the manager is started and can
+  be accessed by calling <A NAME="tex2html155"
+  HREF="cuddExtDet.html#Cudd_ReadReorderings"><EM>    Cudd_ReadReorderings</EM></A><A NAME="1689"></A>. By
+
+taking two readings of the counter, an application can determine if
+  variable reordering has taken place between the first and the second
+  reading.  The package itself, however, does not make use of the
+  counter: It is mentioned here for completeness.
+</LI>
+</OL>
+
+<P>
+The recursive procedure that receives a NULL value from <A NAME="tex2html156"
+  HREF="cuddAllDet.html#cuddUniqueInter"><EM>  cuddUniqueInter</EM></A><A NAME="1691"></A> must free all intermediate
+results that it may have computed before, and return NULL in its turn.
+
+<P>
+The wrapper<A NAME="1051"></A> function does not
+decide whether reordering occurred based on the NULL return value,
+because the NULL value may be the result of lack of memory. Instead,
+it checks the <EM>reordered</EM> flag.
+
+<P>
+When a recursive procedure calls another recursive procedure that may
+cause reordering, it should bypass the wrapper and call the recursive
+procedure directly. Otherwise, the calling procedure will not know
+whether reordering occurred, and will not be able to restart.  This is
+the main reason why most recursive procedures are internal, rather
+than static. (The wrappers, on the other hand, are mostly exported.)
+
+<P>
+
+<H2><A NAME="SECTION00047000000000000000"></A>
+<A NAME="1054"></A><A NAME="sec:debug"></A>
+<BR>
+Debugging
+</H2>
+
+<P>
+By defining the symbol DD_DEBUG<A NAME="1056"></A> during compilation,
+numerous checks are added to the code. In addition, the procedures
+<A NAME="tex2html157"
+  HREF="cuddExtDet.html#Cudd_DebugCheck"><EM>Cudd_DebugCheck</EM></A><A NAME="1693"></A>, <A NAME="tex2html158"
+  HREF="cuddExtDet.html#Cudd_CheckKeys"><EM>  Cudd_CheckKeys</EM></A><A NAME="1695"></A>, and <A NAME="tex2html159"
+  HREF="cuddAllDet.html#cuddHeapProfile"><EM>  cuddHeapProfile</EM></A><A NAME="1697"></A> can be called at any point
+to verify the consistency of the data structure. (<A NAME="tex2html160"
+  HREF="cuddAllDet.html#cuddHeapProfile"><EM>  cuddHeapProfile</EM></A>
+is an internal procedure. It is declared in <EM>  cuddInt.h</EM><A NAME="1069"></A>.) Procedures <A NAME="tex2html161"
+  HREF="cuddExtDet.html#Cudd_DebugCheck"><EM>Cudd_DebugCheck</EM></A>
+and <A NAME="tex2html162"
+  HREF="cuddExtDet.html#Cudd_CheckKeys"><EM>Cudd_CheckKeys</EM></A>
+are especially useful when CUDD reports
+that during garbage collection the number of nodes actually deleted
+from the unique table is different from the count of dead nodes kept
+by the manager. The error causing the discrepancy may have occurred
+much earlier than it is discovered.  A few strategicaly placed calls
+to the debugging procedures can considerably narrow down the search
+for the source of the problem. (For instance, a call to <A NAME="tex2html163"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A>
+where one to <A NAME="tex2html164"
+  HREF="cuddExtDet.html#Cudd_Deref"><EM>Cudd_Deref</EM></A>
+was required
+may be identified in this way.)
+
+<P>
+One of the most common problems encountered in debugging code based on
+the CUDD package is a missing call to <A NAME="tex2html165"
+  HREF="cuddExtDet.html#Cudd_RecursiveDeref"><EM>  Cudd_RecursiveDeref</EM></A><A NAME="1699"></A>.  To help
+identify this type of problems, the package provides a function called
+<A NAME="tex2html166"
+  HREF="cuddExtDet.html#Cudd_CheckZeroRef"><EM>Cudd_CheckZeroRef</EM></A><A NAME="1701"></A>. This
+function should be called immediately before shutting down the
+manager. <A NAME="tex2html167"
+  HREF="cuddExtDet.html#Cudd_CheckZeroRef"><EM>Cudd_CheckZeroRef</EM></A>
+checks that the only nodes left
+with non-zero reference<A NAME="1086"></A> counts are the
+predefined constants, the BDD projection<A NAME="1087"></A>
+functions, and nodes whose reference counts are
+saturated<A NAME="1088"></A>.
+
+<P>
+For this function to be effective the application must explicitly
+dispose of all diagrams to which it has pointers before calling it.
+
+<P>
+
+<H2><A NAME="SECTION00048000000000000000"></A>
+<A NAME="1090"></A><A NAME="sec:stats"></A>
+<BR>
+Gathering and Interpreting Statistics
+</H2>
+
+<P>
+Function <A NAME="tex2html168"
+  HREF="cuddExtDet.html#Cudd_PrintInfo"><EM>Cudd_PrintInfo</EM></A><A NAME="1703"></A> can be called
+to print out the values of parameters and statistics for a manager.
+The output of <A NAME="tex2html169"
+  HREF="cuddExtDet.html#Cudd_PrintInfo"><EM>Cudd_PrintInfo</EM></A>
+is divided in two sections. The
+first reports the values of parameters that are under the application
+control. The second reports the values of statistical counters and
+other non-modifiable parameters. A
+quick guide to the interpretation of all these quantities follows. For
+ease of exposition, we reverse the order and describe the
+non-modifiable parameters first. We'll use a sample run as
+example. There is nothing special about this run.
+
+<P>
+
+<H3><A NAME="SECTION00048100000000000000"></A>
+<A NAME="sec:nonModPar"></A>
+<BR>
+Non Modifiable Parameters
+</H3>
+
+<P>
+The list of non-modifiable parameters starts with:
+<PRE>
+    **** CUDD non-modifiable parameters ****
+    Memory in use: 32544220
+</PRE>
+This is the memory used by CUDD for three things mainly: Unique table
+(including all DD nodes in use), node free list, and computed table.
+This number almost never decreases in the lifetime of a CUDD manager,
+because CUDD does not release memory when it frees nodes.  Rather, it
+puts the nodes on its own free list. This number is in bytes. It does
+not represent the peak memory occupation, because it does not include
+the size of data structures created temporarily by some functions (e.g.,
+local look-up tables).
+
+<P>
+<PRE>
+    Peak number of nodes: 837018
+</PRE>
+This number is the number of nodes that the manager has allocated.
+This is not the largest size of the BDDs, because the manager will
+normally have some dead nodes and some nodes on the free list.
+
+<P>
+<PRE>
+    Peak number of live nodes: 836894
+</PRE>
+This is the largest number of live nodes that the manager has held
+since its creation.
+
+<P>
+<PRE>
+    Number of BDD variables: 198
+    Number of ZDD variables: 0
+</PRE>
+These numbers tell us this run was not using ZDDs.
+
+<P>
+<PRE>
+    Number of cache entries: 1048576
+</PRE>
+Current number of slots of the computed table.  If one has a
+performance problem, this is one of the numbers to look at. The cache
+size is always a power of 2.
+
+<P>
+<PRE>
+    Number of cache look-ups: 2996536
+    Number of cache hits: 1187087
+</PRE>
+These numbers give an indication of the hit rate in the computed
+table. It is not unlikely for model checking runs to get
+hit rates even higher than this one (39.62%).
+
+<P>
+<PRE>
+    Number of cache insertions: 1809473
+    Number of cache collisions: 961208
+    Number of cache deletions: 0
+</PRE>
+A collision<A NAME="1113"></A> occurs when a cache entry is
+overwritten. A deletion<A NAME="1114"></A>
+occurs when a cache entry is invalidated (e.g., during garbage
+collection).  If the number of deletions is high compared to the
+number of collisions, it means that garbage collection occurs too
+often. In this case there were no garbage collections; hence, no
+deletions.
+
+<P>
+<PRE>
+    Cache used slots = 80.90% (expected 82.19%)
+</PRE>
+Percentage of cache slots that contain a valid entry. If this
+number is small, it may signal one of three conditions:
+
+<OL>
+<LI>The cache may have been recently resized and it is still filling
+  up.
+</LI>
+<LI>The cache is too large for the BDDs. This should not happen if
+  the size of the cache is determined by CUDD.
+</LI>
+<LI>The hash function is not working properly. This is accompanied
+  by a degradation in performance. Conversely, a degradation in
+  performance may be due to bad hash function behavior.
+</LI>
+</OL>
+The expected value is computed assuming a uniformly random
+distribution of the accesses.  If the difference between the measured
+value and the expected value is large (unlike this case), the cache is
+not working properly.
+
+<P>
+<PRE>
+    Soft limit for cache size: 1318912
+</PRE>
+This number says how large the cache can grow. This limit is based on
+the size of the unique table.  CUDD uses a reward-based policy for
+growing the cache. (See Section&nbsp;<A HREF="node4.html#sec:cache-sizing">4.4.1</A>.)  The default
+hit rate for resizing is 30% and the value in effect is reported
+among the modifiable parameters.
+
+<P>
+<PRE>
+    Number of buckets in unique table: 329728
+</PRE>
+This number is exactly one quarter of the one above. This is indeed
+how the soft limit is determined currently, unless the computed table
+hits the specified hard limit. (See below.)
+
+<P>
+<PRE>
+    Used buckets in unique table: 87.96% (expected 87.93%)
+</PRE>
+Percentage of unique table buckets that contain at least one
+node. Remarks analogous to those made about the used cache slots apply.
+
+<P>
+<PRE>
+    Number of BDD and ADD nodes: 836894
+    Number of ZDD nodes: 0
+</PRE>
+How many nodes are currently in the unique table, either alive or dead.
+
+<P>
+<PRE>
+    Number of dead BDD and ADD nodes: 0
+    Number of dead ZDD nodes: 0
+</PRE>
+Subtract these numbers from those above to get the number of live
+nodes. In this case there are no dead nodes because the application
+uses delayed dereferencing
+<A NAME="tex2html170"
+  HREF="cuddExtDet.html#Cudd_DelayedDerefBdd"><EM>Cudd_DelayedDerefBdd</EM></A><A NAME="1705"></A>.
+
+<P>
+<PRE>
+    Total number of nodes allocated: 836894
+</PRE>
+This is the total number of nodes that were requested and obtained
+from the free list. It never decreases, and is not an indication of
+memory occupation after the first garbage collection. Rather, it is a
+measure of the package activity.
+
+<P>
+<PRE>
+    Total number of nodes reclaimed: 0
+</PRE>
+These are the nodes that were resuscitated from the dead.  If they are
+many more than the allocated nodes, and the total
+number of slots is low relative to the number of nodes, then one may
+want to increase the limit for fast unique table growth. In this case,
+the number is 0 because of delayed dereferencing.
+
+<P>
+<PRE>
+    Garbage collections so far: 0
+    Time for garbage collections: 0.00 sec
+    Reorderings so far: 0
+    Time for reordering: 0.00 sec
+</PRE>
+There is a GC for each reordering. Hence the first count will always be
+at least as large as the second.
+
+<P>
+<PRE>
+    Node swaps in reordering: 0
+</PRE>
+This is the number of elementary reordering steps. Each step consists
+of the re-expression of one node while swapping two adjacent
+variables. This number is a good measure of the amount of work done in
+reordering.
+
+<P>
+
+<H3><A NAME="SECTION00048200000000000000"></A>
+<A NAME="sec:modPar"></A>
+<BR>
+Modifiable Parameters
+</H3>
+
+<P>
+Let us now consider the modifiable parameters, that is, those settings on
+which the application or the user has control.
+
+<P>
+<PRE>
+    **** CUDD modifiable parameters ****
+    Hard limit for cache size: 8388608
+</PRE>
+This number counts entries. Each entry is 16 bytes if CUDD is compiled
+to use 32-bit pointers. Two important observations are in order:
+
+<OL>
+<LI>If the datasize limit is set, CUDD will use it to determine this
+  number automatically. On a Unix system, one can type ``limit" to
+  verify if this value is set. If the datasize limit is not set, CUDD
+  uses a default which is rather small. If you have enough memory (say
+  64MB or more) you should seriously consider <EM>not</EM> using the
+  default. So, either set the datasize limit, or override the default
+  with <A NAME="tex2html171"
+  HREF="cuddExtDet.html#Cudd_SetMaxCacheHard"><EM>Cudd_SetMaxCacheHard</EM></A><A NAME="1707"></A>.
+</LI>
+<LI>If a process seems to be going nowhere, a small value for
+
+this parameter may be the culprit. One cannot overemphasize the
+  importance of the computed table in BDD algorithms.
+</LI>
+</OL>
+In this case the limit was automatically set for a target maximum
+memory occupation of 104 MB.
+
+<P>
+<PRE>
+    Cache hit threshold for resizing: 15%
+</PRE>
+This number can be changed if one suspects performance is hindered by
+the small size of the cache, and the cache is not growing towards the
+soft limit sufficiently fast. In such a case one can change the
+default 30% to 15% (as in this case) or even 1%.
+
+<P>
+<PRE>
+    Garbage collection enabled: yes
+</PRE>
+One can disable it, but there are few good reasons for doing
+so. It is normally preferable to raise the limit for fast unique table
+growth. (See below.)
+
+<P>
+<PRE>
+    Limit for fast unique table growth: 1363148
+</PRE>
+See Section&nbsp;<A HREF="node4.html#sec:unique">4.5</A> and the comments above about reclaimed
+nodes and hard limit for the cache size. This value was chosen
+automatically by CUDD for a datasize limit of 1 GB.
+
+<P>
+<PRE>
+    Maximum number of variables sifted per reordering: 1000
+    Maximum number of variable swaps per reordering: 2000000
+    Maximum growth while sifting a variable: 1.2
+</PRE>
+Lowering these numbers will cause reordering to be less accurate and
+faster. Results are somewhat unpredictable, because larger BDDs after one
+reordering do not necessarily mean the process will go faster or slower.
+
+<P>
+<PRE>
+    Dynamic reordering of BDDs enabled: yes
+    Default BDD reordering method: 4
+    Dynamic reordering of ZDDs enabled: no
+    Default ZDD reordering method: 4
+</PRE>
+These lines tell whether automatic reordering can take place and
+what method would be used. The mapping from numbers to methods is in
+<TT>cudd.h</TT>. One may want to try different BDD
+reordering methods. If variable groups are used, however, one should
+not expect to see big differences, because CUDD uses the reported
+method only to reorder each leaf variable group (typically corresponding
+present and next state variables). For the relative order of the
+groups, it always uses the same algorithm, which is effectively
+sifting.
+
+<P>
+As for enabling dynamic reordering or not, a sensible recommendation is the
+following: Unless the circuit is rather small or one has a pretty good
+idea of what the order should be, reordering should be enabled.
+
+<P>
+<PRE>
+    Realignment of ZDDs to BDDs enabled: no
+    Realignment of BDDs to ZDDs enabled: no
+    Dead nodes counted in triggering reordering: no
+    Group checking criterion: 7
+    Recombination threshold: 0
+    Symmetry violation threshold: 0
+    Arc violation threshold: 0
+    GA population size: 0
+    Number of crossovers for GA: 0
+</PRE>
+Parameters for reordering. See the documentation of the functions used
+to control these parameters for the details.
+
+<P>
+<PRE>
+    Next reordering threshold: 100000
+</PRE>
+When the number of nodes crosses this threshold, reordering will be
+triggered. (If enabled; in this case it is not.)  This parameter is
+updated by the package whenever reordering takes place.  The
+application can change it, for instance at start-up.  Another
+possibility is to use a hook function (see Section&nbsp;<A HREF="node3.html#sec:hooks">3.16</A>) to
+override the default updating policy.
+
+<P>
+
+<H3><A NAME="SECTION00048300000000000000"></A>
+<A NAME="sec:extendedStats"></A>
+<BR>
+Extended Statistics and Reporting
+</H3>
+
+<P>
+The following symbols can be defined during compilation to increase
+the amount of statistics gathered and the number of messages produced
+by the package:
+
+<UL>
+<LI>DD_STATS<A NAME="1171"></A>;
+</LI>
+<LI>DD_CACHE_PROFILE<A NAME="1172"></A>;
+</LI>
+<LI>DD_UNIQUE_PROFILE<A NAME="1173"></A>.
+</LI>
+<LI>DD_VERBOSE<A NAME="1174"></A>;
+</LI>
+</UL>
+Defining DD_CACHE_PROFILE causes each entry of the cache to include
+an access counter, which is used to compute simple statistics on the
+distribution of the keys.
+
+<P>
+
+<H2><A NAME="SECTION00049000000000000000"></A>
+<A NAME="sec:doc"></A><A NAME="1178"></A>
+<BR>
+Guidelines for Documentation
+</H2>
+
+<P>
+The documentation of the CUDD functions is extracted automatically
+from the sources by Stephen Edwards's extdoc. (The Ext system is
+available via anonymous FTP<A NAME="1179"></A> from
+<A NAME="tex2html172"
+  HREF="ftp://ic.eecs.berkeley.edu"><TT>ic.eecs.berkeley.edu</TT></A>.)
+The following guidelines are followed in CUDD to insure consistent and
+effective use of automatic extraction. It is recommended that
+extensions to CUDD follow the same documentation guidelines.
+
+<UL>
+<LI>The documentation of an exported procedure should be sufficient
+  to allow one to use it without reading the code. It is not necessary
+  to explain how the procedure works; only what it does.
+</LI>
+<LI>The <I>SeeAlso</I><A NAME="1411"></A>
+  fields should be space-separated lists of function names.  The
+  <I>SeeAlso</I> field of an exported procedure should only reference
+  other exported procedures. The <I>SeeAlso</I> field of an internal
+  procedure may reference other internal procedures as well as
+  exported procedures, but no static procedures.
+</LI>
+<LI>The return values are detailed in the
+  <I>Description</I><A NAME="1412"></A>
+  field, not in the
+  <I>Synopsis</I><A NAME="1413"></A> field.
+</LI>
+<LI>The parameters are documented alongside their declarations.
+  Further comments may appear in the <I>Description</I> field.
+</LI>
+<LI>If the <I>Description</I> field is non-empty--which is the
+  normal case for an exported procedure--then the synopsis is
+  repeated--possibly slightly changed--at the beginning of the
+  <I>Description</I> field. This is so because extdoc will not put the
+  synopsis in the same HTML file<A NAME="1194"></A> as
+  the description.
+</LI>
+<LI>The <I>Synopsis</I> field should be about one line long.
+</LI>
+</UL>
+
+<P>
+<HR>
+<!--Navigation Panel-->
+<A NAME="tex2html313"
+  HREF="node5.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html309"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html303"
+  HREF="node3.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html311"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html314"
+  HREF="node5.html">The C++ Interface</A>
+<B> Up:</B> <A NAME="tex2html310"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html304"
+  HREF="node3.html">User's Manual</A>
+ &nbsp <B>  <A NAME="tex2html312"
+  HREF="node8.html">Index</A></B> 
+<!--End of Navigation Panel-->
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node5.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node5.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node5.html	(revision 8)
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>The C++ Interface</TITLE>
+<META NAME="description" CONTENT="The C++ Interface">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node6.html">
+<LINK REL="previous" HREF="node4.html">
+<LINK REL="up" HREF="cuddIntro.html">
+<LINK REL="next" HREF="node6.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html343"
+  HREF="node6.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html339"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html333"
+  HREF="node4.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html341"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html344"
+  HREF="node6.html">Acknowledgments</A>
+<B> Up:</B> <A NAME="tex2html340"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html334"
+  HREF="node4.html">Programmer's Manual</A>
+ &nbsp <B>  <A NAME="tex2html342"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+<!--Table of Child-Links-->
+<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></A>
+
+<UL>
+<LI><A NAME="tex2html345"
+  HREF="#SECTION00051000000000000000">Compiling and Linking</A>
+<LI><A NAME="tex2html346"
+  HREF="#SECTION00052000000000000000">Basic Manipulation</A>
+</UL>
+<!--End of Table of Child-Links-->
+<HR>
+
+<H1><A NAME="SECTION00050000000000000000"></A>
+<A NAME="sec:cpp"></A>
+<BR>
+The C++ Interface
+</H1>
+
+<P>
+
+<H2><A NAME="SECTION00051000000000000000"></A>
+<A NAME="sec:compileCpp"></A>
+<BR>
+Compiling and Linking
+</H2>
+
+<P>
+To build an application that uses the CUDD C++ interface, you should
+add
+<PRE>
+#include "cuddObj.hh"
+</PRE>
+to your source files. In addition to the normal CUDD libraries (see
+Section&nbsp;<A HREF="node3.html#sec:compileExt">3.1</A>) you should link 
+<code>libobj.a</code><A NAME="1204"></A> to your executable. Refer to the
+<TT>Makefile<A NAME="1205"></A></TT> in the top level directory of the
+distribution for further details.
+
+<P>
+
+<H2><A NAME="SECTION00052000000000000000"></A>
+<A NAME="sec:basicCpp"></A>
+<BR>
+Basic Manipulation
+</H2>
+
+<P>
+The following fragment of code illustrates some simple operations on
+BDDs using the C++ interface.
+<PRE>
+        Cudd mgr(0,0);
+        BDD x = mgr.bddVar();
+        BDD y = mgr.bddVar();
+        BDD f = x * y;
+        BDD g = y + !x;
+        cout &lt;&lt; "f is" &lt;&lt; (f &lt;= g ? "" : " not")
+             &lt;&lt; " less than or equal to g\n";
+</PRE>
+This code creates a manager called <code>mgr</code> and two variables in it.
+It then defines two functions <code>f</code> and <code>g</code> in terms of the
+variables. Finally, it prints a message based on the comparison of the
+two functions. No explicit referencing or dereferencing is required.
+The operators are overloaded in the intuitive way. BDDs are freed when
+execution leaves the scope in which they are defined or when the
+variables referring to them are overwritten.
+
+<P>
+<BR><HR>
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node6.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node6.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node6.html	(revision 8)
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>Acknowledgments</TITLE>
+<META NAME="description" CONTENT="Acknowledgments">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node7.html">
+<LINK REL="previous" HREF="node5.html">
+<LINK REL="up" HREF="cuddIntro.html">
+<LINK REL="next" HREF="node7.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html357"
+  HREF="node7.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html353"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html347"
+  HREF="node5.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html355"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html358"
+  HREF="node7.html">Bibliography</A>
+<B> Up:</B> <A NAME="tex2html354"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html348"
+  HREF="node5.html">The C++ Interface</A>
+ &nbsp <B>  <A NAME="tex2html356"
+  HREF="node8.html">Index</A></B> 
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+
+<H1><A NAME="SECTION00060000000000000000"></A>
+<A NAME="sec:ack"></A>
+<BR>
+Acknowledgments
+</H1>
+
+<P>
+The contributors: Iris Bahar, Hyunwoo Cho, Erica Frohm, Charlie Gaona,
+Cheng Hua, Jae-Young Jang, Seh-Woong Jeong, Balakrishna Kumthekar,
+Enrico Macii, Bobbie Manne, In-Ho Moon, Curt Musfeldt, Shipra Panda,
+Abelardo Pardo, Bernard Plessier, Kavita Ravi, Hyongkyoon Shin, Alan
+Shuler, Arun Sivakumaran, Jorgen Sivesind.
+
+<P>
+The early adopters: Gianpiero Cabodi, Jordi Cortadella, Mario Escobar,
+Gayani Gamage, Gary Hachtel, Mariano Hermida, Woohyuk Lee, Enric
+Pastor, Massimo Poncino, Ellen Sentovich, the students of ECEN5139.
+
+<P>
+I am also particularly indebted to the following people for in-depth
+discussions on BDDs: Armin Biere, Olivier Coudert, Geert Janssen, David
+Long, Jean Christophe Madre, Ken McMillan, Shin-Ichi Minato, Jaehong
+Park, Rajeev Ranjan, Rick Rudell, Ellen Sentovich, Tom Shiple, and
+Bwolen Yang.
+
+<P>
+Special thanks to Norris Ip for guiding my faltering steps
+in the design of the C++ interface.
+Gianpiero Cabodi and Stefano Quer have graciously agreed to let me
+distribute their dddmp library with CUDD.
+
+<P>
+Masahiro Fujita, Gary Hachtel, and Carl Pixley have provided
+encouragement and advice.
+
+<P>
+The National Science Foundation and the Semiconductor Research Council
+have supported in part the development of this package.
+
+<P>
+
+<HR>
+<!--Navigation Panel-->
+<A NAME="tex2html357"
+  HREF="node7.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html353"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html347"
+  HREF="node5.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html355"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html358"
+  HREF="node7.html">Bibliography</A>
+<B> Up:</B> <A NAME="tex2html354"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html348"
+  HREF="node5.html">The C++ Interface</A>
+ &nbsp <B>  <A NAME="tex2html356"
+  HREF="node8.html">Index</A></B> 
+<!--End of Navigation Panel-->
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node7.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node7.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node7.html	(revision 8)
@@ -0,0 +1,196 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>Bibliography</TITLE>
+<META NAME="description" CONTENT="Bibliography">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="next" HREF="node8.html">
+<LINK REL="previous" HREF="node6.html">
+<LINK REL="up" HREF="cuddIntro.html">
+<LINK REL="next" HREF="node8.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<A NAME="tex2html369"
+  HREF="node8.html">
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next.png"></A> 
+<A NAME="tex2html365"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html359"
+  HREF="node6.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>  
+<A NAME="tex2html367"
+  HREF="node8.html">
+<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
+ SRC="icons/index.png"></A> 
+<BR>
+<B> Next:</B> <A NAME="tex2html370"
+  HREF="node8.html">Index</A>
+<B> Up:</B> <A NAME="tex2html366"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html360"
+  HREF="node6.html">Acknowledgments</A>
+ &nbsp <B>  <A NAME="tex2html368"
+  HREF="node8.html">Index</A></B> 
+<BR><BR>
+<!--End of Navigation Panel-->
+
+<H2><A NAME="SECTION00070000000000000000">
+Bibliography</A>
+</H2><DL COMPACT><DD><P></P><DT><A NAME="Bahar93">1</A>
+<DD>
+R.&nbsp;I. Bahar, E.&nbsp;A. Frohm, C.&nbsp;M. Gaona, G.&nbsp;D. Hachtel, E.&nbsp;Macii, A.&nbsp;Pardo, and
+  F.&nbsp;Somenzi.
+<BR>Algebraic decision diagrams and their applications.
+<BR>In <EM>Proceedings of the International Conference on Computer-Aided
+  Design</EM>, pages 188-191, Santa Clara, CA, November 1993.
+
+<P></P><DT><A NAME="Bollig95">2</A>
+<DD>
+B.&nbsp;Bollig, M.&nbsp;L&#246;bbing, and I.&nbsp;Wegener.
+<BR>Simulated annealing to improve variable orderings for OBDDs.
+<BR>Presented at the International Workshop on Logic Synthesis,
+  Granlibakken, CA, May 1995.
+
+<P></P><DT><A NAME="BBR">3</A>
+<DD>
+K.&nbsp;S. Brace, R.&nbsp;L. Rudell, and R.&nbsp;E. Bryant.
+<BR>Efficient implementation of a BDD package.
+<BR>In <EM>Proceedings of the 27th Design Automation Conference</EM>, pages
+  40-45, Orlando, FL, June 1990.
+
+<P></P><DT><A NAME="VIS">4</A>
+<DD>
+R.&nbsp;K. Brayton et&nbsp;al.
+<BR>VIS: A system for verification and synthesis.
+<BR>Technical Report UCB/ERL M95/104, Electronics Research Lab, Univ. of
+  California, December 1995.
+
+<P></P><DT><A NAME="BDD">5</A>
+<DD>
+R.&nbsp;E. Bryant.
+<BR>Graph-based algorithms for Boolean function manipulation.
+<BR><EM>IEEE Transactions on Computers</EM>, C-35(8):677-691, August 1986.
+
+<P></P><DT><A NAME="Drechs95">6</A>
+<DD>
+R.&nbsp;Drechsler, B.&nbsp;Becker, and N.&nbsp;G&#246;ckel.
+<BR>A genetic algorithm for variable ordering of OBDDs.
+<BR>Presented at the International Workshop on Logic Synthesis,
+  Granlibakken, CA, May 1995.
+
+<P></P><DT><A NAME="Friedman90">7</A>
+<DD>
+S.&nbsp;J. Friedman and K.&nbsp;J. Supowit.
+<BR>Finding the optimal variable ordering for binary decision diagrams.
+<BR><EM>IEEE Transactions on Computers</EM>, 39(5):710-713, May 1990.
+
+<P></P><DT><A NAME="Fujita91b">8</A>
+<DD>
+M.&nbsp;Fujita, Y.&nbsp;Matsunaga, and T.&nbsp;Kakuda.
+<BR>On variable ordering of binary decision diagrams for the application
+  of multi-level logic synthesis.
+<BR>In <EM>Proceedings of the European Conference on Design Automation</EM>,
+  pages 50-54, Amsterdam, February 1991.
+
+<P></P><DT><A NAME="Held62">9</A>
+<DD>
+M.&nbsp;Held and R.&nbsp;M. Karp.
+<BR>A dynamic programming approach to sequencing problems.
+<BR><EM>J. SIAM</EM>, 10(1):196-210, 1962.
+
+<P></P><DT><A NAME="Ishiur91">10</A>
+<DD>
+N.&nbsp;Ishiura, H.&nbsp;Sawada, and S.&nbsp;Yajima.
+<BR>Minimization of binary decision diagrams based on exchanges of
+  variables.
+<BR>In <EM>Proceedings of the International Conference on Computer-Aided
+  Design</EM>, pages 472-475, Santa Clara, CA, November 1991.
+
+<P></P><DT><A NAME="Jeong93">11</A>
+<DD>
+S.-W. Jeong, T.-S. Kim, and F.&nbsp;Somenzi.
+<BR>An efficient method for optimal BDD ordering computation.
+<BR>In <EM>International Conference on VLSI and CAD (ICVC'93)</EM>, Taejon,
+  Korea, November 1993.
+
+<P></P><DT><A NAME="Minato93">12</A>
+<DD>
+S.-I. Minato.
+<BR>Zero-suppressed BDDs for set manipulation in combinatorial
+  problems.
+<BR>In <EM>Proceedings of the Design Automation Conference</EM>, pages
+  272-277, Dallas, TX, June 1993.
+
+<P></P><DT><A NAME="Panda95b">13</A>
+<DD>
+S.&nbsp;Panda and F.&nbsp;Somenzi.
+<BR>Who are the variables in your neighborhood.
+<BR>In <EM>Proceedings of the International Conference on Computer-Aided
+  Design</EM>, pages 74-77, San Jose, CA, November 1995.
+
+<P></P><DT><A NAME="Panda94">14</A>
+<DD>
+S.&nbsp;Panda, F.&nbsp;Somenzi, and B.&nbsp;F. Plessier.
+<BR>Symmetry detection and dynamic variable ordering of decision
+  diagrams.
+<BR>In <EM>Proceedings of the International Conference on Computer-Aided
+  Design</EM>, pages 628-631, San Jose, CA, November 1994.
+
+<P></P><DT><A NAME="Plessi93">15</A>
+<DD>
+B.&nbsp;F. Plessier.
+<BR><EM>A General Framework for Verification of Sequential Circuits</EM>.
+<BR>PhD thesis, University of Colorado at Boulder, Dept. of Electrical
+  and Computer Engineering, 1993.
+
+<P></P><DT><A NAME="Rudell93">16</A>
+<DD>
+R.&nbsp;Rudell.
+<BR>Dynamic variable ordering for ordered binary decision diagrams.
+<BR>In <EM>Proceedings of the International Conference on Computer-Aided
+  Design</EM>, pages 42-47, Santa Clara, CA, November 1993.
+
+<P></P><DT><A NAME="Sentov92">17</A>
+<DD>
+E.&nbsp;M. Sentovich, K.&nbsp;J. Singh, C.&nbsp;Moon, H.&nbsp;Savoj, R.&nbsp;K. Brayton, and
+  A.&nbsp;Sangiovanni-Vincentelli.
+<BR>Sequential circuit design using synthesis and optimization.
+<BR>In <EM>Proceedings of the International Conference on Computer
+  Design</EM>, pages 328-333, Cambridge, MA, October 1992.
+</DL>
+<A NAME="1416"></A>
+<A NAME="1417"></A>
+<A NAME="1418"></A>
+<A NAME="1419"></A>
+<A NAME="1420"></A>
+<A NAME="1421"></A>
+
+<P>
+<BR><HR>
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/doc/node8.html
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/doc/node8.html	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/doc/node8.html	(revision 8)
@@ -0,0 +1,843 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+
+<!--Converted with LaTeX2HTML 2K.1beta (1.47)
+original version by:  Nikos Drakos, CBLU, University of Leeds
+* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
+* with significant contributions from:
+  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
+<HTML>
+<HEAD>
+<TITLE>Index</TITLE>
+<META NAME="description" CONTENT="Index">
+<META NAME="keywords" CONTENT="cuddIntro">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
+
+<LINK REL="STYLESHEET" HREF="cuddIntro.css">
+
+<LINK REL="previous" HREF="node7.html">
+<LINK REL="up" HREF="cuddIntro.html">
+</HEAD>
+
+<BODY >
+<!--Navigation Panel-->
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
+ SRC="icons/next_g.png"> 
+<A NAME="tex2html375"
+  HREF="cuddIntro.html">
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
+ SRC="icons/up.png"></A> 
+<A NAME="tex2html371"
+  HREF="node7.html">
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
+ SRC="icons/prev.png"></A>   
+<BR>
+<B> Up:</B> <A NAME="tex2html376"
+  HREF="cuddIntro.html">CUDD: CU Decision Diagram</A>
+<B> Previous:</B> <A NAME="tex2html372"
+  HREF="node7.html">Bibliography</A>
+<BR>
+<BR>
+<!--End of Navigation Panel-->
+<BR>
+
+<H2><A NAME="SECTION00080000000000000000">
+Index</A>
+</H2><DL COMPACT>
+<DT><STRONG>ADD</STRONG>
+<DD><A HREF="node1.html#15">Introduction</A>
+ | <A HREF="node3.html#119">Nodes</A>
+ | <A HREF="node3.html#289">New Constants</A>
+ | <A HREF="node3.html#379">Basic ADD Manipulation</A>
+<DT><STRONG>aggregation</STRONG>
+<DD><A HREF="node3.html#547">Variable Reordering for BDDs</A>
+<DT><STRONG>Algebraic Decision Diagram</STRONG>
+<DD><i>see </i> ADD
+<DT><STRONG>arc</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>complement</STRONG>
+<DD><A HREF="node3.html#298">New BDD and ADD</A>
+ | <A HREF="node3.html#768">Writing Decision Diagrams to</A>
+ | <A HREF="node3.html#768">Writing Decision Diagrams to</A>
+ | <A HREF="node4.html#926">Complement Arcs</A>
+ | <A HREF="node4.html#930">Complement Arcs</A>
+<DT><STRONG>regular</STRONG>
+<DD><A HREF="node3.html#769">Writing Decision Diagrams to</A>
+ | <A HREF="node3.html#769">Writing Decision Diagrams to</A>
+ | <A HREF="node4.html#929">Complement Arcs</A>
+</DL>
+<DT><STRONG>background value</STRONG>
+<DD><A HREF="node3.html#254">Background</A>
+<DT><STRONG>BDD</STRONG>
+<DD><A HREF="node1.html#13">Introduction</A>
+ | <A HREF="node3.html#118">Nodes</A>
+ | <A HREF="node3.html#213">One, Logic Zero, and</A>
+ | <A HREF="node3.html#339">Basic BDD Manipulation</A>
+<DT><STRONG>Binary Decision Diagram</STRONG>
+<DD><i>see </i> BDD
+<DT><STRONG>box</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>black</STRONG>
+<DD><A HREF="node1.html#26">Introduction</A>
+<DT><STRONG>clear</STRONG>
+<DD><A HREF="node1.html#31">Introduction</A>
+ | <A HREF="node4.html#795">Compiling and Linking</A>
+</DL>
+<DT><STRONG>cache</STRONG>
+<DD><A HREF="node3.html#147">Cache</A>
+ | <A HREF="node3.html#150">Cache</A>
+ | <A HREF="node3.html#152">Cache</A>
+ | <A HREF="node3.html#170">Initializing and Shutting Down</A>
+ | <A HREF="node4.html#928">Complement Arcs</A>
+ | <A HREF="node4.html#941">The Cache</A>
+<DL COMPACT>
+<DT><STRONG>collision</STRONG>
+<DD><A HREF="node4.html#1113">Non Modifiable Parameters</A>
+<DT><STRONG>collision list</STRONG>
+<DD><A HREF="node4.html#1010">The Unique Table</A>
+<DT><STRONG>deletion</STRONG>
+<DD><A HREF="node4.html#1114">Non Modifiable Parameters</A>
+<DT><STRONG>local</STRONG>
+<DD><A HREF="node4.html#951">The Cache</A>
+ | <A HREF="node4.html#987">Local Caches</A>
+<DT><STRONG>lossless</STRONG>
+<DD><A HREF="node4.html#989">Local Caches</A>
+<DT><STRONG>reward-based resizing</STRONG>
+<DD><A HREF="node4.html#981">Cache Sizing</A>
+ | <A HREF="node4.html#984">Cache Sizing</A>
+<DT><STRONG>sizing</STRONG>
+<DD><A HREF="node4.html#976">Cache Sizing</A>
+</DL>
+<DT><STRONG>cacheSize</STRONG>
+<DD><A HREF="node3.html#169">Initializing and Shutting Down</A>
+<DT><STRONG>canonical</STRONG>
+<DD><A HREF="node3.html#138">The Manager</A>
+ | <A HREF="node4.html#990">Local Caches</A>
+<DT><STRONG>compiling</STRONG>
+<DD><A HREF="node3.html#78">Compiling and Linking</A>
+ | <A HREF="node3.html#234">Predefined Constants</A>
+ | <A HREF="node4.html#793">Compiling and Linking</A>
+<DT><STRONG>configuration</STRONG>
+<DD><A HREF="node2.html#54">The CUDD Package</A>
+<DT><STRONG>conversion</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>of ADDs to BDDs</STRONG>
+<DD><A HREF="node3.html#429">Converting ADDs to BDDs</A>
+<DT><STRONG>of BDDs to ADDs</STRONG>
+<DD><A HREF="node3.html#430">Converting ADDs to BDDs</A>
+<DT><STRONG>of BDDs to ZDDs</STRONG>
+<DD><A HREF="node3.html#406">Basic ZDD Manipulation</A>
+ | <A HREF="node3.html#451">Converting BDDs to ZDDs</A>
+<DT><STRONG>of ZDDs to BDDs</STRONG>
+<DD><A HREF="node3.html#450">Converting BDDs to ZDDs</A>
+</DL>
+<DT><STRONG>cube sets</STRONG>
+<DD><A HREF="node1.html#22">Introduction</A>
+<DT><STRONG>cudd.h</STRONG>
+<DD><A HREF="node3.html#81">Compiling and Linking</A>
+ | <A HREF="node3.html#504">Variable Reordering for BDDs</A>
+ | <A HREF="node4.html#916">Saturating Increments and Decrements</A>
+<DT><STRONG><I>Cudd_addApply</I></STRONG>
+<DD><A HREF="node3.html#1505">Basic ADD Manipulation</A>
+ | <A HREF="node3.html#1507">Basic ADD Manipulation</A>
+<DT><STRONG><I>Cudd_addBddInterval</I></STRONG>
+<DD><A HREF="node3.html#1523">Converting ADDs to BDDs</A>
+<DT><STRONG><I>Cudd_addBddPattern</I></STRONG>
+<DD><A HREF="node3.html#1521">Converting ADDs to BDDs</A>
+<DT><STRONG><I>Cudd_addBddThreshold</I></STRONG>
+<DD><A HREF="node3.html#1525">Converting ADDs to BDDs</A>
+<DT><STRONG><I>Cudd_addConst</I></STRONG>
+<DD><A HREF="node3.html#1475">New Constants</A>
+<DT><STRONG><I>Cudd_addHarwell</I></STRONG>
+<DD><A HREF="node3.html#1467">Background</A>
+<DT><STRONG><I>Cudd_AddHook</I></STRONG>
+<DD><A HREF="node3.html#1591">Hooks</A>
+<DT><STRONG><I>Cudd_addIthBit</I></STRONG>
+<DD><A HREF="node3.html#1529">Converting ADDs to BDDs</A>
+<DT><STRONG><I>Cudd_addIthVar</I></STRONG>
+<DD><A HREF="node3.html#1487">New BDD and ADD</A>
+<DT><STRONG><I>Cudd_addNewVar</I></STRONG>
+<DD><A HREF="node3.html#1489">New BDD and ADD</A>
+<DT><STRONG><I>Cudd_addNewVarAtLevel</I></STRONG>
+<DD><A HREF="node3.html#1491">New BDD and ADD</A>
+ | <A HREF="node3.html#1573">Grouping Variables</A>
+<DT><STRONG><I>Cudd_addRead</I></STRONG>
+<DD><A HREF="node3.html#1465">Background</A>
+<DT><STRONG><I>Cudd_addTimes</I></STRONG>
+<DD><A HREF="node3.html#1509">Basic ADD Manipulation</A>
+<DT><STRONG><I>Cudd_AutodynDisable</I></STRONG>
+<DD><A HREF="node3.html#1543">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_AutodynDisableZdd</I></STRONG>
+<DD><A HREF="node3.html#1581">Variable Reordering for ZDDs</A>
+<DT><STRONG><I>Cudd_AutodynEnable</I></STRONG>
+<DD><A HREF="node3.html#1541">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#1547">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_AutodynEnableZdd</I></STRONG>
+<DD><A HREF="node3.html#1579">Variable Reordering for ZDDs</A>
+<DT><STRONG><I>Cudd_bddAnd</I></STRONG>
+<DD><A HREF="node3.html#1497">Basic BDD Manipulation</A>
+ | <A HREF="node3.html#1501">Basic BDD Manipulation</A>
+ | <A HREF="node3.html#1511">Basic ADD Manipulation</A>
+<DT><STRONG><I>Cudd_bddConstrain</I></STRONG>
+<DD><A HREF="node3.html#1427">Nodes</A>
+<DT><STRONG><I>Cudd_bddIte</I></STRONG>
+<DD><A HREF="node3.html#1495">Basic BDD Manipulation</A>
+<DT><STRONG><I>Cudd_bddIthVar</I></STRONG>
+<DD><A HREF="node3.html#1477">New BDD and ADD</A>
+<DT><STRONG><I>Cudd_bddNewVar</I></STRONG>
+<DD><A HREF="node3.html#1479">New BDD and ADD</A>
+ | <A HREF="node3.html#1483">New BDD and ADD</A>
+ | <A HREF="node3.html#1485">New BDD and ADD</A>
+<DT><STRONG><I>Cudd_bddNewVarAtLevel</I></STRONG>
+<DD><A HREF="node3.html#1481">New BDD and ADD</A>
+ | <A HREF="node3.html#1571">Grouping Variables</A>
+<DT><STRONG><I>Cudd_BddToAdd</I></STRONG>
+<DD><A HREF="node3.html#1527">Converting ADDs to BDDs</A>
+<DT><STRONG><I>Cudd_bddXor</I></STRONG>
+<DD><A HREF="node3.html#1513">Basic ADD Manipulation</A>
+<DT><STRONG>CUDD_CACHE_SLOTS</STRONG>
+<DD><A HREF="node3.html#171">Initializing and Shutting Down</A>
+<DT><STRONG><I>Cudd_CheckKeys</I></STRONG>
+<DD><A HREF="node4.html#1695">Debugging</A>
+<DT><STRONG><I>Cudd_CheckZeroRef</I></STRONG>
+<DD><A HREF="node4.html#1701">Debugging</A>
+<DT><STRONG><I>Cudd_CountMinterm</I></STRONG>
+<DD><A HREF="node3.html#1473">Background</A>
+<DT><STRONG><I>Cudd_DebugCheck</I></STRONG>
+<DD><A HREF="node4.html#1693">Debugging</A>
+<DT><STRONG><I>Cudd_DelayedDerefBdd</I></STRONG>
+<DD><A HREF="node4.html#1705">Non Modifiable Parameters</A>
+<DT><STRONG><I>Cudd_Deref</I></STRONG>
+<DD><A HREF="node4.html#1641"><EM>Cudd_RecursiveDeref</EM> vs. <EM>Cudd_Deref</EM></A>
+ | <A HREF="node4.html#1653">Saturating Increments and Decrements</A>
+<DT><STRONG><I>Cudd_DumpBlif</I></STRONG>
+<DD><A HREF="node3.html#1597">Writing Decision Diagrams to</A>
+<DT><STRONG><I>Cudd_DumpDaVinci</I></STRONG>
+<DD><A HREF="node3.html#1603">Writing Decision Diagrams to</A>
+<DT><STRONG><I>Cudd_DumpDot</I></STRONG>
+<DD><A HREF="node3.html#1599">Writing Decision Diagrams to</A>
+<DT><STRONG><I>Cudd_ForeachCube</I></STRONG>
+<DD><A HREF="node3.html#1423">Nodes</A>
+ | <A HREF="node3.html#1471">Background</A>
+<DT><STRONG><I>Cudd_ForeachNode</I></STRONG>
+<DD><A HREF="node3.html#1425">Nodes</A>
+<DT><STRONG><I>Cudd_HookType</I></STRONG>
+<DD><A HREF="node3.html#1589">Hooks</A>
+<DT><STRONG><I>Cudd_Init</I></STRONG>
+<DD><A HREF="node3.html#1435">Initializing and Shutting Down</A>
+ | <A HREF="node3.html#1437">Initializing and Shutting Down</A>
+<DT><STRONG><I>Cudd_MakeTreeNode</I></STRONG>
+<DD><A HREF="node3.html#1563">Grouping Variables</A>
+ | <A HREF="node3.html#1569">Grouping Variables</A>
+<DT><STRONG><I>Cudd_MakeZddTreeNode</I></STRONG>
+<DD><A HREF="node3.html#1583">Variable Reordering for ZDDs</A>
+<DT><STRONG><I>Cudd_Not</I></STRONG>
+<DD><A HREF="node3.html#1449">One, Logic Zero, and</A>
+<DT><STRONG><I>Cudd_PrintInfo</I></STRONG>
+<DD><A HREF="node4.html#1703">Gathering and Interpreting Statistics</A>
+<DT><STRONG><I>Cudd_PrintMinterm</I></STRONG>
+<DD><A HREF="node3.html#1469">Background</A>
+<DT><STRONG><I>Cudd_Quit</I></STRONG>
+<DD><A HREF="node3.html#1439">Initializing and Shutting Down</A>
+<DT><STRONG><I>Cudd_ReadBackground</I></STRONG>
+<DD><A HREF="node3.html#1463">Background</A>
+<DT><STRONG><I>Cudd_ReadEpsilon</I></STRONG>
+<DD><A HREF="node3.html#1459">Predefined Constants</A>
+<DT><STRONG><I>Cudd_ReadErrorCode</I></STRONG>
+<DD><A HREF="node4.html#1637">NULL Return Values</A>
+<DT><STRONG><I>Cudd_ReadInvPerm</I></STRONG>
+<DD><A HREF="node3.html#1503">Basic BDD Manipulation</A>
+<DT><STRONG><I>Cudd_ReadLogicZero</I></STRONG>
+<DD><A HREF="node3.html#1451">One, Logic Zero, and</A>
+<DT><STRONG><I>Cudd_ReadLooseUpto</I></STRONG>
+<DD><A HREF="node3.html#1441">Setting Parameters</A>
+<DT><STRONG><I>Cudd_ReadMaxGrowth</I></STRONG>
+<DD><A HREF="node3.html#1555">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_ReadMinusInfinity</I></STRONG>
+<DD><A HREF="node3.html#1457">Predefined Constants</A>
+<DT><STRONG><I>Cudd_ReadOne</I></STRONG>
+<DD><A HREF="node3.html#1445">One, Logic Zero, and</A>
+<DT><STRONG><I>Cudd_ReadPlusInfinity</I></STRONG>
+<DD><A HREF="node3.html#1455">Predefined Constants</A>
+<DT><STRONG><I>Cudd_ReadReorderings</I></STRONG>
+<DD><A HREF="node4.html#1689">Allowing Asynchronous Reordering</A>
+<DT><STRONG><I>Cudd_ReadSiftMaxVar</I></STRONG>
+<DD><A HREF="node3.html#1551">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_ReadTree</I></STRONG>
+<DD><A HREF="node3.html#1567">Grouping Variables</A>
+<DT><STRONG><I>Cudd_ReadZddOne</I></STRONG>
+<DD><A HREF="node3.html#1447">One, Logic Zero, and</A>
+ | <A HREF="node3.html#1515">Basic ZDD Manipulation</A>
+<DT><STRONG><I>Cudd_ReadZero</I></STRONG>
+<DD><A HREF="node3.html#1453">Predefined Constants</A>
+<DT><STRONG><I>Cudd_RecursiveDeref</I></STRONG>
+<DD><A HREF="node3.html#1431">Nodes</A>
+ | <A HREF="node4.html#1619">Reference Counts</A>
+ | <A HREF="node4.html#1623">Reference Counts</A>
+ | <A HREF="node4.html#1633">Reference Counts</A>
+ | <A HREF="node4.html#1639"><EM>Cudd_RecursiveDeref</EM> vs. <EM>Cudd_Deref</EM></A>
+ | <A HREF="node4.html#1645">When Increasing the Reference</A>
+ | <A HREF="node4.html#1649">Saturating Increments and Decrements</A>
+ | <A HREF="node4.html#1677">Local Caches</A>
+ | <A HREF="node4.html#1699">Debugging</A>
+<DT><STRONG><I>Cudd_RecursiveDerefZdd</I></STRONG>
+<DD><A HREF="node3.html#1433">Nodes</A>
+ | <A HREF="node4.html#1621">Reference Counts</A>
+ | <A HREF="node4.html#1625">Reference Counts</A>
+ | <A HREF="node4.html#1635">Reference Counts</A>
+ | <A HREF="node4.html#1647">When Increasing the Reference</A>
+ | <A HREF="node4.html#1651">Saturating Increments and Decrements</A>
+<DT><STRONG><I>Cudd_ReduceHeap</I></STRONG>
+<DD><A HREF="node3.html#1539">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#1545">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#1549">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_Ref</I></STRONG>
+<DD><A HREF="node3.html#1429">Nodes</A>
+ | <A HREF="node3.html#1499">Basic BDD Manipulation</A>
+ | <A HREF="node4.html#1617">Reference Counts</A>
+ | <A HREF="node4.html#1643">When Increasing the Reference</A>
+<DT><STRONG><I>Cudd_Regular</I></STRONG>
+<DD><A HREF="node4.html#1659">Complement Arcs</A>
+<DT><STRONG>CUDD_REORDER_ANNEALING</STRONG>
+<DD><A HREF="node3.html#559">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_EXACT</STRONG>
+<DD><A HREF="node3.html#565">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_GENETIC</STRONG>
+<DD><A HREF="node3.html#562">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_GROUP_SIFT</STRONG>
+<DD><A HREF="node3.html#544">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_GROUP_SIFT_CONV</STRONG>
+<DD><A HREF="node3.html#548">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_NONE</STRONG>
+<DD><A HREF="node3.html#507">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#631">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_RANDOM</STRONG>
+<DD><A HREF="node3.html#515">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#633">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_RANDOM_PIVOT</STRONG>
+<DD><A HREF="node3.html#517">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#634">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_SAME</STRONG>
+<DD><A HREF="node3.html#508">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#632">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_SIFT</STRONG>
+<DD><A HREF="node3.html#518">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#635">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_SIFT_CONVERGE</STRONG>
+<DD><A HREF="node3.html#533">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#636">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_SYMM_SIFT</STRONG>
+<DD><A HREF="node3.html#535">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#637">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_SYMM_SIFT_CONV</STRONG>
+<DD><A HREF="node3.html#542">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#638">Variable Reordering for ZDDs</A>
+<DT><STRONG>CUDD_REORDER_WINDOW2</STRONG>
+<DD><A HREF="node3.html#549">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_WINDOW2_CONV</STRONG>
+<DD><A HREF="node3.html#555">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_WINDOW3</STRONG>
+<DD><A HREF="node3.html#553">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_WINDOW3_CONV</STRONG>
+<DD><A HREF="node3.html#557">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_WINDOW4</STRONG>
+<DD><A HREF="node3.html#554">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_REORDER_WINDOW4_CONV</STRONG>
+<DD><A HREF="node3.html#558">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_SetEpsilon</I></STRONG>
+<DD><A HREF="node3.html#1461">Predefined Constants</A>
+<DT><STRONG><I>Cudd_SetLooseUpTo</I></STRONG>
+<DD><A HREF="node3.html#1443">Setting Parameters</A>
+<DT><STRONG><I>Cudd_SetMaxCacheHard</I></STRONG>
+<DD><A HREF="node4.html#1707">Modifiable Parameters</A>
+<DT><STRONG><I>Cudd_SetMaxGrowth</I></STRONG>
+<DD><A HREF="node3.html#1557">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_SetSiftMaxVar</I></STRONG>
+<DD><A HREF="node3.html#1553">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_SetTree</I></STRONG>
+<DD><A HREF="node3.html#1565">Grouping Variables</A>
+<DT><STRONG><I>Cudd_ShuffleHeap</I></STRONG>
+<DD><A HREF="node3.html#1561">Variable Reordering for BDDs</A>
+<DT><STRONG><I>Cudd_StdPostReordHook</I></STRONG>
+<DD><A HREF="node3.html#1595">Hooks</A>
+<DT><STRONG><I>Cudd_StdPreReordHook</I></STRONG>
+<DD><A HREF="node3.html#1593">Hooks</A>
+<DT><STRONG><I>Cudd_SymmProfile</I></STRONG>
+<DD><A HREF="node3.html#1559">Variable Reordering for BDDs</A>
+<DT><STRONG>CUDD_UNIQUE_SLOTS</STRONG>
+<DD><A HREF="node3.html#168">Initializing and Shutting Down</A>
+<DT><STRONG><I>Cudd_zddDumpDot</I></STRONG>
+<DD><A HREF="node3.html#1601">Writing Decision Diagrams to</A>
+<DT><STRONG><I>Cudd_zddIsop</I></STRONG>
+<DD><A HREF="node3.html#1517">Basic ZDD Manipulation</A>
+<DT><STRONG><I>Cudd_zddIthVar</I></STRONG>
+<DD><A HREF="node3.html#1493">New ZDD Variables</A>
+<DT><STRONG><I>Cudd_zddPortFromBdd</I></STRONG>
+<DD><A HREF="node3.html#1533">Converting BDDs to ZDDs</A>
+<DT><STRONG><I>Cudd_zddPortToBdd</I></STRONG>
+<DD><A HREF="node3.html#1535">Converting BDDs to ZDDs</A>
+<DT><STRONG><I>Cudd_zddRealignDisable</I></STRONG>
+<DD><A HREF="node3.html#1587">Keeping Consistent Variable Orders</A>
+<DT><STRONG><I>Cudd_zddRealignEnable</I></STRONG>
+<DD><A HREF="node3.html#1585">Keeping Consistent Variable Orders</A>
+<DT><STRONG><I>Cudd_zddReduceHeap</I></STRONG>
+<DD><A HREF="node3.html#1575">Variable Reordering for ZDDs</A>
+<DT><STRONG><I>Cudd_zddShuffleHeap</I></STRONG>
+<DD><A HREF="node3.html#1577">Variable Reordering for ZDDs</A>
+<DT><STRONG><I>Cudd_zddVarsFromBddVars</I></STRONG>
+<DD><A HREF="node3.html#1531">Converting BDDs to ZDDs</A>
+ | <A HREF="node3.html#1537">Converting BDDs to ZDDs</A>
+<DT><STRONG><I>Cudd_zddWeakDiv</I></STRONG>
+<DD><A HREF="node3.html#1519">Basic ZDD Manipulation</A>
+<DT><STRONG><I>cuddCacheInsert</I></STRONG>
+<DD><A HREF="node4.html#1665">The Cache</A>
+<DT><STRONG><I>cuddCacheInsert1</I></STRONG>
+<DD><A HREF="node4.html#1673">The Cache</A>
+<DT><STRONG><I>cuddCacheInsert2</I></STRONG>
+<DD><A HREF="node4.html#1669">The Cache</A>
+<DT><STRONG><I>cuddCacheLookup</I></STRONG>
+<DD><A HREF="node4.html#1667">The Cache</A>
+<DT><STRONG><I>cuddCacheLookup1</I></STRONG>
+<DD><A HREF="node4.html#1675">The Cache</A>
+<DT><STRONG><I>cuddCacheLookup2</I></STRONG>
+<DD><A HREF="node4.html#1671">The Cache</A>
+<DT><STRONG>CUDDDIR</STRONG>
+<DD><A HREF="node3.html#680">Using the CUDD Package</A>
+<DT><STRONG><I>cuddHeapProfile</I></STRONG>
+<DD><A HREF="node4.html#1697">Debugging</A>
+<DT><STRONG><I>cuddI</I></STRONG>
+<DD><A HREF="node4.html#1679">The Unique Table</A>
+<DT><STRONG>cuddInt.h</STRONG>
+<DD><A HREF="node4.html#1069">Debugging</A>
+<DT><STRONG><I>cuddIZ</I></STRONG>
+<DD><A HREF="node4.html#1681">The Unique Table</A>
+<DT><STRONG><I>cuddSatDec</I></STRONG>
+<DD><A HREF="node4.html#1657">Saturating Increments and Decrements</A>
+<DT><STRONG><I>cuddSatInc</I></STRONG>
+<DD><A HREF="node4.html#1655">Saturating Increments and Decrements</A>
+<DT><STRONG><I>cuddUniqueConst</I></STRONG>
+<DD><A HREF="node4.html#1609">Reference Counts</A>
+ | <A HREF="node4.html#1615">Reference Counts</A>
+ | <A HREF="node4.html#1631">Reference Counts</A>
+<DT><STRONG><I>cuddUniqueInter</I></STRONG>
+<DD><A HREF="node4.html#1605">Reference Counts</A>
+ | <A HREF="node4.html#1611">Reference Counts</A>
+ | <A HREF="node4.html#1627">Reference Counts</A>
+ | <A HREF="node4.html#1661">Complement Arcs</A>
+ | <A HREF="node4.html#1663">Complement Arcs</A>
+ | <A HREF="node4.html#1683">Allowing Asynchronous Reordering</A>
+ | <A HREF="node4.html#1687">Allowing Asynchronous Reordering</A>
+ | <A HREF="node4.html#1691">Allowing Asynchronous Reordering</A>
+<DT><STRONG><I>cuddUniqueInterZdd</I></STRONG>
+<DD><A HREF="node4.html#1607">Reference Counts</A>
+ | <A HREF="node4.html#1613">Reference Counts</A>
+ | <A HREF="node4.html#1629">Reference Counts</A>
+ | <A HREF="node4.html#1685">Allowing Asynchronous Reordering</A>
+<DT><STRONG>DD_CACHE_PROFILE</STRONG>
+<DD><A HREF="node4.html#1172">Extended Statistics and Reporting</A>
+<DT><STRONG>DD_DEBUG</STRONG>
+<DD><A HREF="node4.html#1056">Debugging</A>
+<DT><STRONG>DD_STATS</STRONG>
+<DD><A HREF="node4.html#1171">Extended Statistics and Reporting</A>
+<DT><STRONG>DD_UNIQUE_PROFILE</STRONG>
+<DD><A HREF="node4.html#1173">Extended Statistics and Reporting</A>
+<DT><STRONG>DD_VERBOSE</STRONG>
+<DD><A HREF="node4.html#1174">Extended Statistics and Reporting</A>
+<DT><STRONG>DdManager</STRONG>
+<DD><A HREF="node3.html#140">The Manager</A>
+ | <A HREF="node3.html#155">Initializing and Shutting Down</A>
+<DT><STRONG>DdNode</STRONG>
+<DD><A HREF="node3.html#91">Nodes</A>
+ | <A HREF="node4.html#949">The Cache</A>
+<DT><STRONG>debugging</STRONG>
+<DD><A HREF="node4.html#1054">Debugging</A>
+<DT><STRONG>DEC Alpha</STRONG>
+<DD><A HREF="node3.html#233">Predefined Constants</A>
+ | <A HREF="node3.html#747">Using the CUDD Package</A>
+<DT><STRONG>documentation</STRONG>
+<DD><A HREF="node4.html#1178">Guidelines for Documentation</A>
+<DL COMPACT>
+<DT><STRONG><I>Description</I></STRONG>
+<DD><A HREF="node4.html#1412">Guidelines for Documentation</A>
+<DT><STRONG>HTML files</STRONG>
+<DD><A HREF="node4.html#1194">Guidelines for Documentation</A>
+<DT><STRONG><I>SeeAlso</I></STRONG>
+<DD><A HREF="node4.html#1411">Guidelines for Documentation</A>
+<DT><STRONG><I>Synopsis</I></STRONG>
+<DD><A HREF="node4.html#1413">Guidelines for Documentation</A>
+</DL>
+<DT><STRONG>dot</STRONG>
+<DD><i>see </i> graph, drawing
+<DT><STRONG>Epsilon</STRONG>
+<DD><A HREF="node3.html#244">Predefined Constants</A>
+<DT><STRONG>extdoc</STRONG>
+<DD><i>see </i> documentation
+<DT><STRONG>floating point</STRONG>
+<DD><A HREF="node3.html#231">Predefined Constants</A>
+<DL COMPACT>
+<DT><STRONG>double (C type)</STRONG>
+<DD><A HREF="node3.html#132">Nodes</A>
+<DT><STRONG>IEEE Standard 754</STRONG>
+<DD><A HREF="node3.html#230">Predefined Constants</A>
+</DL>
+<DT><STRONG>free list</STRONG>
+<DD><A HREF="node4.html#845">Reference Counts</A>
+<DT><STRONG>FTP</STRONG>
+<DD><A HREF="node2.html#45">The CUDD Package</A>
+ | <A HREF="node2.html#67">CUDD Friends</A>
+ | <A HREF="node3.html#742">Using the CUDD Package</A>
+ | <A HREF="node4.html#1179">Guidelines for Documentation</A>
+<DT><STRONG>function</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>characteristic</STRONG>
+<DD><A HREF="node1.html#21">Introduction</A>
+ | <A HREF="node3.html#476">Converting BDDs to ZDDs</A>
+<DT><STRONG>cover</STRONG>
+<DD><A HREF="node3.html#417">Basic ZDD Manipulation</A>
+ | <A HREF="node3.html#467">Converting BDDs to ZDDs</A>
+ | <A HREF="node3.html#475">Converting BDDs to ZDDs</A>
+<DD><DL COMPACT>
+<DT><STRONG>irredundant</STRONG>
+<DD><A HREF="node3.html#421">Basic ZDD Manipulation</A>
+</DL>
+<DT><STRONG>minterms</STRONG>
+<DD><A HREF="node3.html#279">Background</A>
+ | <A HREF="node4.html#1027">Allowing Asynchronous Reordering</A>
+<DT><STRONG>ON-set</STRONG>
+<DD><A HREF="node1.html#23">Introduction</A>
+<DT><STRONG>sum of products</STRONG>
+<DD><A HREF="node3.html#272">Background</A>
+<DT><STRONG>switching</STRONG>
+<DD><A HREF="node1.html#19">Introduction</A>
+ | <A HREF="node1.html#20">Introduction</A>
+</DL>
+<DT><STRONG>garbage collection</STRONG>
+<DD><A HREF="node3.html#116">Nodes</A>
+ | <A HREF="node3.html#151">Cache</A>
+ | <A HREF="node3.html#189">Setting Parameters</A>
+ | <A HREF="node4.html#802">Reference Counts</A>
+ | <A HREF="node4.html#844">Reference Counts</A>
+ | <A HREF="node4.html#946">The Cache</A>
+ | <A HREF="node4.html#991">Local Caches</A>
+ | <A HREF="node4.html#1012">The Unique Table</A>
+<DL COMPACT>
+<DT><STRONG>hooks</STRONG>
+<DD><A HREF="node3.html#659">Hooks</A>
+</DL>
+<DT><STRONG>gcc</STRONG>
+<DD><A HREF="node3.html#235">Predefined Constants</A>
+<DT><STRONG>generator</STRONG>
+<DD><A HREF="node3.html#103">Nodes</A>
+<DT><STRONG>global variables</STRONG>
+<DD><A HREF="node3.html#144">The Manager</A>
+<DT><STRONG>graph</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>arc capacity</STRONG>
+<DD><A HREF="node3.html#259">Background</A>
+<DT><STRONG>arc length</STRONG>
+<DD><A HREF="node3.html#257">Background</A>
+<DT><STRONG>drawing</STRONG>
+<DD><A HREF="node3.html#760">Writing Decision Diagrams to</A>
+ | <A HREF="node3.html#780">Writing Decision Diagrams to</A>
+</DL>
+<DT><STRONG>growth</STRONG>
+<DD><A HREF="node3.html#190">Setting Parameters</A>
+<DT><STRONG>gzip</STRONG>
+<DD><A HREF="node2.html#49">The CUDD Package</A>
+<DT><STRONG>HAVE_IEEE_754</STRONG>
+<DD><A HREF="node3.html#236">Predefined Constants</A>
+<DT><STRONG>header files</STRONG>
+<DD><A HREF="node3.html#505">Variable Reordering for BDDs</A>
+ | <A HREF="node4.html#914">Saturating Increments and Decrements</A>
+<DT><STRONG>hook</STRONG>
+<DD><A HREF="node3.html#652">Hooks</A>
+<DT><STRONG>infinities</STRONG>
+<DD><A HREF="node3.html#232">Predefined Constants</A>
+<DT><STRONG>installation</STRONG>
+<DD><A HREF="node2.html#55">The CUDD Package</A>
+<DT><STRONG>Intel PentiumPro</STRONG>
+<DD><A HREF="node2.html#60">The CUDD Package</A>
+<DT><STRONG>interface</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>cache</STRONG>
+<DD><A HREF="node4.html#956">The Cache</A>
+<DT><STRONG>SIS</STRONG>
+<DD><A HREF="node3.html#669">The SIS/VIS Interface</A>
+ | <A HREF="node3.html#677">Using the CUDD Package</A>
+<DT><STRONG>VIS</STRONG>
+<DD><A HREF="node3.html#670">The SIS/VIS Interface</A>
+</DL>
+<DT><STRONG>libraries</STRONG>
+<DD><A HREF="node2.html#52">The CUDD Package</A>
+<DL COMPACT>
+<DT><STRONG>cudd</STRONG>
+<DD><A HREF="node3.html#82">Compiling and Linking</A>
+<DT><STRONG>dddmp</STRONG>
+<DD><A HREF="node3.html#789">Saving and Restoring BDDs</A>
+<DT><STRONG>mtr</STRONG>
+<DD><A HREF="node3.html#83">Compiling and Linking</A>
+ | <A HREF="node3.html#581">Grouping Variables</A>
+<DT><STRONG>obj</STRONG>
+<DD><A HREF="node5.html#1204">Compiling and Linking</A>
+<DT><STRONG>st</STRONG>
+<DD><A HREF="node3.html#84">Compiling and Linking</A>
+ | <A HREF="node4.html#953">The Cache</A>
+<DT><STRONG>util</STRONG>
+<DD><A HREF="node3.html#85">Compiling and Linking</A>
+</DL>
+<DT><STRONG>Makefile</STRONG>
+<DD><A HREF="node3.html#86">Compiling and Linking</A>
+ | <A HREF="node3.html#237">Predefined Constants</A>
+ | <A HREF="node5.html#1205">Compiling and Linking</A>
+<DT><STRONG>manager</STRONG>
+<DD><A HREF="node3.html#134">The Manager</A>
+ | <A HREF="node3.html#141">The Manager</A>
+ | <A HREF="node3.html#201">Constant Functions</A>
+<DT><STRONG>matrix</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>sparse</STRONG>
+<DD><A HREF="node3.html#260">Background</A>
+</DL>
+<DT><STRONG>maxCache</STRONG>
+<DD><A HREF="node4.html#979">Cache Sizing</A>
+<DT><STRONG>maxMemory</STRONG>
+<DD><A HREF="node3.html#172">Initializing and Shutting Down</A>
+<DT><STRONG>MinusInfinity</STRONG>
+<DD><A HREF="node3.html#229">Predefined Constants</A>
+<DT><STRONG>MTR_DEFAULT</STRONG>
+<DD><A HREF="node3.html#598">Grouping Variables</A>
+<DT><STRONG>MTR_FIXED</STRONG>
+<DD><A HREF="node3.html#593">Grouping Variables</A>
+<DT><STRONG>nanotrav</STRONG>
+<DD><A HREF="node2.html#58">The CUDD Package</A>
+ | <A HREF="node2.html#62">The CUDD Package</A>
+<DT><STRONG>node</STRONG>
+<DD><A HREF="node3.html#92">Nodes</A>
+<DL COMPACT>
+<DT><STRONG>constant</STRONG>
+<DD><A HREF="node3.html#99">Nodes</A>
+ | <A HREF="node3.html#199">Constant Functions</A>
+ | <A HREF="node3.html#206">One, Logic Zero, and</A>
+ | <A HREF="node3.html#226">Predefined Constants</A>
+ | <A HREF="node3.html#256">Background</A>
+ | <A HREF="node3.html#285">New Constants</A>
+ | <A HREF="node4.html#809">Reference Counts</A>
+ | <A HREF="node4.html#883">When Increasing the Reference</A>
+<DD><DL COMPACT>
+<DT><STRONG>value</STRONG>
+<DD><A HREF="node3.html#131">Nodes</A>
+</DL>
+<DT><STRONG>dead</STRONG>
+<DD><A HREF="node4.html#833">Reference Counts</A>
+ | <A HREF="node4.html#947">The Cache</A>
+ | <A HREF="node4.html#1011">The Unique Table</A>
+<DT><STRONG>dereference</STRONG>
+<DD><A HREF="node3.html#389">Basic ADD Manipulation</A>
+<DT><STRONG>reclaimed</STRONG>
+<DD><A HREF="node4.html#1015">The Unique Table</A>
+<DT><STRONG>recycling</STRONG>
+<DD><A HREF="node3.html#130">Nodes</A>
+<DT><STRONG>reference</STRONG>
+<DD><A HREF="node3.html#388">Basic ADD Manipulation</A>
+<DT><STRONG>reference count</STRONG>
+<DD><A HREF="node3.html#94">Nodes</A>
+ | <A HREF="node3.html#117">Nodes</A>
+ | <A HREF="node3.html#356">Basic BDD Manipulation</A>
+ | <A HREF="node3.html#370">Basic BDD Manipulation</A>
+ | <A HREF="node4.html#800">Reference Counts</A>
+ | <A HREF="node4.html#831">Reference Counts</A>
+ | <A HREF="node4.html#846">Reference Counts</A>
+ | <A HREF="node4.html#881">When Increasing the Reference</A>
+ | <A HREF="node4.html#899">Saturating Increments and Decrements</A>
+ | <A HREF="node4.html#945">The Cache</A>
+ | <A HREF="node4.html#992">Local Caches</A>
+ | <A HREF="node4.html#1086">Debugging</A>
+<DD><DL COMPACT>
+<DT><STRONG>saturated</STRONG>
+<DD><A HREF="node4.html#1088">Debugging</A>
+</DL>
+<DT><STRONG>terminal</STRONG>
+<DD><i>see </i> node, constant
+<DT><STRONG>variable index</STRONG>
+<DD><A HREF="node3.html#93">Nodes</A>
+</DL>
+<DT><STRONG>numSlots</STRONG>
+<DD><A HREF="node3.html#165">Initializing and Shutting Down</A>
+<DT><STRONG>numVars</STRONG>
+<DD><A HREF="node3.html#161">Initializing and Shutting Down</A>
+<DT><STRONG>numVarsZ</STRONG>
+<DD><A HREF="node3.html#162">Initializing and Shutting Down</A>
+<DT><STRONG>PlusInfinity</STRONG>
+<DD><A HREF="node3.html#228">Predefined Constants</A>
+ | <A HREF="node3.html#258">Background</A>
+<DT><STRONG>projection functions</STRONG>
+<DD><A HREF="node3.html#293">Creating Variables</A>
+ | <A HREF="node3.html#296">New BDD and ADD</A>
+ | <A HREF="node3.html#305">New BDD and ADD</A>
+ | <A HREF="node3.html#309">New BDD and ADD</A>
+ | <A HREF="node3.html#333">New ZDD Variables</A>
+ | <A HREF="node3.html#355">Basic BDD Manipulation</A>
+ | <A HREF="node3.html#387">Basic ADD Manipulation</A>
+ | <A HREF="node3.html#408">Basic ZDD Manipulation</A>
+ | <A HREF="node3.html#412">Basic ZDD Manipulation</A>
+ | <A HREF="node4.html#1087">Debugging</A>
+<DT><STRONG>README file</STRONG>
+<DD><A HREF="node2.html#63">The CUDD Package</A>
+ | <A HREF="node2.html#53">The CUDD Package</A>
+<DT><STRONG>reordering</STRONG>
+<DD><A HREF="node1.html#24">Introduction</A>
+ | <A HREF="node1.html#28">Introduction</A>
+ | <A HREF="node3.html#101">Nodes</A>
+ | <A HREF="node4.html#948">The Cache</A>
+<DL COMPACT>
+<DT><STRONG>abort and retry</STRONG>
+<DD><A HREF="node4.html#1029">Allowing Asynchronous Reordering</A>
+<DT><STRONG>asynchronous</STRONG>
+<DD><A HREF="node3.html#489">Variable Reordering for BDDs</A>
+ | <A HREF="node4.html#1024">Allowing Asynchronous Reordering</A>
+<DT><STRONG>converging</STRONG>
+<DD><A HREF="node3.html#499">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#534">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#543">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#556">Variable Reordering for BDDs</A>
+<DT><STRONG>Cudd_ReorderingType</STRONG>
+<DD><A HREF="node3.html#503">Variable Reordering for BDDs</A>
+<DT><STRONG>dynamic</STRONG>
+<DD><A HREF="node1.html#33">Introduction</A>
+ | <A HREF="node3.html#480">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#623">Variable Reordering for ZDDs</A>
+<DT><STRONG>exact</STRONG>
+<DD><A HREF="node3.html#566">Variable Reordering for BDDs</A>
+<DT><STRONG>function wrapper</STRONG>
+<DD><A HREF="node4.html#1031">Allowing Asynchronous Reordering</A>
+ | <A HREF="node4.html#1051">Allowing Asynchronous Reordering</A>
+<DT><STRONG>genetic</STRONG>
+<DD><A HREF="node3.html#563">Variable Reordering for BDDs</A>
+<DT><STRONG>group</STRONG>
+<DD><A HREF="node3.html#501">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#545">Variable Reordering for BDDs</A>
+<DT><STRONG>hooks</STRONG>
+<DD><A HREF="node3.html#660">Hooks</A>
+<DT><STRONG>interruptible procedure</STRONG>
+<DD><A HREF="node4.html#1030">Allowing Asynchronous Reordering</A>
+<DT><STRONG>of BDDs and ADDs</STRONG>
+<DD><A HREF="node3.html#478">Variable Reordering for BDDs</A>
+<DT><STRONG>of ZDDs</STRONG>
+<DD><A HREF="node3.html#426">Basic ZDD Manipulation</A>
+ | <A HREF="node3.html#611">Variable Reordering for ZDDs</A>
+<DT><STRONG>random</STRONG>
+<DD><A HREF="node3.html#516">Variable Reordering for BDDs</A>
+<DT><STRONG>sifting</STRONG>
+<DD><A HREF="node3.html#502">Variable Reordering for BDDs</A>
+ | <A HREF="node3.html#519">Variable Reordering for BDDs</A>
+<DT><STRONG>simulated annealing</STRONG>
+<DD><A HREF="node3.html#560">Variable Reordering for BDDs</A>
+<DT><STRONG>symmetric</STRONG>
+<DD><A HREF="node3.html#536">Variable Reordering for BDDs</A>
+<DT><STRONG>threshold</STRONG>
+<DD><A HREF="node3.html#488">Variable Reordering for BDDs</A>
+ | <A HREF="node4.html#1026">Allowing Asynchronous Reordering</A>
+<DT><STRONG>window</STRONG>
+<DD><A HREF="node3.html#550">Variable Reordering for BDDs</A>
+</DL>
+<DT><STRONG>saturating</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>decrements</STRONG>
+<DD><A HREF="node4.html#897">Saturating Increments and Decrements</A>
+<DT><STRONG>increments</STRONG>
+<DD><A HREF="node4.html#896">Saturating Increments and Decrements</A>
+</DL>
+<DT><STRONG>SISDIR</STRONG>
+<DD><A HREF="node3.html#679">Using the CUDD Package</A>
+<DT><STRONG>SIZEOF_INT</STRONG>
+<DD><A HREF="node4.html#913">Saturating Increments and Decrements</A>
+ | <A HREF="node4.html#924">Saturating Increments and Decrements</A>
+<DT><STRONG>SIZEOF_VOID_P</STRONG>
+<DD><A HREF="node4.html#912">Saturating Increments and Decrements</A>
+ | <A HREF="node4.html#923">Saturating Increments and Decrements</A>
+<DT><STRONG>statistical counters</STRONG>
+<DD><A HREF="node3.html#143">The Manager</A>
+ | <A HREF="node4.html#834">Reference Counts</A>
+ | <A HREF="node4.html#983">Cache Sizing</A>
+<DT><STRONG>statistics</STRONG>
+<DD><A HREF="node4.html#1090">Gathering and Interpreting Statistics</A>
+<DT><STRONG>subtable</STRONG>
+<DD><A HREF="node3.html#166">Initializing and Shutting Down</A>
+ | <A HREF="node4.html#835">Reference Counts</A>
+<DT><STRONG>symmetry</STRONG>
+<DD><A HREF="node3.html#538">Variable Reordering for BDDs</A>
+<DT><STRONG>table</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>computed</STRONG>
+<DD><A HREF="node3.html#149">Cache</A>
+<DT><STRONG>growth</STRONG>
+<DD><A HREF="node3.html#188">Setting Parameters</A>
+<DT><STRONG>hash</STRONG>
+<DD><A HREF="node3.html#136">The Manager</A>
+ | <A HREF="node4.html#1007">The Unique Table</A>
+<DT><STRONG>unique</STRONG>
+<DD><A HREF="node3.html#95">Nodes</A>
+ | <A HREF="node3.html#137">The Manager</A>
+ | <A HREF="node3.html#139">The Manager</A>
+ | <A HREF="node3.html#167">Initializing and Shutting Down</A>
+ | <A HREF="node3.html#174">Initializing and Shutting Down</A>
+ | <A HREF="node3.html#187">Setting Parameters</A>
+ | <A HREF="node3.html#483">Variable Reordering for BDDs</A>
+ | <A HREF="node4.html#836">Reference Counts</A>
+ | <A HREF="node4.html#980">Cache Sizing</A>
+ | <A HREF="node4.html#985">Cache Sizing</A>
+ | <A HREF="node4.html#998">The Unique Table</A>
+<DD><DL COMPACT>
+<DT><STRONG>fast growth</STRONG>
+<DD><A HREF="node4.html#1018">The Unique Table</A>
+<DT><STRONG>reward-based resizing</STRONG>
+<DD><A HREF="node4.html#1016">The Unique Table</A>
+<DT><STRONG>slow growth</STRONG>
+<DD><A HREF="node4.html#1019">The Unique Table</A>
+</DL>
+</DL>
+<DT><STRONG>variable</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>groups</STRONG>
+<DD><A HREF="node3.html#574">Grouping Variables</A>
+<DT><STRONG>order</STRONG>
+<DD><A HREF="node3.html#98">Nodes</A>
+ | <A HREF="node3.html#316">New BDD and ADD</A>
+<DT><STRONG>permutation</STRONG>
+<DD><A HREF="node3.html#100">Nodes</A>
+ | <A HREF="node4.html#1000">The Unique Table</A>
+<DT><STRONG>tree</STRONG>
+<DD><A HREF="node3.html#576">Grouping Variables</A>
+ | <A HREF="node3.html#603">Grouping Variables</A>
+</DL>
+<DT><STRONG>ZDD</STRONG>
+<DD><A HREF="node1.html#17">Introduction</A>
+ | <A HREF="node3.html#120">Nodes</A>
+ | <A HREF="node3.html#331">New ZDD Variables</A>
+ | <A HREF="node3.html#404">Basic ZDD Manipulation</A>
+ | <A HREF="node3.html#453">Converting BDDs to ZDDs</A>
+<DT><STRONG>zero</STRONG>
+<DD><DL COMPACT>
+<DT><STRONG>arithmetic</STRONG>
+<DD><A HREF="node3.html#204">One, Logic Zero, and</A>
+ | <A HREF="node3.html#300">New BDD and ADD</A>
+ | <A HREF="node3.html#445">Converting ADDs to BDDs</A>
+<DT><STRONG>logical</STRONG>
+<DD><A HREF="node3.html#203">One, Logic Zero, and</A>
+ | <A HREF="node3.html#444">Converting ADDs to BDDs</A>
+</DL>
+<DT><STRONG>Zero-suppressed Binary Decision Diagram</STRONG>
+<DD><i>see </i> ZDD
+
+</DL>
+<BR><HR>
+<ADDRESS>
+Fabio Somenzi
+2005-05-17
+</ADDRESS>
+</BODY>
+</HTML>
Index: /vis_dev/glu-2.1/src/cuBdd/r7x8.1.mat
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/r7x8.1.mat	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/r7x8.1.mat	(revision 8)
@@ -0,0 +1,53 @@
+7 9
+0 0 1
+0 1 1
+0 2 1
+0 3 4
+0 4 3
+0 5 3
+0 6 3
+0 8 3
+1 0 4
+1 1 3
+1 2 2
+1 3 4
+1 4 1
+1 5 2
+1 6 4
+1 8 3
+2 0 1
+2 1 1
+2 2 4
+2 4 2
+2 5 3
+2 6 3
+2 8 3
+3 0 2
+3 1 1
+3 3 4
+3 4 4
+3 5 1
+3 8 1
+4 0 2
+4 1 3
+4 2 2
+4 3 4
+4 4 1
+4 5 1
+4 6 2
+4 8 2
+5 0 3
+5 1 3
+5 2 4
+5 3 4
+5 4 1
+5 5 3
+5 6 3
+5 8 4
+6 1 1
+6 2 1
+6 3 4
+6 4 2
+6 5 4
+6 6 4
+6 8 2
Index: /vis_dev/glu-2.1/src/cuBdd/testcudd.c
===================================================================
--- /vis_dev/glu-2.1/src/cuBdd/testcudd.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuBdd/testcudd.c	(revision 8)
@@ -0,0 +1,1037 @@
+/**CFile***********************************************************************
+
+  FileName    [testcudd.c]
+
+  PackageName [cudd]
+
+  Synopsis    [Sanity check tests for some CUDD functions.]
+
+  Description [testcudd reads a matrix with real coefficients and
+  transforms it into an ADD. It then performs various operations on
+  the ADD and on the BDD corresponding to the ADD pattern. Finally,
+  testcudd tests functions relate to Walsh matrices and matrix
+  multiplication.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "cuddInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define TESTCUDD_VERSION	"TestCudd Version #1.0, Release date 3/17/01"
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: testcudd.c,v 1.16 2004/08/13 18:04:54 fabio Exp $";
+#endif
+
+static const char *onames[] = { "C", "M" }; /* names of functions to be dumped */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void usage (char * prog);
+static FILE *open_file (char *filename, const char *mode);
+static int testIterators (DdManager *dd, DdNode *M, DdNode *C, int pr);
+static int testXor (DdManager *dd, DdNode *f, int pr, int nvars);
+static int testHamming (DdManager *dd, DdNode *f, int pr);
+static int testWalsh (DdManager *dd, int N, int cmu, int approach, int pr);
+
+/**AutomaticEnd***************************************************************/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main function for testcudd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+main(int argc, char **argv)
+{
+    FILE *fp;           /* pointer to input file */
+    char *file = (char *) "";	/* input file name */
+    FILE *dfp = NULL;	/* pointer to dump file */
+    char *dfile;	/* file for DD dump */
+    DdNode *dfunc[2];	/* addresses of the functions to be dumped */
+    DdManager *dd;	/* pointer to DD manager */
+    DdNode *one;	/* fast access to constant function */
+    DdNode *M;
+    DdNode **x;		/* pointers to variables */
+    DdNode **y;		/* pointers to variables */
+    DdNode **xn;       	/* complements of row variables */
+    DdNode **yn_;      	/* complements of column variables */
+    DdNode **xvars;
+    DdNode **yvars;
+    DdNode *C;		/* result of converting from ADD to BDD */
+    DdNode *ess;	/* cube of essential variables */
+    DdNode *shortP;	/* BDD cube of shortest path */
+    DdNode *largest;	/* BDD of largest cube */
+    DdNode *shortA;	/* ADD cube of shortest path */
+    DdNode *constN;	/* value returned by evaluation of ADD */
+    DdNode *ycube;	/* cube of the negated y vars for c-proj */
+    DdNode *CP;		/* C-Projection of C */
+    DdNode *CPr;	/* C-Selection of C */
+    int    length;	/* length of the shortest path */
+    int    nx;			/* number of variables */
+    int    ny;
+    int    maxnx;
+    int    maxny;
+    int    m;
+    int    n;
+    int    N;
+    int    cmu;			/* use CMU multiplication */
+    int    pr;			/* verbose printout level */
+    int    harwell;
+    int    multiple;		/* read multiple matrices */
+    int    ok;
+    int    c;			/* variable to read in options */
+    int    approach;		/* reordering approach */
+    int    autodyn;		/* automatic reordering */
+    int    groupcheck;		/* option for group sifting */
+    int    profile;		/* print heap profile if != 0 */
+    int    keepperm;		/* keep track of permutation */
+    int    clearcache;		/* clear the cache after each matrix */
+    int    blifOrDot;		/* dump format: 0 -> dot, 1 -> blif, ... */
+    int    retval;		/* return value */
+    int    i;			/* loop index */
+    long   startTime;		/* initial time */
+    long   lapTime;
+    int    size;
+    unsigned int cacheSize, maxMemory;
+    unsigned int nvars,nslots;
+
+    startTime = util_cpu_time();
+
+    approach = CUDD_REORDER_NONE;
+    autodyn = 0;
+    pr = 0;
+    harwell = 0;
+    multiple = 0;
+    profile = 0;
+    keepperm = 0;
+    cmu = 0;
+    N = 4;
+    nvars = 4;
+    cacheSize = 127;
+    maxMemory = 0;
+    nslots = CUDD_UNIQUE_SLOTS;
+    clearcache = 0;
+    groupcheck = CUDD_GROUP_CHECK7;
+    dfile = NULL;
+    blifOrDot = 0; /* dot format */
+
+    /* Parse command line. */
+    while ((c = util_getopt(argc, argv, (char *) "CDHMPS:a:bcd:g:hkmn:p:v:x:X:"))
+	   != EOF) {
+	switch(c) {
+	case 'C':
+	    cmu = 1;
+	    break;
+	case 'D':
+	    autodyn = 1;
+	    break;
+	case 'H':
+	    harwell = 1;
+	    break;
+	case 'M':
+#ifdef MNEMOSYNE
+	    (void) mnem_setrecording(0);
+#endif
+	    break;
+	case 'P':
+	    profile = 1;
+	    break;
+	case 'S':
+	    nslots = atoi(util_optarg);
+	    break;
+	case 'X':
+	    maxMemory = atoi(util_optarg);
+	    break;
+	case 'a':
+	    approach = atoi(util_optarg);
+	    break;
+	case 'b':
+	    blifOrDot = 1; /* blif format */
+	    break;
+	case 'c':
+	    clearcache = 1;
+	    break;
+	case 'd':
+	    dfile = util_optarg;
+	    break;
+	case 'g':
+	    groupcheck = atoi(util_optarg);
+	    break;
+	case 'k':
+	    keepperm = 1;
+	    break;
+	case 'm':
+	    multiple = 1;
+	    break;
+	case 'n':
+	    N = atoi(util_optarg);
+	    break;
+	case 'p':
+	    pr = atoi(util_optarg);
+	    break;
+	case 'v':
+	    nvars = atoi(util_optarg);
+	    break;
+	case 'x':
+	    cacheSize = atoi(util_optarg);
+	    break;
+	case 'h':
+	default:
+	    usage(argv[0]);
+	    break;
+	}
+    }
+
+    if (argc - util_optind == 0) {
+	file = (char *) "-";
+    } else if (argc - util_optind == 1) {
+	file = argv[util_optind];
+    } else {
+	usage(argv[0]);
+    }
+    if ((approach<0) || (approach>17)) {
+	(void) fprintf(stderr,"Invalid approach: %d \n",approach);
+	usage(argv[0]);
+    }
+
+    if (pr >= 0) {
+	(void) printf("# %s\n", TESTCUDD_VERSION);
+	/* Echo command line and arguments. */
+	(void) printf("#");
+	for (i = 0; i < argc; i++) {
+	    (void) printf(" %s", argv[i]);
+	}
+	(void) printf("\n");
+	(void) fflush(stdout);
+    }
+
+    /* Initialize manager and provide easy reference to terminals. */
+    dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory);
+    one = DD_ONE(dd);
+    dd->groupcheck = (Cudd_AggregationType) groupcheck;
+    if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME);
+
+    /* Open input file. */
+    fp = open_file(file, "r");
+
+    /* Open dump file if requested */
+    if (dfile != NULL) {
+	dfp = open_file(dfile, "w");
+    }
+
+    x = y = xn = yn_ = NULL;
+    do {
+	/* We want to start anew for every matrix. */
+	maxnx = maxny = 0;
+	nx = maxnx; ny = maxny;
+	if (pr>0) lapTime = util_cpu_time();
+	if (harwell) {
+	    if (pr >= 0) (void) printf(":name: ");
+	    ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
+	    &m, &n, 0, 2, 1, 2, pr);
+	} else {
+	    ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
+	    &m, &n, 0, 2, 1, 2);
+	    if (pr >= 0)
+		(void) printf(":name: %s: %d rows %d columns\n", file, m, n);
+	}
+	if (!ok) {
+	    (void) fprintf(stderr, "Error reading matrix\n");
+	    exit(1);
+	}
+
+	if (nx > maxnx) maxnx = nx;
+	if (ny > maxny) maxny = ny;
+
+	/* Build cube of negated y's. */
+	ycube = DD_ONE(dd);
+	Cudd_Ref(ycube);
+	for (i = maxny - 1; i >= 0; i--) {
+	    DdNode *tmpp;
+	    tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube);
+	    if (tmpp == NULL) exit(2);
+	    Cudd_Ref(tmpp);
+	    Cudd_RecursiveDeref(dd,ycube);
+	    ycube = tmpp;
+	}
+	/* Initialize vectors of BDD variables used by priority func. */
+	xvars = ALLOC(DdNode *, nx);
+	if (xvars == NULL) exit(2);
+	for (i = 0; i < nx; i++) {
+	    xvars[i] = dd->vars[x[i]->index];
+	}
+	yvars = ALLOC(DdNode *, ny);
+	if (yvars == NULL) exit(2);
+	for (i = 0; i < ny; i++) {
+	    yvars[i] = dd->vars[y[i]->index];
+	}
+
+	/* Clean up */
+	for (i=0; i < maxnx; i++) {
+	    Cudd_RecursiveDeref(dd, x[i]);
+	    Cudd_RecursiveDeref(dd, xn[i]);
+	}
+	FREE(x);
+	FREE(xn);
+	for (i=0; i < maxny; i++) {
+	    Cudd_RecursiveDeref(dd, y[i]);
+	    Cudd_RecursiveDeref(dd, yn_[i]);
+	}
+	FREE(y);
+	FREE(yn_);
+
+	if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}
+
+	if (pr>0) (void) printf(":2: time to read the matrix = %s\n",
+		    util_print_time(util_cpu_time() - lapTime));
+
+	C = Cudd_addBddPattern(dd, M);
+	if (C == 0) exit(2);
+	Cudd_Ref(C);
+	if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);}
+
+	/* Test iterators. */
+	retval = testIterators(dd,M,C,pr);
+	if (retval == 0) exit(2);
+
+	cuddCacheProfile(dd,stdout);
+
+	/* Test XOR */
+	retval = testXor(dd,C,pr,nx+ny);
+	if (retval == 0) exit(2);
+
+	/* Test Hamming distance functions. */
+	retval = testHamming(dd,C,pr);
+	if (retval == 0) exit(2);
+
+	/* Test selection functions. */
+	CP = Cudd_CProjection(dd,C,ycube);
+	if (CP == NULL) exit(2);
+	Cudd_Ref(CP);
+	if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);}
+	if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);}
+
+	if (nx == ny) {
+	    CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL,
+		(DdNode *)NULL,ny,Cudd_Xgty);
+	    if (CPr == NULL) exit(2);
+	    Cudd_Ref(CPr);
+	    if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);}
+	    if (CP != CPr) {
+		(void) printf("CP != CPr!\n");
+	    }
+	    Cudd_RecursiveDeref(dd, CPr);
+	}
+	FREE(xvars); FREE(yvars);
+
+	Cudd_RecursiveDeref(dd, CP);
+	Cudd_RecursiveDeref(dd, ycube);
+
+	/* Test functions for essential variables. */
+	ess = Cudd_FindEssential(dd,C);
+	if (ess == NULL) exit(2);
+	Cudd_Ref(ess);
+	if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);}
+	Cudd_RecursiveDeref(dd, ess);
+
+	/* Test functions for shortest paths. */
+	shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length);
+	if (shortP == NULL) exit(2);
+	Cudd_Ref(shortP);
+	if (pr>0) {
+	    (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
+	}
+	/* Test functions for largest cubes. */
+	largest = Cudd_LargestCube(dd, Cudd_Not(C), &length);
+	if (largest == NULL) exit(2);
+	Cudd_Ref(largest);
+	if (pr>0) {
+	    (void) printf(":5b: largest");
+	    Cudd_PrintDebug(dd,largest,nx+ny,pr);
+	}
+	Cudd_RecursiveDeref(dd, largest);
+
+	/* Test Cudd_addEvalConst and Cudd_addIteConstant. */
+	shortA = Cudd_BddToAdd(dd,shortP);
+	if (shortA == NULL) exit(2);
+	Cudd_Ref(shortA);
+	Cudd_RecursiveDeref(dd, shortP);
+	constN = Cudd_addEvalConst(dd,shortA,M);
+	if (constN == DD_NON_CONSTANT) exit(2);
+	if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2);
+	if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));}
+	Cudd_RecursiveDeref(dd, shortA);
+
+	shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length);
+	if (shortP == NULL) exit(2);
+	Cudd_Ref(shortP);
+	if (pr>0) {
+	    (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
+	}
+
+	/* Test Cudd_bddIteConstant and Cudd_bddLeq. */
+	if (!Cudd_bddLeq(dd,shortP,C)) exit(2);
+	if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2);
+	Cudd_RecursiveDeref(dd, shortP);
+
+	if (profile) {
+	    retval = cuddHeapProfile(dd);
+	}
+
+	size = dd->size;
+
+	if (pr>0) {
+	    (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
+	}
+
+	/* Reorder if so requested. */
+        if (approach != CUDD_REORDER_NONE) {
+#ifndef DD_STATS
+	    retval = Cudd_EnableReorderingReporting(dd);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n");
+		exit(3);
+	    }
+#endif
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		exit(3);
+	    }
+	    retval = Cudd_CheckKeys(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
+		exit(3);
+	    }
+#endif
+	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
+		exit(3);
+	    }
+#ifndef DD_STATS
+	    retval = Cudd_DisableReorderingReporting(dd);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n");
+		exit(3);
+	    }
+#endif
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		exit(3);
+	    }
+	    retval = Cudd_CheckKeys(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
+		exit(3);
+	    }
+#endif
+	    if (approach == CUDD_REORDER_SYMM_SIFT ||
+	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
+		Cudd_SymmProfile(dd,0,dd->size-1);
+	    }
+
+	    if (pr>0) {
+		(void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
+	    }
+
+	    if (keepperm) {
+		/* Print variable permutation. */
+		(void) printf("Variable Permutation:");
+		for (i=0; i<size; i++) {
+		    if (i%20 == 0) (void) printf("\n");
+		    (void) printf("%d ", dd->invperm[i]);
+		}
+		(void) printf("\n");
+		(void) printf("Inverse Permutation:");
+		for (i=0; i<size; i++) {
+		    if (i%20 == 0) (void) printf("\n");
+		    (void) printf("%d ", dd->perm[i]);
+		}
+		(void) printf("\n");
+	    }
+
+	    if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}
+
+	    if (profile) {
+		retval = cuddHeapProfile(dd);
+	    }
+
+	}
+
+	/* Dump DDs of C and M if so requested. */
+	if (dfile != NULL) {
+	    dfunc[0] = C;
+	    dfunc[1] = M;
+	    if (blifOrDot == 1) {
+		/* Only dump C because blif cannot handle ADDs */
+		retval = Cudd_DumpBlif(dd,1,dfunc,NULL,(char **)onames,
+				       NULL,dfp);
+	    } else {
+		retval = Cudd_DumpDot(dd,2,dfunc,NULL,(char **)onames,dfp);
+	    }
+	    if (retval != 1) {
+		(void) fprintf(stderr,"abnormal termination\n");
+		exit(2);
+	    }
+	}
+
+	Cudd_RecursiveDeref(dd, C);
+	Cudd_RecursiveDeref(dd, M);
+
+	if (clearcache) {
+	    if (pr>0) {(void) printf("Clearing the cache... ");}
+	    for (i = dd->cacheSlots - 1; i>=0; i--) {
+		dd->cache[i].data = NIL(DdNode);
+	    }
+	    if (pr>0) {(void) printf("done\n");}
+	}
+	if (pr>0) {
+	    (void) printf("Number of variables = %6d\t",dd->size);
+	    (void) printf("Number of slots     = %6d\n",dd->slots);
+	    (void) printf("Number of keys      = %6d\t",dd->keys);
+	    (void) printf("Number of min dead  = %6d\n",dd->minDead);
+	}
+
+    } while (multiple && !feof(fp));
+
+    fclose(fp);
+    if (dfile != NULL) {
+	fclose(dfp);
+    }
+
+    /* Second phase: experiment with Walsh matrices. */
+    if (!testWalsh(dd,N,cmu,approach,pr)) {
+	exit(2);
+    }
+
+    /* Check variable destruction. */
+    assert(cuddDestroySubtables(dd,3));
+    assert(Cudd_DebugCheck(dd) == 0);
+    assert(Cudd_CheckKeys(dd) == 0);
+
+    retval = Cudd_CheckZeroRef(dd);
+    ok = retval != 0;  /* ok == 0 means O.K. */
+    if (retval != 0) {
+	(void) fprintf(stderr,
+	    "%d non-zero DD reference counts after dereferencing\n", retval);
+    }
+
+    if (pr >= 0) {
+	(void) Cudd_PrintInfo(dd,stdout);
+    }
+
+    Cudd_Quit(dd);
+
+#ifdef MNEMOSYNE
+    mnem_writestats();
+#endif
+
+    if (pr>0) (void) printf("total time = %s\n",
+		util_print_time(util_cpu_time() - startTime));
+
+    if (pr >= 0) util_print_cpu_stats(stdout);
+    exit(ok);
+    /* NOTREACHED */
+
+} /* end of main */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints usage info for testcudd.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+usage(char *prog)
+{
+    (void) fprintf(stderr, "usage: %s [options] [file]\n", prog);
+    (void) fprintf(stderr, "   -C\t\tuse CMU multiplication algorithm\n");
+    (void) fprintf(stderr, "   -D\t\tenable automatic dynamic reordering\n");
+    (void) fprintf(stderr, "   -H\t\tread matrix in Harwell format\n");
+    (void) fprintf(stderr, "   -M\t\tturns off memory allocation recording\n");
+    (void) fprintf(stderr, "   -P\t\tprint BDD heap profile\n");
+    (void) fprintf(stderr, "   -S n\t\tnumber of slots for each subtable\n");
+    (void) fprintf(stderr, "   -X n\t\ttarget maximum memory in bytes\n");
+    (void) fprintf(stderr, "   -a n\t\tchoose reordering approach (0-13)\n");
+    (void) fprintf(stderr, "   \t\t\t0: same as autoMethod\n");
+    (void) fprintf(stderr, "   \t\t\t1: no reordering (default)\n");
+    (void) fprintf(stderr, "   \t\t\t2: random\n");
+    (void) fprintf(stderr, "   \t\t\t3: pivot\n");
+    (void) fprintf(stderr, "   \t\t\t4: sifting\n");
+    (void) fprintf(stderr, "   \t\t\t5: sifting to convergence\n");
+    (void) fprintf(stderr, "   \t\t\t6: symmetric sifting\n");
+    (void) fprintf(stderr, "   \t\t\t7: symmetric sifting to convergence\n");
+    (void) fprintf(stderr, "   \t\t\t8-10: window of size 2-4\n");
+    (void) fprintf(stderr, "   \t\t\t11-13: window of size 2-4 to conv.\n");
+    (void) fprintf(stderr, "   \t\t\t14: group sifting\n");
+    (void) fprintf(stderr, "   \t\t\t15: group sifting to convergence\n");
+    (void) fprintf(stderr, "   \t\t\t16: simulated annealing\n");
+    (void) fprintf(stderr, "   \t\t\t17: genetic algorithm\n");
+    (void) fprintf(stderr, "   -b\t\tuse blif as format for dumps\n");
+    (void) fprintf(stderr, "   -c\t\tclear the cache after each matrix\n");
+    (void) fprintf(stderr, "   -d file\tdump DDs to file\n");
+    (void) fprintf(stderr, "   -g\t\tselect aggregation criterion (0,5,7)\n");
+    (void) fprintf(stderr, "   -h\t\tprints this message\n");
+    (void) fprintf(stderr, "   -k\t\tprint the variable permutation\n");
+    (void) fprintf(stderr, "   -m\t\tread multiple matrices (only with -H)\n");
+    (void) fprintf(stderr, "   -n n\t\tnumber of variables\n");
+    (void) fprintf(stderr, "   -p n\t\tcontrol verbosity\n");
+    (void) fprintf(stderr, "   -v n\t\tinitial variables in the unique table\n");
+    (void) fprintf(stderr, "   -x n\t\tinitial size of the cache\n");
+    exit(2);
+} /* end of usage */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Opens a file.]
+
+  Description [Opens a file, or fails with an error message and exits.
+  Allows '-' as a synonym for standard input.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static FILE *
+open_file(char *filename, const char *mode)
+{
+    FILE *fp;
+
+    if (strcmp(filename, "-") == 0) {
+        return mode[0] == 'r' ? stdin : stdout;
+    } else if ((fp = fopen(filename, mode)) == NULL) {
+        perror(filename);
+        exit(1);
+    }
+    return fp;
+
+} /* end of open_file */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests Walsh matrix multiplication.]
+
+  Description [Tests Walsh matrix multiplication.  Return 1 if successful;
+  0 otherwise.]
+
+  SideEffects [May create new variables in the manager.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testWalsh(
+  DdManager *dd /* manager */,
+  int N /* number of variables */,
+  int cmu /* use CMU approach to matrix multiplication */,
+  int approach /* reordering approach */,
+  int pr /* verbosity level */)
+{
+    DdNode *walsh1, *walsh2, *wtw;
+    DdNode **x, **v, **z;
+    int i, retval;
+    DdNode *one = DD_ONE(dd);
+    DdNode *zero = DD_ZERO(dd);
+
+    if (N > 3) {
+	x = ALLOC(DdNode *,N);
+	v = ALLOC(DdNode *,N);
+	z = ALLOC(DdNode *,N);
+
+	for (i = N-1; i >= 0; i--) {
+	    Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero));
+	    Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero));
+	    Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero));
+	}
+	Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N));
+	if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);}
+	Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N));
+	if (cmu) {
+	    Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N));
+	} else {
+	    Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N));
+	}
+	if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);}
+
+	if (approach != CUDD_REORDER_NONE) {
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		return(0);
+	    }
+#endif
+	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
+	    if (retval == 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
+		return(0);
+	    }
+#ifdef DD_DEBUG
+	    retval = Cudd_DebugCheck(dd);
+	    if (retval != 0) {
+		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
+		return(0);
+	    }
+#endif
+	    if (approach == CUDD_REORDER_SYMM_SIFT ||
+	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
+		Cudd_SymmProfile(dd,0,dd->size-1);
+	    }
+	}
+	/* Clean up. */
+	Cudd_RecursiveDeref(dd, wtw);
+	Cudd_RecursiveDeref(dd, walsh1);
+	Cudd_RecursiveDeref(dd, walsh2);
+	for (i=0; i < N; i++) {
+	    Cudd_RecursiveDeref(dd, x[i]);
+	    Cudd_RecursiveDeref(dd, v[i]);
+	    Cudd_RecursiveDeref(dd, z[i]);
+	}
+	FREE(x);
+	FREE(v);
+	FREE(z);
+    }
+    return(1);
+
+} /* end of testWalsh */
+
+/**Function********************************************************************
+
+  Synopsis    [Tests iterators.]
+
+  Description [Tests iterators on cubes and nodes.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testIterators(
+  DdManager *dd,
+  DdNode *M,
+  DdNode *C,
+  int pr)
+{
+    int *cube;
+    CUDD_VALUE_TYPE value;
+    DdGen *gen;
+    int q;
+
+    /* Test iterator for cubes. */
+    if (pr>1) {
+	(void) printf("Testing iterator on cubes:\n");
+	Cudd_ForeachCube(dd,M,gen,cube,value) {
+	    for (q = 0; q < dd->size; q++) {
+		switch (cube[q]) {
+		case 0:
+		    (void) printf("0");
+		    break;
+		case 1:
+		    (void) printf("1");
+		    break;
+		case 2:
+		    (void) printf("-");
+		    break;
+		default:
+		    (void) printf("?");
+		}
+	    }
+	    (void) printf(" %g\n",value);
+	}
+	(void) printf("\n");
+    }
+
+    if (pr>1) {
+	(void) printf("Testing prime expansion of cubes:\n");
+	if (!Cudd_bddPrintCover(dd,C,C)) return(0);
+    }
+
+    if (pr>1) {
+	(void) printf("Testing iterator on primes (CNF):\n");
+	Cudd_ForeachPrime(dd,Cudd_Not(C),Cudd_Not(C),gen,cube) {
+	    for (q = 0; q < dd->size; q++) {
+		switch (cube[q]) {
+		case 0:
+		    (void) printf("1");
+		    break;
+		case 1:
+		    (void) printf("0");
+		    break;
+		case 2:
+		    (void) printf("-");
+		    break;
+		default:
+		    (void) printf("?");
+		}
+	    }
+	    (void) printf(" 1\n");
+	}
+	(void) printf("\n");
+    }
+
+    /* Test iterator on nodes. */
+    if (pr>2) {
+	DdGen *gen;
+	DdNode *node;
+	(void) printf("Testing iterator on nodes:\n");
+	Cudd_ForeachNode(dd,M,gen,node) {
+	    if (Cudd_IsConstant(node)) {
+#if SIZEOF_VOID_P == 8
+		(void) printf("ID = 0x%lx\tvalue = %-9g\n",
+			      (unsigned long) node /
+			      (unsigned long) sizeof(DdNode),
+			      Cudd_V(node));
+#else
+		(void) printf("ID = 0x%x\tvalue = %-9g\n",
+			      (unsigned int) node /
+			      (unsigned int) sizeof(DdNode),
+			      Cudd_V(node));
+#endif
+	    } else {
+#if SIZEOF_VOID_P == 8
+		(void) printf("ID = 0x%lx\tindex = %d\tr = %d\n",
+			      (unsigned long) node /
+			      (unsigned long) sizeof(DdNode),
+			      node->index, node->ref);
+#else
+		(void) printf("ID = 0x%x\tindex = %d\tr = %d\n",
+			      (unsigned int) node /
+			      (unsigned int) sizeof(DdNode),
+			      node->index, node->ref);
+#endif
+	    }
+	}
+	(void) printf("\n");
+    }
+    return(1);
+
+} /* end of testIterators */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests the functions related to the exclusive OR.]
+
+  Description [Tests the functions related to the exclusive OR. It
+  builds the boolean difference of the given function in three
+  different ways and checks that the results is the same. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testXor(DdManager *dd, DdNode *f, int pr, int nvars)
+{
+    DdNode *f1, *f0, *res1, *res2;
+    int x;
+
+    /* Extract cofactors w.r.t. mid variable. */
+    x = nvars / 2;
+    f1 = Cudd_Cofactor(dd,f,dd->vars[x]);
+    if (f1 == NULL) return(0);
+    Cudd_Ref(f1);
+
+    f0 = Cudd_Cofactor(dd,f,Cudd_Not(dd->vars[x]));
+    if (f0 == NULL) {
+	Cudd_RecursiveDeref(dd,f1);
+	return(0);
+    }
+    Cudd_Ref(f0);
+
+    /* Compute XOR of cofactors with ITE. */
+    res1 = Cudd_bddIte(dd,f1,Cudd_Not(f0),f0);
+    if (res1 == NULL) return(0);
+    Cudd_Ref(res1);
+
+    if (pr>0) {(void) printf("xor1"); Cudd_PrintDebug(dd,res1,nvars,pr);}
+
+    /* Compute XOR of cofactors with XOR. */
+    res2 = Cudd_bddXor(dd,f1,f0);
+    if (res2 == NULL) {
+	Cudd_RecursiveDeref(dd,res1);
+	return(0);
+    }
+    Cudd_Ref(res2);
+
+    if (res1 != res2) {
+	if (pr>0) {(void) printf("xor2"); Cudd_PrintDebug(dd,res2,nvars,pr);}
+	Cudd_RecursiveDeref(dd,res1);
+	Cudd_RecursiveDeref(dd,res2);
+	return(0);
+    }
+    Cudd_RecursiveDeref(dd,res1);
+    Cudd_RecursiveDeref(dd,f1);
+    Cudd_RecursiveDeref(dd,f0);
+
+    /* Compute boolean difference directly. */
+    res1 = Cudd_bddBooleanDiff(dd,f,x);
+    if (res1 == NULL) {
+	Cudd_RecursiveDeref(dd,res2);
+	return(0);
+    }
+    Cudd_Ref(res1);
+
+    if (res1 != res2) {
+	if (pr>0) {(void) printf("xor3"); Cudd_PrintDebug(dd,res1,nvars,pr);}
+	Cudd_RecursiveDeref(dd,res1);
+	Cudd_RecursiveDeref(dd,res2);
+	return(0);
+    }
+    Cudd_RecursiveDeref(dd,res1);
+    Cudd_RecursiveDeref(dd,res2);
+    return(1);
+
+} /* end of testXor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests the Hamming distance functions.]
+
+  Description [Tests the Hammming distance functions. Returns
+  1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+testHamming(
+  DdManager *dd,
+  DdNode *f,
+  int pr)
+{
+    DdNode **vars, *minBdd, *zero, *scan;
+    int i;
+    int d;
+    int *minterm;
+    int size = Cudd_ReadSize(dd);
+
+    vars = ALLOC(DdNode *, size);
+    if (vars == NULL) return(0);
+    for (i = 0; i < size; i++) {
+	vars[i] = Cudd_bddIthVar(dd,i);
+    }
+
+    minBdd = Cudd_bddPickOneMinterm(dd,Cudd_Not(f),vars,size);
+    Cudd_Ref(minBdd);
+    if (pr > 0) {
+	(void) printf("Chosen minterm for Hamming distance test: ");
+	Cudd_PrintDebug(dd,minBdd,size,pr);
+    }
+
+    minterm = ALLOC(int,size);
+    if (minterm == NULL) {
+	FREE(vars);
+	Cudd_RecursiveDeref(dd,minBdd);
+	return(0);
+    }
+    scan = minBdd;
+    zero = Cudd_Not(DD_ONE(dd));
+    while (!Cudd_IsConstant(scan)) {
+	DdNode *R = Cudd_Regular(scan);
+	DdNode *T = Cudd_T(R);
+	DdNode *E = Cudd_E(R);
+	if (R != scan) {
+	    T = Cudd_Not(T);
+	    E = Cudd_Not(E);
+	}
+	if (T == zero) {
+	    minterm[R->index] = 0;
+	    scan = E;
+	} else {
+	    minterm[R->index] = 1;
+	    scan = T;
+	}
+    }
+    Cudd_RecursiveDeref(dd,minBdd);
+
+    d = Cudd_MinHammingDist(dd,f,minterm,size);
+
+    (void) printf("Minimum Hamming distance = %d\n", d);
+
+    FREE(vars);
+    FREE(minterm);
+    return(1);
+
+} /* end of testHamming */
Index: /vis_dev/glu-2.1/src/cuPort/cuPort.c
===================================================================
--- /vis_dev/glu-2.1/src/cuPort/cuPort.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuPort/cuPort.c	(revision 8)
@@ -0,0 +1,7332 @@
+/**CFile***********************************************************************
+
+  FileName    [cuPort.c]
+
+  PackageName [cudd]
+
+  Synopsis [SIS/VIS interface to the Decision Diagram Package of the University
+  of Colorado.]
+
+  Description [This file implements an interface between the functions in the
+    Berkeley BDD package and the functions provided by the CUDD (decision
+    diagram) package from the University of Colorado. The CUDD package is a
+    generic implementation of a decision diagram data structure. For the time
+    being, only Boole expansion is implemented and the leaves in the in the
+    nodes can be the constants zero, one or any arbitrary value.]
+
+  Author      [Abelardo Pardo, Kavita Ravi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "cuPortInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] DD_UNUSED = "$Id: cuPort.c,v 1.127 2004/08/13 18:39:30 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void InvalidType( FILE *file, char *field, char *expected);
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the bdd_t structure.]
+
+  Description [Builds the bdd_t structure from manager and node.
+  Assumes that the reference count of the node has already been
+  increased. If it fails to create a new bdd_t structure it disposes of
+  the node to simplify error handling for the caller. Returns a
+  pointer to the newly created structure if successful; NULL
+  otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_construct_bdd_t(bdd_manager *mgr, bdd_node *fn)
+{
+  bdd_t *result;
+
+  result = ALLOC(bdd_t, 1);
+  if (result == NULL) {
+    printf("problem d'allocation \n");	  
+    Cudd_RecursiveDeref((DdManager *)mgr,(DdNode *)fn);
+    return(NULL);
+  }
+  result->mgr = (DdManager *) mgr;
+  result->node = (DdNode *) fn;
+  result->free = FALSE;
+  return(result);
+
+} /* end of bdd_construct_bdd_t */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Function to identify the bdd package being used]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_package_type_t
+bdd_get_package_name(void)
+{
+  return(CUDD);
+
+} /* end of bdd_get_package_name */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Terminates the bdd package.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_end(bdd_manager *mgr)
+{
+  DdManager *manager;
+
+  manager = (DdManager *)mgr;
+  if (manager->hooks != NULL) FREE(manager->hooks);
+  Cudd_Quit(manager);
+
+} /* end of bdd_end */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Starts the manager with nvariables variables.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_manager *
+bdd_start(int nvariables)
+{
+  DdManager *mgr;
+  bdd_external_hooks *hooks;
+
+  mgr =  Cudd_Init((unsigned int)nvariables, 0, CUDD_UNIQUE_SLOTS,
+		   CUDD_CACHE_SLOTS, getSoftDataLimit() / 10 * 9);
+
+  hooks = ALLOC(bdd_external_hooks,1);
+  hooks->mdd = hooks->network = hooks->undef1 = (char *) 0;
+  mgr->hooks = (char *) hooks;
+
+  return(bdd_manager *)mgr;
+
+} /* end of bdd_start */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new variable in the manager.]
+
+  SideEffects [Modifies the manager]
+
+  SeeAlso     [bdd_create_variable_after]
+
+******************************************************************************/
+bdd_t *
+bdd_create_variable(bdd_manager *mgr)
+{
+  DdNode *var;
+  DdManager *dd = (DdManager *) mgr;
+  DdNode *one = DD_ONE(dd);
+
+  if (dd->size >= CUDD_MAXINDEX -1) return(NULL);
+  do {
+    dd->reordered = 0;
+    var = cuddUniqueInter(dd,dd->size,one,Cudd_Not(one));
+  } while (dd->reordered == 1);
+
+  if (var == NULL) return((bdd_t *)NULL);
+  cuddRef(var);
+  return(bdd_construct_bdd_t(dd,var));
+
+} /* end of bdd_create_variable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new variable and positions it after the
+  variable with the specified index.]
+
+  SideEffects [Modifies the manager.]
+
+  SeeAlso     [bdd_create_variable]
+
+******************************************************************************/
+bdd_t *
+bdd_create_variable_after(bdd_manager *mgr, bdd_variableId after_id)
+{
+  DdNode *var;
+  DdManager *dd = (DdManager *) mgr;
+  int level;
+
+  if (after_id >= (bdd_variableId) dd->size) return(NULL);
+  level = 1 + dd->perm[after_id];
+  var = Cudd_bddNewVarAtLevel(dd,level);
+  if (var == NULL) return((bdd_t *)NULL);
+  cuddRef(var);
+  return(bdd_construct_bdd_t(dd,var));
+
+} /* end of bdd_create_variable_after */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD representing the variable with given ID.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_get_variable(bdd_manager *mgr, bdd_variableId variable_ID)
+{
+  DdNode *var;
+  DdManager *dd = (DdManager *) mgr;
+  DdNode *one = DD_ONE(dd);
+
+  if (variable_ID >= CUDD_MAXINDEX -1) return(NULL);
+  do {
+    dd->reordered = 0;
+    var = cuddUniqueInter(dd,(int)variable_ID,one,Cudd_Not(one));
+  } while (dd->reordered == 1);
+
+  if (var == NULL) return((bdd_t *)NULL);
+  cuddRef(var);
+  return(bdd_construct_bdd_t(dd,var));
+
+} /* end of bdd_get_variable */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a copy of the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_dup(bdd_t *f)
+{
+  cuddRef(f->node);
+  return(bdd_construct_bdd_t(f->mgr,f->node));
+
+} /* end of bdd_dup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes the BDD of f.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_free(bdd_t *f)
+{
+  if (f == NULL) {
+    fail("bdd_free: trying to free a NULL bdd_t");
+  }
+
+  if (f->free == TRUE) {
+    fail("bdd_free: trying to free a freed bdd_t");
+  }
+
+  Cudd_RecursiveDeref(f->mgr,f->node);
+  /* This is a bit overconservative. */
+  f->node = NULL;
+  f->mgr = NULL;
+  f->free = TRUE;
+  FREE(f);
+  return;
+
+} /* end of bdd_free */
+
+
+/**Function********************************************************************
+
+  Synopsis    [And of two BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_and(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase)
+{
+  DdManager *dd;
+  DdNode *newf, *newg, *fandg;
+
+  /* Make sure both BDDs belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  /* Modify the phases of the operands according to the parameters. */
+  newf = Cudd_NotCond(f->node,!f_phase);
+  newg = Cudd_NotCond(g->node,!g_phase);
+
+  /* Perform the AND operation. */
+  dd = f->mgr;
+  fandg = Cudd_bddAnd(f->mgr,newf,newg);
+  if (fandg == NULL) return(NULL);
+  cuddRef(fandg);
+
+  return(bdd_construct_bdd_t(dd,fandg));
+
+} /* end of bdd_and */
+
+
+/**Function********************************************************************
+
+  Synopsis    [And of two BDDs with limit on new nodes.]
+
+  Description [If more new nodes than specified by limit must be created,
+  this function returns NULL.  The caller must be prepared for this
+  occurrence.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_and_with_limit(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase,
+  unsigned int limit)
+{
+  DdManager *dd;
+  DdNode *newf, *newg, *fandg;
+
+  /* Make sure both BDDs belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  /* Modify the phases of the operands according to the parameters. */
+  newf = Cudd_NotCond(f->node,!f_phase);
+  newg = Cudd_NotCond(g->node,!g_phase);
+
+  /* Perform the AND operation. */
+  dd = f->mgr;
+  fandg = Cudd_bddAndLimit(f->mgr,newf,newg,limit);
+  if (fandg == NULL) return(NULL);
+  cuddRef(fandg);
+
+  return(bdd_construct_bdd_t(dd,fandg));
+
+} /* end of bdd_and_with_limit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [And of a BDD and an array of BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_and_array(
+  bdd_t *f,
+  array_t *g_array,
+  boolean f_phase,
+  boolean g_phase)
+{
+  bdd_t *g;
+  DdNode *result, *temp;
+  int i;
+  DdNode *newf, *newg;
+
+  /* Modify the phases of the operands according to the parameters. */
+  newf = Cudd_NotCond(f->node,!f_phase);
+
+  Cudd_Ref(result = newf);
+
+  for (i = 0; i < array_n(g_array); i++) {
+    g = array_fetch(bdd_t *, g_array, i);
+
+    /* Modify the phases of the operands according to the parameters. */
+    newg = Cudd_NotCond(g->node,!g_phase);
+
+    temp = Cudd_bddAnd(f->mgr, result, newg);
+    if (temp == NULL) {
+      Cudd_RecursiveDeref(f->mgr, result);
+      return(NULL);
+    }
+    cuddRef(temp);
+    Cudd_RecursiveDeref(f->mgr, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_and_array */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Takes the and of an array of functions.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+bdd_t *
+bdd_multiway_and(bdd_manager *manager, array_t *bddArray)
+{
+  DdManager *mgr;
+  bdd_t *operand;
+  DdNode *result, *temp;
+  int i;
+
+  mgr = (DdManager *)manager;
+
+  Cudd_Ref(result = DD_ONE(mgr));
+
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = Cudd_bddAnd(mgr, result, operand->node);
+    if (temp == NULL) {
+      Cudd_RecursiveDeref(mgr, result);
+      return(NULL);
+    }
+    cuddRef(temp);
+    Cudd_RecursiveDeref(mgr, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_multiway_and */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Takes the or of an array of functions.]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_t *
+bdd_multiway_or(bdd_manager *manager, array_t *bddArray)
+{
+  DdManager *mgr;
+  bdd_t *operand;
+  DdNode *result, *temp;
+  int i;
+  
+  mgr = (DdManager *)manager;
+  Cudd_Ref(result = Cudd_Not(DD_ONE(mgr)));
+
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = Cudd_bddOr(mgr, result, operand->node);
+    if (temp == NULL) {
+      Cudd_RecursiveDeref(mgr, result);
+      return(NULL);
+    }
+    cuddRef(temp);
+    Cudd_RecursiveDeref(mgr, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_multiway_or */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Takes the xor of an array of functions.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+bdd_t *
+bdd_multiway_xor(bdd_manager *manager, array_t *bddArray)
+{
+  DdManager *mgr;
+  bdd_t *operand;
+  DdNode *result, *temp;
+  int i;
+
+  mgr = (DdManager *)manager;
+
+  Cudd_Ref(result = Cudd_Not(DD_ONE(mgr)));
+
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = Cudd_bddXor(mgr, result, operand->node);
+    if (temp == NULL) {
+      Cudd_RecursiveDeref(mgr, result);
+      return(NULL);
+    }
+    cuddRef(temp);
+    Cudd_RecursiveDeref(mgr, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_multiway_xor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Takes the pairwise or of two arrays of bdds of the same length.]
+
+  SideEffects [None]
+
+******************************************************************************/
+array_t *
+bdd_pairwise_or(bdd_manager *manager, array_t *bddArray1, array_t *bddArray2)
+{
+  DdManager *mgr;
+  bdd_t *op1, *op2;
+  bdd_t *unit;
+  DdNode *result;
+  array_t *resultArray;
+  int i;
+
+  mgr = (DdManager *)manager;
+
+  if (array_n(bddArray1) != array_n(bddArray2)) {
+    (void) fprintf(stderr,
+		   "bdd_pairwise_or: Arrays of different lengths.\n");
+    return(NULL);
+  }
+
+  resultArray = array_alloc(bdd_t *, array_n(bddArray1));
+  for (i = 0; i < array_n(bddArray1); i++) {
+    op1 = array_fetch(bdd_t *, bddArray1, i);
+    op2 = array_fetch(bdd_t *, bddArray2, i);
+
+    result = Cudd_bddOr(mgr, op1->node, op2->node);
+    if (result == NULL) {
+      int j;
+      bdd_t *item;
+      for (j = 0; j < array_n(resultArray); j++) {
+	item = array_fetch(bdd_t *, resultArray, j);
+	bdd_free(item);
+      }
+      array_free(resultArray);
+      return((array_t *)NULL);
+    }
+    cuddRef(result);
+    
+    unit = bdd_construct_bdd_t(mgr, result);
+    array_insert(bdd_t *, resultArray, i, unit);
+  }
+
+  return(resultArray);
+
+} /* end of bdd_pairwise_or */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the pairwise and of two arrays of bdds of the same length.]
+
+  SideEffects [required]
+
+******************************************************************************/
+array_t *
+bdd_pairwise_and(bdd_manager *manager, array_t *bddArray1, array_t *bddArray2)
+{
+  DdManager *mgr;
+  bdd_t *op1, *op2;
+  bdd_t *unit;
+  DdNode *result;
+  array_t *resultArray;
+  int i;
+
+  mgr = (DdManager *)manager;
+
+  if (array_n(bddArray1) != array_n(bddArray2)) {
+    (void) fprintf(stderr,
+		   "bdd_pairwise_or: Arrays of different lengths.\n");
+    return(NULL);
+  }
+        
+  resultArray = array_alloc(bdd_t *, array_n(bddArray1));
+  for (i = 0; i < array_n(bddArray1); i++) {
+    op1 = array_fetch(bdd_t *, bddArray1, i);
+    op2 = array_fetch(bdd_t *, bddArray2, i);
+
+    result = Cudd_bddAnd(mgr, op1->node, op2->node);
+    if (result == NULL) {
+      int j;
+      bdd_t *item;
+      for (j = 0; j < array_n(resultArray); j++) {
+	item = array_fetch(bdd_t *, resultArray, j);
+	bdd_free(item);
+      }
+      array_free(resultArray);
+      return((array_t *)NULL);
+    }
+    cuddRef(result);
+
+    unit = bdd_construct_bdd_t(mgr, result);
+    array_insert(bdd_t *, resultArray, i, unit);
+  }
+
+  return(resultArray);
+
+} /* end of bdd_pairwise_and */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the pairwise xor of two arrays of bdds of the same length.]
+
+  SideEffects [required]
+
+******************************************************************************/
+array_t *
+bdd_pairwise_xor(bdd_manager *manager, array_t *bddArray1, array_t *bddArray2)
+{
+  DdManager *mgr;
+  bdd_t *op1, *op2;
+  bdd_t *unit;
+  DdNode *result;
+  array_t *resultArray;
+  int i;
+
+  mgr = (DdManager *)manager;
+
+  if (array_n(bddArray1) != array_n(bddArray2)) {
+    (void) fprintf(stderr,
+		   "bdd_pairwise_or: Arrays of different lengths.\n");
+    return(NULL);
+  }
+   
+  resultArray = array_alloc(bdd_t *, array_n(bddArray1));
+  for (i = 0; i < array_n(bddArray1); i++) {
+    op1 = array_fetch(bdd_t *, bddArray1, i);
+    op2 = array_fetch(bdd_t *, bddArray2, i);
+
+    result = Cudd_bddXor(mgr, op1->node, op2->node);
+    if (result == NULL) {
+      int j;
+      bdd_t *item;
+      for (j = 0; j < array_n(resultArray); j++) {
+	item = array_fetch(bdd_t *, resultArray, j);
+	bdd_free(item);
+      }
+      array_free(resultArray);
+      return((array_t *)NULL);
+    }
+    cuddRef(result);
+
+    unit = bdd_construct_bdd_t(mgr, result);
+    array_insert(bdd_t *, resultArray, i, unit);
+  }
+
+  return(resultArray);
+
+} /* end of bdd_pairwise_xor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts variables from the product of two BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_and_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars	/* of bdd_t *'s */)
+{
+  int i;
+  bdd_t *variable;
+  DdNode *cube, *tmpDd, *result;
+  DdManager *mgr;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  /* CUDD needs the smothing variables passed as a cube.
+   * Therefore we must build that cube from the indices of variables
+   * in the array before calling the procedure.
+   */
+  mgr = f->mgr;
+  Cudd_Ref(cube = DD_ONE(mgr));
+  for (i = 0; i < array_n(smoothing_vars); i++) {
+    variable = array_fetch(bdd_t *,smoothing_vars,i);
+
+    /* Make sure the variable belongs to the same manager. */
+    assert(mgr == variable->mgr);
+
+    tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
+    if (tmpDd == NULL) {
+      Cudd_RecursiveDeref(mgr,cube);
+      return(NULL);
+    }
+    cuddRef(tmpDd);
+    Cudd_RecursiveDeref(mgr, cube);
+    cube = tmpDd;
+  }
+
+  /* Perform the smoothing */
+  result = Cudd_bddAndAbstract(mgr,f->node,g->node,cube);
+  if (result == NULL) {
+    Cudd_RecursiveDeref(mgr, cube);
+    return(NULL);
+  }
+  cuddRef(result);
+  /* Get rid of temporary results. */
+  Cudd_RecursiveDeref(mgr, cube);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_and_smooth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts variables from the product of two BDDs with limit
+  on new nodes.]
+
+  Description [If more new nodes than specified by limit must be created,
+  this function returns NULL.  The caller must be prepared for this
+  occurrence.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_and_smooth_with_limit(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars /* of bdd_t *'s */,
+  unsigned int limit)
+{
+  int i;
+  bdd_t *variable;
+  DdNode *cube, *tmpDd, *result;
+  DdManager *mgr;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  /* CUDD needs the smothing variables passed as a cube.
+   * Therefore we must build that cube from the indices of variables
+   * in the array before calling the procedure.
+   */
+  mgr = f->mgr;
+  Cudd_Ref(cube = DD_ONE(mgr));
+  for (i = 0; i < array_n(smoothing_vars); i++) {
+    variable = array_fetch(bdd_t *,smoothing_vars,i);
+
+    /* Make sure the variable belongs to the same manager. */
+    assert(mgr == variable->mgr);
+
+    tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
+    if (tmpDd == NULL) {
+      Cudd_RecursiveDeref(mgr,cube);
+      return(NULL);
+    }
+    cuddRef(tmpDd);
+    Cudd_RecursiveDeref(mgr, cube);
+    cube = tmpDd;
+  }
+
+  /* Perform the smoothing */
+  result = Cudd_bddAndAbstractLimit(mgr,f->node,g->node,cube,limit);
+  if (result == NULL) {
+    Cudd_RecursiveDeref(mgr, cube);
+    return(NULL);
+  }
+  cuddRef(result);
+  /* Get rid of temporary results. */
+  Cudd_RecursiveDeref(mgr, cube);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_and_smooth_with_limit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts variables from the product of two BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_and_smooth_with_cube(bdd_t *f, bdd_t *g, bdd_t *cube)
+{
+  DdNode *result;
+  DdManager *mgr;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  /* The Boulder package needs the smothing variables passed as a cube.
+   * Therefore we must build that cube from the indices of variables
+   * in the array before calling the procedure.
+   */
+  mgr = f->mgr;
+
+  /* Perform the smoothing */
+  result = Cudd_bddAndAbstract(mgr,f->node,g->node,cube->node);
+  if (result == NULL)
+    return(NULL);
+  cuddRef(result);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_and_smooth_with_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Abstracts variables from the product of two
+  BDDs. Computation is clipped at a certain depth.]
+
+  Description [Abstracts variables from the product of two
+  BDDs. Computation is clipped at a certain depth. This procedure is
+  similar to bdd_and_smooth but large depth recursions are
+  avoided. maxDepth specifies the recursion depth. over specifies
+  which kind of approximation is used 0 - under approximation and 1 -
+  for over approximation. ]
+  
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_clipping_and_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars /* of bdd_t *'s */,
+  int maxDepth,
+  int over)
+{
+  int i;
+  bdd_t *variable;
+  DdNode *cube,*tmpDd,*result;
+  DdManager *mgr;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  /* The Boulder package needs the smothing variables passed as a cube.
+   * Therefore we must build that cube from the indices of variables
+   * in the array before calling the procedure.
+   */
+  mgr = f->mgr;
+  Cudd_Ref(cube = DD_ONE(mgr));
+  for (i = 0; i < array_n(smoothing_vars); i++) {
+    variable = array_fetch(bdd_t *,smoothing_vars,i);
+
+    /* Make sure the variable belongs to the same manager. */
+    assert(mgr == variable->mgr);
+
+    tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
+    if (tmpDd == NULL) {
+      Cudd_RecursiveDeref(mgr,cube);
+      return(NULL);
+    }
+    cuddRef(tmpDd);
+    Cudd_RecursiveDeref(mgr, cube);
+    cube = tmpDd;
+  }
+
+  /* Perform the smoothing */
+  result = Cudd_bddClippingAndAbstract(mgr,f->node,g->node,cube, maxDepth, over);
+  if (result == NULL) {
+    Cudd_RecursiveDeref(mgr, cube);
+    return(NULL);
+  }
+  cuddRef(result);
+  /* Get rid of temporary results. */
+  Cudd_RecursiveDeref(mgr, cube);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_clipping_and_smooth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts variables from the exclusive OR of two BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_xor_smooth(
+  bdd_t *f,
+  bdd_t *g,
+  array_t *smoothing_vars /* of bdd_t *'s */)
+{
+  int i;
+  bdd_t *variable;
+  DdNode *cube,*tmpDd,*result;
+  DdManager *mgr;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  /* The Boulder package needs the smothing variables passed as a cube.
+   * Therefore we must build that cube from the indices of variables
+   * in the array before calling the procedure.
+   */
+  mgr = f->mgr;
+  Cudd_Ref(cube = DD_ONE(mgr));
+  for (i = 0; i < array_n(smoothing_vars); i++) {
+    variable = array_fetch(bdd_t *,smoothing_vars,i);
+
+    /* Make sure the variable belongs to the same manager. */
+    assert(mgr == variable->mgr);
+
+    tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
+    if (tmpDd == NULL) {
+      Cudd_RecursiveDeref(mgr,cube);
+      return(NULL);
+    }
+    cuddRef(tmpDd);
+    Cudd_RecursiveDeref(mgr, cube);
+    cube = tmpDd;
+  }
+
+  /* Perform the smoothing */
+  result = Cudd_bddXorExistAbstract(mgr,f->node,g->node,cube);
+  if (result == NULL) {
+    Cudd_RecursiveDeref(mgr, cube);
+    return(NULL);
+  }
+  cuddRef(result);
+  /* Get rid of temporary results. */
+  Cudd_RecursiveDeref(mgr, cube);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_xor_smooth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return a minimum size BDD between bounds.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_between(bdd_t *f_min, bdd_t *f_max)
+{
+  bdd_t *care_set, *ret;
+
+  if (bdd_equal(f_min, f_max)) {
+    return (bdd_dup(f_min));
+  }
+  care_set = bdd_or(f_min, f_max, 1, 0);
+  ret = bdd_minimize(f_min, care_set);
+  bdd_free(care_set);
+  /* The size of ret is never larger than the size of f_min. We need
+  ** only to check ret against f_max. */
+  if (bdd_size(f_max) <= bdd_size(ret)) {
+    bdd_free(ret);
+    return(bdd_dup(f_max));
+  } else {
+    return(ret);
+  }
+
+} /* end of bdd_between */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the cube of an array of mdd ids. The cube
+  is positive unate.  Returns a pointer to the result if successful;
+  NULL otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_compute_cube(bdd_manager *mgr, array_t *vars)
+{
+  DdNode *result;
+  DdNode **nodeArray;
+  int i, id;
+    
+  if (vars == NIL(array_t)) return NIL(bdd_t);
+  if (array_n(vars) == 0) return NIL(bdd_t);
+  /* create an array of DdNodes */
+  nodeArray = ALLOC(DdNode *, array_n(vars));
+  arrayForEachItem(int, vars, i, id) {
+    assert(id < bdd_num_vars(mgr));
+    nodeArray[i] = Cudd_bddIthVar((DdManager *)mgr, id);
+  }
+  result = Cudd_bddComputeCube((DdManager *)mgr, (DdNode **)nodeArray,
+			       NULL, array_n(vars));
+  FREE(nodeArray);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_compute_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the cube of an array of mdd ids. The phase if
+  each variable is given in the phase array.  Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_compute_cube_with_phase(bdd_manager *mgr, array_t *vars, array_t *phase)
+{
+  DdNode *result;
+  DdNode **nodeArray;
+  int *phaseArray;
+  int i, id, ph;
+    
+  if (vars == NIL(array_t)) return NIL(bdd_t);
+  if (array_n(vars) == 0) return NIL(bdd_t);
+  if (phase != NIL(array_t) && array_n(vars) != array_n(phase))
+    return NIL(bdd_t);
+  /* create an array of DdNodes */
+  nodeArray = ALLOC(DdNode *, array_n(vars));
+  phaseArray = NIL(int);
+  if (phase != NIL(array_t)) phaseArray = ALLOC(int, array_n(phase));
+  arrayForEachItem(int, vars, i, id) {
+    assert(id < bdd_num_vars(mgr));
+    nodeArray[i] = Cudd_bddIthVar((DdManager *)mgr, id);
+  }
+  arrayForEachItem(int, phase, i, ph) {
+    assert(ph == 0 || ph == 1);
+    phaseArray[i] = ph;
+  }
+  result = Cudd_bddComputeCube((DdManager *)mgr, (DdNode **)nodeArray,
+			       phaseArray, array_n(vars));
+  FREE(nodeArray);
+  if (phaseArray != NIL(int)) FREE(phaseArray);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_compute_cube_with_phase */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cofactor of f with respect to g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_cofactor(bdd_t *f, bdd_t *g)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager */
+  assert(f->mgr == g->mgr);
+
+  /* We use Cudd_bddConstrain instead of Cudd_Cofactor for generality. */
+  result = Cudd_bddConstrain(f->mgr,f->node,
+			     g->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_cofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cofactor of f with respect to g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_cofactor_array(bdd_t *f, array_t *bddArray)
+{
+  bdd_t *operand;
+  DdNode *result, *temp;
+  int i;
+
+  Cudd_Ref(result = f->node);
+
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = Cudd_bddConstrain(f->mgr, result, operand->node);
+    if (temp == NULL) {
+      Cudd_RecursiveDeref(f->mgr, result);
+      return(NULL);
+    }
+    cuddRef(temp);
+    Cudd_RecursiveDeref(f->mgr, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_cofactor_array */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cofactor of f with respect to g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_var_cofactor(bdd_t *f, bdd_t *g)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager */
+  assert(f->mgr == g->mgr);
+
+  result = Cudd_Cofactor(f->mgr,f->node,
+			 g->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_var_cofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the cofactor of f with respect to g in a safe manner.]
+
+  Description [Performs safe minimization of a BDD. Given the BDD
+  <code>f</code> of a function to be minimized and a BDD
+  <code>c</code> representing the care set, Cudd_bddLICompaction
+  produces the BDD of a function that agrees with <code>f</code>
+  wherever <code>c</code> is 1.  Safe minimization means that the size
+  of the result is guaranteed not to exceed the size of
+  <code>f</code>. This function is based on the DAC97 paper by Hong et
+  al..  Returns a pointer to the result if successful; NULL
+  otherwise.]
+  
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_compact(bdd_t *f, bdd_t *g)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager */
+  assert(f->mgr == g->mgr);
+
+  result = Cudd_bddLICompaction(f->mgr,f->node,
+				g->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_compact */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a bdd between l and u.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_squeeze(bdd_t *l, bdd_t *u)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager */
+  assert(l->mgr == u->mgr);
+
+  result = Cudd_bddSqueeze(l->mgr,l->node,
+			   u->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(l->mgr,result));
+
+} /* end of bdd_squeeze */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Functional composition of a function by a variable.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_compose(bdd_t *f, bdd_t *v, bdd_t *g)
+{
+  DdNode *result;
+
+  /* Make sure all operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+  assert(f->mgr == v->mgr);
+
+  result = Cudd_bddCompose(f->mgr,f->node,
+			   g->node,
+			   (int)Cudd_Regular(v->node)->index);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_compose */
+
+
+/**Function********************************************************************
+
+  Synopsis [Composes a BDD with a vector of BDDs. Given a vector of
+  BDDs, creates a new BDD by substituting the BDDs for the variables
+  of the BDD f.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_vector_compose(bdd_t *f, array_t *varArray, array_t *funcArray)
+{
+  int i, n, nVars, index;
+  bdd_t *var, *func;
+  DdNode *result;
+  DdNode **vector;
+
+  assert(array_n(varArray) == array_n(funcArray));
+  n = array_n(varArray);
+  nVars = ((DdManager *)f->mgr)->size;
+  vector = ALLOC(DdNode *, sizeof(DdNode *) * nVars);
+  memset(vector, 0, sizeof(DdNode *) * nVars);
+
+  for (i = 0; i < n; i++) {
+    var = array_fetch(bdd_t *, varArray, i);
+    func = array_fetch(bdd_t *, funcArray, i);
+    index = (int)bdd_top_var_id(var);
+    vector[index] = (DdNode *)func->node;
+    cuddRef(vector[index]);
+  }
+  for (i = 0; i < nVars; i++) {
+    if (!vector[i]) {
+      vector[i] = Cudd_bddIthVar((DdManager *)f->mgr, i);
+      cuddRef(vector[i]);
+    }
+  }
+
+  result = Cudd_bddVectorCompose(f->mgr, f->node, vector);
+
+  for (i = 0; i < nVars; i++)
+    Cudd_RecursiveDeref((DdManager *)f->mgr, vector[i]);
+  FREE(vector);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_vector_compose */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Universal Abstraction of Variables.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_consensus(
+  bdd_t *f,
+  array_t *quantifying_vars /* of bdd_t *'s */)
+{
+  int i;
+  bdd_t *variable;
+  DdNode *cube,*tmpDd,*result;
+  DdManager *mgr;
+
+  /* The Boulder package needs the smothing variables passed as a cube.
+   * Therefore we must build that cube from the indices of the variables
+   * in the array before calling the procedure.
+   */
+  mgr = f->mgr;
+  Cudd_Ref(cube = DD_ONE(mgr));
+  for (i = 0; i < array_n(quantifying_vars); i++) {
+    variable = array_fetch(bdd_t *,quantifying_vars,i);
+
+    /* Make sure the variable belongs to the same manager */
+    assert(mgr == variable->mgr);
+
+    tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
+    if (tmpDd == NULL) {
+      Cudd_RecursiveDeref(mgr, cube);
+      return(NULL);
+    }
+    cuddRef(tmpDd);
+    Cudd_RecursiveDeref(mgr, cube);
+    cube = tmpDd;
+  }
+
+  /* Perform the consensus */
+  result = Cudd_bddUnivAbstract(mgr,f->node,cube);
+  if (result == NULL) {
+    Cudd_RecursiveDeref(mgr, cube);
+    return(NULL);
+  }
+  cuddRef(result);
+  /* Get rid of temporary results */
+  Cudd_RecursiveDeref(mgr, cube);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_consensus */
+
+bdd_t *
+bdd_consensus_with_cube(
+  bdd_t *f,
+  bdd_t *cube)
+{
+  DdNode *result;
+  DdManager *mgr;
+
+  mgr = f->mgr;
+  /* Perform the consensus */
+  result = Cudd_bddUnivAbstract(mgr,f->node,cube->node);
+  if (result == NULL)
+    return(NULL);
+  cuddRef(result);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_consensus */
+
+/**Function********************************************************************
+
+  Synopsis    [The compatible projection function.]
+
+  Description [The compatible projection function. The reference minterm
+  is chosen based on the phases of the quantifying variables. If all
+  variables are in positive phase, the minterm 111...111 is used as
+  reference.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_cproject(
+  bdd_t *f,
+  array_t *quantifying_vars /* of bdd_t* */)
+{
+  DdManager *dd;
+  DdNode *cube;
+  DdNode *res;
+  bdd_t *fi;
+  int nvars, i;
+
+  if (f == NULL) {
+    fail ("bdd_cproject: invalid BDD");
+  }
+
+  nvars = array_n(quantifying_vars);
+  if (nvars <= 0) {
+    fail("bdd_cproject: no projection variables");
+  }
+  dd = f->mgr;
+
+  cube = DD_ONE(dd);
+  cuddRef(cube);
+  for (i = nvars - 1; i >= 0; i--) {
+    DdNode *tmpp;
+    fi = array_fetch(bdd_t *, quantifying_vars, i);
+    tmpp = Cudd_bddAnd(dd,fi->node,cube);
+    if (tmpp == NULL) {
+      Cudd_RecursiveDeref(dd,cube);
+      return(NULL);
+    }
+    cuddRef(tmpp);
+    Cudd_RecursiveDeref(dd,cube);
+    cube = tmpp;
+  }
+
+  res = Cudd_CProjection(dd,f->node,cube);
+  if (res == NULL) {
+    Cudd_RecursiveDeref(dd,cube);
+    return(NULL);
+  }
+  cuddRef(res);
+  Cudd_RecursiveDeref(dd,cube);
+
+  return(bdd_construct_bdd_t(dd,res));
+
+} /* end of bdd_cproject */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the else branch of a BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_else(bdd_t *f)
+{
+  DdNode *result;
+
+  result = Cudd_E(f->node);
+  result =  Cudd_NotCond(result,Cudd_IsComplement(f->node));
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_else */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ITE.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_ite(
+  bdd_t *i,
+  bdd_t *t,
+  bdd_t *e,
+  boolean i_phase,
+  boolean t_phase,
+  boolean e_phase)
+{
+  DdNode *newi,*newt,*newe,*ite;
+
+  /* Make sure both bdds belong to the same mngr */
+  assert(i->mgr == t->mgr);
+  assert(i->mgr == e->mgr);
+
+  /* Modify the phases of the operands according to the parameters */
+  if (!i_phase) {
+    newi = Cudd_Not(i->node);
+  } else {
+    newi = i->node;
+  }
+  if (!t_phase) {
+    newt = Cudd_Not(t->node);
+  } else {
+    newt = t->node;
+  }
+  if (!e_phase) {
+    newe = Cudd_Not(e->node);
+  } else {
+    newe = e->node;
+  }
+
+  /* Perform the ITE operation */
+  ite = Cudd_bddIte(i->mgr,newi,newt,newe);
+  if (ite == NULL) return(NULL);
+  cuddRef(ite);
+  return(bdd_construct_bdd_t(i->mgr,ite));
+
+} /* end of bdd_ite */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Restrict operator as described in Coudert et al. ICCAD90.]
+
+  Description [Restrict operator as described in Coudert et
+  al. ICCAD90.  Always returns a BDD not larger than the input
+  <code>f</code> if successful; NULL otherwise.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_minimize(bdd_t *f, bdd_t *c)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == c->mgr);
+
+  result = Cudd_bddRestrict(f->mgr, f->node, c->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t(f->mgr,result);
+  return(output);
+
+} /* end of bdd_minimize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Restrict operator as described in Coudert et al. ICCAD90.]
+
+  Description [Restrict operator as described in Coudert et
+  al. ICCAD90.  Always returns a BDD not larger than the input
+  <code>f</code> if successful; NULL otherwise.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_minimize_array(bdd_t *f, array_t *bddArray)
+{
+  bdd_t *operand;
+  DdNode *result, *temp;
+  int i;
+
+  Cudd_Ref(result = f->node);
+
+  for (i = 0; i < array_n(bddArray); i++) {
+    operand = array_fetch(bdd_t *, bddArray, i);
+    temp = Cudd_bddRestrict(f->mgr, result, operand->node);
+    if (temp == NULL) {
+      Cudd_RecursiveDeref(f->mgr, result);
+      return(NULL);
+    }
+    cuddRef(temp);
+    Cudd_RecursiveDeref(f->mgr, result);
+    result = temp;
+  }
+
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_minimize_array */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subset (superset) operator.]
+
+  Description [It computes a bdd which is a subset (superset) of the
+  given operand and has less nodes. approxDir specifies over/under
+  approximation. The number of variables is an estimate of the support
+  of the operand, and threshold is the maximum number of vertices
+  allowed in the result. The technique applied to eliminate nodes is
+  to remove a child of a node, starting with the root, that contribute
+  to fewer minterms than the other child. Refer to Ravi & Somenzi
+  ICCAD95.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_approx_hb(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  switch (approxDir) {
+  case BDD_OVER_APPROX:
+    result = Cudd_SupersetHeavyBranch(f->mgr, f->node, numVars, threshold);
+    break;
+  case BDD_UNDER_APPROX:
+    result = Cudd_SubsetHeavyBranch(f->mgr, f->node, numVars, threshold);
+    break;
+  default:
+    result = NULL;
+  }
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t(f->mgr,result);
+  return(output);
+
+} /* end of bdd_approx_hb */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subset (superset) operator.]
+
+  Description [It computes a bdd which is a subset (superset) of the
+  given operand and it has less nodes. approxDir specifies over/under
+  approximation. The number of variables is an estimate of the support
+  of the operand, and threshold is the maximum number of vertices
+  allowed in the result. If unsure, pass NULL for the number of
+  variables.  The method used is to extract the smallest cubes in the
+  bdd which also correspond to the shortest paths in the bdd to the
+  constant 1. hardlimit indicates that the node limit is strict. Refer
+  to Ravi and Somenzi ICCAD95.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_approx_sp(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  int hardlimit)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  switch (approxDir) {
+  case BDD_OVER_APPROX:
+    result = Cudd_SupersetShortPaths(f->mgr, f->node, numVars, threshold, hardlimit);
+    break;
+  case BDD_UNDER_APPROX:
+    result = Cudd_SubsetShortPaths(f->mgr, f->node, numVars, threshold, hardlimit);
+    break;
+  default:
+    result = NULL;
+  }
+
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t(f->mgr,result);
+  return(output);
+
+} /* end of bdd_approx_sp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subset (superset) operator.]
+
+  Description [It computes a bdd which is a subset (superset) of the
+  given operand and it has less nodes. The bdd chooses to preserve
+  nodes that contribute a large number and throws away those that
+  contribute fewer minterms and dominate a large number of
+  nodes. approxDir specifies over/under approximation. numVars is the
+  number of variables in the true support of f. threshold is a limit
+  specified on the number of nodes. safe is a parameter to ensure that
+  the result is never larger than the operand. quality is a factor
+  that affects replacement of nodes: 1 is the default value. Values
+  for quality imply that the ratio of the density of the result of
+  replaced nodes to the original original is equal to the value. Refer
+  to Shiple thesis.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_approx_ua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  int safe,
+  double quality)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  switch (approxDir) {
+  case BDD_OVER_APPROX:
+    result = Cudd_OverApprox(f->mgr, f->node, numVars, threshold, safe, quality);
+    break;
+  case BDD_UNDER_APPROX:
+    result = Cudd_UnderApprox(f->mgr, f->node, numVars, threshold, safe, quality);
+    break;
+  default:
+    result = NULL;
+  }
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t(f->mgr,result);
+  return(output);
+
+} /* end of bdd_approx_ua */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subset (superset) operator.]
+
+  Description [It computes a bdd which is a subset (superset) of the
+  given operand and it has less nodes.The bdd chooses to preserve
+  nodes that contribute a large number and throws away those that
+  contribute fewer minterms and dominate a large number of nodes. Some
+  nodes may be remapped to existing nodes in the BDD. approxDir
+  specifies over/under approximation. numVars is the number of
+  variables in the true support of f. threshold is a limit specified
+  on the number of nodes. safe is a parameter to ensure that the
+  result is never larger than the operand. quality is a factor that
+  affects replacement of nodes: 1 is the default value. Values for
+  quality imply that the ratio of the density of the result with
+  replaced nodes to the original bdd is equal to the value. Refer to
+  Shiple, Somenzi DAC98. ]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_approx_remap_ua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold,
+  double quality)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  switch (approxDir) {
+  case BDD_OVER_APPROX:
+    result = Cudd_RemapOverApprox((DdManager *)f->mgr, (DdNode *)f->node, numVars, threshold, quality);
+    break;
+  case BDD_UNDER_APPROX:
+    result = Cudd_RemapUnderApprox((DdManager *)f->mgr, (DdNode *)f->node, numVars, threshold, quality);
+    break;
+  default:
+    result = NULL;
+  }
+
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t((DdManager *)f->mgr,result);
+  return(output);
+
+} /* end of bdd_approx_remap_ua */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subset (superset) operator.]
+
+  Description [It computes a bdd which is a subset (superset) of the
+  given operand and it has less nodes.The bdd chooses to preserve
+  nodes that contribute a large number and throws away those that
+  contribute fewer minterms and dominate a large number of nodes. Some
+  nodes may be remapped to existing nodes in the BDD. approxDir
+  specifies over/under approximation. numVars is the number of
+  variables in the true support of f. threshold is a limit specified
+  on the number of nodes. safe is a parameter to ensure that the
+  result is never larger than the operand. quality is a factor that
+  affects replacement of nodes: 1 is the default value. Values for
+  quality imply that the ratio of the density of the result with
+  replaced nodes to the original bdd is equal to the value. Refer
+  Shiple, Somenzi DAC98. The only difference between this function and
+  bdd_approx_remap_ua is that this function takes a bias BDD and tries
+  to lean the approximation towards the bias]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_approx_biased_rua(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  bdd_t *bias,
+  int numVars,
+  int threshold,
+  double quality,
+  double qualityBias)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  assert(bias->mgr == f->mgr);
+  switch (approxDir) {
+  case BDD_OVER_APPROX:
+    result = Cudd_BiasedOverApprox((DdManager *)f->mgr, (DdNode *)f->node, (DdNode *)bias->node,  numVars, threshold, quality, qualityBias);
+    break;
+  case BDD_UNDER_APPROX:
+    result = Cudd_BiasedUnderApprox((DdManager *)f->mgr, (DdNode *)f->node, (DdNode *)bias->node, numVars, threshold, quality, qualityBias);
+    break;
+  default:
+    result = NULL;
+  }
+
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t((DdManager *)f->mgr,result);
+  return(output);
+
+} /* end of bdd_approx_biased_rua */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subset (superset) operator.]
+
+  Description [It computes a bdd which is a subset (superset) of the
+  given operand and it has less nodes. approxDir specifies over/under
+  approximation. The number of variables is an estimate of the support
+  of the operand, and threshold is the maximum number of vertices
+  allowed in the result. It applies short paths with the given
+  threshold first and then uses remap_ua to increase density.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_t *
+bdd_approx_compress(
+  bdd_t *f,
+  bdd_approx_dir_t approxDir,
+  int numVars,
+  int threshold)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  switch (approxDir) {
+  case BDD_OVER_APPROX:
+    result = Cudd_SupersetCompress(f->mgr, f->node, numVars, threshold);
+    break;
+  case BDD_UNDER_APPROX:
+    result = Cudd_SubsetCompress(f->mgr, f->node, numVars, threshold);
+    break;
+  default:
+    result = NULL;
+  }
+
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t(f->mgr,result);
+  return(output);
+
+} /* end of bdd_approx_compress */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a shortest path in a DD.]
+
+  Description [Finds a shortest path in a DD. f is the DD we want to
+  get the shortest path for; weight\[i\] is the weight of the THEN arc
+  coming from the node whose index is i. If weight is NULL, then unit
+  weights are assumed for all THEN arcs. All ELSE arcs have 0 weight.
+  If non-NULL, both weight and support should point to arrays with at
+  least as many entries as there are variables in the manager.
+  Returns the shortest path as the BDD of a cube.]
+
+  SideEffects [support contains on return the true support of f.
+  If support is NULL on entry, then Cudd_ShortestPath does not compute
+  the true support info. length contains the length of the path.]
+
+******************************************************************************/
+bdd_t *
+bdd_shortest_path(
+  bdd_t *f,
+  int *weight,
+  int *support,
+  int *length)
+{
+  DdNode *result;
+  bdd_t *output;
+
+  result = Cudd_ShortestPath(f->mgr, f->node, weight, support, length);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+
+  output = bdd_construct_bdd_t(f->mgr,result);
+  return(output);
+
+} /* end of bdd_shortest_path */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Negation.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_not(bdd_t *f)
+{
+  DdNode *result;
+
+  Cudd_Ref(result = Cudd_Not(f->node));
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_not */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the one BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_one(bdd_manager *mgr)
+{
+  DdNode *result;
+
+  Cudd_Ref(result = DD_ONE((DdManager *)mgr));
+  return(bdd_construct_bdd_t((DdManager *)mgr,result));
+
+} /* end of bdd_one */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Or of two BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_or(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase)
+{
+  DdNode *newf,*newg,*forg;
+  bdd_t *result;
+
+  /* Make sure both bdds belong to the same mngr */
+  assert(f->mgr == g->mgr);
+
+  /* Modify the phases of the operands according to the parameters */
+  if (f_phase) {
+    newf = Cudd_Not(f->node);
+  } else {
+    newf = f->node;
+  }
+  if (g_phase) {
+    newg = Cudd_Not(g->node);
+  } else {
+    newg = g->node;
+  }
+
+  /* Perform the OR operation */
+  forg = Cudd_bddAnd(f->mgr,newf,newg);
+  if (forg == NULL) return(NULL);
+  forg = Cudd_Not(forg);
+  cuddRef(forg);
+  result = bdd_construct_bdd_t(f->mgr,forg);
+
+  return(result);
+
+} /* end of bdd_or */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Existential abstraction of variables.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_smooth(
+  bdd_t *f,
+  array_t *smoothing_vars /* of bdd_t *'s */)
+{
+  int i;
+  bdd_t *variable;
+  DdNode *cube,*tmpDd,*result;
+  DdManager *mgr;
+  DdNode **vars;
+  int nVars, level;
+
+  /* The Boulder package needs the smoothing variables passed as a cube.
+   * Therefore we must build that cube from the indices of the variables
+   * in the array before calling the procedure.
+   */
+  mgr = f->mgr;
+  nVars = mgr->size;
+  vars = ALLOC(DdNode *, sizeof(DdNode *) * nVars);
+  memset(vars, 0, sizeof(DdNode *) * nVars);
+  for (i = 0; i < array_n(smoothing_vars); i++) {
+    variable = array_fetch(bdd_t *,smoothing_vars,i);
+
+    /* Make sure the variable belongs to the same manager. */
+    assert(mgr == variable->mgr);
+
+    level = Cudd_ReadPerm(mgr, Cudd_NodeReadIndex(variable->node));
+    vars[level] = variable->node;
+  }
+  Cudd_Ref(cube = DD_ONE(mgr));
+  for (i = nVars - 1; i >= 0; i--) {
+    if (!vars[i])
+      continue;
+    tmpDd = Cudd_bddAnd(mgr,cube,vars[i]);
+    if (tmpDd == NULL) {
+      Cudd_RecursiveDeref(mgr, cube);
+      return(NULL);
+    }
+    cuddRef(tmpDd);
+    Cudd_RecursiveDeref(mgr, cube);
+    cube = tmpDd;
+  }
+  FREE(vars);
+
+  /* Perform the smoothing */
+  result = Cudd_bddExistAbstract(mgr,f->node,cube);
+  if (result == NULL) {
+    Cudd_RecursiveDeref(mgr, cube);
+    return(NULL);
+  }
+  cuddRef(result);
+
+  /* Get rid of temporary results */
+  Cudd_RecursiveDeref(mgr, cube);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_smooth */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Existential abstraction of variables.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_smooth_with_cube(bdd_t *f, bdd_t *cube)
+{
+  DdNode *result;
+  DdManager *mgr;
+
+  mgr = f->mgr;
+
+  /* Perform the smoothing */
+  result = Cudd_bddExistAbstract(mgr,f->node,cube->node);
+  if (result == NULL)
+    return(NULL);
+  cuddRef(result);
+
+  /* Build the bdd_t structure for the result */
+  return(bdd_construct_bdd_t(mgr,result));
+
+} /* end of bdd_smooth_with_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_substitute(
+  bdd_t *f,
+  array_t *old_array /* of bdd_t *'s */,
+  array_t *new_array /* of bdd_t *'s */)
+{
+  int i,from,to;
+  int *permut;
+  bdd_t *variable;
+  DdNode *result;
+
+  /* Make sure both arrays have the same number of elements. */
+  assert(array_n(old_array) == array_n(new_array));
+
+  /* Allocate and fill the array with the trivial permutation. */
+  permut = ALLOC(int, Cudd_ReadSize((DdManager *)f->mgr));
+  for (i = 0; i < Cudd_ReadSize((DdManager *)f->mgr); i++) permut[i] = i;
+
+  /* Modify the permutation by looking at both arrays old and new. */
+  for (i = 0; i < array_n(old_array); i++) {
+    variable = array_fetch(bdd_t *, old_array, i);
+    from = Cudd_Regular(variable->node)->index;
+    variable = array_fetch(bdd_t *, new_array, i);
+    /* Make sure the variable belongs to this manager. */
+    assert(f->mgr == variable->mgr);
+
+    to = Cudd_Regular(variable->node)->index;
+    permut[from] = to;
+  }
+
+  result = Cudd_bddPermute(f->mgr,f->node,permut);
+  FREE(permut);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_substitute */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_substitute_with_permut(
+  bdd_t *f,
+  int *permut)
+{
+  DdNode *result;
+
+  result = Cudd_bddPermute(f->mgr,f->node,permut);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_substitute_with_permut */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+bdd_substitute_array(
+  array_t *f_array,
+  array_t *old_array,	/* of bdd_t *'s */
+  array_t *new_array)	/* of bdd_t *'s */
+{
+  int	i;
+  bdd_t	*f, *new_;
+  array_t *substitute_array = array_alloc(bdd_t *, 0);
+
+  arrayForEachItem(bdd_t *, f_array, i, f) {
+    new_ = bdd_substitute(f, old_array, new_array);
+    array_insert_last(bdd_t *, substitute_array, new_);
+  }
+  return(substitute_array);
+
+} /* end of bdd_substitute_array */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Permutes the variables.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+bdd_substitute_array_with_permut(
+  array_t *f_array,
+  int *permut)
+{
+  int	i;
+  bdd_t	*f, *new_;
+  array_t *substitute_array = array_alloc(bdd_t *, 0);
+
+  arrayForEachItem(bdd_t *, f_array, i, f) {
+    new_ = bdd_substitute_with_permut(f, permut);
+    array_insert_last(bdd_t *, substitute_array, new_);
+  }
+  return(substitute_array);
+
+} /* end of bdd_substitute_array_with_permut */
+
+
+/**Function********************************************************************
+ 
+  Synopsis    [Returns the pointer of the BDD.]
+ 
+  SideEffects []
+ 
+******************************************************************************/
+void *
+bdd_pointer(bdd_t *f)
+{
+  return((void *)f->node);
+
+} /* end of bdd_pointer */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the Then branch of the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_then(bdd_t *f)
+{
+  DdNode *result;
+
+  result = Cudd_T(f->node);
+  result =  Cudd_NotCond(result,Cudd_IsComplement(f->node));
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_then */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the BDD of the top variable.]
+
+  Description [Returns the BDD of the top variable of the argument. If
+  the argument is constant, it returns the constant function itself.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_top_var(bdd_t *f)
+{
+  DdNode *result;
+
+  if (Cudd_IsConstant(f->node)) {
+    result = f->node;
+  } else {
+    result = f->mgr->vars[Cudd_Regular(f->node)->index];
+  }
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_top_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the exclusive nor of two BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_xnor(bdd_t *f, bdd_t *g)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  result = Cudd_bddXnor(f->mgr,f->node,g->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_xnor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the exclusive or of two BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_xor(bdd_t *f, bdd_t *g)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  result = Cudd_bddXor(f->mgr,f->node,g->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_xor */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the constant logical zero BDD.]
+
+  SideEffects [bdd_read_zero]
+
+******************************************************************************/
+bdd_t *
+bdd_zero(bdd_manager *mgr)
+{
+  DdManager *manager;
+  DdNode *result;
+
+  manager = (DdManager *)mgr;
+  Cudd_Ref(result = Cudd_Not(DD_ONE((manager))));
+  return(bdd_construct_bdd_t(manager,result));
+
+} /* end of bdd_zero */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Equality check.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+bdd_equal(bdd_t *f, bdd_t *g)
+{
+  return(f->node == g->node);
+
+} /* end of bdd_equal */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Equality check with don't care conditions.]
+
+  Description [Returns 1 if f equals g wherever careSet is 1.]
+
+  SideEffects [None: No new nodes are created.]
+
+******************************************************************************/
+boolean
+bdd_equal_mod_care_set(
+  bdd_t *f,
+  bdd_t *g,
+  bdd_t *careSet)
+{
+  /* Make sure all operands belong to the same manager. */
+  assert(f->mgr == g->mgr && f->mgr == careSet->mgr);
+  return(Cudd_EquivDC(f->mgr, f->node, g->node, Cudd_Not(careSet->node)));
+
+} /* end of bdd_equal_mod_care_set */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a BDD included in the intersection of f and g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_intersects(
+  bdd_t *f,
+  bdd_t *g)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  result = Cudd_bddIntersect(f->mgr,f->node,g->node);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_intersects */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a BDD included in f at minimum distance from g.]
+
+  SideEffects [The distance is returned as a side effect in dist.]
+
+******************************************************************************/
+bdd_t *
+bdd_closest_cube(
+  bdd_t *f,
+  bdd_t *g,
+  int *dist)
+{
+  DdNode *result;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+
+  result = Cudd_bddClosestCube(f->mgr,f->node,g->node,dist);
+  if (result == NULL) return(NULL);
+  cuddRef(result);
+  return(bdd_construct_bdd_t(f->mgr,result));
+
+} /* end of bdd_closest_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks a BDD for tautology.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+bdd_is_tautology(bdd_t *f, boolean phase)
+{
+  if (phase) {
+    return(f->node == DD_ONE(f->mgr));
+  } else {
+    return(f->node == Cudd_Not(DD_ONE(f->mgr)));
+  }
+
+} /* end of bdd_is_tautology */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests for containment of f in g.]
+
+  SideEffects [None: No new nodes are created.]
+
+******************************************************************************/
+boolean
+bdd_leq(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase)
+{
+  DdNode *newf, *newg;
+
+  /* Make sure both operands belong to the same manager. */
+  assert(f->mgr == g->mgr);
+  newf = Cudd_NotCond(f->node, !f_phase);
+  newg = Cudd_NotCond(g->node, !g_phase);
+
+  return(Cudd_bddLeq(f->mgr,newf,newg));
+
+} /* end of bdd_leq */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implication check with don't care conditions.]
+
+  Description [Returns 1 if f implies g wherever careSet is 1.]
+
+  SideEffects [None: No new nodes are created.]
+
+******************************************************************************/
+boolean
+bdd_lequal_mod_care_set(
+  bdd_t *f,
+  bdd_t *g,
+  boolean f_phase,
+  boolean g_phase,
+  bdd_t *careSet)
+{
+  DdNode *newf, *newg;
+
+  /* Make sure all operands belong to the same manager. */
+  assert(f->mgr == g->mgr && f->mgr == careSet->mgr);
+  newf = Cudd_NotCond(f->node, !f_phase);
+  newg = Cudd_NotCond(g->node, !g_phase);
+    
+  return(Cudd_bddLeqUnless(f->mgr, newf, newg, Cudd_Not(careSet->node)));
+
+} /* end of bdd_lequal_mod_care_set */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests for containment of f in g.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+bdd_leq_array(
+  bdd_t *f,
+  array_t *g_array,
+  boolean f_phase,
+  boolean g_phase)
+{
+  int	i;
+  bdd_t	*g;
+  boolean result;
+
+  arrayForEachItem(bdd_t *, g_array, i, g) {
+    result = bdd_leq(f, g, f_phase, g_phase);
+    if (g_phase) {
+      if (!result)
+	return(0);
+    } else {
+      if (result)
+	return(1);
+    }
+  }
+  if (g_phase)
+    return(1);
+  else
+    return(0);
+
+} /* end of bdd_leq_array */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms in the on set.]
+
+  SideEffects []
+
+******************************************************************************/
+double
+bdd_count_onset(
+  bdd_t *f,
+  array_t *var_array /* of bdd_t *'s */)
+{
+  return(Cudd_CountMinterm(f->mgr,f->node,array_n(var_array)));
+
+} /* end of bdd_count_onset */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of minterms in the on set.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_epd_count_onset(
+  bdd_t *f,
+  array_t *var_array /* of bdd_t *'s */,
+  EpDouble *epd)
+{
+  return(Cudd_EpdCountMinterm(f->mgr,f->node,array_n(var_array),epd));
+
+} /* end of bdd_epd_count_onset */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the free field of the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_get_free(bdd_t *f)
+{
+  return(f->free);
+
+} /* end of bdd_get_free */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Obtains the manager of the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_manager *
+bdd_get_manager(bdd_t *f)
+{
+  return(f->mgr);
+
+} /* end of bdd_get_manager */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the node of the BDD.]
+
+  SideEffects [Sets is_complemented.]
+
+******************************************************************************/
+bdd_node *
+bdd_get_node(
+  bdd_t *f,
+  boolean *is_complemented /* return */)
+{
+  if (Cudd_IsComplement(f->node)) {
+    *is_complemented = TRUE;
+    return(Cudd_Regular(f->node));
+  }
+  *is_complemented = FALSE;
+  return(f->node);
+
+} /* end of bdd_get_node */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Obtains the support of the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+var_set_t *
+bdd_get_support(bdd_t *f)
+{
+  int i, size, *support;
+  var_set_t *result;
+
+  size = (unsigned int)Cudd_ReadSize((DdManager *)f->mgr);
+  support = Cudd_SupportIndex(f->mgr,f->node);
+  if (support == NULL) return(NULL);
+
+  result = var_set_new((int) f->mgr->size);
+  for (i = 0; i < size; i++) {
+    if (support[i])
+      var_set_set_elt(result, i);
+  }
+  FREE(support);
+
+  return(result);
+
+} /* end of bdd_get_support */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a BDD is a support of f.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_is_support_var(bdd_t *f, bdd_t *var)
+{
+  return(bdd_is_support_var_id(f, bdd_top_var_id(var)));
+
+} /* end of bdd_is_support_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a BDD index is a support of f.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_is_support_var_id(bdd_t *f, int index)
+{
+  DdNode *support, *scan;
+
+  support = Cudd_Support(f->mgr,f->node);
+  if (support == NULL) return(-1);
+  cuddRef(support);
+
+  scan = support;
+  while (!cuddIsConstant(scan)) {
+    if (scan->index == index) {
+      Cudd_RecursiveDeref(f->mgr,support);
+      return(1);
+    }
+    scan = cuddT(scan);
+  }
+  Cudd_RecursiveDeref(f->mgr,support);
+
+  return(0);
+
+} /* end of bdd_is_support_var_id */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Obtains the array of indices of an array of variables.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+bdd_get_varids(array_t *var_array)
+{
+  int i;
+  int index;
+  bdd_t *var;
+  array_t *result = array_alloc(int,array_n(var_array));
+
+  for (i = 0; i < array_n(var_array); i++) {
+    var = array_fetch(bdd_t *, var_array, i);
+    index = Cudd_Regular(var->node)->index;
+    (void) array_insert_last(int, result, index);
+  }
+  return(result);
+
+} /* end of bdd_get_varids */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of variables in the manager.]
+
+  SideEffects []
+
+******************************************************************************/
+unsigned int
+bdd_num_vars(bdd_manager *mgr)
+{
+  unsigned int size;
+  size = (unsigned int)Cudd_ReadSize((DdManager *)mgr);
+  return(size);
+
+} /* end of bdd_num_vars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_print(bdd_t *f)
+{
+  (void) cuddP(f->mgr,f->node);
+
+} /* end of bdd_print */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics about the package.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_print_stats(bdd_manager *mgr, FILE *file)
+{
+  Cudd_PrintInfo((DdManager *)mgr, file);
+
+  /* Print some guidance to the parameters */
+  (void) fprintf(file, "\nMore detailed information about the semantics ");
+  (void) fprintf(file, "and values of these parameters\n");
+  (void) fprintf(file, "can be found in the documentation about the CU ");
+  (void) fprintf(file, "Decision Diagram Package.\n");
+  
+  return;
+
+} /* end of bdd_print_stats */
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the internal parameters of the package to the given values.]
+
+  Description [The CUDD package has a set of parameters that can be assigned
+  different values. This function receives a table which maps strings to
+  values and sets the parameters represented by the strings to the pertinent
+  values. Some basic type checking is done. It returns 1 if everything is
+  correct and 0 otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_set_parameters(
+  bdd_manager *mgr,
+  avl_tree *valueTable,
+  FILE *file)
+{
+  Cudd_ReorderingType reorderMethod;
+  Cudd_ReorderingType zddReorderMethod;
+  st_table *newValueTable;
+  st_generator *stgen;
+  avl_generator *avlgen;
+  char *paramName;
+  char *paramValue;
+
+  /* Initial value of the variables. */
+  reorderMethod = CUDD_REORDER_SAME;
+  zddReorderMethod = CUDD_REORDER_SAME;
+
+  /* Build a new table with the parameter names but with
+  ** the prefix removed. */
+  newValueTable = st_init_table(st_ptrcmp, st_ptrhash);
+  avl_foreach_item(valueTable, avlgen, AVL_FORWARD, (char **)&paramName, 
+		   (char **)&paramValue) {
+    if (strncmp(paramName, "BDD.", 4) == 0) {
+      st_insert(newValueTable, (char *)&paramName[4],
+		(char *)paramValue);
+    }
+  }
+
+  st_foreach_item(newValueTable, stgen, &paramName, &paramValue) {
+    int uvalue;
+    char *invalidChar;
+
+    invalidChar = NIL(char);
+
+    if (strcmp(paramName, "Hard limit for cache size") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Hard limit for cache size",
+		    "unsigned integer");
+      }
+      else {
+	Cudd_SetMaxCacheHard((DdManager *) mgr, (unsigned int) uvalue);
+      }
+    }
+    else if (strcmp(paramName, "Cache hit threshold for resizing") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Cache hit threshold for resizing",
+		    "unsigned integer");
+      }
+      else {
+	Cudd_SetMinHit((DdManager *) mgr, (unsigned int) uvalue);
+      }
+    }
+    else if (strcmp(paramName, "Garbage collection enabled") == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	Cudd_EnableGarbageCollection((DdManager *) mgr);
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	Cudd_DisableGarbageCollection((DdManager *) mgr);
+      }
+      else {
+	InvalidType(file, "Garbage collection enabled", "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, "Limit for fast unique table growth")
+	     == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Limit for fast unique table growth", 
+		    "unsigned integer");
+      }
+      else {
+	Cudd_SetLooseUpTo((DdManager *) mgr, (unsigned int) uvalue);
+      }
+    }
+    else if (strcmp(paramName, 
+		    "Maximum number of variables sifted per reordering") 
+	     == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Maximum number of variables sifted per reordering",
+		    "unsigned integer");
+      }
+      else {
+	Cudd_SetSiftMaxVar((DdManager *) mgr, uvalue);
+      }
+    }
+    else if (strcmp(paramName, 
+		    "Maximum number of variable swaps per reordering")
+	     == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Maximum number of variable swaps per reordering", 
+		    "unsigned integer");
+      }
+      else {
+	Cudd_SetSiftMaxSwap((DdManager *) mgr, uvalue);
+      }
+    }
+    else if (strcmp(paramName, 
+		    "Maximum growth while sifting a variable") == 0) {
+      double value;
+
+      value = strtod(paramValue, &invalidChar);
+      if (*invalidChar) {
+	InvalidType(file, "Maximum growth while sifting a variable",
+		    "real");
+      }
+      else {
+	Cudd_SetMaxGrowth((DdManager *) mgr, value);
+      }
+    }
+    else if (strcmp(paramName, "Dynamic reordering of BDDs enabled")
+	     == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	Cudd_AutodynEnable((DdManager *) mgr, reorderMethod);
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	Cudd_AutodynDisable((DdManager *) mgr);
+      }
+      else {
+	InvalidType(file, "Dynamic reordering of BDDs enabled",
+		    "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, "Default BDD reordering method") == 0) {
+      Cudd_ReorderingType reorderInt;
+
+      reorderMethod = (Cudd_ReorderingType) strtol(paramValue,
+						   &invalidChar, 10);
+      if (*invalidChar || reorderMethod < 0) {
+	InvalidType(file, "Default BDD reordering method", "integer");
+      }
+      else {
+	if (Cudd_ReorderingStatus((DdManager *) mgr, &reorderInt)) {
+	  Cudd_AutodynEnable((DdManager *) mgr, reorderMethod);
+	}
+      }
+    }
+    else if (strcmp(paramName, "Dynamic reordering of ZDDs enabled")
+	     == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	Cudd_AutodynEnableZdd((DdManager *) mgr, zddReorderMethod);
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	Cudd_AutodynDisableZdd((DdManager *) mgr);
+      }
+      else {
+	InvalidType(file, "Dynamic reordering of ZDDs enabled", "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, "Default ZDD reordering method") == 0) {
+      Cudd_ReorderingType reorderInt;
+
+      zddReorderMethod = (Cudd_ReorderingType) strtol(paramValue,
+						      &invalidChar, 10);
+      if (*invalidChar || zddReorderMethod < 0) {
+	InvalidType(file, "Default ZDD reordering method", "integer");
+      }
+      else {
+	if (Cudd_ReorderingStatusZdd((DdManager *) mgr, &reorderInt)) {
+	  Cudd_AutodynEnableZdd((DdManager *) mgr, zddReorderMethod);
+	}
+      }
+    }
+    else if (strcmp(paramName, "Realignment of ZDDs to BDDs enabled")
+	     == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	Cudd_zddRealignEnable((DdManager *) mgr);
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	Cudd_zddRealignDisable((DdManager *) mgr);
+      }
+      else {
+	InvalidType(file, "Realignment of ZDDs to BDDs enabled",
+		    "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, 
+		    "Dead node counted in triggering reordering") == 0) {
+      if (strcmp(paramValue, "yes") == 0) {
+	Cudd_TurnOnCountDead((DdManager *) mgr);
+      }
+      else if (strcmp(paramValue, "no") == 0) {
+	Cudd_TurnOffCountDead((DdManager *) mgr);
+      }
+      else {
+	InvalidType(file,
+		    "Dead node counted in triggering reordering", 
+		    "(yes,no)");
+      }
+    }
+    else if (strcmp(paramName, "Group checking criterion") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Group checking criterion", "integer");
+      }
+      else {
+	Cudd_SetGroupcheck((DdManager *) mgr, (Cudd_AggregationType) uvalue);
+      }
+    }
+    else if (strcmp(paramName, "Recombination threshold") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Recombination threshold", "integer");
+      }
+      else {
+	Cudd_SetRecomb((DdManager *) mgr, uvalue);
+      }
+    }
+    else if (strcmp(paramName, "Symmetry violation threshold") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Symmetry violation threshold", "integer");
+      }
+      else {
+	Cudd_SetSymmviolation((DdManager *) mgr, uvalue);
+      }
+    }
+    else if (strcmp(paramName, "Arc violation threshold") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Arc violation threshold", "integer");
+      }
+      else {
+	Cudd_SetArcviolation((DdManager *) mgr, uvalue);
+      }
+    }
+    else if (strcmp(paramName, "GA population size") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar  || uvalue < 0) {
+	InvalidType(file, "GA population size", "integer");
+      }
+      else {
+	Cudd_SetPopulationSize((DdManager *) mgr, uvalue);
+      }
+    }
+    else if (strcmp(paramName, "Number of crossovers for GA") == 0) {
+
+      uvalue = strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Number of crossovers for GA", "integer");
+      }
+      else {
+	Cudd_SetNumberXovers((DdManager *) mgr, uvalue);
+      }
+    }
+    else if (strcmp(paramName, "Next reordering threshold") == 0) {
+
+      uvalue = (unsigned int) strtol(paramValue, &invalidChar, 10);
+      if (*invalidChar || uvalue < 0) {
+	InvalidType(file, "Next reordering threshold", "integer");
+      }
+      else {
+	Cudd_SetNextReordering((DdManager *) mgr, uvalue);
+      }
+    }
+    else {
+      (void) fprintf(file, "Warning: Parameter %s not recognized.",
+		     paramName);
+      (void) fprintf(file, " Ignored.\n");
+    }
+  } /* end of st_foreach_item */
+
+  /* Clean up. */
+  st_free_table(newValueTable);
+
+  return(1);
+
+} /* end of bdd_set_parameters */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the number of nodes of a BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_size(bdd_t *f)
+{
+  return(Cudd_DagSize(f->node));
+
+} /* end of bdd_size */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the number of nodes of a BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_node_size(bdd_node *f)
+{
+  return(Cudd_DagSize((DdNode *) f));
+
+} /* end of bdd_node_size */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the shared size of an array of BDDs.]
+
+  Description [Computes the shared size of an array of BDDs. Returns
+  CUDD_OUT_OF_MEM in case of failure.]
+
+  SideEffects []
+
+******************************************************************************/
+long
+bdd_size_multiple(array_t *bddArray)
+{
+  DdNode **nodeArray;
+  bdd_t *bddUnit;
+  long result;
+  int i;
+
+  nodeArray = ALLOC(DdNode *, array_n(bddArray));
+  if (nodeArray == NULL) return(CUDD_OUT_OF_MEM);
+  for (i = 0; i < array_n(bddArray); i++) {
+    bddUnit = array_fetch(bdd_t *, bddArray, i);
+    nodeArray[i] = bddUnit->node;
+  }
+
+  result = Cudd_SharingSize(nodeArray,array_n(bddArray));
+
+  /* Clean up */
+  FREE(nodeArray);
+
+  return(result);
+
+} /* end of bdd_size_multiple */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Accesses the id of the top variable.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_variableId
+bdd_top_var_id(bdd_t *f)
+{
+  return(Cudd_Regular(f->node)->index);
+
+} /* end of bdd_top_var_id */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Accesses the external_hooks field of the manager.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_external_hooks *
+bdd_get_external_hooks(bdd_manager *mgr)
+{
+  return((bdd_external_hooks *)(((DdManager *)mgr)->hooks));
+
+} /* end of bdd_get_external_hooks */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a function to a hook.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_add_hook(
+  bdd_manager *mgr,
+  int (*procedure)(bdd_manager *, char *, void *),
+  bdd_hook_type_t whichHook)
+{
+  int retval;
+  Cudd_HookType hook;
+  switch (whichHook) {
+  case BDD_PRE_GC_HOOK: hook = CUDD_PRE_GC_HOOK; break;
+  case BDD_POST_GC_HOOK: hook = CUDD_POST_GC_HOOK; break;
+  case BDD_PRE_REORDERING_HOOK: hook = CUDD_PRE_REORDERING_HOOK; break;
+  case BDD_POST_REORDERING_HOOK: hook = CUDD_POST_REORDERING_HOOK; break;
+  default: fprintf(stderr, "Dont know which hook"); return 0;
+  }
+    
+  retval = Cudd_AddHook((DdManager *)mgr, (DD_HFP)procedure, hook);
+  return retval;
+
+} /* end of bdd_add_hook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes the function from the hook.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_remove_hook(
+  bdd_manager *mgr,
+  int (*procedure)(bdd_manager *, char *, void *),
+  bdd_hook_type_t whichHook)
+{
+  int retval;
+  Cudd_HookType hook;
+  switch (whichHook) {
+  case BDD_PRE_GC_HOOK: hook = CUDD_PRE_GC_HOOK; break;
+  case BDD_POST_GC_HOOK: hook = CUDD_POST_GC_HOOK; break;
+  case BDD_PRE_REORDERING_HOOK: hook = CUDD_PRE_REORDERING_HOOK; break;
+  case BDD_POST_REORDERING_HOOK: hook = CUDD_POST_REORDERING_HOOK; break;
+  default: fprintf(stderr, "Dont know which hook"); return 0;
+  }
+  retval = Cudd_RemoveHook((DdManager *)mgr, (DD_HFP)procedure, hook);
+  return retval;
+
+} /* end of bdd_remove_hook */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enables reporting of reordering stats.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_enable_reordering_reporting(bdd_manager *mgr)
+{
+  int retval;
+  retval = Cudd_EnableReorderingReporting((DdManager *) mgr);
+  return retval;
+
+} /* end of bdd_enable_reordering_reporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disables reporting of reordering stats.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_disable_reordering_reporting(bdd_manager *mgr)
+{
+  int retval;
+  retval = Cudd_DisableReorderingReporting((DdManager *) mgr);
+  return retval;
+
+} /* end of bdd_disable_reordering_reporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Reporting of reordering stats.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_reorder_verbosity_t 
+bdd_reordering_reporting(bdd_manager *mgr)
+{
+  int retval;
+  bdd_reorder_verbosity_t reorderVerbosity;
+  retval = Cudd_ReorderingReporting((DdManager *) mgr);
+  switch(retval) {
+  case 0: reorderVerbosity = BDD_REORDER_NO_VERBOSITY; break;
+  case 1: reorderVerbosity = BDD_REORDER_VERBOSITY; break;
+  default: reorderVerbosity = BDD_REORDER_VERBOSITY_DEFAULT; break;
+  }
+  return reorderVerbosity;
+
+} /* end of bdd_reordering_reporting */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Turns on or off garbage collection.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_set_gc_mode(bdd_manager *mgr, boolean no_gc)
+{
+  if (no_gc) {
+    Cudd_DisableGarbageCollection((DdManager *) mgr);
+  } else {
+    Cudd_EnableGarbageCollection((DdManager *) mgr);
+  }
+  return;
+
+} /* end of bdd_set_gc_mode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders the BDD pool.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_dynamic_reordering(
+  bdd_manager *mgr_,
+  bdd_reorder_type_t algorithm_type,
+  bdd_reorder_verbosity_t verbosity)
+{
+  DdManager *mgr;
+
+  mgr = (DdManager *)mgr_;
+
+  switch (algorithm_type) {
+  case BDD_REORDER_SIFT:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_SIFT);
+    break;
+  case BDD_REORDER_WINDOW:
+  case BDD_REORDER_WINDOW3_CONV:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_WINDOW3_CONV);
+    break;
+  case BDD_REORDER_NONE:
+    Cudd_AutodynDisable(mgr);
+    break;
+  case BDD_REORDER_SAME:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_SAME);
+    break;
+  case BDD_REORDER_RANDOM:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_RANDOM);
+    break;
+  case BDD_REORDER_RANDOM_PIVOT:	
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_RANDOM_PIVOT);
+    break;
+  case BDD_REORDER_SIFT_CONVERGE:
+    Cudd_AutodynEnable(mgr,CUDD_REORDER_SIFT_CONVERGE);
+    break;
+  case BDD_REORDER_SYMM_SIFT:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_SYMM_SIFT);
+    break;
+  case BDD_REORDER_SYMM_SIFT_CONV:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_SYMM_SIFT_CONV);
+    break;
+  case BDD_REORDER_WINDOW2:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_WINDOW2);
+    break;
+  case BDD_REORDER_WINDOW4:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_WINDOW4);
+    break;
+  case BDD_REORDER_WINDOW2_CONV:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_WINDOW2_CONV);
+    break;
+  case BDD_REORDER_WINDOW3:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_WINDOW3);
+    break;
+  case BDD_REORDER_WINDOW4_CONV:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_WINDOW4_CONV);
+    break;
+  case BDD_REORDER_GROUP_SIFT:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_GROUP_SIFT);
+    break;
+  case BDD_REORDER_GROUP_SIFT_CONV:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_GROUP_SIFT_CONV);	
+    break;
+  case BDD_REORDER_ANNEALING:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_ANNEALING);
+    break;
+  case BDD_REORDER_GENETIC:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_GENETIC);
+    break;
+  case BDD_REORDER_EXACT:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_EXACT);
+    break;
+  case BDD_REORDER_LAZY_SIFT:
+    Cudd_AutodynEnable(mgr, CUDD_REORDER_LAZY_SIFT);
+    break;
+  default:
+    fprintf(stderr,"CU DD Package: Reordering algorithm not considered\n");
+  }
+
+  if (verbosity == BDD_REORDER_NO_VERBOSITY) {
+    (void) bdd_disable_reordering_reporting((DdManager *)mgr);
+  } else if (verbosity ==  BDD_REORDER_VERBOSITY) {
+    (void) bdd_enable_reordering_reporting((DdManager *)mgr);
+  }
+    
+} /* end of bdd_dynamic_reordering */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorders the ZDD pool.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_dynamic_reordering_zdd(
+  bdd_manager *mgr_,
+  bdd_reorder_type_t algorithm_type,
+  bdd_reorder_verbosity_t verbosity)
+{
+  DdManager *mgr;
+
+  mgr = (DdManager *)mgr_;
+
+  switch (algorithm_type) {
+  case BDD_REORDER_SIFT:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_SIFT);
+    break;
+  case BDD_REORDER_WINDOW:
+  case BDD_REORDER_WINDOW3_CONV:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_WINDOW3_CONV);
+    break;
+  case BDD_REORDER_NONE:
+    Cudd_AutodynDisable(mgr);
+    break;
+  case BDD_REORDER_SAME:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_SAME);
+    break;
+  case BDD_REORDER_RANDOM:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_RANDOM);
+    break;
+  case BDD_REORDER_RANDOM_PIVOT:	
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_RANDOM_PIVOT);
+    break;
+  case BDD_REORDER_SIFT_CONVERGE:
+    Cudd_AutodynEnableZdd(mgr,CUDD_REORDER_SIFT_CONVERGE);
+    break;
+  case BDD_REORDER_SYMM_SIFT:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_SYMM_SIFT);
+    break;
+  case BDD_REORDER_SYMM_SIFT_CONV:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_SYMM_SIFT_CONV);
+    break;
+  case BDD_REORDER_WINDOW2:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_WINDOW2);
+    break;
+  case BDD_REORDER_WINDOW4:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_WINDOW4);
+    break;
+  case BDD_REORDER_WINDOW2_CONV:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_WINDOW2_CONV);
+    break;
+  case BDD_REORDER_WINDOW3:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_WINDOW3);
+    break;
+  case BDD_REORDER_WINDOW4_CONV:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_WINDOW4_CONV);
+    break;
+  case BDD_REORDER_GROUP_SIFT:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_GROUP_SIFT);
+    break;
+  case BDD_REORDER_GROUP_SIFT_CONV:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_GROUP_SIFT_CONV);	
+    break;
+  case BDD_REORDER_ANNEALING:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_ANNEALING);
+    break;
+  case BDD_REORDER_GENETIC:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_GENETIC);
+    break;
+  case BDD_REORDER_EXACT:
+    Cudd_AutodynEnableZdd(mgr, CUDD_REORDER_EXACT);
+    break;
+  default:
+    fprintf(stderr,"CU DD Package: Reordering algorithm not considered\n");
+  }
+  if (verbosity == BDD_REORDER_NO_VERBOSITY) {
+    (void) bdd_disable_reordering_reporting((DdManager *)mgr);
+  } else if (verbosity ==  BDD_REORDER_VERBOSITY) {
+    (void) bdd_enable_reordering_reporting((DdManager *)mgr);
+  }
+    
+} /* end of bdd_dynamic_reordering_zdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Calls reordering explicitly.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_reorder(bdd_manager *mgr)
+{
+  /* 10 = whatever (Verbatim from file ddTable.c) */
+  (void) Cudd_ReduceHeap((DdManager *)mgr,((DdManager *)mgr)->autoMethod,10);
+  return;
+
+} /* end of bdd_reorder */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the id variable for one level in the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_variableId
+bdd_get_id_from_level(bdd_manager *mgr, long level)
+{
+  int result;
+  result = Cudd_ReadInvPerm((DdManager *) mgr, (int)level);
+  return(result);
+
+} /* end of bdd_get_id_from_level */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the level of the top variable of the BDD.]
+
+  SideEffects []
+
+******************************************************************************/
+long
+bdd_top_var_level(bdd_manager *mgr, bdd_t *fn)
+{
+  return((long) cuddI((DdManager *)mgr,Cudd_Regular(fn->node)->index));
+
+} /* end of bdd_top_var_level */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns TRUE if the argument BDD is a cube; FALSE
+  otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+bdd_is_cube(bdd_t *f)
+{
+  struct DdManager *manager;
+
+  if (f == NULL) {
+    fail("bdd_is_cube: invalid BDD");
+  }
+  if (f->free) fail ("Freed BDD passed to bdd_is_cube");
+  manager =  f->mgr;
+  return((boolean)cuddCheckCube(manager,f->node));
+
+} /* end of bdd_is_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a group of variables that should stay adjacent
+  during reordering.]
+
+  Description [Builds a group of variables that should stay adjacent
+  during reordering. The group is made up of n variables. The first
+  variable in the group is f. The other variables are the n-1
+  variables following f in the order at the time of invocation of this
+  function. Returns a handle to the variable group if successful; NULL
+  otherwise.]
+
+  SideEffects [Modifies the variable tree.]
+
+******************************************************************************/
+bdd_block *
+bdd_new_var_block(bdd_t *f, long n)
+{
+  DdManager *manager;
+  DdNode *node;
+  MtrNode *group;
+  int index;
+
+  manager = (DdManager *) f->mgr;
+  node = Cudd_Regular(f->node);
+  index = node->index;
+  if (index == CUDD_MAXINDEX)
+    return(NULL);
+  group = Cudd_MakeTreeNode(manager, index, n, MTR_DEFAULT);
+    
+  return((bdd_block *) group);
+
+} /* end of bdd_new_var_block */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Function that creates a variable of a given index.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_var_with_index(bdd_manager *manager, int index)
+{
+  DdNode *var;
+
+  var = Cudd_bddIthVar((DdManager *) manager, index);
+  cuddRef(var);
+  return(bdd_construct_bdd_t(manager, var));
+
+} /* end of bdd_var_with_index */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is dependent on others in a
+  function f. Returns 1 if it is, else 0. ]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_var_is_dependent(bdd_t *f, bdd_t *var)
+{
+  return (Cudd_bddVarIsDependent((DdManager *)f->mgr, (DdNode *)f->node,
+				 (DdNode *)var->node));
+
+} /* end of bdd_var_is_dependent */
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_reordering_status(bdd_manager *mgr, bdd_reorder_type_t *method)
+{
+  int dyn;
+
+  dyn = Cudd_ReorderingStatus((DdManager *)mgr, (Cudd_ReorderingType  *)method);
+  switch (*method) {
+  case CUDD_REORDER_SIFT:
+    *method = BDD_REORDER_SIFT;
+    break;
+  case CUDD_REORDER_WINDOW3_CONV:
+    *method = BDD_REORDER_WINDOW3_CONV;
+    break;
+  case CUDD_REORDER_NONE:
+    *method = BDD_REORDER_NONE;
+    break;
+  case CUDD_REORDER_SAME:
+    *method = BDD_REORDER_SAME;
+    break;
+  case CUDD_REORDER_RANDOM:
+    *method = BDD_REORDER_RANDOM;
+    break;
+  case CUDD_REORDER_RANDOM_PIVOT:	
+    *method = BDD_REORDER_RANDOM_PIVOT;
+    break;
+  case CUDD_REORDER_SIFT_CONVERGE:
+    *method = BDD_REORDER_SIFT_CONVERGE;
+    break;
+  case CUDD_REORDER_SYMM_SIFT:
+    *method = BDD_REORDER_SYMM_SIFT;
+    break;
+  case CUDD_REORDER_SYMM_SIFT_CONV:
+    *method = BDD_REORDER_SYMM_SIFT_CONV;
+    break;
+  case CUDD_REORDER_WINDOW2:
+    *method = BDD_REORDER_WINDOW2;
+    break;
+  case CUDD_REORDER_WINDOW4:
+    *method = BDD_REORDER_WINDOW4;
+    break;
+  case CUDD_REORDER_WINDOW2_CONV:
+    *method = BDD_REORDER_WINDOW2_CONV;
+    break;
+  case CUDD_REORDER_WINDOW3:
+    *method = BDD_REORDER_WINDOW3;
+    break;
+  case CUDD_REORDER_WINDOW4_CONV:
+    *method = BDD_REORDER_WINDOW4_CONV;
+    break;
+  case CUDD_REORDER_GROUP_SIFT:
+    *method = BDD_REORDER_GROUP_SIFT;
+    break;
+  case CUDD_REORDER_GROUP_SIFT_CONV:
+    *method = BDD_REORDER_GROUP_SIFT_CONV;	
+    break;
+  case CUDD_REORDER_ANNEALING:
+    *method = BDD_REORDER_ANNEALING;
+    break;
+  case CUDD_REORDER_GENETIC:
+    *method = BDD_REORDER_GENETIC;
+    break;
+  case CUDD_REORDER_EXACT:
+    *method = BDD_REORDER_EXACT;
+    break;
+  default:
+    break;
+  }
+  return(dyn);
+
+} /* end of bdd_reordering_status */
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_reordering_zdd_status(bdd_manager *mgr, bdd_reorder_type_t *method)
+{
+  int dyn;
+  dyn = Cudd_ReorderingStatusZdd((DdManager *)mgr, (Cudd_ReorderingType  *)method);
+  switch (*method) {
+  case CUDD_REORDER_SIFT:
+    *method = BDD_REORDER_SIFT;
+    break;
+  case CUDD_REORDER_WINDOW3_CONV:
+    *method = BDD_REORDER_WINDOW3_CONV;
+    break;
+  case CUDD_REORDER_NONE:
+    *method = BDD_REORDER_NONE;
+    break;
+  case CUDD_REORDER_SAME:
+    *method = BDD_REORDER_SAME;
+    break;
+  case CUDD_REORDER_RANDOM:
+    *method = BDD_REORDER_RANDOM;
+    break;
+  case CUDD_REORDER_RANDOM_PIVOT:	
+    *method = BDD_REORDER_RANDOM_PIVOT;
+    break;
+  case CUDD_REORDER_SIFT_CONVERGE:
+    *method = BDD_REORDER_SIFT_CONVERGE;
+    break;
+  case CUDD_REORDER_SYMM_SIFT:
+    *method = BDD_REORDER_SYMM_SIFT;
+    break;
+  case CUDD_REORDER_SYMM_SIFT_CONV:
+    *method = BDD_REORDER_SYMM_SIFT_CONV;
+    break;
+  case CUDD_REORDER_WINDOW2:
+    *method = BDD_REORDER_WINDOW2;
+    break;
+  case CUDD_REORDER_WINDOW4:
+    *method = BDD_REORDER_WINDOW4;
+    break;
+  case CUDD_REORDER_WINDOW2_CONV:
+    *method = BDD_REORDER_WINDOW2_CONV;
+    break;
+  case CUDD_REORDER_WINDOW3:
+    *method = BDD_REORDER_WINDOW3;
+    break;
+  case CUDD_REORDER_WINDOW4_CONV:
+    *method = BDD_REORDER_WINDOW4_CONV;
+    break;
+  case CUDD_REORDER_GROUP_SIFT:
+    *method = BDD_REORDER_GROUP_SIFT;
+    break;
+  case CUDD_REORDER_GROUP_SIFT_CONV:
+    *method = BDD_REORDER_GROUP_SIFT_CONV;
+    break;
+  case CUDD_REORDER_ANNEALING:
+    *method = BDD_REORDER_ANNEALING;
+    break;
+  case CUDD_REORDER_GENETIC:
+    *method = BDD_REORDER_GENETIC;
+    break;
+  case CUDD_REORDER_EXACT:
+    *method = BDD_REORDER_EXACT;
+    break;
+  default:
+    break;
+  }
+  return(dyn);
+
+} /* end of bdd_reordering_zdd_status */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Converts a bdd to an add.]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_to_add(bdd_manager *mgr, bdd_node *fn)
+{
+  DdNode *result;
+  result = Cudd_BddToAdd((DdManager *)mgr,(DdNode *)fn);
+  return((bdd_node *)result);
+
+} /* end of bdd_bdd_to_add */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Permutes the variables in a given function using the permut array..]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_permute(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  int *permut)
+{
+  DdNode *result;
+  result = Cudd_addPermute((DdManager *)mgr, (DdNode *)fn, permut);
+  return(result);
+
+} /* end of bdd_add_permute */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Permutes the variables in a given function using the permut array..]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_permute(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  int *permut)
+{
+  DdNode *result;
+  result = Cudd_bddPermute((DdManager *)mgr, (DdNode *)fn, permut);
+  return(result);
+
+} /* end of bdd_bdd_permute */
+
+
+/**Function********************************************************************
+
+  Synopsis           [References a bdd]
+
+  SideEffects        []
+
+******************************************************************************/
+void
+bdd_ref(bdd_node *fn)
+{
+  Cudd_Ref((DdNode *)fn);
+  return;
+
+} /* end of bdd_ref */
+
+
+/**Function********************************************************************
+
+  Synopsis [Decreases the reference count of node.If f dies,
+  recursively decreases the reference counts of its children.  It is
+  used to dispose of a DD that is no longer needed.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_recursive_deref(bdd_manager *mgr, bdd_node *f)
+{
+  Cudd_RecursiveDeref((DdManager *)mgr, (DdNode *)f);
+
+} /* end of bdd_recursive_deref */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Existentially abstracts out the variables from the function]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_exist_abstract(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *vars)
+{
+  DdNode *result;
+  result = Cudd_addExistAbstract((DdManager *)mgr, (DdNode *)fn,
+				 (DdNode *)vars);
+  return(result);
+
+} /* end of bdd_add_exist_abstract */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs the apply operation on ADds]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_apply(
+  bdd_manager *mgr,
+  bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **),
+  bdd_node *fn1,
+  bdd_node *fn2)
+{
+  DdNode *result;
+  result = Cudd_addApply((DdManager *)mgr,
+			 (DdNode *(*)(DdManager *, DdNode **, DdNode **))
+			 operation, (DdNode *)fn1, (DdNode *)fn2);
+  return(result);
+
+} /* end of bdd_add_apply */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs the non-simple compose on ADds]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_nonsim_compose(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node **vector)
+{
+  DdNode *result;
+  result = Cudd_addNonSimCompose((DdManager *)mgr, (DdNode *)fn,
+				 (DdNode **)vector);
+  return(result);
+
+} /* end of bdd_add_nonsim_compose */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Computes the residue ADD of n variables with respect to m]
+  
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_residue(
+  bdd_manager *mgr,
+  int n,
+  int m,
+  int options,
+  int top)
+{
+  DdNode *result;
+  result = Cudd_addResidue((DdManager *)mgr, n, m, options, top);
+  return(result);
+
+} /* end of bdd_add_residue */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs the vector compose on ADds]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node **vector)
+{
+  DdNode *result;
+  result = Cudd_addVectorCompose((DdManager *)mgr, (DdNode *)fn,
+				 (DdNode **)vector);
+  return(result);
+
+} /* end of bdd_add_vector_compose */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs the times (multiplication operation)  on Adds]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_times(
+  bdd_manager *mgr,
+  bdd_node **fn1,
+  bdd_node **fn2)
+{
+  DdNode *result;
+  result = Cudd_addTimes((DdManager *)mgr, (DdNode **)fn1, (DdNode **)fn2);
+  return(result);
+
+} /* end of bdd_add_times */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs the zero reference count check on the manager.]
+
+  SideEffects        []
+
+******************************************************************************/
+int
+bdd_check_zero_ref(bdd_manager *mgr)
+{
+  int result;
+  result = Cudd_CheckZeroRef((DdManager *)mgr);
+  return(result);
+
+} /* end of bdd_check_zero_ref */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Disables dynamic reordering in the manager.]
+
+  SideEffects        []
+
+******************************************************************************/
+void
+bdd_dynamic_reordering_disable(bdd_manager *mgr)
+{
+  Cudd_AutodynDisable((DdManager *)mgr);
+  return;
+
+} /* end of bdd_dynamic_reordering_disable */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Disables dynamic reordering for ZDD in the manager.]
+
+  SideEffects        []
+
+******************************************************************************/
+void
+bdd_dynamic_reordering_zdd_disable(bdd_manager *mgr)
+{
+  Cudd_AutodynDisableZdd((DdManager *)mgr);
+  return;
+
+} /* end of bdd_dynamic_reordering_zdd_disable */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs the xnor (\equiv operation)  on Adds]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_xnor(bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2)
+{
+  DdNode *result;
+  result = Cudd_addXnor((DdManager *)mgr, (DdNode **)fn1, (DdNode **)fn2);
+  return(result);
+
+} /* end of bdd_add_xnor */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Shuffles the variables in the manager in the given order.]
+
+  SideEffects        []
+
+******************************************************************************/
+int
+bdd_shuffle_heap(bdd_manager *mgr, int *permut)
+{
+  int result;
+  result = Cudd_ShuffleHeap((DdManager *)mgr, permut);
+  return(result);
+
+} /* end of bdd_shuffle_heap */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs compose operation on  ADds]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_compose(
+  bdd_manager *mgr,
+  bdd_node *fn1,
+  bdd_node *fn2,
+  int var)
+{
+  DdNode *result;
+  result = Cudd_addCompose((DdManager *)mgr, (DdNode *)fn1,
+			   (DdNode *)fn2, var);
+  return(result);
+
+} /* end of bdd_add_compose */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Gets the ith add variable in the manager ]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_ith_var(bdd_manager *mgr, int i)
+{
+  DdNode *result;
+  result = Cudd_addIthVar((DdManager *)mgr, i);
+  return(result);
+
+} /* end of bdd_add_ith_var */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Gets the level of the ith variable in the manager ]
+
+  SideEffects        []
+
+******************************************************************************/
+int
+bdd_get_level_from_id(bdd_manager *mgr, int id)
+{
+  int level;
+  level = Cudd_ReadPerm((DdManager *)mgr, id);
+  return(level);
+
+} /* end of bdd_get_level_from_id */
+
+
+/**Function********************************************************************
+
+  Synopsis [Existentially abstracts out the variables from the function.
+  Here the fn is assumed to be a BDD function.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_exist_abstract(bdd_manager *mgr, bdd_node *fn, bdd_node *cube)
+{
+  DdNode *result;
+  result = Cudd_bddExistAbstract((DdManager *)mgr, (DdNode *)fn, 
+				 (DdNode *)cube);
+  return(result);
+
+} /* end of bdd_bdd_exist_abstract */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compares two ADDs for equality within tolerance. pr is verbosity
+  level.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_equal_sup_norm(
+  bdd_manager *mgr,
+  bdd_node *fn,
+  bdd_node *gn,
+  BDD_VALUE_TYPE tolerance,
+  int pr)
+{
+  int result;
+  result = Cudd_EqualSupNorm((DdManager *)mgr, (DdNode *)fn, 
+			     (DdNode *)gn, (CUDD_VALUE_TYPE)tolerance, pr);
+  return(result);
+
+} /* end of bdd_equal_sup_norm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Reads constant logic zero bdd_node.]
+
+
+  SideEffects [bdd_zero]
+
+******************************************************************************/
+bdd_node *
+bdd_read_logic_zero(bdd_manager *mgr)
+{
+  DdNode *result;
+  result = Cudd_ReadLogicZero((DdManager *)mgr);
+
+  return(result);
+
+} /* end of bdd_read_logic_zero */
+
+
+/**Function********************************************************************
+
+  Synopsis [Get the ith bdd node in the manager.]
+
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_ith_var(bdd_manager *mgr, int i)
+{
+  DdNode *result;
+  result = Cudd_bddIthVar((DdManager *)mgr, i);
+    
+  return(result);
+
+} /* end of bdd_bdd_ith_var */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Performs the divide operation on ADDs]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_divide(bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2)
+{
+  DdNode *result;
+  result = Cudd_addDivide((DdManager *)mgr, (DdNode **)fn1, (DdNode **)fn2);
+
+  return(result);
+
+} /* end of bdd_add_divide */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the constrain operation.]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_constrain(bdd_manager *mgr, bdd_node *f, bdd_node *c)
+{
+  DdNode *result;
+  result = Cudd_bddConstrain((DdManager *)mgr, (DdNode *)f, (DdNode *)c);
+
+  return(result);
+
+} /* end of bdd_bdd_constrain */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the restrict operation.]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_restrict(bdd_manager *mgr, bdd_node *f, bdd_node *c)
+{
+  DdNode *result;
+  result = Cudd_bddRestrict((DdManager *)mgr, (DdNode *)f, (DdNode *)c);
+
+  return(result);
+
+} /* end of bdd_bdd_restrict */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the hamming distance ADD between two sets of variables.]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_hamming(
+  bdd_manager *mgr,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  int nVars)
+{
+  DdNode *result;
+  result = Cudd_addHamming((DdManager *)mgr, (DdNode **)xVars,
+			   (DdNode **)yVars, nVars);
+
+  return(result);
+
+} /* end of bdd_add_hamming */
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs the ITE operation for ADDs.]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_ite(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *h)
+{
+  DdNode *result;
+  result = Cudd_addIte((DdManager *)mgr, (DdNode *)f, (DdNode *)g,
+		       (DdNode *)h);
+
+  return(result);
+
+} /* end of bdd_add_ite */
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds the maximum discriminant of f. Returns a pointer to a 
+  constant ADD.]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_find_max(bdd_manager *mgr, bdd_node *f)
+{
+  DdNode *result;
+  result = Cudd_addFindMax((DdManager *)mgr, (DdNode *)f);
+
+  return(result);
+
+} /* end of bdd_add_find_max */
+
+
+/**Function********************************************************************
+
+  Synopsis [Picks one on-set cube randomly from the given DD. The cube is 
+  written into an array of characters. The array must have at least as many
+  entries as there are variables. Returns 1 if successful; 0 otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_bdd_pick_one_cube(bdd_manager *mgr, bdd_node *node, char *string)
+{
+  return(Cudd_bddPickOneCube((DdManager *)mgr, (DdNode *)node, string));
+
+} /* end of bdd_bdd_pick_one_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swap two sets of variables in ADD f]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_add_swap_variables(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  bdd_node **y,
+  int n)
+{
+  DdNode *result;
+  result = Cudd_addSwapVariables((DdManager *)mgr, (DdNode *)f,
+				 (DdNode **)x, (DdNode **)y, n);
+
+  return(result);
+
+} /* end of bdd_add_swap_variables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the disjunction of two BDDs f and g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_or(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_bddOr((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+
+  return(result);
+
+} /* end of bdd_bdd_or */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the cube of an array of BDD variables.If
+  non-null, the phase argument indicates which literal of each
+  variable should appear in the cube. If phase\[i\] is nonzero, then
+  the positive literal is used. If phase is NULL, the cube is positive
+  unate.  Returns a pointer to the result if successful; NULL
+  otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_compute_cube(
+  bdd_manager *mgr,
+  bdd_node **vars,
+  int *phase,
+  int n)
+{
+  DdNode *result;
+  result = Cudd_bddComputeCube((DdManager *)mgr, (DdNode **)vars,
+			       phase, n);
+
+  return(result);
+
+} /* end of bdd_bdd_compute_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a cube of BDD variables from an array of indices.]
+
+  Description [Builds a cube of BDD variables from an array of indices.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [bdd_bdd_compute_cube]
+
+******************************************************************************/
+bdd_node *
+bdd_indices_to_cube(bdd_manager *mgr, int *idArray, int n)
+{
+  DdNode *result;
+  result = Cudd_IndicesToCube((DdManager *)mgr, idArray, n); 
+
+  return(result);
+
+} /* end of bdd_indices_to_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the conjunction of two BDDs f and g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_and(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_bddAnd((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+    
+  return(result);
+
+} /* end of bdd_bdd_and */
+
+
+/**Function********************************************************************
+
+  Synopsis [Multiply two matrices represented by A and B. A is assumed to
+  depend on x (rows) and z (columns). B is assumed to depend on z (rows)
+  and y (columns). The product depends on x and y. Only z needs to be 
+  explicitly identified.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_matrix_multiply(
+  bdd_manager *mgr,
+  bdd_node *A,
+  bdd_node *B,
+  bdd_node **z,
+  int nz)
+{
+  DdNode *result;
+  result = Cudd_addMatrixMultiply((DdManager *)mgr, (DdNode *)A,
+				  (DdNode *)B, (DdNode **)z, nz);
+
+  return(result);
+
+} /* end of bdd_add_matrix_multiply */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the cube of an array of ADD variables.  If
+  non-null, the phase argument indicates which literal of each
+  variable should appear in the cube. If phase\[i\] is nonzero, then the
+  positive literal is used. If phase is NULL, the cube is positive unate.
+  Returns a pointer to the result if successful; NULL otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_compute_cube(
+  bdd_manager *mgr,
+  bdd_node **vars,
+  int *phase,
+  int n)
+{
+  DdNode *result;
+  result = Cudd_addComputeCube((DdManager *)mgr, (DdNode **)vars, phase, n);
+				 
+  return(result);
+
+} /* end of bdd_add_compute_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the ADD for constant c.]
+
+  Description [Returns the ADD for constant c if successful. NULL otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_const(bdd_manager *mgr, BDD_VALUE_TYPE c)
+{
+  DdNode *result;
+  result = Cudd_addConst((DdManager *)mgr, (CUDD_VALUE_TYPE)c);
+
+  return(result);
+
+} /* end of bdd_add_const */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swaps two sets of variables of the same size (x and y) in
+  the BDD f.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_swap_variables(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  bdd_node **y,
+  int n)
+{
+  DdNode *result;
+  result = Cudd_bddSwapVariables((DdManager *)mgr, (DdNode *)f, 
+				 (DdNode **)x, (DdNode **)y, n);
+
+  return(result);
+
+} /* end of bdd_bdd_swap_variables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of minters in the on set of f which depends on
+  atmost n variables.]
+
+  SideEffects []
+
+******************************************************************************/
+double
+bdd_count_minterm(bdd_manager *mgr, bdd_node *f, int n)
+{
+  double result;
+  result = Cudd_CountMinterm((DdManager *)mgr, (DdNode *)f, n);
+
+  return(result);
+
+} /* end of bdd_count_minterm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts an ADD to a BDD by replacing all
+  discriminants greater than or equal to value with 1, and all other
+  discriminants with 0. Returns a pointer to the resulting BDD if
+  successful; NULL otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_bdd_threshold(
+  bdd_manager *mgr,
+  bdd_node *f,
+  BDD_VALUE_TYPE value)
+{
+  DdNode *result;
+  result = Cudd_addBddThreshold((DdManager *) mgr, (DdNode *) f,
+				(CUDD_VALUE_TYPE)value);
+    
+  return(result);
+
+} /* end of bdd_add_bdd_threshold */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts an ADD to a BDD by replacing all discriminants strictly
+  greater than value with 1, and all other discriminants with 0. Returns a
+  pointer to the resulting BDD if successful; NULL otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_bdd_strict_threshold(
+  bdd_manager *mgr,
+  bdd_node *f,
+  BDD_VALUE_TYPE value)
+{
+  DdNode *result;
+  result = Cudd_addBddStrictThreshold((DdManager *) mgr, (DdNode *) f,
+				      (CUDD_VALUE_TYPE)value);
+    
+  return(result);
+
+} /* end of bdd_add_bdd_strict_threshold */
+
+
+/**Function********************************************************************
+
+  Synopsis [Reads the epsilon parameter of the manager.]
+
+  SideEffects []
+
+******************************************************************************/
+BDD_VALUE_TYPE
+bdd_read_epsilon(bdd_manager *mgr)
+{
+  return((DdManager *)mgr)->epsilon;
+
+} /* end of bdd_read_epsilon */
+
+
+/**Function********************************************************************
+
+  Synopsis [Reads the constant 1 of the manager.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_read_one(bdd_manager *mgr)
+{
+  return(DD_ONE((DdManager *)mgr));
+
+} /* end of bdd_read_one */
+
+
+/**Function********************************************************************
+
+  Synopsis [Pick a random minterm from the onset of f.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_pick_one_minterm(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vars,
+  int n)
+{
+  DdNode *result;
+  result = Cudd_bddPickOneMinterm((DdManager *)mgr, (DdNode *)f,
+				  (DdNode **)vars, n);
+
+  return(result);
+
+} /* end of bdd_bdd_pick_one_minterm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Pick a random minterm from the onset of f.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+bdd_pick_one_minterm(bdd_t *f, array_t *varsArray /* of bdd_t * */)
+{
+  DdNode **vars, *minterm;
+  int i, n;
+
+  n = array_n(varsArray);
+  vars = ALLOC(DdNode *, n);
+  if (vars == NIL(DdNode *)) return NIL(bdd_t);
+  for (i = 0; i < n; i++) {
+    bdd_t *var = array_fetch(bdd_t *, varsArray, i);
+    assert(f->mgr == var->mgr);
+    vars[i] = var->node;
+  }
+  minterm = Cudd_bddPickOneMinterm(f->mgr, f->node, vars, n);
+  cuddRef(minterm);
+  FREE(vars);
+  if (minterm == NIL(DdNode)) return NIL(bdd_t);
+  return bdd_construct_bdd_t(f->mgr,minterm);
+
+} /* end of bdd_pick_one_minterm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Pick arbitrary number of minterms evenly distributed from the
+  onset of f.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+bdd_bdd_pick_arbitrary_minterms(
+  bdd_t *f,
+  array_t *varsArray,
+  int n,
+  int k)
+{
+  int i;
+  DdNode **minterms, **vars;
+  bdd_t *var;
+  array_t *resultArray;
+
+  vars = ALLOC(DdNode *, n);
+  if (vars == NULL)
+    return((array_t *)NULL);
+  for (i = 0; i < n; i++) {
+    var = array_fetch(bdd_t *, varsArray, i);
+    vars[i] = var->node;
+  }
+
+  minterms = (DdNode **)Cudd_bddPickArbitraryMinterms((DdManager *)f->mgr,
+						      (DdNode *)f->node, (DdNode **)vars, n, k);
+
+  resultArray = array_alloc(bdd_t *, k);
+  for (i = 0; i < k; i++) {
+    cuddRef(minterms[i]);
+    array_insert(bdd_t *, resultArray, i,
+		 bdd_construct_bdd_t(f->mgr,minterms[i]));
+  }
+
+  FREE(vars);
+  FREE(minterms);
+  return(resultArray);
+
+} /* end of bdd_bdd_pick_arbitrary_minterms */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts a subset from a BDD with mask variables.]
+
+  Description [Extracts a subset from a BDD in the following procedure.
+  1. Compute the weight for each mask variable by counting the number of
+     minterms for both positive and negative cofactors of the BDD with
+     respect to each mask variable. (weight = #positive - #negative)
+  2. Find a representative cube of the BDD by using the weight. From the
+     top variable of the BDD, for each variable, if the weight is greater
+     than 0.0, choose THEN branch, othereise ELSE branch, until meeting
+     the constant 1.
+  3. Quantify out the variables not in maskVars from the representative
+     cube and if a variable in maskVars is don't care, replace the
+     variable with a constant(1 or 0) depending on the weight.
+  4. Make a subset of the BDD by multiplying with the modified cube.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_t *
+bdd_subset_with_mask_vars(bdd_t *f, array_t *varsArray, array_t *maskVarsArray)
+{
+  int i;
+  DdNode *subset, **vars, **maskVars;
+  bdd_t *var;
+  int	n = array_n(varsArray);
+  int	m = array_n(maskVarsArray);
+
+  vars = ALLOC(DdNode *, n);
+  if (vars == NULL)
+    return((bdd_t *)NULL);
+  for (i = 0; i < n; i++) {
+    var = array_fetch(bdd_t *, varsArray, i);
+    vars[i] = var->node;
+  }
+
+  maskVars = ALLOC(DdNode *, m);
+  if (maskVars == NULL) {
+    FREE(vars);
+    return((bdd_t *)NULL);
+  }
+  for (i = 0; i < m; i++) {
+    var = array_fetch(bdd_t *, maskVarsArray, i);
+    maskVars[i] = var->node;
+  }
+
+  subset = (DdNode *)Cudd_SubsetWithMaskVars((DdManager *)f->mgr,
+					     (DdNode *)f->node, (DdNode **)vars, n, (DdNode **)maskVars, m);
+  if (subset == NULL) return((bdd_t *)NULL);
+
+  cuddRef(subset);
+  FREE(vars);
+  FREE(maskVars);
+
+  return(bdd_construct_bdd_t(f->mgr,subset));
+
+} /* end of bdd_subset_with_mask_vars */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read constant zero of the manager. This is different from the
+  logical zero which is the complement of logical one.]
+
+  SideEffects [bdd_zero]
+
+******************************************************************************/
+bdd_node *
+bdd_read_zero(bdd_manager *mgr)
+{
+  return(DD_ZERO((DdManager *)mgr));
+
+} /* bdd_read_zero */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a new BDD variable.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_new_var(bdd_manager *mgr)
+{
+  DdNode *result;
+  result = Cudd_bddNewVar((DdManager *)mgr);
+
+  return(result);
+
+} /* end of bdd_bdd_new_var */
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+  variables in cube.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_and_abstract(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node *g,
+  bdd_node *cube)
+{
+  DdNode *result;
+  result = Cudd_bddAndAbstract((DdManager *)mgr, (DdNode *)f,
+			       (DdNode *)g, (DdNode *)cube);
+  return(result);
+
+} /* end of bdd_bdd_and_abstract */
+
+
+/**Function********************************************************************
+
+  Synopsis [Decreases the reference count of node.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_deref(bdd_node *f)
+{
+  Cudd_Deref((DdNode *)f);
+
+} /* end of bdd_deref */
+
+
+/**Function********************************************************************
+
+  Synopsis [Integer and floating point addition.Returns NULL if not
+  a terminal case; f+g otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_plus(bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2)
+{
+  DdNode *result;
+  result = Cudd_addPlus((DdManager *)mgr, (DdNode **)fn1, (DdNode **)fn2);
+  return(result);
+
+} /* end of bdd_add_plus */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the number of times reordering has occurred.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_read_reorderings(bdd_manager *mgr)
+{
+  return(Cudd_ReadReorderings((DdManager *)mgr));
+
+} /* end of bdd_read_reorderings */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the threshold for the next dynamic reordering.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_read_next_reordering(bdd_manager *mgr)
+{
+  return(Cudd_ReadNextReordering((DdManager *)mgr));
+
+} /* end of bdd_read_next_reordering */
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the threshold for the next dynamic reordering.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_set_next_reordering(bdd_manager *mgr, int next)
+{
+  Cudd_SetNextReordering((DdManager *)mgr, next);
+
+} /* end of bdd_set_next_reordering */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the exclusive-nor of f and g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_xnor(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_bddXnor((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+
+  return(result);
+
+} /* end of bdd_bdd_xnor */
+
+
+/**Function********************************************************************
+
+  Synopsis [Composes a BDD with a vector of BDDs.Given a vector of
+  BDDs, creates a new BDD by substituting the BDDs for the variables
+  of the BDD f.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_vector_compose(bdd_manager *mgr, bdd_node *f, bdd_node **vector)
+{
+  DdNode *result;
+  result = Cudd_bddVectorCompose((DdManager *)mgr, (DdNode *)f,
+				 (DdNode **)vector);
+  return(result);
+
+} /* end of bdd_bdd_vector_compose */
+
+
+/**Function********************************************************************
+
+  Synopsis [Extracts a BDD node from the bdd_t structure without making
+  it regular.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_extract_node_as_is(bdd_t *fn)
+{
+  return((bdd_node *)fn->node);
+
+} /* end of bdd_extract_node_as_is */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a zdd node with index i and g and h as its children.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_get_node(
+  bdd_manager *mgr,
+  int id,
+  bdd_node *g,
+  bdd_node *h)
+{
+  DdNode *result;
+  result = cuddZddGetNode((DdManager *)mgr, id, (DdNode *)g,
+			  (DdNode *)h);
+
+  return(result);
+
+} /*end of bdd_zdd_get_node */ 
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the product of two cover represented by ZDDs. The covers
+  on which bdd_zdd_product operates use two ZDD variables for each
+  function variable (one ZDD variable for each literal of the variable). Those
+  two ZDD variables should be adjacent in the order.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_product(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_zddProduct((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+  return(result);
+
+} /* end of bdd_zdd_product */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the product of two cover represented by ZDDs. The covers
+  on which bdd_zdd_product_recur operates use two ZDD variables for each
+  function variable (one ZDD variable for each literal of the variable). Those
+  two ZDD variables should be adjacent in the order.  This is a recursive
+  procedure. It returns the ZDD of the product if successful. Reference count
+  of the result is not incremented. NULL is returned if re-ordering takes place
+  or if memory is exhausted.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_product_recur(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = cuddZddProduct((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+  return(result);
+
+} /* end of bdd_zdd_product_recur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the union of two ZDDs.]
+
+  Description [Computes the union of two ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_union(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_zddUnion((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+  return(result);
+
+} /* end of bdd_zdd_union */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the union of two ZDDs.]
+
+  Description [Computes the union of two ZDDs. Returns a pointer to the
+  result if successful; NULL otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_union_recur(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = cuddZddUnion((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+  return(result);
+
+} /* end of bdd_zdd_union_recur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Applies weak division to two ZDDs representing two covers. The
+  result of weak division depends on the variable order. The covers on which
+  bdd_zdd_weak_div operates use two ZDD variables for each function
+  variable (one ZDD variable for each literal of the variable). Those two ZDD
+  variables should be adjacent in the order.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_weak_div(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_zddWeakDiv((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+  return(result);
+
+} /* end of bdd_zdd_weak_div */
+
+
+/**Function********************************************************************
+
+  Synopsis [Applies weak division to two ZDDs representing two covers. The
+  result of weak division depends on the variable order. The covers on which
+  bdd_zdd_weak_div_recur operates use two ZDD variables for each function
+  variable (one ZDD variable for each literal of the variable). Those two ZDD
+  variables should be adjacent in the order. This is a recursive procedure. It
+  returns a pointer to the result if successful; Reference count of the result
+  is not incremented. NULL is returned if re-ordering takes place or if memory
+  is exhausted.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_weak_div_recur(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = cuddZddWeakDiv((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+
+  return(result);
+
+} /* end of bdd_zdd_weak_div_recur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes an irredundant sum of products (ISOP) in ZDD form from
+  BDDs. This is a recursive procedure. Returns the pointer to the ZDD on
+  success. Reference count of the result is not incremented. NULL in the case
+  of re-ordering or if memory is exhausted.]
+
+  SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on successful
+  return.]
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_isop_recur(
+  bdd_manager *mgr,
+  bdd_node *L,
+  bdd_node *U,
+  bdd_node **zdd_I)
+{
+  DdNode *result;
+  result = cuddZddIsop((DdManager *)mgr, (DdNode *)L, (DdNode *)U,
+		       (DdNode **)zdd_I);
+
+  return(result);
+
+} /* end of bdd_zdd_isop_recur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes an irredundant sum of products (ISOP) in ZDD form from
+  BDDs. This is an interface to an external function.]
+
+  SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on successful
+  return.]
+  
+  SeeAlso [bdd_zdd_isop_recur]
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_isop(
+  bdd_manager *mgr,
+  bdd_node *L,
+  bdd_node *U,
+  bdd_node **zdd_I)
+{
+  DdNode *result;
+  result = Cudd_zddIsop((DdManager *)mgr, (DdNode *)L, (DdNode *)U,
+			(DdNode **)zdd_I);
+
+  return(result);
+
+} /* end of bdd_zdd_isop */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the three-way decomposition of f w.r.t. v.]
+
+  Description [Computes the three-way decomposition of function f (represented
+  by a ZDD) w.r.t respect to variable v. Returns 1 on failure, 0 on
+  success. Reference counts of f1, f0 and fd are not incremented. ]
+
+  SideEffects [The results are returned in f1, f0, and fd. They are NULL in
+  case of failure.]
+
+******************************************************************************/
+int
+bdd_zdd_get_cofactors3(
+  bdd_manager *mgr,
+  bdd_node *f,
+  int v,
+  bdd_node **f1,
+  bdd_node **f0,
+  bdd_node **fd)
+{
+  int result;
+  result = cuddZddGetCofactors3((DdManager *)mgr, (DdNode *)f, v,
+				(DdNode **)f1, (DdNode **)f0,
+				(DdNode **)fd);
+
+  return(result);
+
+} /* end of bdd_zdd_get_cofactors3 */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive procedure to compute AND of two bdd_nodes.]
+
+  Description [Recursive procedure to compute AND of two bdd_nodes.  Returns
+  the pointer to the BDD on success. The reference count of the result is not
+  incremented. NULL is returned in case of reordering or if memory is
+  exhausted.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_and_recur(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = cuddBddAndRecur((DdManager *)mgr, (DdNode *)f,
+			   (DdNode *)g);
+  return(result);
+
+} /* end of bdd_bdd_and_recur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a bdd_node whose index is v and g and h as its
+  children.]
+
+  Description [Returns a bdd_node whose index is v and g and h as its
+  children. Returns the bdd_node after success. The reference count of the
+  returned BDD is not incremented. Returns NULL in case of reordering or if
+  memory is exhausted.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_node *
+bdd_unique_inter(
+  bdd_manager *mgr,
+  int v,
+  bdd_node *f,
+  bdd_node *g)
+{
+  DdNode *result;
+  result = cuddUniqueInter((DdManager *)mgr, v, (DdNode *)f,
+			   (DdNode *)g);
+  return(result);
+
+} /* end of bdd_unique_inter */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a bdd_node whose index is v and f and g as its
+  children.]
+
+  Description [Returns a bdd_node whose index is v and f and g as its
+  children. Returns the bdd_node after success. The reference count of the
+  returned BDD is not incremented. Returns NULL in case of reordering or if
+  memory is exhausted.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_node *
+bdd_unique_inter_ivo(
+  bdd_manager *mgr,
+  int v,
+  bdd_node *f,
+  bdd_node *g)
+{
+  DdNode *result;
+  DdNode *t;
+
+  t = cuddUniqueInter((DdManager *)mgr, v, (DdNode *)bdd_read_one(mgr),
+		      (DdNode *)bdd_not_bdd_node(bdd_read_one(mgr)));
+  if (t == NULL)
+    return(NULL);
+  Cudd_Ref(t);
+  result = cuddBddIteRecur((DdManager *)mgr, t, (DdNode *)f, (DdNode *)g);
+  Cudd_RecursiveDeref((DdManager *)mgr,(DdNode *)t);
+  return(result);
+
+} /* end of bdd_unique_inter_ivo */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set difference of two ZDDs.]
+
+  Description [Computes the set difference of two ZDDs. Returns a pointer to
+  the result if successful. The reference count of the result is not
+  incremented. NULL is returned in case of re-ordering of if memory is
+  exhausted.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_diff(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_zddDiff((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+  return(result);
+
+} /* end of bdd_zdd_diff */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set difference of two ZDDs.]
+
+  Description [Computes the set difference of two ZDDs. Returns a pointer to
+  the result if successful. The reference count of the result is not
+  incremented. NULL is returned in case of re-ordering of if memory is
+  exhausted.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_diff_recur(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = cuddZddDiff((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+  return(result);
+
+} /* end of bdd_zdd_diff_recur */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of ZDD variables.]
+
+  Description [Returns the number of ZDD variables.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_num_zdd_vars(bdd_manager *mgr)
+{
+  return(((DdManager *)mgr)->sizeZ);
+
+} /* end of bdd_num_zdd_vars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes the bdd_node a regular one.]
+
+  Description [Makes the bdd_node a retular one.]
+
+  SideEffects [none]
+
+******************************************************************************/
+bdd_node *
+bdd_regular(bdd_node *f)
+{
+  return(Cudd_Regular((DdNode *)f));
+
+} /* end of bdd_regular */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the bdd_node is a constant; 0 otherwise.]
+
+  Description [Returns 1 if the bdd_node is a constant; 0 otherwise.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_constant(bdd_node *f)
+{
+  return(Cudd_IsConstant((DdNode *)f));
+
+} /* end of bdd_is_constant */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the bdd_node is complemented. 0 otherwise.]
+
+  Description [Returns 1 if the bdd_node is complemented. 0 otherwise.]]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_complement(bdd_node *f)
+{
+  return(Cudd_IsComplement((DdNode *)f));
+
+} /* end of bdd_is_complement */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the then child of f.]
+
+  Description [Returns the then child of f. This is different from
+  bdd_then.]
+
+  SideEffects [none]
+
+  SeeAlso [bdd_then]
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_T(bdd_node *f)
+{
+  return(Cudd_T((DdNode *)f));
+
+} /* end of bdd_bdd_T */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the else child of f.]
+
+  Description [Returns the else child of f. This is different from
+  bdd_else.]
+
+  SideEffects []
+
+  SeeAlso [bdd_else]
+******************************************************************************/
+bdd_node *
+bdd_bdd_E(bdd_node *f)
+{
+  return(Cudd_E((DdNode *)f));
+
+} /* end of bdd_bdd_E */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the complement of a bdd_node.]
+
+  Description [Returns the complement of a bdd_node.]
+
+  SideEffects []
+
+  SeeAlso [bdd_not]
+******************************************************************************/
+bdd_node *
+bdd_not_bdd_node(bdd_node *f)
+{
+  return(Cudd_Not((DdNode *)f));
+
+} /* end of bdd_not_bdd_node */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively derefs a ZDD.]
+
+  Description [Recursively derefs a ZDD.]
+
+  SideEffects [bdd_recursive_deref]
+
+  
+******************************************************************************/
+void
+bdd_recursive_deref_zdd(bdd_manager *mgr, bdd_node *f)
+{
+  Cudd_RecursiveDerefZdd((DdManager *)mgr, (DdNode *)f);
+
+} /* end of bdd_recursive_deref_zdd */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Count the number of mintems of a ZDD.]
+
+  Description [Count the number of mintems of a ZDD.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_zdd_count(bdd_manager *mgr, bdd_node *f)
+{
+  return(Cudd_zddCount((DdManager *)mgr, (DdNode *)f));
+
+} /* end of bdd_zdd_count */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the level of a of a bdd_node with index, index.]
+
+  Description [Returns the level of a of a bdd_node with index, index.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_read_zdd_level(bdd_manager *mgr, int index)
+{
+  return(Cudd_ReadPermZdd((DdManager *)mgr, index));
+
+} /* end of bdd_read_zdd_level  */
+
+
+/**Function********************************************************************
+
+  Synopsis [Creates multiplicity number of ZDD vars for each BDD var.]
+
+  Description [Creates one or more ZDD variables for each BDD variable.  If
+  some ZDD variables already exist, only the missing variables are created.
+  Parameter multiplicity allows the caller to control how many variables are
+  created for each BDD variable in existence. For instance, if ZDDs are used to
+  represent covers, two ZDD variables are required for each BDD variable.  The
+  order of the BDD variables is transferred to the ZDD variables. If a variable
+  group tree exists for the BDD variables, a corresponding ZDD variable group
+  tree is created by expanding the BDD variable tree. In any case, the ZDD
+  variables derived from the same BDD variable are merged in a ZDD variable
+  group. If a ZDD variable group tree exists, it is freed. Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_zdd_vars_from_bdd_vars(bdd_manager *mgr, int multiplicity)
+{
+  return(Cudd_zddVarsFromBddVars((DdManager *)mgr, multiplicity));
+
+} /* end of bdd_zdd_vars_from_bdd_vars */
+
+
+/**Function********************************************************************
+
+  Synopsis [Enables the alignment of ZDD vars with that of corresponding BDD
+  vars.]
+
+  Description [Enables the alignment of ZDD vars with that of corresponding BDD
+  vars.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_zdd_realign_enable(bdd_manager *mgr)
+{
+  Cudd_zddRealignEnable((DdManager *)mgr);
+
+} /* end of bdd_zdd_realign_enable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Disables the alignment of ZDD vars with that of corresponding BDD
+  vars.]
+
+  Description [Disables the alignment of ZDD vars with that of corresponding BDD
+  vars.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_zdd_realign_disable(bdd_manager *mgr)
+{
+  Cudd_zddRealignDisable((DdManager *)mgr);
+
+} /* end of bdd_zdd_realign_disable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the value of the variable for the alignment of ZDD vars
+  with that of corresponding BDD vars.]
+
+  Description [Returns the value of the variable for the alignment of ZDD vars
+  with that of corresponding BDD vars.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_zdd_realignment_enabled(bdd_manager *mgr)
+{
+  return(Cudd_zddRealignmentEnabled((DdManager *)mgr));
+
+} /* end of bdd_zdd_realignment_enabled */
+
+
+/**Function********************************************************************
+
+  Synopsis [Enables the alignment of BDD vars with that of corresponding ZDD
+  vars.]
+
+  Description [Enables the alignment of BDD vars with that of corresponding ZDD
+  vars.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_realign_enable(bdd_manager *mgr)
+{
+  Cudd_bddRealignEnable((DdManager *)mgr);
+
+} /* end of bdd_realign_enable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Disables the alignment of BDD vars with that of corresponding ZDD
+  vars.]
+
+  Description [Disables the alignment of BDD vars with that of corresponding ZDD
+  vars.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_realign_disable(bdd_manager *mgr)
+{
+  Cudd_bddRealignDisable((DdManager *)mgr);
+
+} /* end of bdd_realign_disable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the value of the variable for the alignment of BDD vars
+  with that of corresponding ZDD vars.]
+
+  Description [Returns the value of the variable for the alignment of BDD vars
+  with that of corresponding ZDD vars.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_realignment_enabled(bdd_manager *mgr)
+{
+  return(Cudd_bddRealignmentEnabled((DdManager *)mgr));
+
+} /* end of bdd_realignment_enabled */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of bdd_node f.]
+
+  Description [Returns the index of bdd_node f.]
+
+  SideEffects []
+
+  SeeAlso     [bdd_top_var_id]
+
+******************************************************************************/
+int
+bdd_node_read_index(bdd_node *f)
+{
+  return(Cudd_NodeReadIndex((DdNode *)f));
+
+} /* end of bdd_node_read_index */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the next field of a DdNode.]
+
+  Description [Reads the next field of a DdNode.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_read_next(bdd_node *f)
+{
+  return(((DdNode *)f)->next);
+
+} /* end of bdd_read_next */
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the next field of a DdNode. This function should NOT be used
+  by an external user. This is provided here as a patch.  This will not be a
+  part of any further release.]
+
+  Description [Sets the next field of a DdNode. This function should NOT be
+  used by an external user. This is provided here as a patch.  This will not be
+  a part of any further release.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_set_next(bdd_node *f, bdd_node *g)
+{
+  ((DdNode *)f)->next = (DdNode *)g;
+
+} /* end of bdd_set_next */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the reordered field of the manager.]
+
+  Description [Read the reordered field of the manager.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_read_reordered_field(bdd_manager *mgr)
+{
+  return(((DdManager *)mgr)->reordered);
+
+} /* end of bdd_read_reordered_field */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set the reordered field of the manager.This is NOT to be
+  used by an external user. This function will not be a part of future
+  release.]
+
+  Description [Set the reordered field of the manager.This is NOT to be
+  used by an external user. This function will not be a part of future
+  release.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_set_reordered_field(bdd_manager *mgr, int n)
+{
+  ((DdManager *)mgr)->reordered = n;
+
+} /* end of bdd_set_reordered_field */
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the recursive call of bdd_add_apply.]
+
+  Description [Implements the recursive call of bdd_add_apply. This should be
+  used only in recursive procedures where the order of the variables needs to
+  remain constant during the entire operation of the procedure. Returns a
+  pointer to the result if successful. NULL is returned if reordering takes
+  place or if memory is exhausted.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_apply_recur(
+  bdd_manager *mgr,
+  bdd_node *(*operation)(bdd_manager *, bdd_node **, bdd_node **),
+  bdd_node *fn1,
+  bdd_node *fn2)
+{
+  DdNode *result;
+  result = cuddAddApplyRecur((DdManager *)mgr,
+			     (DdNode *(*)(DdManager *, DdNode **, DdNode **))
+			     operation, (DdNode *)fn1, (DdNode *)fn2);
+  return(result);
+
+} /* end of bdd_add_apply_recur */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the value of the ADD node.]
+
+  Description [Returns the value of the ADD node.]
+
+  SideEffects []
+
+******************************************************************************/
+BDD_VALUE_TYPE
+bdd_add_value(bdd_node *f)
+{
+  return(Cudd_V((DdNode *)f));
+
+} /* end of bdd_add_value */
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints minterms of the bdd.]
+
+  Description [.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_print_minterm(bdd_t *f)
+{
+  int result;
+  result = Cudd_PrintMinterm((DdManager *)f->mgr, (DdNode *)f->node);
+  return result;
+
+} /* end of bdd_print_minterm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Reads the plus inifinity field of the BDD manager.]
+
+  Description [Reads the plus inifinity field of the BDD manager.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_read_plus_infinity(bdd_manager *mgr)
+{
+  DdNode *result;
+  result = Cudd_ReadPlusInfinity((DdManager *)mgr);
+  return (bdd_node *)result;
+
+} /* end of bdd_read_plus_infinity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Selects pairs from R using a priority function.]
+
+  Description [Selects pairs from a relation R(x,y) (given as a BDD)
+  in such a way that a given x appears in one pair only. Uses a
+  priority function to determine which y should be paired to a given
+  x.  bdd_priority_select returns a pointer to the selected function
+  if successful; NULL otherwise. Three of the arguments--x, y, and
+  z--are vectors of BDD variables. The first two are the variables on
+  which R depends. The third is a vector of auxiliary variables, used
+  during the computation. This vector is optional. If a NULL value is
+  passed instead, bdd_priority_select will create the working
+  variables on the fly.  The sizes of x and y (and z if it is not
+  NULL) should equal n.  The priority function Pi can be passed as a
+  BDD, or can be built by Cudd_PrioritySelect. If NULL is passed
+  instead of a bdd_node *, parameter Pifunc is used by
+  Cudd_PrioritySelect to build a BDD for the priority
+  function. (Pifunc is a pointer to a C function.) If Pi is not NULL,
+  then Pifunc is ignored. Pifunc should have the same interface as the
+  standard priority functions (e.g., bdd_dxygtdxz).]
+
+  SideEffects [If called with z == NULL, will create new variables in
+  the manager.]
+
+  SeeAlso     [bdd_dxygtdxz bdd_xgty]
+
+******************************************************************************/
+bdd_node *
+bdd_priority_select(
+  bdd_manager *mgr,
+  bdd_node *R,
+  bdd_node **x,
+  bdd_node **y,
+  bdd_node **z,
+  bdd_node *Pi,
+  int n,
+  bdd_node  *(*Pifunc)(bdd_manager *, int, bdd_node **, bdd_node **, bdd_node **))
+{
+  DdNode *result;
+  result = Cudd_PrioritySelect((DdManager *)mgr,(DdNode *)R,
+			       (DdNode **)x,(DdNode **)y,
+			       (DdNode **)z,(DdNode *)Pi,
+			       n,(DdNode *(*)(DdManager *, int, DdNode **,
+					      DdNode **, DdNode **))Pifunc);
+  return (bdd_node *)result;
+
+} /* end of bdd_priority_select */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set the background value of BDD manager.]
+
+  Description [Set the background value of BDD manager.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+bdd_set_background(bdd_manager *mgr, bdd_node *f)
+{
+  Cudd_SetBackground((DdManager *)mgr,(DdNode *)f);
+ 
+} /* end of bdd_set_background */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the background value of BDD manager.]
+
+  Description [Read the background value of BDD manager.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_read_background(bdd_manager *mgr)
+{
+  DdNode *result;
+  result = Cudd_ReadBackground((DdManager *)mgr);
+  return (bdd_node *)result;
+
+} /* end of bdd_read_background */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the cofactor of f w.r.t g]
+
+  Description [Returns the cofactor of f w.r.t g]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_cofactor(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_Cofactor((DdManager *)mgr,(DdNode *)f,
+			 (DdNode *)g);
+  return (bdd_node *)result;
+
+} /* end of bdd_bdd_cofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the ITE of f,g and h]
+
+  Description [Returns the ITE of f,g and h]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_ite(bdd_manager *mgr, bdd_node *f, bdd_node *g, bdd_node *h)
+{
+  DdNode *result;
+  result = Cudd_bddIte((DdManager *)mgr,(DdNode *)f,
+		       (DdNode *)g,(DdNode *)h);
+  return (bdd_node *)result;
+
+} /* end of bdd_bdd_ite */
+
+
+/**Function********************************************************************
+
+  Synopsis [Integer and floating point subtraction.Returns NULL if not a
+  terminal case; f-g otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_minus(bdd_manager *mgr, bdd_node **fn1, bdd_node **fn2)
+{
+  DdNode *result;
+  result = Cudd_addMinus((DdManager *)mgr, (DdNode **)fn1, (DdNode **)fn2);
+  return((bdd_node *)result);
+
+} /* end of bdd_add_plus */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function d(x,y) &gt; d(x,z).]
+
+  Description [This function generates a BDD for the function d(x,y)
+  &gt; d(x,z);
+  x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\],
+  y\[0\] y\[1\] ...  y\[N-1\], and z\[0\] z\[1\] ...  z\[N-1\],
+  with 0 the most significant bit.
+  The distance d(x,y) is defined as:
+	\sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).
+  The BDD is built bottom-up.
+  It has 7*N-3 internal nodes, if the variables are ordered as follows: 
+  x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ]
+
+  SideEffects [None]
+
+  SeeAlso     [bdd_xgty]
+
+******************************************************************************/
+bdd_node *
+bdd_dxygtdxz(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y,
+  bdd_node **z)
+{
+  DdNode *result;
+  result = Cudd_Dxygtdxz((DdManager *)mgr,N,(DdNode **)x,
+			 (DdNode **)y,(DdNode **)z);
+  return((bdd_node *)result);
+
+} /* end of bdd_dxygtdxz */
+
+
+/**Function********************************************************************
+
+  Synopsis [Universally abstracts out the variables from the function]
+
+  SideEffects        []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_univ_abstract(bdd_manager *mgr, bdd_node *fn, bdd_node *vars)
+{
+  DdNode *result;
+  result = Cudd_bddUnivAbstract((DdManager *)mgr, (DdNode *)fn,
+				(DdNode *)vars);
+  return((bdd_node *)result);
+
+} /* end of bdd_bdd_univ_abstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the compatible projection of R w.r.t. cube Y.]
+
+  Description [Computes the compatible projection of relation R with
+  respect to cube Y.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_cprojection(bdd_manager *mgr, bdd_node *R, bdd_node *Y)
+{
+  DdNode *result;
+  result = Cudd_CProjection((DdManager *)mgr,(DdNode *)R,
+			    (DdNode *)Y);
+  return (bdd_node *)result;
+
+} /* end of bdd_bdd_cprojection */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the correlation of f and g.]
+
+  Description [Computes the correlation of f and g. If f == g, their
+  correlation is 1. If f == g', their correlation is 0.  Returns the
+  fraction of minterms in the ON-set of the EXNOR of f and g.]
+
+  SideEffects [None]
+
+******************************************************************************/
+double
+bdd_correlation(bdd_t *f, bdd_t *g)
+{
+  double result ;
+  assert(f->mgr == g->mgr);
+  result = Cudd_bddCorrelation(f->mgr, f->node, g->node);
+  return (result);
+
+} /* end of bdd_correlation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes 2 partitions of a function.]
+
+  Description [Computes 2 partitions of a function. Method based on
+  DAC98 - Ravi, Somenzi. Picks decomposition points and replaces one
+  child in each conjunct with 1 (0). returns 2 conjuncts(disjuncts).]
+  
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_gen_decomp(bdd_t *f, bdd_partition_type_t partType, bdd_t ***conjArray)
+{
+  DdNode **ddArray = NULL;
+  int i, num = 0;
+  bdd_t *result;
+  
+  switch (partType) {
+  case BDD_CONJUNCTS:
+    num = Cudd_bddGenConjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  case BDD_DISJUNCTS:
+    num = Cudd_bddGenDisjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  }
+  if ((ddArray == NULL) || (!num)) {
+    return 0;
+  }
+  
+  *conjArray = ALLOC(bdd_t *, num);
+  if ((*conjArray) == NULL) goto outOfMem;
+  for (i = 0; i < num; i++) {
+    result = ALLOC(bdd_t, 1);
+    if (result == NULL) {
+      FREE(*conjArray);
+      goto outOfMem;
+    }
+    result->mgr = f->mgr;
+    result->node = ddArray[i];
+    result->free = FALSE;
+    (*conjArray)[i] = result;
+  }
+  FREE(ddArray);
+  return (num);
+
+ outOfMem:
+  for (i = 0; i < num; i++) {
+    Cudd_RecursiveDeref((DdManager *)f->mgr,(DdNode *)ddArray[i]);
+  }
+  FREE(ddArray);
+  return(0);
+
+} /* end of bdd_gen_decomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes 2 partitions of a function.]
+
+  Description [Computes 2 partitions of a function. Method based on
+  Cabodi 94. Picks a var and replaces one child in each conjunct with
+  1 (0). returns 2 conjuncts(disjuncts).]
+  
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_var_decomp(bdd_t *f, bdd_partition_type_t partType, bdd_t ***conjArray)
+{
+  DdNode **ddArray = NULL;
+  int i, num = 0;
+  bdd_t *result;
+
+  switch (partType) {
+  case BDD_CONJUNCTS:
+    num = Cudd_bddVarConjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  case BDD_DISJUNCTS:
+    num = Cudd_bddVarDisjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  }
+  if ((ddArray == NULL) || (!num)) {
+    return 0;
+  }
+  
+  *conjArray = ALLOC(bdd_t *, num);
+  if ((*conjArray) == NULL) goto outOfMem;
+  for (i = 0; i < num; i++) {
+    result = ALLOC(bdd_t, 1);
+    if (result == NULL) {
+      FREE(*conjArray);
+      goto outOfMem;
+    }
+    result->mgr = f->mgr;
+    result->node = (ddArray)[i];
+    result->free = FALSE;
+    (*conjArray)[i] = result;
+  }
+  FREE(ddArray);
+  return (num);
+
+ outOfMem:
+  for (i = 0; i < num; i++) {
+    Cudd_RecursiveDeref((DdManager *)f->mgr,(DdNode *)ddArray[i]);
+  }
+  FREE(ddArray);
+  return(0);
+
+} /* end of bdd_var_decomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes 2 partitions of a function.]
+
+  Description [Computes 2 partitions of a function.  Picks a subset of
+  a function and minimizes the rest of the function w.r.t. the subset.
+  returns 2 conjuncts(disjuncts).]
+  
+  SideEffects []
+
+******************************************************************************/
+int 
+bdd_approx_decomp(bdd_t *f, bdd_partition_type_t partType, bdd_t ***conjArray)
+{
+  DdNode **ddArray = NULL;
+  int i, num = 0;
+  bdd_t *result;
+
+  switch (partType) {
+  case BDD_CONJUNCTS:
+    num = Cudd_bddApproxConjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  case BDD_DISJUNCTS:
+    num = Cudd_bddApproxDisjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  }
+  if ((ddArray == NULL) || (!num)) {
+    return 0;
+  }
+  
+  *conjArray = ALLOC(bdd_t *, num);
+  if ((*conjArray) == NULL) goto outOfMem;
+  for (i = 0; i < num; i++) {
+    result = ALLOC(bdd_t, 1);
+    if (result == NULL) {
+      FREE(*conjArray);
+      goto outOfMem;
+    }
+    result->mgr = f->mgr;
+    result->node = ddArray[i];
+    result->free = FALSE;
+    (*conjArray)[i] = result;
+  }
+  FREE(ddArray);
+  return (num);
+
+ outOfMem:
+  for (i = 0; i < num; i++) {
+    Cudd_RecursiveDeref((DdManager *)f->mgr,(DdNode *)ddArray[i]);
+  }
+  FREE(ddArray);
+  return(0);
+
+} /* end of bdd_approx_decomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes 2 partitions of a function.]
+
+  Description [Computes 2 partitions of a function.  Picks a subset of
+  a function and minimizes the rest of the function w.r.t. the
+  subset. Performs this iteratively.  returns 2 conjuncts(disjuncts).]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_iter_decomp(bdd_t *f, bdd_partition_type_t partType, bdd_t ***conjArray)
+{
+  DdNode **ddArray;
+  int i, num = 0;
+  bdd_t *result;
+
+  switch (partType) {
+  case BDD_CONJUNCTS:
+    num = Cudd_bddIterConjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  case BDD_DISJUNCTS:
+    num = Cudd_bddIterDisjDecomp(f->mgr, f->node, &ddArray);
+    break;
+  }
+  if ((ddArray == NULL) || (!num)) {
+    return 0;
+  }
+  
+  *conjArray = ALLOC(bdd_t *, num);
+  if ((*conjArray) == NULL) goto outOfMem;
+  for (i = 0; i < num; i++) {
+    result = ALLOC(bdd_t, 1);
+    if (result == NULL) {
+      FREE(*conjArray);
+      goto outOfMem;
+    }
+    result->mgr = f->mgr;
+    result->node = ddArray[i];
+    result->free = FALSE;
+    (*conjArray)[i] = result;
+  }
+  FREE(ddArray);
+  return (num);
+
+ outOfMem:
+  for (i = 0; i < num; i++) {
+    Cudd_RecursiveDeref((DdManager *)f->mgr,(DdNode *)ddArray[i]);
+  }
+  FREE(ddArray);
+  return(0);
+  
+} /* end of bdd_iter_decomp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reports the number of nodes in the manager.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_read_node_count(bdd_manager *mgr)
+{
+  return(Cudd_ReadNodeCount((DdManager *)mgr));
+
+} /* end of bdd_read_node_count */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the fraction of minterms in the on-set of all the
+  positive cofactors of a BDD, called signatures.]
+
+  SideEffects [Creates an array of doubles as large as the number of
+  variables in the manager + 1. The extra position is to the fraction
+  of minterms in the on-set of the function.]
+
+******************************************************************************/
+double *
+bdd_cof_minterm(bdd_t *f)
+{
+  double *signatures;
+  signatures = Cudd_CofMinterm((DdManager *)f->mgr, (DdNode *)f->node);
+  return (signatures);
+
+} /* end of bdd_cof_minterm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Estimates the size of the cofactor of f with respect to
+  var in the specified phase. Return the number of nodes in the
+  estimated size.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_estimate_cofactor(bdd_t *f, bdd_t *var, int phase)
+{
+  return (Cudd_EstimateCofactor((DdManager *)f->mgr, (DdNode *)f->node,
+				(int)bdd_top_var_id(var), phase));
+
+} /* end of bdd_estimate_cofactor */
+
+
+/**Function********************************************************************
+
+  Synopsis [Tests if the varid is unate in f in the specified
+  phase. If yes, return 1, else 0.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_test_unate(bdd_t *f, int varId, int phase)
+{
+  DdNode *result;
+  DdNode *one = DD_ONE((DdManager *)f->mgr);
+
+  if (phase) {
+    result = Cudd_Increasing((DdManager *)f->mgr, (DdNode *)f->node, varId);
+  } else {
+    result = Cudd_Decreasing((DdManager *)f->mgr, (DdNode *)f->node, varId);
+  }
+
+  if (result == one) {
+    return 1;
+  } else {
+    return 0;
+  }
+    
+} /* end of bdd_test_unate */
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds the essential variable in a bdd f. Returns an
+  array_t of vars which are the projection variables.]
+
+  SideEffects [Creates an array_t of bdd_t. Freed by the caller ]
+
+******************************************************************************/
+array_t *
+bdd_find_essential(bdd_t *f)
+{
+  DdNode *C, *result, *scan, *cube;
+  array_t *varArray = NIL(array_t);
+  bdd_t *var;
+    
+  result = Cudd_FindEssential((DdManager *)f->mgr, (DdNode *)f->node);
+  if (result == NULL) return NULL;
+  cuddRef(result);
+    
+  cube = result;
+  C = Cudd_Regular(cube);
+  varArray = array_alloc(bdd_t *, 0);
+  if (!cuddIsConstant(C)) {
+    while (!cuddIsConstant(C)) {
+      var = bdd_var_with_index(f->mgr, C->index);
+      array_insert_last(bdd_t *, varArray, var);
+      scan = cuddT(C);
+      if (cuddIsConstant(scan)) scan = cuddE(C);
+      cube = Cudd_NotCond(scan, Cudd_IsComplement(cube));
+      C = Cudd_Regular(cube);
+    }
+  }
+
+  Cudd_RecursiveDeref((DdManager *)f->mgr,result);
+  return varArray;
+
+} /* end of bdd_find_essential */
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds the essential variables in a bdd f. Returns a cube
+  of the variables.]
+
+  SideEffects [ ]
+
+******************************************************************************/
+bdd_t *
+bdd_find_essential_cube(bdd_t *f)
+{
+  DdNode *cube;
+  bdd_t *result;
+    
+  cube = Cudd_FindEssential((DdManager *)f->mgr, (DdNode *)f->node);
+  if (cube == NULL) return NULL;
+  cuddRef(cube);
+  result = bdd_construct_bdd_t(f->mgr,cube);
+
+  return(result);
+
+} /* end of bdd_find_essential_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generates a BDD for the function x==y.]]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_xeqy(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y)
+{
+  DdNode *result;
+  result = Cudd_Xeqy((DdManager *)mgr,N,(DdNode **)x,
+		     (DdNode **)y);
+  return((bdd_node *)result);
+
+} /* end of bdd_xeqy */
+
+
+/**Function********************************************************************
+
+  Synopsis [Rounds off the discriminants of an ADD.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_roundoff(bdd_manager *mgr, bdd_node *f, int N)
+{
+  DdNode *result;
+  result = Cudd_addRoundOff((DdManager *)mgr,(DdNode *)f,N);
+  return((bdd_node *)result);
+
+} /* end of bdd_add_roundoff */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a BDD for the function x &gt; y.]
+
+  Description [This function generates a BDD for the function x &gt; y.
+  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
+  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
+  The BDD is built bottom-up.
+  It has 3*N-1 internal nodes, if the variables are ordered as follows: 
+  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].]
+
+  SideEffects [None]
+
+  SeeAlso     [bdd_dxygtdxz]
+
+******************************************************************************/
+bdd_node *
+bdd_xgty(
+  bdd_manager *mgr,
+  int N,
+  bdd_node **x,
+  bdd_node **y)
+{
+  DdNode *result;
+  result = Cudd_Xgty((DdManager *)mgr,N, NIL(DdNode *),
+		     (DdNode **)x, (DdNode **)y);
+  return((bdd_node *)result);
+
+} /* end of bdd_xgty */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the complement of an ADD a la C language.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_cmpl(bdd_manager *mgr, bdd_node *f)
+{
+  DdNode *result;
+  result = Cudd_addCmpl((DdManager *)mgr,(DdNode *)f);
+  return((bdd_node *)result);
+
+} /* end of bdd_add_cmpl */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns m minterms from a BDD.]
+
+  Description [Returns <code>m</code> minterms from a BDD whose
+  support has <code>n</code> variables at most.  The procedure tries
+  to create as few extra nodes as possible. The function represented
+  by <code>f</code> depends on at most <code>n</code> of the variables
+  in <code>x</code>. Returns a BDD with <code>m</code> minterms of the
+  on-set of f if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node *
+bdd_split_set(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **x,
+  int n,
+  double m)
+{
+  DdNode *result;
+  result = Cudd_SplitSet((DdManager *)mgr,(DdNode *)f,
+			 (DdNode **)x, n, m);
+  return((bdd_node *)result);
+
+} /* end of bdd_split_set */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for inconsistencies in the BDD manager.]
+
+  Description [Checks for inconsistencies in the BDD manager.]
+
+  SideEffects [None]
+
+  SeeAlso [Cudd_DebugCheck]
+
+******************************************************************************/
+int
+bdd_debug_check(bdd_manager *mgr)
+{
+  return Cudd_DebugCheck((DdManager *)mgr);
+
+} /* end of bdd_debug_check */
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints the minterns of f in the file stream fp. Precision
+  can be specified in the last argument. Result is 1 if printing is
+  successful, else 0.]
+
+  SideEffects []
+
+******************************************************************************/
+int 
+bdd_print_apa_minterm(
+  FILE *fp,
+  bdd_t *f,
+  int nvars,
+  int precision)
+{
+  int result;
+  result = Cudd_ApaPrintMintermExp(fp, (DdManager *)f->mgr,(DdNode *)f->node, nvars, precision);
+  return(result);
+
+} /* end of bdd_print_apa_minterm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compares the ratios of the minterms of 2 bdds and two numbers.
+  The ratio compared is  ((Min(f1)/f1Num)/(Min(f2)/f2Num)). The procedure
+  returns 1 if the ratio is greater than 1, 0 if they are equal and -1 if the
+  ratio is less than 1. ]
+
+  SideEffects []
+
+******************************************************************************/
+int 
+bdd_apa_compare_ratios(
+  int nvars,
+  bdd_t *f1,
+  bdd_t *f2,
+  int f1Num,
+  int f2Num)
+{
+  int result;
+  DdApaNumber f1Min, f2Min;
+  int digits1, digits2;
+
+  f1Min = Cudd_ApaCountMinterm((DdManager *)f1->mgr, (DdNode *)f1->node, nvars, &digits1);
+  f2Min = Cudd_ApaCountMinterm((DdManager *)f2->mgr, (DdNode *)f2->node, nvars, &digits2);
+    
+  result = Cudd_ApaCompareRatios(digits1, f1Min, f1Num, digits2, f2Min, f2Num);
+  return(result);
+
+} /* end of bdd_apa_compare_ratios */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the exclusive-or of f and g.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_xor(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  DdNode *result;
+  result = Cudd_bddXor((DdManager *)mgr, (DdNode *)f, (DdNode *)g);
+
+  return(result);
+
+} /* end of bdd_bdd_xor */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generates a blif file by dumpping BDDs. nBdds is the number
+  of BDDs, bdds is the array of BDDs, inames is the array of primary
+  input variable names, onames is the array of variable names of BDDs,
+  and model is a model name in BLIF. inames, onames and model can be
+  NULL.]
+
+  SideEffects []
+
+******************************************************************************/
+void 
+bdd_dump_blif(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  char *model,
+  FILE *fp)
+{
+  Cudd_DumpBlif((DdManager *)mgr, nBdds, (DdNode **)bdds, inames, onames,
+		model, fp);
+
+} /* end of bdd_dump_blif */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generates a blif body by dumpping BDDs. nBdds is the number
+  of BDDs, bdds is the array of BDDs, inames is the array of primary
+  input variable names, onames is the array of variable names of BDDs,
+  and inames, onames and model can be NULL. This function prints out
+  only .names body.]
+
+  SideEffects []
+
+******************************************************************************/
+void 
+bdd_dump_blif_body(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  FILE *fp)
+{
+  Cudd_DumpBlifBody((DdManager *)mgr, nBdds, (DdNode **)bdds, inames, onames,
+		    fp);
+
+} /* end of bdd_dump_blif_body */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generates a dot file by dumpping BDDs. nBdds is the number
+  of BDDs, bdds is the array of BDDs, inames is the array of primary
+  input variable names, and onames is the array of variable names of BDDs.
+  inames, onames and model can be NULL.]
+
+  SideEffects []
+
+******************************************************************************/
+void 
+bdd_dump_dot(
+  bdd_manager *mgr,
+  int nBdds,
+  bdd_node **bdds,
+  char **inames,
+  char **onames,
+  FILE *fp)
+{
+  Cudd_DumpDot((DdManager *)mgr, nBdds, (DdNode **)bdds, inames, onames, fp);
+
+} /* end of bdd_dump_dot */
+
+
+/**Function********************************************************************
+
+  Synopsis [Converts a ZDD cover to a BDD graph.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_make_bdd_from_zdd_cover(bdd_manager *mgr, bdd_node *node)
+{
+  return((bdd_node *)Cudd_MakeBddFromZddCover((DdManager *)mgr, (DdNode *)node));
+
+} /* end of bdd_make_bdd_from_zdd_cover */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the complement of a ZDD cover.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_zdd_complement(bdd_manager *mgr, bdd_node *node)
+{
+  return((bdd_node *)Cudd_zddComplement((DdManager *)mgr, (DdNode *)node));
+
+} /* end of bdd_zdd_complement */
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds the variables on which a set of DDs depends.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_vector_support(bdd_manager *mgr, bdd_node **F, int n)
+{
+  return((bdd_node *)Cudd_VectorSupport((DdManager *)mgr,(DdNode **)F,n));
+
+} /* end of bdd_bdd_vector_support */
+
+
+/**Function********************************************************************
+
+  Synopsis [Count the variables on which a set of DDs depend.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_bdd_vector_support_size(bdd_manager *mgr, bdd_node **F, int n)
+{
+  return(Cudd_VectorSupportSize((DdManager *)mgr,(DdNode **)F,n));
+
+} /* end of bdd_bdd_vector_support_size */
+
+
+/**Function********************************************************************
+
+  Synopsis [Count the variables on which a DD depends.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_bdd_support_size(bdd_manager *mgr, bdd_node *F)
+{
+  return(Cudd_SupportSize((DdManager *)mgr,(DdNode *)F));
+
+} /* end of bdd_bdd_support_size */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the BDD of the variables on which F depends.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_support(bdd_manager *mgr, bdd_node *F)
+{
+  return((bdd_node *)Cudd_Support((DdManager *)mgr,(DdNode *)F));
+
+} /* end of bdd_bdd_support */
+
+
+/**Function********************************************************************
+
+  Synopsis [Composes an ADD with a vector of ADDs.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_add_general_vector_compose(
+  bdd_manager *mgr,
+  bdd_node *f,
+  bdd_node **vectorOn,
+  bdd_node **vectorOff)
+{
+  return((bdd_node *)Cudd_addGeneralVectorCompose((DdManager *)mgr,
+						  (DdNode *)f,
+						  (DdNode **)vectorOn,
+						  (DdNode **)vectorOff));
+
+} /* end of bdd_add_general_vector_compose */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the boolean difference of f w.r.t to variable x.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_node *
+bdd_bdd_boolean_diff(bdd_manager *mgr, bdd_node *f, int x)
+{
+  return ((bdd_node *)Cudd_bddBooleanDiff((DdManager *)mgr,(DdNode *)f,x));
+
+} /* end of bdd_bdd_boolean_diff */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check whether two BDDs intersect.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_bdd_leq(bdd_manager *mgr, bdd_node *f, bdd_node *g)
+{
+  return Cudd_bddLeq((DdManager *)mgr,(DdNode *)f,(DdNode *)g);
+
+} /* end of bdd_bdd_leq */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether two bdds are same.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_ptrcmp(bdd_t *f, bdd_t *g)
+{
+  if (f->node == g->node)
+    return(0);
+  else
+    return(1);
+
+} /* end of bdd_ptrcmp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash value of a bdd.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_ptrhash(bdd_t *f, int size)
+{
+  int hash;
+
+  hash = (int)((unsigned long)f->node >> 2) % size;
+  return(hash);
+
+} /* end of bdd_ptrhash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the peak memory in use.]
+
+  SideEffects []
+
+******************************************************************************/
+long
+bdd_read_peak_memory(bdd_manager *mgr)
+{
+  return((long) Cudd_ReadMemoryInUse((DdManager *) mgr));
+
+} /* end of bdd_read_peak_memory */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the peak live node count.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bdd_read_peak_live_node(bdd_manager *mgr)
+{
+  return(Cudd_ReadPeakLiveNodeCount((DdManager *) mgr));
+
+} /* end of bdd_read_peak_live_node */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to primary input.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_set_pi_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddSetPiVar((DdManager *) mgr, index);
+
+} /* bdd_set_pi_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to present state.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_set_ps_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddSetPsVar((DdManager *) mgr, index);
+
+} /* end of bdd_set_ps_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable type to next state.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_set_ns_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddSetNsVar((DdManager *) mgr, index);
+
+} /* end of bdd_set_ns_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is primary input.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_pi_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddIsPiVar((DdManager *) mgr, index);
+
+} /* end of bdd_is_pi_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is present state.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_ps_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddIsPsVar((DdManager *) mgr, index);
+
+} /* end of bdd_is_ps_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is next state.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_ns_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddIsNsVar((DdManager *) mgr, index);
+
+} /* end of bdd_is_ns_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a corresponding pair index for a given index.]
+
+  Description [Sets a corresponding pair index for a given index.
+  These pair indices are present and next state variable.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_set_pair_index(bdd_manager *mgr, int index, int pairidx)
+{
+  return Cudd_bddSetPairIndex((DdManager *) mgr, index, pairidx);
+
+} /* end of bdd_set_pair_index */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads a corresponding pair index for a given index.]
+
+  Description [Reads a corresponding pair index for a given index.
+  These pair indices are present and next state variable.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_read_pair_index(bdd_manager *mgr, int index)
+{
+  return Cudd_bddReadPairIndex((DdManager *) mgr, index);
+
+} /* end of bdd_read_pair_index */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be grouped.]
+
+  Description [Sets a variable to be grouped. This function is used for
+  lazy sifting.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_set_var_to_be_grouped(bdd_manager *mgr, int index)
+{
+  return Cudd_bddSetVarToBeGrouped((DdManager *) mgr, index);
+
+} /* end of bdd_set_var_to_be_grouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be a hard group.]
+
+  Description [Sets a variable to be a hard group. This function is used
+  for lazy sifting.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_set_var_hard_group(bdd_manager *mgr, int index)
+{
+  return Cudd_bddSetVarHardGroup((DdManager *) mgr, index);
+
+} /* end of bdd_set_var_hard_group */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resets a variable not to be grouped.]
+
+  Description [Resets a variable not to be grouped. This function is
+  used for lazy sifting.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_reset_var_to_be_grouped(bdd_manager *mgr, int index)
+{
+  return Cudd_bddResetVarToBeGrouped((DdManager *) mgr, index);
+
+} /* end of bdd_reset_var_to_be_grouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be grouped.]
+
+  Description [Checks whether a variable is set to be grouped. This
+  function is used for lazy sifting.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_var_to_be_grouped(bdd_manager *mgr, int index)
+{
+  return Cudd_bddIsVarToBeGrouped((DdManager *) mgr, index);
+
+} /* end of bdd_is_var_to_be_grouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a variable is set to be a hard group.]
+
+  Description [Checks whether a variable is set to be a hard group. This
+  function is used for lazy sifting.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_var_hard_group(bdd_manager *mgr, int index)
+{
+  return Cudd_bddIsVarHardGroup((DdManager *) mgr, index);
+
+} /* end of bdd_is_var_hard_group */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be ungrouped.]
+
+  Description [Sets a variable to be ungrouped. This function is used
+  for lazy sifting.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_var_to_be_ungrouped(bdd_manager *mgr, int index)
+{
+  return Cudd_bddIsVarToBeUngrouped((DdManager *) mgr, index);
+
+} /* end of bdd_is_var_to_be_ungrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets a variable to be ungrouped.]
+
+  Description [Sets a variable to be ungrouped. This function is used
+  for lazy sifting.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_set_var_to_be_ungrouped(bdd_manager *mgr, int index)
+{
+  return Cudd_bddSetVarToBeUngrouped((DdManager *) mgr, index);
+
+} /* end of bdd_set_var_to_be_ungrouped */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prevents sifting of a variable.]
+
+  Description [This function sets a flag to prevent sifting of a
+  variable.  Returns 1 if successful; 0 otherwise (i.e., invalid
+  variable index).]
+
+  SideEffects [Changes the "bindVar" flag in DdSubtable.]
+
+******************************************************************************/
+int
+bdd_bind_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddBindVar((DdManager *) mgr, index);
+
+} /* end of bdd_bind_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allows the sifting of a variable.]
+
+  Description [This function resets the flag that prevents the sifting
+  of a variable. In successive variable reorderings, the variable will
+  NOT be skipped, that is, sifted.  Initially all variables can be
+  sifted. It is necessary to call this function only to re-enable
+  sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0
+  otherwise (i.e., invalid variable index).]
+
+  SideEffects [Changes the "bindVar" flag in DdSubtable.]
+
+******************************************************************************/
+int
+bdd_unbind_var(bdd_manager *mgr, int index)
+{
+  return Cudd_bddUnbindVar((DdManager *) mgr, index);
+
+} /* end of bdd_unbind_var */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether lazy sifting is on.]
+
+  SideEffects [none]
+
+******************************************************************************/
+int
+bdd_is_lazy_sift(bdd_manager *mgr)
+{
+  Cudd_ReorderingType method;
+
+  Cudd_ReorderingStatus((DdManager *) mgr, &method);
+  if (method == CUDD_REORDER_LAZY_SIFT)
+    return(1);
+  return(0);
+
+} /* end of bdd_is_lazy_sift */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the variable group tree of the manager.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+bdd_discard_all_var_groups(bdd_manager *mgr)
+{
+  Cudd_FreeTree((DdManager *) mgr);
+
+} /* end of bdd_discard_all_var_groups */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Function to print a warning that an illegal value was read.]
+
+  SideEffects        []
+
+  SeeAlso            [bdd_set_parameters]
+
+******************************************************************************/
+static void
+InvalidType(FILE *file, char *field, char *expected)
+{
+  (void) fprintf(file, "Warning: In parameter \"%s\"\n", field);
+  (void) fprintf(file, "Illegal type detected. %s expected\n", expected);
+
+} /* end of InvalidType */
Index: /vis_dev/glu-2.1/src/cuPort/cuPort.make
===================================================================
--- /vis_dev/glu-2.1/src/cuPort/cuPort.make	(revision 8)
+++ /vis_dev/glu-2.1/src/cuPort/cuPort.make	(revision 8)
@@ -0,0 +1,4 @@
+CSRC_cu += cuPortIter.c cuPort.c
+HEADERS_cu += cuPortInt.h
+
+DEPENDENCYFILES = $(CSRC_cu)
Index: /vis_dev/glu-2.1/src/cuPort/cuPortInt.h
===================================================================
--- /vis_dev/glu-2.1/src/cuPort/cuPortInt.h	(revision 8)
+++ /vis_dev/glu-2.1/src/cuPort/cuPortInt.h	(revision 8)
@@ -0,0 +1,96 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cuddPortInt.h]
+
+  PackageName [cu_port]
+
+  Synopsis    [Header file used by cu_port.]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: cuPortInt.h,v 1.5 2004/08/13 18:39:31 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CU_PORT_INT
+#define _CU_PORT_INT
+
+#include "util.h"
+#include "array.h"
+#include "st.h"
+
+#include "cuddInt.h"
+#include "bdd.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+struct bdd_t {
+  boolean free; /* TRUE if this is free, FALSE otherwise ... */
+  DdNode *node; /* ptr to the top node of the function */
+  DdManager *mgr; /* the manager */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CU_PORT_INT */
+
Index: /vis_dev/glu-2.1/src/cuPort/cuPortIter.c
===================================================================
--- /vis_dev/glu-2.1/src/cuPort/cuPortIter.c	(revision 8)
+++ /vis_dev/glu-2.1/src/cuPort/cuPortIter.c	(revision 8)
@@ -0,0 +1,399 @@
+/**CFile***********************************************************************
+
+  FileName    [cuPortIter.c]
+
+  PackageName [cu_port]
+
+  Synopsis    [Port routines for CU package.]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu> ]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "cuPortInt.h"
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: cuPortIter.c,v 1.13 2004/08/13 18:39:31 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+typedef struct {
+    DdManager   *manager;
+    DdGen	*ddGen;
+    array_t	*cube;
+} cu_bdd_gen;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the status of a bdd generator.]
+
+  SideEffects []
+
+  SeeAlso [bdd_first_cube bdd_next_cube bdd_gen_free]
+
+******************************************************************************/
+bdd_gen_status
+bdd_gen_read_status(bdd_gen *gen)
+{
+  if (Cudd_IsGenEmpty(((cu_bdd_gen *)gen)->ddGen)) {
+    return bdd_EMPTY;
+  }
+  else {
+    return bdd_NONEMPTY;
+  }
+
+} /* end of bdd_gen_read_status */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the first disjoint cube of the function.
+  A generator is also returned, which will iterate over the rest.]
+
+  Description [Defines an iterator on the onset of a BDD.  Two routines
+  are provided: bdd_first_cube, which extracts one cube from a BDD and
+  returns a bdd_gen structure containing the information necessary to
+  continue the enumeration; and bdd_next_disjoint_cube, which returns 1 if
+  another cube was found, and 0 otherwise. A cube is represented as an
+  array of bdd_literal (which are integers in {0, 1, 2}), where 0
+  represents negated literal, 1 for literal, and 2 for don't care.
+  Returns a disjoint cover.  A third routine is there to clean up.]
+
+  SideEffects []
+
+  SeeAlso [bdd_next_cube bdd_gen_free]
+
+******************************************************************************/
+bdd_gen *
+bdd_first_disjoint_cube(bdd_t *fn, array_t **cube /* of bdd_literal */)
+{
+    DdManager *manager;
+    cu_bdd_gen *gen;
+    int i;
+    int *icube;
+    CUDD_VALUE_TYPE value;
+
+    /* Make sure we receive a valid bdd_t. (So to speak.) */
+    assert(fn != 0);
+
+    manager = (DdManager *)fn->mgr;
+
+    /* Initialize the generator. */
+    gen = ALLOC(cu_bdd_gen,1);
+    if (gen == NULL) {
+      return(NIL(bdd_gen));
+    }
+    gen->manager = manager;
+
+    gen->cube = array_alloc(bdd_literal, manager->size);
+    if (gen->cube == NULL) {
+	fail("Bdd Package: Out of memory in bdd_first_cube");
+    }
+
+    gen->ddGen = Cudd_FirstCube(manager,(DdNode *)fn->node,&icube,&value);
+    if (gen->ddGen == NULL) {
+	fail("Cudd Package: Out of memory in bdd_first_cube");
+    }
+
+    if (!Cudd_IsGenEmpty(gen->ddGen)) {
+	/* Copy icube to the array_t cube. */
+	for (i = 0; i < manager->size; i++) {
+	    int myconst = icube[i];
+	    array_insert(bdd_literal, gen->cube, i, myconst);
+	}
+	*cube = gen->cube;
+    }
+
+    return(gen);
+
+} /* end of bdd_first_disjoint_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the next cube on the generator. Returns {TRUE,
+  FALSE} when {more, no more}.]
+
+  SideEffects []
+
+  SeeAlso     [bdd_first_cube bdd_gen_free]
+
+******************************************************************************/
+boolean
+bdd_next_disjoint_cube(bdd_gen *gen_, array_t **cube /* of bdd_literal */)
+{
+    cu_bdd_gen *gen;
+    int retval;
+    int *icube;
+    CUDD_VALUE_TYPE value;
+    int i;
+
+    gen = (cu_bdd_gen *)gen_;
+
+    retval = Cudd_NextCube(gen->ddGen,&icube,&value);
+    if (!Cudd_IsGenEmpty(gen->ddGen)) {
+	/* Copy icube to the array_t cube. */
+	for (i = 0; i < gen->manager->size; i++) {
+	    int myconst = icube[i];
+	    array_insert(bdd_literal, gen->cube, i, myconst);
+	}
+	*cube = gen->cube;
+    }
+
+    return(retval);
+
+} /* end of bdd_next_disjoint_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the first cube of the function.
+  A generator is also returned, which will iterate over the rest.]
+
+  Description [Defines an iterator on the onset of a BDD.  Two routines
+  are provided: bdd_first_cube, which extracts one cube from a BDD and
+  returns a bdd_gen structure containing the information necessary to
+  continue the enumeration; and bdd_next_cube, which returns 1 if
+  another cube was found, and 0 otherwise. A cube is represented as an
+  array of bdd_literal (which are integers in {0, 1, 2}), where 0
+  represents negated literal, 1 for literal, and 2 for don't care.
+  Returns a prime and irredundant cover.  A third routine is there to
+  clean up.]
+
+  SideEffects []
+
+  SeeAlso [bdd_next_cube bdd_gen_free]
+
+******************************************************************************/
+bdd_gen *
+bdd_first_cube(bdd_t *fn, array_t **cube /* of bdd_literal */)
+{
+    DdManager *manager;
+    cu_bdd_gen *gen;
+    int i;
+    int *icube;
+
+    /* Make sure we receive a valid bdd_t. (So to speak.) */
+    assert(fn != 0);
+
+    manager = (DdManager *)fn->mgr;
+
+    /* Initialize the generator. */
+    gen = ALLOC(cu_bdd_gen,1);
+    if (gen == NULL) {
+      return(NIL(bdd_gen));
+    }
+    gen->manager = manager;
+
+    gen->cube = array_alloc(bdd_literal, manager->size);
+    if (gen->cube == NULL) {
+	fail("Bdd Package: Out of memory in bdd_first_cube");
+    }
+
+    gen->ddGen = Cudd_FirstPrime(manager,(DdNode *)fn->node,
+				 (DdNode *)fn->node,&icube);
+    if (gen->ddGen == NULL) {
+	fail("Cudd Package: Out of memory in bdd_first_cube");
+    }
+
+    if (!Cudd_IsGenEmpty(gen->ddGen)) {
+	/* Copy icube to the array_t cube. */
+	for (i = 0; i < manager->size; i++) {
+	    int myconst = icube[i];
+	    array_insert(bdd_literal, gen->cube, i, myconst);
+	}
+	*cube = gen->cube;
+    }
+
+    return(gen);
+
+} /* end of bdd_first_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the next cube on the generator. Returns {TRUE,
+  FALSE} when {more, no more}.]
+
+  SideEffects []
+
+  SeeAlso     [bdd_first_prime bdd_gen_free]
+
+******************************************************************************/
+boolean
+bdd_next_cube(bdd_gen *gen_, array_t **cube /* of bdd_literal */)
+{
+    cu_bdd_gen *gen;
+    int retval;
+    int *icube;
+    int i;
+
+    gen = (cu_bdd_gen *)gen_;
+
+    retval = Cudd_NextPrime(gen->ddGen,&icube);
+    if (!Cudd_IsGenEmpty(gen->ddGen)) {
+	/* Copy icube to the array_t cube. */
+	for (i = 0; i < gen->manager->size; i++) {
+	    int myconst = icube[i];
+	    array_insert(bdd_literal, gen->cube, i, myconst);
+	}
+	*cube = gen->cube;
+    }
+
+    return(retval);
+
+} /* end of bdd_next_cube */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the first node in the BDD and returns a generator.]
+
+  SideEffects []
+
+  SeeAlso [bdd_next_node]
+
+******************************************************************************/
+bdd_gen *
+bdd_first_node(bdd_t *fn, bdd_node **node /* return */)
+{
+    bdd_manager *manager;
+    cu_bdd_gen *gen;
+
+    /* Make sure we receive a valid bdd_t. (So to speak.) */
+    assert(fn != 0);
+
+    manager = fn->mgr;
+
+    /* Initialize the generator. */
+    gen = ALLOC(cu_bdd_gen,1);
+    if (gen == NULL) return(NULL);
+    gen->manager = (DdManager *) manager;
+    gen->cube = NULL;
+
+    gen->ddGen = Cudd_FirstNode((DdManager *)manager,(DdNode *)fn->node,
+				(DdNode **)node);
+    if (gen->ddGen == NULL) {
+	fail("Cudd Package: Out of memory in bdd_first_node");
+    }
+
+    return(gen);
+
+} /* end of bdd_first_node */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the next node in the BDD. Returns {TRUE, FALSE} when
+  {more, no more}.]
+
+  SideEffects []
+
+  SeeAlso [bdd_first_node]
+
+******************************************************************************/
+boolean
+bdd_next_node(bdd_gen *gen, bdd_node **node /* return */)
+{
+    return(Cudd_NextNode(((cu_bdd_gen *)gen)->ddGen,(DdNode **)node));
+
+} /* end of bdd_next_node */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees up the space used by the generator. Returns an int
+  so that it is easier to fit in a foreach macro. Returns 0 (to make it
+  easy to put in expressions).]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+int
+bdd_gen_free(bdd_gen *gen_)
+{
+    cu_bdd_gen *gen;
+
+    gen = (cu_bdd_gen *)gen_;
+    if (gen->cube != NULL) array_free(gen->cube);
+    Cudd_GenFree(gen->ddGen);
+    FREE(gen);
+    return(0);
+
+} /* end of bdd_gen_free */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: /vis_dev/glu-2.1/src/epd/epd.c
===================================================================
--- /vis_dev/glu-2.1/src/epd/epd.c	(revision 8)
+++ /vis_dev/glu-2.1/src/epd/epd.c	(revision 8)
@@ -0,0 +1,1344 @@
+/**CFile***********************************************************************
+
+  FileName    [epd.c]
+
+  PackageName [epd]
+
+  Synopsis    [Arithmetic functions with extended double precision.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: epd.c,v 1.10 2004/08/13 18:20:30 fabio Exp $]
+
+******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "util.h"
+#include "epd.h"
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates an EpDouble struct.]
+
+  Description [Allocates an EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+EpDouble *
+EpdAlloc(void)
+{
+  EpDouble	*epd;
+
+  epd = ALLOC(EpDouble, 1);
+  return(epd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two EpDouble struct.]
+
+  Description [Compares two EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdCmp(const char *key1, const char *key2)
+{
+  EpDouble *epd1 = (EpDouble *) key1;
+  EpDouble *epd2 = (EpDouble *) key2;
+  if (epd1->type.value != epd2->type.value ||
+      epd1->exponent != epd2->exponent) {
+    return(1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an EpDouble struct.]
+
+  Description [Frees an EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdFree(EpDouble *epd)
+{
+  FREE(epd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an arbitrary precision double value to a string.]
+
+  Description [Converts an arbitrary precision double value to a string.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdGetString(EpDouble *epd, char *str)
+{
+  double	value;
+  int		exponent;
+  char		*pos;
+
+  if (IsNanDouble(epd->type.value)) {
+    sprintf(str, "NaN");
+    return;
+  } else if (IsInfDouble(epd->type.value)) {
+    if (epd->type.bits.sign == 1)
+      sprintf(str, "-Inf");
+    else
+      sprintf(str, "Inf");
+    return;
+  }
+
+  assert(epd->type.bits.exponent == EPD_MAX_BIN ||
+	 epd->type.bits.exponent == 0);
+
+  EpdGetValueAndDecimalExponent(epd, &value, &exponent);
+  sprintf(str, "%e", value);
+  pos = strstr(str, "e");
+  if (exponent >= 0) {
+    if (exponent < 10)
+      sprintf(pos + 1, "+0%d", exponent);
+    else
+      sprintf(pos + 1, "+%d", exponent);
+  } else {
+    exponent *= -1;
+    if (exponent < 10)
+      sprintf(pos + 1, "-0%d", exponent);
+    else
+      sprintf(pos + 1, "-%d", exponent);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts double to EpDouble struct.]
+
+  Description [Converts double to EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdConvert(double value, EpDouble *epd)
+{
+  epd->type.value = value;
+  epd->exponent = 0;
+  EpdNormalize(epd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply(EpDouble *epd1, double value)
+{
+  EpDouble	epd2;
+  double	tmp;
+  int		exponent;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int	sign;
+
+    EpdConvert(value, &epd2);
+    sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+    EpdMakeInf(epd1, sign);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  tmp = epd1->type.value * epd2.type.value;
+  exponent = epd1->exponent + epd2.exponent;
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply2(EpDouble *epd1, EpDouble *epd2)
+{
+  double	value;
+  int		exponent;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd1, sign);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  value = epd1->type.value * epd2->type.value;
+  exponent = epd1->exponent + epd2->exponent;
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2)
+{
+  double	value;
+  int		exponent;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd1, sign);
+    return;
+  }
+
+  value = epd1->type.value * epd2->type.value;
+  exponent = epd1->exponent + epd2->exponent;
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalizeDecimal(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd3, sign);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  epd3->type.value = epd1->type.value * epd2->type.value;
+  epd3->exponent = epd1->exponent + epd2->exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Multiplies two arbitrary precision double values.]
+
+  Description [Multiplies two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+    EpdMakeInf(epd3, sign);
+    return;
+  }
+
+  epd3->type.value = epd1->type.value * epd2->type.value;
+  epd3->exponent = epd1->exponent + epd2->exponent;
+  EpdNormalizeDecimal(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides two arbitrary precision double values.]
+
+  Description [Divides two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdDivide(EpDouble *epd1, double value)
+{
+  EpDouble	epd2;
+  double	tmp;
+  int		exponent;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int	sign;
+
+    EpdConvert(value, &epd2);
+    if (EpdIsInf(epd1) && IsInfDouble(value)) {
+      EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd1)) {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      EpdMakeInf(epd1, sign);
+    } else {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      EpdMakeZero(epd1, sign);
+    }
+    return;
+  }
+
+  if (value == 0.0) {
+    EpdMakeNan(epd1);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  tmp = epd1->type.value / epd2.type.value;
+  exponent = epd1->exponent - epd2.exponent;
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides two arbitrary precision double values.]
+
+  Description [Divides two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdDivide2(EpDouble *epd1, EpDouble *epd2)
+{
+  double	value;
+  int		exponent;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd1)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeInf(epd1, sign);
+    } else {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeZero(epd1, sign);
+    }
+    return;
+  }
+
+  if (epd2->type.value == 0.0) {
+    EpdMakeNan(epd1);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  value = epd1->type.value / epd2->type.value;
+  exponent = epd1->exponent - epd2->exponent;
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Divides two arbitrary precision double values.]
+
+  Description [Divides two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd3);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      EpdMakeNan(epd3);
+    } else if (EpdIsInf(epd1)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeInf(epd3, sign);
+    } else {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      EpdMakeZero(epd3, sign);
+    }
+    return;
+  }
+
+  if (epd2->type.value == 0.0) {
+    EpdMakeNan(epd3);
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  epd3->type.value = epd1->type.value / epd2->type.value;
+  epd3->exponent = epd1->exponent - epd2->exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision double values.]
+
+  Description [Adds two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdAdd(EpDouble *epd1, double value)
+{
+  EpDouble	epd2;
+  double	tmp;
+  int		exponent, diff;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int	sign;
+
+    EpdConvert(value, &epd2);
+    if (EpdIsInf(epd1) && IsInfDouble(value)) {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      if (sign == 1)
+	EpdMakeNan(epd1);
+    } else if (EpdIsInf(&epd2)) {
+      EpdCopy(&epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  if (epd1->exponent > epd2.exponent) {
+    diff = epd1->exponent - epd2.exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value + epd2.type.value / pow((double)2.0, (double)diff);
+    else
+      tmp = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2.exponent) {
+    diff = epd2.exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value / pow((double)2.0, (double)diff) + epd2.type.value;
+    else
+      tmp = epd2.type.value;
+    exponent = epd2.exponent;
+  } else {
+    tmp = epd1->type.value + epd2.type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision double values.]
+
+  Description [Adds two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdAdd2(EpDouble *epd1, EpDouble *epd2)
+{
+  double	value;
+  int		exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 1)
+	EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd2)) {
+      EpdCopy(epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value +
+		epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) +
+		epd2->type.value;
+    } else
+      value = epd2->type.value;
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value + epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds two arbitrary precision double values.]
+
+  Description [Adds two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  double	value;
+  int		exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd3);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 1)
+	EpdMakeNan(epd3);
+      else
+	EpdCopy(epd1, epd3);
+    } else if (EpdIsInf(epd1)) {
+      EpdCopy(epd1, epd3);
+    } else {
+      EpdCopy(epd2, epd3);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value +
+		epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) +
+		epd2->type.value;
+    } else
+      value = epd2->type.value;
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value + epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd3->type.value = value;
+  epd3->exponent = exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision double values.]
+
+  Description [Subtracts two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdSubtract(EpDouble *epd1, double value)
+{
+  EpDouble	epd2;
+  double	tmp;
+  int		exponent, diff;
+
+  if (EpdIsNan(epd1) || IsNanDouble(value)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || IsInfDouble(value)) {
+    int	sign;
+
+    EpdConvert(value, &epd2);
+    if (EpdIsInf(epd1) && IsInfDouble(value)) {
+      sign = epd1->type.bits.sign ^ epd2.type.bits.sign;
+      if (sign == 0)
+	EpdMakeNan(epd1);
+    } else if (EpdIsInf(&epd2)) {
+      EpdCopy(&epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+
+  EpdConvert(value, &epd2);
+  if (epd1->exponent > epd2.exponent) {
+    diff = epd1->exponent - epd2.exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value - epd2.type.value / pow((double)2.0, (double)diff);
+    else
+      tmp = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2.exponent) {
+    diff = epd2.exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN)
+      tmp = epd1->type.value / pow((double)2.0, (double)diff) - epd2.type.value;
+    else
+      tmp = epd2.type.value * (double)(-1.0);
+    exponent = epd2.exponent;
+  } else {
+    tmp = epd1->type.value - epd2.type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = tmp;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision double values.]
+
+  Description [Subtracts two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdSubtract2(EpDouble *epd1, EpDouble *epd2)
+{
+  double	value;
+  int		exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd1);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 0)
+	EpdMakeNan(epd1);
+    } else if (EpdIsInf(epd2)) {
+      EpdCopy(epd2, epd1);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value -
+		epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) -
+		epd2->type.value;
+    } else
+      value = epd2->type.value * (double)(-1.0);
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value - epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd1->type.value = value;
+  epd1->exponent = exponent;
+  EpdNormalize(epd1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtracts two arbitrary precision double values.]
+
+  Description [Subtracts two arbitrary precision double values.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3)
+{
+  double	value;
+  int		exponent, diff;
+
+  if (EpdIsNan(epd1) || EpdIsNan(epd2)) {
+    EpdMakeNan(epd3);
+    return;
+  } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) {
+    int	sign;
+
+    if (EpdIsInf(epd1) && EpdIsInf(epd2)) {
+      sign = epd1->type.bits.sign ^ epd2->type.bits.sign;
+      if (sign == 0)
+	EpdCopy(epd1, epd3);
+      else
+	EpdMakeNan(epd3);
+    } else if (EpdIsInf(epd1)) {
+      EpdCopy(epd1, epd1);
+    } else {
+      sign = epd2->type.bits.sign ^ 0x1;
+      EpdMakeInf(epd3, sign);
+    }
+    return;
+  }
+
+  assert(epd1->type.bits.exponent == EPD_MAX_BIN);
+  assert(epd2->type.bits.exponent == EPD_MAX_BIN);
+
+  if (epd1->exponent > epd2->exponent) {
+    diff = epd1->exponent - epd2->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value -
+		epd2->type.value / pow((double)2.0, (double)diff);
+    } else
+      value = epd1->type.value;
+    exponent = epd1->exponent;
+  } else if (epd1->exponent < epd2->exponent) {
+    diff = epd2->exponent - epd1->exponent;
+    if (diff <= EPD_MAX_BIN) {
+      value = epd1->type.value / pow((double)2.0, (double)diff) -
+		epd2->type.value;
+    } else
+      value = epd2->type.value * (double)(-1.0);
+    exponent = epd2->exponent;
+  } else {
+    value = epd1->type.value - epd2->type.value;
+    exponent = epd1->exponent;
+  }
+  epd3->type.value = value;
+  epd3->exponent = exponent;
+  EpdNormalize(epd3);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes arbitrary precision pow of base 2.]
+
+  Description [Computes arbitrary precision pow of base 2.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdPow2(int n, EpDouble *epd)
+{
+  if (n <= EPD_MAX_BIN) {
+    EpdConvert(pow((double)2.0, (double)n), epd);
+  } else {
+    EpDouble	epd1, epd2;
+    int		n1, n2;
+
+    n1 = n / 2;
+    n2 = n - n1;
+    EpdPow2(n1, &epd1);
+    EpdPow2(n2, &epd2);
+    EpdMultiply3(&epd1, &epd2, epd);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes arbitrary precision pow of base 2.]
+
+  Description [Computes arbitrary precision pow of base 2.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdPow2Decimal(int n, EpDouble *epd)
+{
+  if (n <= EPD_MAX_BIN) {
+    epd->type.value = pow((double)2.0, (double)n);
+    epd->exponent = 0;
+    EpdNormalizeDecimal(epd);
+  } else {
+    EpDouble	epd1, epd2;
+    int		n1, n2;
+
+    n1 = n / 2;
+    n2 = n - n1;
+    EpdPow2Decimal(n1, &epd1);
+    EpdPow2Decimal(n2, &epd2);
+    EpdMultiply3Decimal(&epd1, &epd2, epd);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Normalize an arbitrary precision double value.]
+
+  Description [Normalize an arbitrary precision double value.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdNormalize(EpDouble *epd)
+{
+  int		exponent;
+
+  if (IsNanOrInfDouble(epd->type.value)) {
+    epd->exponent = 0;
+    return;
+  }
+
+  exponent = EpdGetExponent(epd->type.value);
+  if (exponent == EPD_MAX_BIN)
+    return;
+  exponent -= EPD_MAX_BIN;
+  epd->type.bits.exponent = EPD_MAX_BIN;
+  epd->exponent += exponent;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Normalize an arbitrary precision double value.]
+
+  Description [Normalize an arbitrary precision double value.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdNormalizeDecimal(EpDouble *epd)
+{
+  int		exponent;
+
+  if (IsNanOrInfDouble(epd->type.value)) {
+    epd->exponent = 0;
+    return;
+  }
+
+  exponent = EpdGetExponentDecimal(epd->type.value);
+  epd->type.value /= pow((double)10.0, (double)exponent);
+  epd->exponent += exponent;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns value and decimal exponent of EpDouble.]
+
+  Description [Returns value and decimal exponent of EpDouble.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent)
+{
+  EpDouble	epd1, epd2;
+
+  if (EpdIsNanOrInf(epd))
+    return;
+
+  if (EpdIsZero(epd)) {
+    *value = 0.0;
+    *exponent = 0;
+    return;
+  }
+
+  epd1.type.value = epd->type.value;
+  epd1.exponent = 0;
+  EpdPow2Decimal(epd->exponent, &epd2);
+  EpdMultiply2Decimal(&epd1, &epd2);
+
+  *value = epd1.type.value;
+  *exponent = epd1.exponent;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the exponent value of a double.]
+
+  Description [Returns the exponent value of a double.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdGetExponent(double value)
+{
+  int		exponent;
+  EpDouble	epd;
+
+  epd.type.value = value;
+  exponent = epd.type.bits.exponent;
+  return(exponent);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the decimal exponent value of a double.]
+
+  Description [Returns the decimal exponent value of a double.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdGetExponentDecimal(double value)
+{
+  char	*pos, str[24];
+  int	exponent;
+
+  sprintf(str, "%E", value);
+  pos = strstr(str, "E");
+  sscanf(pos, "E%d", &exponent);
+  return(exponent);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes EpDouble Inf.]
+
+  Description [Makes EpDouble Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMakeInf(EpDouble *epd, int sign)
+{
+  epd->type.bits.mantissa1 = 0;
+  epd->type.bits.mantissa0 = 0;
+  epd->type.bits.exponent = EPD_EXP_INF;
+  epd->type.bits.sign = sign;
+  epd->exponent = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes EpDouble Zero.]
+
+  Description [Makes EpDouble Zero.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMakeZero(EpDouble *epd, int sign)
+{
+  epd->type.bits.mantissa1 = 0;
+  epd->type.bits.mantissa0 = 0;
+  epd->type.bits.exponent = 0;
+  epd->type.bits.sign = sign;
+  epd->exponent = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes EpDouble NaN.]
+
+  Description [Makes EpDouble NaN.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdMakeNan(EpDouble *epd)
+{
+  epd->type.nan.mantissa1 = 0;
+  epd->type.nan.mantissa0 = 0;
+  epd->type.nan.quiet_bit = 1;
+  epd->type.nan.exponent = EPD_EXP_INF;
+  epd->type.nan.sign = 1;
+  epd->exponent = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copies a EpDouble struct.]
+
+  Description [Copies a EpDouble struct.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+EpdCopy(EpDouble *from, EpDouble *to)
+{
+  to->type.value = from->type.value;
+  to->exponent = from->exponent;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is Inf.]
+
+  Description [Checks whether the value is Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsInf(EpDouble *epd)
+{
+  return(IsInfDouble(epd->type.value));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is Zero.]
+
+  Description [Checks whether the value is Zero.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsZero(EpDouble *epd)
+{
+  if (epd->type.value == 0.0)
+    return(1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN.]
+
+  Description [Checks whether the value is NaN.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsNan(EpDouble *epd)
+{
+  return(IsNanDouble(epd->type.value));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN or Inf.]
+
+  Description [Checks whether the value is NaN or Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+EpdIsNanOrInf(EpDouble *epd)
+{
+  return(IsNanOrInfDouble(epd->type.value));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is Inf.]
+
+  Description [Checks whether the value is Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IsInfDouble(double value)
+{
+  EpType val;
+
+  val.value = value;
+  if (val.bits.exponent == EPD_EXP_INF &&
+      val.bits.mantissa0 == 0 &&
+      val.bits.mantissa1 == 0) {
+    if (val.bits.sign == 0)
+      return(1);
+    else
+      return(-1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN.]
+
+  Description [Checks whether the value is NaN.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IsNanDouble(double value)
+{
+  EpType	val;
+  
+  val.value = value;
+  if (val.nan.exponent == EPD_EXP_INF &&
+      val.nan.sign == 1 &&
+      val.nan.quiet_bit == 1 &&
+      val.nan.mantissa0 == 0 &&
+      val.nan.mantissa1 == 0) {
+    return(1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the value is NaN or Inf.]
+
+  Description [Checks whether the value is NaN or Inf.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IsNanOrInfDouble(double value)
+{
+  EpType	val;
+
+  val.value = value;
+  if (val.nan.exponent == EPD_EXP_INF &&
+      val.nan.mantissa0 == 0 &&
+      val.nan.mantissa1 == 0 &&
+      (val.nan.sign == 1 || val.nan.quiet_bit == 0)) {
+    return(1);
+  }
+  return(0);
+}
Index: /vis_dev/glu-2.1/src/epd/epd.h
===================================================================
--- /vis_dev/glu-2.1/src/epd/epd.h	(revision 8)
+++ /vis_dev/glu-2.1/src/epd/epd.h	(revision 8)
@@ -0,0 +1,200 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [epd.h]
+
+  PackageName [epd]
+
+  Synopsis    [The University of Colorado extended double precision package.]
+
+  Description [arithmetic functions with extended double precision.]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: epd.h,v 1.9 2004/08/13 18:20:30 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _EPD
+#define _EPD
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define	EPD_MAX_BIN	1023
+#define	EPD_MAX_DEC	308
+#define	EPD_EXP_INF	0x7ff
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [IEEE double struct.]
+
+  Description [IEEE double struct.]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef	EPD_BIG_ENDIAN
+struct IeeeDoubleStruct {	/* BIG_ENDIAN */
+  unsigned int sign: 1;
+  unsigned int exponent: 11;
+  unsigned int mantissa0: 20;
+  unsigned int mantissa1: 32;
+};
+#else
+struct IeeeDoubleStruct {	/* LITTLE_ENDIAN */
+  unsigned int mantissa1: 32;
+  unsigned int mantissa0: 20;
+  unsigned int exponent: 11;
+  unsigned int sign: 1;
+};
+#endif
+
+/**Struct**********************************************************************
+
+  Synopsis    [IEEE double NaN struct.]
+
+  Description [IEEE double NaN struct.]
+
+  SeeAlso     []
+
+******************************************************************************/
+#ifdef	EPD_BIG_ENDIAN
+struct IeeeNanStruct {	/* BIG_ENDIAN */
+  unsigned int sign: 1;
+  unsigned int exponent: 11;
+  unsigned int quiet_bit: 1;
+  unsigned int mantissa0: 19;
+  unsigned int mantissa1: 32;
+};
+#else
+struct IeeeNanStruct {	/* LITTLE_ENDIAN */
+  unsigned int mantissa1: 32;
+  unsigned int mantissa0: 19;
+  unsigned int quiet_bit: 1;
+  unsigned int exponent: 11;
+  unsigned int sign: 1;
+};
+#endif
+
+/**Struct**********************************************************************
+
+  Synopsis    [Extended precision double to keep very large value.]
+
+  Description [Extended precision double to keep very large value.]
+
+  SeeAlso     []
+
+******************************************************************************/
+union EpTypeUnion {
+  double			value;
+  struct IeeeDoubleStruct	bits;
+  struct IeeeNanStruct		nan;
+};
+
+struct EpDoubleStruct {
+  union EpTypeUnion		type;
+  int				exponent;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct EpDoubleStruct EpDouble;
+typedef struct IeeeDoubleStruct IeeeDouble;
+typedef struct IeeeNanStruct IeeeNan;
+typedef union EpTypeUnion EpType;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern EpDouble *EpdAlloc(void);
+extern int EpdCmp(const char *key1, const char *key2);
+extern void EpdFree(EpDouble *epd);
+extern void EpdGetString(EpDouble *epd, char *str);
+extern void EpdConvert(double value, EpDouble *epd);
+extern void EpdMultiply(EpDouble *epd1, double value);
+extern void EpdMultiply2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2);
+extern void EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdDivide(EpDouble *epd1, double value);
+extern void EpdDivide2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdAdd(EpDouble *epd1, double value);
+extern void EpdAdd2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdSubtract(EpDouble *epd1, double value);
+extern void EpdSubtract2(EpDouble *epd1, EpDouble *epd2);
+extern void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3);
+extern void EpdPow2(int n, EpDouble *epd);
+extern void EpdPow2Decimal(int n, EpDouble *epd);
+extern void EpdNormalize(EpDouble *epd);
+extern void EpdNormalizeDecimal(EpDouble *epd);
+extern void EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent);
+extern int EpdGetExponent(double value);
+extern int EpdGetExponentDecimal(double value);
+extern void EpdMakeInf(EpDouble *epd, int sign);
+extern void EpdMakeZero(EpDouble *epd, int sign);
+extern void EpdMakeNan(EpDouble *epd);
+extern void EpdCopy(EpDouble *from, EpDouble *to);
+extern int EpdIsInf(EpDouble *epd);
+extern int EpdIsZero(EpDouble *epd);
+extern int EpdIsNan(EpDouble *epd);
+extern int EpdIsNanOrInf(EpDouble *epd);
+extern int IsInfDouble(double value);
+extern int IsNanDouble(double value);
+extern int IsNanOrInfDouble(double value);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EPD */
Index: /vis_dev/glu-2.1/src/epd/epd.make
===================================================================
--- /vis_dev/glu-2.1/src/epd/epd.make	(revision 8)
+++ /vis_dev/glu-2.1/src/epd/epd.make	(revision 8)
@@ -0,0 +1,4 @@
+CSRC += epd.c
+HEADERS += epd.h
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/error/error.c
===================================================================
--- /vis_dev/glu-2.1/src/error/error.c	(revision 8)
+++ /vis_dev/glu-2.1/src/error/error.c	(revision 8)
@@ -0,0 +1,54 @@
+/*
+ * $Id: error.c,v 1.4 2002/09/09 23:55:44 fabio Exp $
+ *
+ */
+#include "util.h"
+#include "error.h"
+
+static char *error_str = 0;
+static int error_str_len, error_str_maxlen;
+
+
+void
+error_init(void)
+{
+    if (error_str != 0) {
+	FREE(error_str);
+    }
+    error_str_len = 0;
+    error_str_maxlen = 100;
+    error_str = ALLOC(char, error_str_maxlen);
+    *error_str = '\0';
+}
+
+
+void
+error_append(char *s)
+{
+    int slen;
+
+    slen = strlen(s);
+    if (error_str_len + slen + 1 > error_str_maxlen) {
+	error_str_maxlen = (error_str_len + slen) * 2;	/* cstevens@ic */
+	error_str = REALLOC(char, error_str, error_str_maxlen);
+    }
+    (void) strcpy(error_str + error_str_len, s);
+    error_str_len += slen;
+}
+
+
+char *
+error_string(void)
+{
+    return error_str;
+}
+
+
+void
+error_cleanup(void)
+{
+    FREE(error_str);
+    error_str_len = 0;
+    error_str_maxlen = 0;
+    error_str = 0;
+}
Index: /vis_dev/glu-2.1/src/error/error.h
===================================================================
--- /vis_dev/glu-2.1/src/error/error.h	(revision 8)
+++ /vis_dev/glu-2.1/src/error/error.h	(revision 8)
@@ -0,0 +1,8 @@
+/*
+ * $Id: error.h,v 1.2 2002/08/26 05:47:09 fabio Exp $
+ *
+ */
+EXTERN void error_init ARGS((void));
+EXTERN void error_append ARGS((char *));
+EXTERN char *error_string ARGS((void));
+EXTERN void error_cleanup ARGS((void));
Index: /vis_dev/glu-2.1/src/error/error.make
===================================================================
--- /vis_dev/glu-2.1/src/error/error.make	(revision 8)
+++ /vis_dev/glu-2.1/src/error/error.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += error.c
+HEADERS += error.h
+MISC += error.doc
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/graph/com_graph.c
===================================================================
--- /vis_dev/glu-2.1/src/graph/com_graph.c	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/com_graph.c	(revision 8)
@@ -0,0 +1,236 @@
+#include "util.h"
+#include "list.h"
+#include "array.h"
+#include "graph.h"
+#include "graph_static.h"
+
+
+static char *month[] = {"Jan", "Feb", "March", "april", "may", "June",
+    "july", "Aug", "Sept", "Oct", "nov", "Dec"
+};
+
+#define voidNULL	(void (*)()) NULL
+#define gGenericNULL	(gGeneric (*)()) NULL
+
+static void
+strfree(thing)
+gGeneric thing;
+{
+    FREE(thing);
+}
+
+static int
+graph_test()
+{
+    graph_t *g1, *g2;
+    int i, j;
+    vertex_t *v[10];
+    lsGen gen, gen2;
+    vertex_t *vert;
+    edge_t *edge;
+
+    g1 = g_alloc();
+
+    for (i = 0; i < 10; i++) {
+        v[i] = g_add_vertex(g1);
+	v[i]->user_data = (gGeneric) i;
+    }
+    for (i = 0; i < 9; i++) {
+        for (j = i + 1; j < 10; j++) {
+	    (void) g_add_edge(v[i],v[j]);
+	}
+    }
+    (void) g_add_edge(v[5],v[5]);			/* self loop */
+
+    (void) lsFirstItem(g_get_out_edges(v[4]),(lsGeneric *) &edge,LS_NH);
+    g_delete_edge(edge,voidNULL);
+
+    g_delete_vertex(v[8],voidNULL,voidNULL);
+        
+    g_add_vertex(g1)->user_data = (gGeneric) 10;  /* unconnected vertex */
+
+    g2 = g_dup(g1,gGenericNULL,gGenericNULL,gGenericNULL);
+    foreach_vertex (g2,gen,vert) {
+        (void) fprintf(stdout,"\nCopy of %d\ngoes to:    ",vert->user_data);
+        foreach_out_edge (vert,gen2,edge) {
+	    (void) fprintf(stdout,"%d ",g_e_dest(edge)->user_data);
+	}
+	(void) fprintf(stdout,"\ncomes from: ");
+	foreach_in_edge (vert,gen2,edge) {
+	    (void) fprintf(stdout,"%d ",g_e_source(edge)->user_data);
+	}
+    }
+    (void) fputc('\n',stdout);
+    g_check(g1);
+    g_check(g2);
+    g_free(g1,voidNULL,voidNULL,voidNULL);
+    g_free(g2,voidNULL,voidNULL,voidNULL);
+
+    g1 = g_alloc();
+    for (i = 0; i < 12; i++) {
+        g_add_vertex(g1)->user_data = (gGeneric) month[i];
+    }
+    g2 = g_dup(g1,gGenericNULL,(gGeneric (*)()) util_strsav,gGenericNULL);
+    foreach_vertex (g1,gen,vert) {
+        ((char *) vert->user_data)[0] = '\0';
+    }
+    foreach_vertex (g2,gen,vert) {		/* strings copied by strsav */
+        (void) fprintf(stdout, "%s\n", (char *) vert->user_data);
+    }
+    g_free(g1, voidNULL, voidNULL, voidNULL); /* don't free static strings */
+    g_free(g2, voidNULL, strfree, voidNULL); /* free copies */
+    return(0);
+}
+
+static void
+edge_free(thing)
+gGeneric thing;
+{
+    FREE(((gGeneric *) thing)[2]);
+}
+
+static gGeneric
+edge_copy(thing)
+gGeneric thing;
+{
+    gGeneric *new = ALLOC(gGeneric,4);
+    gGeneric *old = (gGeneric *) thing;
+
+    new[0] = old[0];
+    new[1] = old[1];
+    new[2] = (gGeneric) util_strsav((char *) old[2]);
+    new[3] = old[3];
+    return((gGeneric) new);
+}
+
+
+static int
+graph_static_test()
+{
+    graph_t *g1, *g2;
+    int i,j,x;
+    vertex_t *v[10], *v1, *v2;
+    edge_t *e, *edge;
+    lsGen gen;
+
+    g1 = g_alloc_static(3,2,4);
+
+    for (i = 0; i < 10; i++) {
+        v[i] = g_add_vertex_static(g1);
+	g_set_v_slot_static(v[i],0,(gGeneric) i);
+	g_set_v_slot_static(v[i],1,(gGeneric) (2 * i));
+    }
+    x = 0;
+    for (i = 0; i < 9; i++) {
+        for (j = i + 1; j < 10; j++) {
+	    e = g_add_edge_static(v[i],v[j]);
+	    g_set_e_slot_static(e,2,(gGeneric) util_strsav(month[i]));
+	    g_set_e_slot_static(e,1,(gGeneric) x++);
+	}
+    }
+    g_delete_vertex_static(v[3],voidNULL,edge_free);	/* kill v[3] */
+    (void) lsLastItem(g_get_out_edges(v[6]),(lsGeneric *) &edge,LS_NH); 
+    g_delete_edge_static(edge,edge_free);	/* kill last edge of v[6] */
+
+    g_set_g_slot_static(g1,1,(gGeneric) 'f');
+    g2 = g_dup_static(g1,gGenericNULL,gGenericNULL,edge_copy);
+
+    v1 = g_add_vertex_static(g2);
+    g_copy_v_slots_static(v[2],v1,gGenericNULL);
+
+    foreach_edge (g2,gen,edge) {
+        v1 = g_e_source(edge);
+	v2 = g_e_dest(edge);
+        (void) fprintf(stdout,
+		"%d (%s) connects %d & %d\n",g_get_e_slot_static(edge,1),
+		g_get_e_slot_static(edge,2),g_get_v_slot_static(v1,0),
+		g_get_v_slot_static(v2,0));
+    }
+    g_free_static(g1,voidNULL,voidNULL,edge_free);
+    g_free_static(g2,voidNULL,voidNULL,edge_free);
+    return(0);
+}
+
+static int
+reverso(a,b)
+char *a,*b;
+{
+    return((int) ((vertex_t *) b)->user_data - (int) ((vertex_t *) a)->user_data);
+}
+
+static int
+graph_dfs_test()
+{
+    int i;
+    vertex_t *v[10];
+    array_t *arr;
+    graph_t *g;
+    vertex_t *x;
+    
+    g = g_alloc();
+    for (i = 0; i < 10; i++) {
+        v[i] = g_add_vertex(g);
+	v[i]->user_data = (gGeneric) i;
+    }
+    (void) g_add_edge(v[3],v[4]);
+    (void) g_add_edge(v[0],v[3]);
+    (void) g_add_edge(v[0],v[6]);
+    (void) g_add_edge(v[0],v[2]);
+    (void) g_add_edge(v[1],v[3]);
+    (void) g_add_edge(v[6],v[3]);
+    (void) g_add_edge(v[2],v[5]);
+    (void) g_add_edge(v[2],v[3]);
+    (void) g_add_edge(v[3],v[5]);
+    (void) g_add_edge(v[6],v[2]);
+
+    (void) g_add_edge(v[7],v[8]);
+    (void) g_add_edge(v[9],v[7]);
+    (void) g_add_edge(v[9],v[8]);
+    arr = g_dfs(g);
+    (void) fprintf(stdout,"Depth first sort\n");
+    for (i = 0; i < 10; i++) {
+        x = array_fetch(vertex_t *,arr,i);
+        (void) fprintf(stdout,"%d\n",x->user_data);
+    }
+    array_free(arr);
+    (void) fprintf(stdout,"\nReverse sort\n");
+    arr = g_graph_sort(g,reverso);
+    for (i = 0; i < 10; i++) {
+        x = array_fetch(vertex_t *,arr,i);
+        (void) fprintf(stdout,"%d\n",x->user_data);
+    }
+    array_free(arr);
+    g_free(g,voidNULL,voidNULL,voidNULL);
+    return(0);
+}
+
+init_graph()
+{
+    extern int g_unique_id;
+
+    g_unique_id = 0;
+    com_add_command("_graph_test",graph_test,0);
+    com_add_command("_graph_static_test",graph_static_test,0);
+    com_add_command("_graph_dfs_test",graph_dfs_test,0);
+}
+
+end_graph()
+{
+}
+
+/*
+
+       ______     1
+      /      \	 /
+     /	      v v 
+     |	0 ---> 3 ----> 4	9 --> 8
+     |	| \    ^\		|    ^
+     |	|  \   | \		|   /
+     |	|   \  |  \		|  /
+      \	|    \ |   \		| /
+       \v     v|    v		v/
+      	6 ---> 2 --> 5		7
+
+  This is the graph represented in test_graph_dfs
+*/
+
Index: /vis_dev/glu-2.1/src/graph/graph.c
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph.c	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph.c	(revision 8)
@@ -0,0 +1,390 @@
+/*
+ * $Id: graph.c,v 1.6 2005/04/15 23:24:21 fabio Exp $
+ */
+
+#include "graph_int.h"
+
+int g_unique_id;
+
+graph_t *
+g_alloc(void)
+{
+    graph_t_int *graph = ALLOC(graph_t_int,1);
+    
+    graph->user_data = (gGeneric) NULL;
+    graph->v_list = lsCreate();
+    graph->e_list = lsCreate();
+
+    return((graph_t *) graph);
+}
+
+void
+g_free(
+  graph_t *g,
+  void (*f_free_g)(gGeneric),
+  void (*f_free_v)(gGeneric),
+  void (*f_free_e)(gGeneric))
+{
+    lsGen gen;
+    vertex_t *v;
+    edge_t *e;
+
+    if (g == NIL(graph_t)) {
+        return;
+    }
+    if (f_free_g != (void (*)(gGeneric)) NULL) {
+        (*f_free_g)(g->user_data);
+    }
+    foreach_vertex (g,gen,v) {
+        if (f_free_v != (void (*)(gGeneric)) NULL) {
+	    (*f_free_v)(v->user_data);
+	}
+	(void) lsDestroy(g_get_in_edges(v),(void (*)(lsGeneric)) NULL);
+	(void) lsDestroy(g_get_out_edges(v),(void (*)(lsGeneric)) NULL);
+	FREE(v);
+    }
+    foreach_edge (g,gen,e) {
+        if (f_free_e != (void (*)(gGeneric)) NULL) {
+	    (*f_free_e)(e->user_data);
+	}
+	FREE(e);
+    }
+    (void) lsDestroy(g_get_vertices(g),(void (*)(lsGeneric)) NULL);
+    (void) lsDestroy(g_get_edges(g),(void (*)(lsGeneric)) NULL);
+    FREE(g);
+}
+
+void
+g_check(graph_t *g)
+{
+    vertex_t *v, *source, *dest;
+    edge_t *e, *test;
+    lsGen gen, gen2;
+    int found;
+
+    if (g == NIL(graph_t)) {
+        return;
+    }
+    foreach_edge (g,gen,e) {
+        source = g_e_source(e);
+	dest = g_e_dest(e);
+        if (source == NIL(vertex_t)) {
+	    fail("g_check: Edge has no source");
+	}
+	if (dest == NIL(vertex_t)) {
+	    fail("g_check: Edge has no destination");
+	}
+	if (g_vertex_graph(source) != g_vertex_graph(dest)) {
+	    fail("g_check: Edge connects different graphs");
+	}
+	found = FALSE;
+	foreach_out_edge (source,gen2,test) {
+	    if (test == e) {
+	        found = TRUE;
+		(void) lsFinish(gen2);
+		break;
+	    }
+	}
+	if (found == FALSE) {
+	    fail("g_check: Vertex does not point back to edge");
+	}
+	found = FALSE;
+	foreach_in_edge (dest,gen2,test) {
+	    if (test == e) {
+	        found = TRUE;
+		(void) lsFinish(gen2);
+		break;
+	    }
+	}
+	if (found == FALSE) {
+	    fail("g_check: Vertex does not point back to edge");
+	}
+    }
+    foreach_vertex (g,gen,v) {
+        if (g_vertex_graph(v) != g) {
+	    fail("g_check: Vertex not a member of graph");
+	}
+        if (lsLength(g_get_in_edges(v)) + lsLength(g_get_out_edges(v)) == 0) {
+	    (void) fprintf(stderr,"Warning: g_check: Unconnected vertex\n");
+	    continue;
+	}
+	foreach_in_edge(v,gen2,test) {
+	    if (g_e_dest(test) != v) {
+	        fail("g_check: Edge does not point back to vertex");
+	    }
+	}
+	foreach_out_edge(v,gen2,test) {
+	    if (g_e_source(test) != v) {
+	        fail("g_check: Edge does not point back to vertex");
+	    }
+	}
+    }
+}
+
+graph_t *
+g_dup(
+  graph_t *g,
+  gGeneric (*f_copy_g)(gGeneric),
+  gGeneric (*f_copy_v)(gGeneric),
+  gGeneric (*f_copy_e)(gGeneric))
+{
+    graph_t *newg;
+    vertex_t *v, *new_v, *from, *to;
+    edge_t *e, *new_e;
+    st_table *ptrtable = st_init_table(st_ptrcmp,st_ptrhash);
+    lsGen gen;
+
+    newg = g_alloc();
+    if (g == NIL(graph_t)) {
+        return(newg);
+    }
+
+    if (f_copy_g == (gGeneric (*)(gGeneric)) NULL) {
+        newg->user_data = g->user_data;
+    }
+    else {
+        newg->user_data = (*f_copy_g)(g->user_data);
+    }
+    foreach_vertex (g,gen,v) {
+        new_v = g_add_vertex(newg);
+	if (f_copy_v == (gGeneric (*)(gGeneric)) NULL) {
+	    new_v->user_data = v->user_data;
+	}
+	else {
+	    new_v->user_data = (*f_copy_v)(v->user_data);
+	}
+	(void) st_insert(ptrtable,(char *) v,(char *) new_v);
+    }
+    foreach_edge (g,gen,e) {
+        (void) st_lookup(ptrtable,g_e_source(e),&from);
+	(void) st_lookup(ptrtable,g_e_dest(e),&to);
+	new_e = g_add_edge(from,to);
+	if (f_copy_e == (gGeneric (*)(gGeneric)) NULL) {
+	    new_e->user_data = e->user_data;
+	}
+	else {
+	    new_e->user_data = (*f_copy_e)(e->user_data);
+	}
+    }
+    st_free_table(ptrtable);
+    return(newg);
+}
+
+array_t *
+g_graph_sort(graph_t *g, int (*cmp)(const void *, const void *))
+{
+    int i;
+    lsGen gen;
+    vertex_t *v;
+    array_t *v_array;
+
+    i = 0;
+    v_array = array_alloc(vertex_t *,0);
+
+    foreach_vertex (g,gen,v) {
+        array_insert(vertex_t *,v_array,i++,v);
+    }
+    array_sort(v_array,cmp);
+    return(v_array);
+}
+
+lsList
+g_get_edges(graph_t *g)
+{
+    if (g == NIL(graph_t)) {
+        fail("g_get_edges: Null graph");
+    }
+    return(((graph_t_int *) g)->e_list);
+}
+
+lsList
+g_get_in_edges(vertex_t *v)
+{
+    if (v == NIL(vertex_t)) {
+        fail("g_get_in_edges: Null vertex");
+    }
+    return(((vertex_t_int *) v)->in_list);
+}
+
+lsList
+g_get_out_edges(vertex_t *v)
+{
+    if (v == NIL(vertex_t)) {
+        fail("g_get_out_edges: Null vertex");
+    }
+    return(((vertex_t_int *) v)->out_list);
+}
+
+edge_t *
+g_add_edge(vertex_t *v1, vertex_t *v2)
+{
+    edge_t_int *edge;
+    lsHandle handle;
+    graph_t *g;
+
+    if (v1 == NIL(vertex_t) || v2 == NIL(vertex_t)) {
+        fail("g_add_edge: Null vertex");
+    }
+    g = g_vertex_graph(v1);
+    if (g != g_vertex_graph(v2)) {
+        fail("g_add_edge: Edge connects different graphs");
+    }
+    edge = ALLOC(edge_t_int,1);
+    (void) lsNewEnd(g_get_edges(g),(lsGeneric) edge,&handle);
+    edge->user_data = (gGeneric) NULL;
+    edge->from = (vertex_t_int *) v1;
+    edge->to = (vertex_t_int *) v2;
+    edge->id = g_unique_id++;
+    edge->handle = handle;
+    (void) lsNewEnd(g_get_out_edges(v1),(lsGeneric) edge,LS_NH);
+    (void) lsNewEnd(g_get_in_edges(v2),(lsGeneric) edge,LS_NH);
+
+    return((edge_t *) edge);
+}
+
+static void
+g_del_from_list(lsList list, lsGeneric item)
+{
+    lsGen gen;
+    lsGeneric looking,dummy;
+    lsHandle handle;
+
+    gen = lsStart(list);
+    while (lsNext(gen,&looking,&handle) != LS_NOMORE) {
+        if (item == looking) {
+	    if (lsRemoveItem(handle,&dummy) != LS_OK) {
+	        fail("g_del_from_list: Can't remove edge");
+	    }
+	    break;
+	}
+    }
+    (void) lsFinish(gen);
+}
+
+void
+g_delete_edge(edge_t *e, void (*f_free_e)(gGeneric))
+{
+    lsGeneric junk;
+
+    if (e == NIL(edge_t)) {
+        fail("g_delete_edge: Null edge");
+    }
+    g_del_from_list(g_get_out_edges(g_e_source(e)),(lsGeneric) e);
+    g_del_from_list(g_get_in_edges(g_e_dest(e)),(lsGeneric) e);
+
+    (void) lsRemoveItem(((edge_t_int *) e)->handle,&junk);
+    if (f_free_e != (void (*)(gGeneric)) NULL) {
+        (*f_free_e)(e->user_data);
+    }
+    FREE(e);
+}
+
+graph_t *
+g_edge_graph(edge_t *e)
+{
+    if (e == NIL(edge_t)) {
+        fail("g_edge_graph: Null edge");
+    }
+    return((graph_t *) (((edge_t_int *) e)->to->g));
+}
+
+vertex_t *
+g_e_source(edge_t *e)
+{
+    if (e == NIL(edge_t)) {
+        fail("g_e_source: Null edge");
+    }
+    return((vertex_t *) (((edge_t_int *) e)->from));
+}
+
+vertex_t *
+g_e_dest(edge_t *e)
+{
+    if (e == NIL(edge_t)) {
+        fail("g_e_dest: Null edge");
+    }
+    return((vertex_t *) (((edge_t_int *) e)->to));
+}
+
+
+lsList
+g_get_vertices(graph_t *g)
+{
+    if (g == NIL(graph_t)) {
+        fail("g_get_vertices: Null graph");
+    }
+    return(((graph_t_int *) g)->v_list);
+}
+
+vertex_t *
+g_add_vertex(graph_t *g)
+{
+    lsHandle handle;
+    vertex_t_int *vert;
+
+    if (g == NIL(graph_t)) {
+        fail("g_add_vertex: Null graph");
+    }
+    vert = ALLOC(vertex_t_int,1);
+    if (lsNewEnd(g_get_vertices(g),(lsGeneric) vert,&handle) != LS_OK) {
+        fail("g_add_vertex: Can't add vertex");
+    }    
+    vert->user_data = (gGeneric) NULL;
+    vert->g = (graph_t_int *) g;
+    vert->in_list = lsCreate();
+    vert->out_list = lsCreate();
+    vert->id = g_unique_id++;
+    vert->handle = handle;
+    return((vertex_t *) vert);
+}
+
+void
+g_delete_vertex(
+  vertex_t *v,
+  void (*f_free_v)(gGeneric),
+  void (*f_free_e)(gGeneric))
+{
+    edge_t *e;
+    lsGeneric junk;
+    lsGen gen;
+
+    if (v == NIL(vertex_t)) {
+        fail("g_delete_vertex: Null vertex");
+    }
+    if (f_free_v != (void (*)(gGeneric)) NULL) {
+        (*f_free_v)(v->user_data);
+    }
+    foreach_in_edge (v,gen,e) {
+        g_del_from_list(g_get_out_edges(g_e_source(e)),(lsGeneric) e);
+	if (f_free_e != (void (*)(gGeneric)) NULL) {
+	    (*f_free_e)(e->user_data);
+	}
+	if (lsRemoveItem(((edge_t_int *) e)->handle,&junk) != LS_OK) {
+	    fail("g_delete_vertex: Can't remove edge from graph");
+	}
+	FREE(e);
+    }
+    foreach_out_edge (v,gen,e) {
+        g_del_from_list(g_get_in_edges(g_e_dest(e)),(lsGeneric) e);
+	if (f_free_e != (void (*)(gGeneric)) NULL) {
+	    (*f_free_e)(e->user_data);
+	}
+	if (lsRemoveItem(((edge_t_int *) e)->handle,&junk) != LS_OK) {
+	    fail("g_delete_vertex: Can't remove edge from graph");
+	}
+	FREE(e);
+    }
+    (void) lsDestroy(g_get_out_edges(v),(void (*)(lsGeneric)) NULL);
+    (void) lsDestroy(g_get_in_edges(v),(void (*)(lsGeneric)) NULL);
+    (void) lsRemoveItem(((vertex_t_int *) v)->handle,&junk);
+    FREE(v);
+}
+
+graph_t *
+g_vertex_graph(vertex_t *v)
+{
+    if (v == NIL(vertex_t)) {
+        fail("g_vertex_graph: Null vertex");
+    }
+    return((graph_t *) ((vertex_t_int *) v)->g);
+}
Index: /vis_dev/glu-2.1/src/graph/graph.h
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph.h	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph.h	(revision 8)
@@ -0,0 +1,70 @@
+#ifndef GRAPH_H
+#define GRAPH_H
+
+typedef char *gGeneric;
+
+typedef struct graph_struct {
+	gGeneric user_data;
+} graph_t;
+
+typedef struct vertex_struct {
+	gGeneric user_data;
+} vertex_t;
+
+typedef struct edge_struct {
+	gGeneric user_data;
+} edge_t;
+
+typedef void (*GRAPH_PFV)(gGeneric);
+typedef gGeneric (*GRAPH_PFG)(gGeneric);
+
+EXTERN graph_t *g_alloc ARGS((void));
+EXTERN void g_free ARGS((graph_t *, void(*)(gGeneric), void(*)(gGeneric), void(*)(gGeneric)));
+EXTERN void g_check ARGS((graph_t *));
+EXTERN graph_t *g_dup ARGS((graph_t *, gGeneric(*)(gGeneric), gGeneric(*)(gGeneric), gGeneric(*)(gGeneric)));
+
+EXTERN lsList g_get_vertices ARGS((graph_t *));
+
+#define foreach_vertex(g, lgen, v)				\
+	for (lgen = lsStart(g_get_vertices(g));			\
+		lsNext(lgen, &v, LS_NH) == LS_OK	\
+		   || ((void) lsFinish(lgen), 0); )
+
+#define foreach_edge(g, lgen, e)				\
+	for (lgen = lsStart(g_get_edges(g));			\
+		lsNext(lgen, &e, LS_NH) == LS_OK	\
+		   || ((void) lsFinish(lgen), 0); )
+
+EXTERN vertex_t *g_add_vertex ARGS((graph_t *));
+EXTERN void g_delete_vertex ARGS((vertex_t *, void (*)(gGeneric), void (*)(gGeneric)));
+EXTERN graph_t *g_vertex_graph ARGS((vertex_t *));
+
+EXTERN lsList g_get_edges ARGS((graph_t *));
+EXTERN lsList g_get_in_edges ARGS((vertex_t *));
+EXTERN lsList g_get_out_edges ARGS((vertex_t *));
+
+#define foreach_in_edge(v, lgen, e)				\
+	for (lgen = lsStart(g_get_in_edges(v));			\
+		lsNext(lgen, &e, LS_NH) == LS_OK	\
+		   || ((void) lsFinish(lgen), 0); )
+
+#define foreach_out_edge(v, lgen, e)				\
+	for (lgen = lsStart(g_get_out_edges(v));		\
+		lsNext(lgen, &e, LS_NH) == LS_OK	\
+		   ||  ((void) lsFinish(lgen), 0); )
+
+EXTERN edge_t *g_add_edge ARGS((vertex_t *, vertex_t *));
+EXTERN void g_delete_edge ARGS((edge_t *, void (*)(gGeneric)));
+EXTERN graph_t *g_edge_graph ARGS((edge_t *));
+EXTERN vertex_t *g_e_source ARGS((edge_t *));
+EXTERN vertex_t *g_e_dest ARGS((edge_t *));
+
+EXTERN array_t *g_dfs ARGS((graph_t *));
+EXTERN int g_is_acyclic ARGS((graph_t *));
+EXTERN array_t *g_graph_sort ARGS((graph_t *, int (*)(const void *, const void *)));
+
+EXTERN st_table *g_reachable ARGS((graph_t *, st_table *));
+EXTERN st_table *g_EF ARGS((graph_t *, st_table *));
+EXTERN st_table *g_SCC ARGS((graph_t *, st_table *));
+
+#endif
Index: /vis_dev/glu-2.1/src/graph/graph.make
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph.make	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += graph.c graph_dfs.c graph_s.c
+HEADERS += graph.h graph_int.h graph_static.h graph_static_int.h
+MISC += graph.doc graph_static.doc com_graph.c
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/graph/graph_dfs.c
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph_dfs.c	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph_dfs.c	(revision 8)
@@ -0,0 +1,264 @@
+/*
+ * $Id: graph_dfs.c,v 1.9 2005/04/15 23:24:21 fabio Exp $
+ */
+
+#include "graph_int.h"
+
+static vertex_t *
+find_an_end_vertex(vertex_t *v, st_table *visit_list)
+{
+    edge_t *e;
+    vertex_t *dest;
+    lsGen gen;
+
+    if (lsLength(g_get_out_edges(v)) == 0) {
+        return(v);
+    }
+    foreach_out_edge (v,gen,e) {
+	(void) lsFinish(gen);
+	dest = g_e_dest(e);
+        if (st_insert(visit_list,(char *) dest,(char *) 0) == 1) {
+	    return(NIL(vertex_t));
+	}
+	return(find_an_end_vertex(dest,visit_list));
+        /* NOTREACHED */
+    }
+    /* no free out_edges */
+    return(NIL(vertex_t));
+}
+
+static int
+dfs_recurr(vertex_t *v, st_table *dfs_list, array_t *dfs_array) 
+{
+    edge_t *e;
+    lsGen gen;
+    int val;
+
+    if (st_lookup_int(dfs_list,(char *) v, &val)) {
+        return(val == 0);
+    }
+    (void) st_insert(dfs_list,(char *) v,(char *) 1);
+
+    foreach_in_edge (v,gen,e) {
+        if (!dfs_recurr(g_e_source(e),dfs_list,dfs_array)) {
+	    return(0);
+	}
+    }
+    (void) st_insert(dfs_list,(char *) v,(char *) 0);
+    array_insert_last(vertex_t *,dfs_array,v);
+    return(1);
+}
+
+static array_t *
+g_dfs_int(graph_t *g)
+{
+    vertex_t *v;
+    lsGen gen;
+    array_t *dfs_array;
+    st_table *visit_list,*dfs_list;
+    int cycle = FALSE;
+
+    dfs_array = array_alloc(vertex_t *,0);
+    visit_list = st_init_table(st_ptrcmp,st_ptrhash);
+    dfs_list = st_init_table(st_ptrcmp,st_ptrhash);
+
+    foreach_vertex (g,gen,v) {
+        if (!st_is_member(dfs_list,(char *) v)) {
+	    (void) st_insert(visit_list,(char *) v,(char *) 0);
+	    v = find_an_end_vertex(v,visit_list);
+	    if (v == NIL(vertex_t) || !dfs_recurr(v,dfs_list,dfs_array)) {
+	        cycle = TRUE;
+		(void) lsFinish(gen);
+		break;
+	    }
+	}
+    }
+
+    st_free_table(visit_list);
+    st_free_table(dfs_list);
+    if (cycle == TRUE) {
+        array_free(dfs_array);
+        return(NIL(array_t));
+    }
+    return(dfs_array);
+}
+
+array_t *
+g_dfs(graph_t *g)
+{
+    array_t *x;
+
+    x = g_dfs_int(g);
+    if (x == NIL(array_t)) {
+        fail("g_dfs: Graph has cycle");
+    }
+    return(x);
+}
+
+int
+g_is_acyclic(graph_t *g)
+{
+    array_t *x;
+
+    x = g_dfs_int(g);
+    if (x) {
+        array_free(x);
+	return(TRUE);
+    }
+    return(FALSE);
+}
+
+
+static int
+reachable_recurr(vertex_t *v, st_table *dfs_list)
+{
+    edge_t *e;
+    lsGen gen;
+    int val;
+
+    if (st_lookup_int(dfs_list,(char *) v, &val)) {
+        return(val == 0);
+    }
+    (void) st_insert(dfs_list,(char *) v,(char *) 1);
+
+    foreach_out_edge (v,gen,e) {
+        reachable_recurr(g_e_dest(e),dfs_list);
+    }
+    (void) st_insert(dfs_list,(char *) v,(char *) 0);
+
+    return(1);
+}
+
+/* compute reachable states from the initial states */
+st_table *
+g_reachable(graph_t *g, st_table *init)
+{
+    vertex_t *v;
+    st_table *dfs_list;
+    st_generator *stgen;
+
+    dfs_list = st_init_table(st_ptrcmp, st_ptrhash);
+
+    st_foreach_item(init, stgen, &v, NIL(char *)) {
+	reachable_recurr(v,dfs_list);
+    }
+
+    return (dfs_list);
+}
+
+
+static int
+EF_recurr(vertex_t *v, st_table *EF_list)
+{
+    edge_t *e;
+    lsGen gen;
+    int val;
+
+    if (st_lookup_int(EF_list,(char *) v, &val)) {
+        return(val == 0);
+    }
+    (void) st_insert(EF_list,(char *) v,(char *) 1);
+
+    foreach_in_edge (v,gen,e) {
+        EF_recurr(g_e_source(e),EF_list);
+    }
+    (void) st_insert(EF_list,(char *) v,(char *) 0);
+
+    return(1);
+}
+
+/* compute EF(goal) of an automaton, might include unreachable states */
+st_table *
+g_EF(graph_t *g, st_table *goal)
+{
+    vertex_t *v;
+    st_table *EF_list;
+    st_generator *stgen;
+
+    EF_list = st_init_table(st_ptrcmp, st_ptrhash);
+
+    st_foreach_item(goal, stgen, &v, NIL(char *)) {
+	EF_recurr(v,EF_list);
+    }
+
+    return (EF_list);
+}
+
+static void
+searchSCC(
+  vertex_t *v,
+  st_table *scc,
+  st_table *old /*visited*/,
+  lsList   stack,
+  st_table *onstack,
+  int *countr)
+{
+    int lowlink_v, dfnumber_v, lowlink_w, dfnumber_w;
+    vertex_t *x, *w;
+    st_table *component;
+    lsGen gen;
+    edge_t *e;
+
+    lowlink_v = dfnumber_v = *countr;
+    (*countr)++;
+    st_insert(old, (char *)v, (char *)(long)dfnumber_v);
+    st_insert(onstack, (char *)v, (char *)(long)lowlink_v);
+    lsNewBegin(stack, (lsGeneric)v, NIL(lsHandle));
+
+    foreach_out_edge (v,gen,e) {
+	w = g_e_dest(e);
+	if (!st_is_member(old, (char *)w)) {
+	    searchSCC(w,scc,old,stack,onstack,countr);
+	    if(st_lookup_int(onstack, (char *)w, &lowlink_w) &&
+	       lowlink_w < lowlink_v) {
+		lowlink_v = lowlink_w;
+		st_insert(onstack, (char *)v, (char *)(long)lowlink_v);
+	    }
+	}else {
+	    st_lookup_int(old, (char *)w, &dfnumber_w);
+	    if (dfnumber_w < dfnumber_v && st_is_member(onstack, (char *)w)) {
+		if (dfnumber_w < lowlink_v) {
+		    lowlink_v = dfnumber_w;
+		    st_insert(onstack, (char *)v, (char *)(long)lowlink_v);
+		}
+	    }
+	}
+    }
+
+    /* put current SCC into st_table, and then insert into 'scc' */
+    if (dfnumber_v == lowlink_v) {
+	component = st_init_table(st_ptrcmp, st_ptrhash);
+	while (lsDelBegin(stack, &x) != LS_NOMORE) {
+	    st_insert(component, (char *)x, NIL(char)); 
+	    st_delete(onstack, &x, NIL(char *));
+	    if (v == x) break;
+	}
+	st_insert(scc, (char *)component, NIL(char)); /* is component fair? */
+    }
+}
+
+/* compute the strongly connected components of a graph (Tarjan's alg.) */
+st_table *
+g_SCC(graph_t *g, st_table *init)
+{
+    vertex_t *v;
+    lsList stack;
+    st_table *old, *onstack, *scc;
+    st_generator *stgen;
+    int countr = 0;
+
+    scc = st_init_table(st_ptrcmp, st_ptrhash);
+    
+    stack = lsCreate();
+    old = st_init_table(st_ptrcmp, st_ptrhash);
+    onstack = st_init_table(st_ptrcmp, st_ptrhash);
+    st_foreach_item(init, stgen, &v, NIL(char *)) {
+	if (!st_is_member(old, (char *)v))
+	    searchSCC(v,scc,old,stack,onstack,&countr);
+    }
+    lsDestroy(stack, (void (*)(lsGeneric))0 );
+    st_free_table(old);
+    st_free_table(onstack);
+
+    return scc;
+}
Index: /vis_dev/glu-2.1/src/graph/graph_int.h
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph_int.h	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph_int.h	(revision 8)
@@ -0,0 +1,31 @@
+#include "util.h"
+#include "list.h"
+#include "array.h"
+#include "st.h"
+#include "graph.h"
+
+typedef struct graph_struct_int {
+	gGeneric user_data;
+	lsList v_list;
+	lsList e_list;
+} graph_t_int;
+
+typedef struct vertex_struct_int {
+	gGeneric user_data;
+	graph_t_int *g;
+	lsList in_list;
+	lsList out_list;
+	int id;
+	lsHandle handle;	/* for quick deletion in the graph v_list */
+} vertex_t_int;
+
+typedef struct edge_struct_int {
+	gGeneric user_data;
+	vertex_t_int *from;
+	vertex_t_int *to;
+	int id;
+	lsHandle handle;	/* for quick deletion in the graph e_list */
+} edge_t_int;
+
+EXTERN void del_from_list(lsList, lsGeneric);
+extern int g_unique_id; 
Index: /vis_dev/glu-2.1/src/graph/graph_s.c
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph_s.c	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph_s.c	(revision 8)
@@ -0,0 +1,367 @@
+/*
+ * $Id: graph_s.c,v 1.4 2002/08/25 20:01:57 fabio Exp $
+ */
+
+#include "graph_int.h"
+#include "graph_static_int.h"
+
+#define g_field(graph)		((g_field_t *) (graph)->user_data)
+
+graph_t *
+g_alloc_static(int ng, int nv, int ne)
+{
+    graph_t *g;
+    g_field_t *gf;;
+
+    g = g_alloc();
+    gf = ALLOC(g_field_t,1);
+    gf->num_g_slots = ng;
+    gf->num_v_slots = nv;
+    gf->num_e_slots = ne;
+    gf->user_data = (gGeneric) ALLOC(gGeneric, ng);
+
+    g->user_data = (gGeneric) gf;
+    return(g);
+}
+
+void
+g_free_static(
+  graph_t *g,
+  void (*f_free_g)(gGeneric),
+  void (*f_free_v)(gGeneric),
+  void (*f_free_e)(gGeneric))
+{
+    vertex_t *v;
+    edge_t *e;
+    lsGen gen;
+    lsGeneric junk;
+
+    if (g == NIL(graph_t)) {
+        return;
+    }
+    if (f_free_g != (void (*)(gGeneric)) NULL) {
+        (*f_free_g)(g_field(g)->user_data);
+    }
+    FREE(g_field(g)->user_data);
+    FREE(g->user_data);
+
+    foreach_vertex(g,gen,v) {
+        if (f_free_v != (void (*)(gGeneric)) NULL) {
+	    (*f_free_v)(v->user_data);
+	}
+	FREE(v->user_data);
+	(void) lsDestroy(g_get_in_edges(v),(void (*)(lsGeneric)) NULL);
+	(void) lsDestroy(g_get_out_edges(v),(void (*)(lsGeneric)) NULL);
+	(void) lsRemoveItem(((vertex_t_int *) v)->handle,&junk);
+	FREE(v);
+    }
+    foreach_edge(g,gen,e) {
+        if (f_free_e != (void (*)(gGeneric)) NULL) {
+	    (*f_free_e)(e->user_data);
+	}
+	FREE(e->user_data);
+	(void) lsRemoveItem(((edge_t_int *) e)->handle,&junk);
+	FREE(e);
+    }
+    g_free(g,(void (*)(gGeneric)) NULL,(void (*)(gGeneric)) NULL,
+	   (void (*)(gGeneric)) NULL);
+}
+
+static graph_t *theGraph;
+
+static gGeneric
+copy_v_slots(gGeneric user_data)
+{
+    int i;
+    int num_v_slots = g_field(theGraph)->num_v_slots;
+    gGeneric *news = ALLOC(gGeneric,num_v_slots);
+
+    for (i = 0; i < num_v_slots; i++) {
+        news[i] = ((gGeneric *) user_data)[i];
+    }
+    return((gGeneric) news);
+}
+
+static gGeneric
+copy_e_slots(gGeneric user_data)
+{
+    int i;
+    int num_e_slots = g_field(theGraph)->num_e_slots;
+    gGeneric *news = ALLOC(gGeneric,num_e_slots);
+
+    for (i = 0; i < num_e_slots; i++) {
+        news[i] = ((gGeneric *) user_data)[i];
+    }
+    return((gGeneric) news);
+}    
+
+graph_t *
+g_dup_static(
+  graph_t *g,
+  gGeneric (*f_copy_g)(gGeneric),
+  gGeneric (*f_copy_v)(gGeneric),
+  gGeneric (*f_copy_e)(gGeneric))
+{
+    g_field_t *gf, *gf2;
+    graph_t *g2;
+    gGeneric *news;
+    int i;
+
+    if (f_copy_v == (gGeneric (*)(gGeneric)) NULL) {
+        theGraph = g;        
+        f_copy_v = copy_v_slots;
+    }
+    if (f_copy_e == (gGeneric (*)(gGeneric)) NULL) {
+        theGraph = g;
+	f_copy_e = copy_e_slots;
+    }
+    g2 = g_dup(g,(gGeneric (*)(gGeneric)) NULL,f_copy_v,f_copy_e);
+    if (g == NIL(graph_t)) {
+        return(g2);
+    }
+
+    gf = g_field(g);
+    gf2 = ALLOC(g_field_t,1);
+    gf2->num_g_slots = gf->num_g_slots;
+    gf2->num_v_slots = gf->num_v_slots;
+    gf2->num_e_slots = gf->num_e_slots;
+    if (f_copy_g == (gGeneric (*)(gGeneric)) NULL) {
+        news = ALLOC(gGeneric,gf->num_g_slots);
+	for (i = gf->num_g_slots - 1; i >= 0; i--) {
+	    news[i] = ((gGeneric *) gf->user_data)[i];
+	}
+	gf2->user_data = (gGeneric) news;
+    }
+    else {
+        gf2->user_data = (*f_copy_g)(gf->user_data);
+    }
+    g2->user_data = (gGeneric) gf2;        
+    return(g2);
+}
+
+
+void
+g_set_g_slot_static(graph_t *g, int i, gGeneric val)
+{
+    if (g == NIL(graph_t)) {
+        fail("g_set_g_slot_static: Null graph");
+    }
+    ((gGeneric *) g_field(g)->user_data)[i] = val;
+    return;
+}
+
+
+gGeneric
+g_get_g_slot_static(graph_t *g, int i)
+{
+    if (g == NIL(graph_t)) {
+        fail("g_get_g_slot_static: Null graph");
+    }
+    return ((gGeneric *) g_field(g)->user_data)[i];
+}
+
+void
+g_copy_g_slots_static(graph_t *g1, graph_t *g2, gGeneric (*f_copy_g)(gGeneric))
+{
+    g_field_t *gf1,*gf2;
+    gGeneric slots1,*slots2;
+    int n;
+
+    if (g1 == NIL(graph_t) || g2 == NIL(graph_t)) {
+        fail("g_copy_g_slots_static: Null graph");
+    }
+    gf1 = g_field(g1);
+    gf2 = g_field(g2);
+    n = gf1->num_g_slots;
+
+    if (n != gf2->num_g_slots) {
+        fail("g_copy_g_slots_static: Graphs have different numbers of slots");
+    }
+    slots1 = gf1->user_data;
+    slots2 = (gGeneric *) gf2->user_data;
+    if (f_copy_g == (gGeneric (*)(gGeneric)) NULL) {
+        for (n-- ; n >= 0; n--) {
+	    slots2[n] = ((gGeneric *) slots1)[n];
+	}
+    }
+    else {
+        FREE(slots2);
+        gf2->user_data = (*f_copy_g)(slots1);
+    }
+}
+
+
+edge_t * 
+g_add_edge_static(vertex_t *v1, vertex_t *v2)
+{
+    edge_t *e;
+    g_field_t *gf;
+
+    if (v1 == NIL(vertex_t) || v2 == NIL(vertex_t)) {
+        fail("g_add_edge_static: Null vertex");
+    }
+    e = g_add_edge(v1, v2);
+    gf = g_field(g_edge_graph(e));
+    e->user_data = (gGeneric) ALLOC(gGeneric, gf->num_e_slots);
+    return(e);
+}
+
+
+void
+g_delete_edge_static(edge_t *e, void (*f_free_e)(gGeneric))
+{
+    if (e == NIL(edge_t)) {
+        fail("g_delete_edge_static: Null edge");
+    }
+    if (f_free_e != (void (*)(gGeneric)) NULL) {
+        (*f_free_e)(e->user_data);
+    }
+    FREE(e->user_data);
+    g_delete_edge(e,(void (*)(gGeneric)) NULL);
+}
+
+
+void
+g_set_e_slot_static(edge_t *e, int i, gGeneric val)
+{
+    if (e == NIL(edge_t)) {
+        fail("g_set_e_slot_static: Null edge");
+    }
+    ((gGeneric *) e->user_data)[i] = val;
+}
+
+
+gGeneric 
+g_get_e_slot_static(edge_t *e, int i)
+{
+    if (e == NIL(edge_t)) {
+        fail("g_get_e_slot_static: Null edge");
+    }
+    return((gGeneric *) e->user_data)[i];
+}
+
+void
+g_copy_e_slots_static(edge_t *e1, edge_t *e2, gGeneric (*f_copy_e)(gGeneric))
+{
+    int n;
+    gGeneric slots1,*slots2;
+
+    if (e1 == NIL(edge_t) || e2 == NIL(edge_t)) {
+        fail("g_copy_e_slots_static: Null edge");
+    }
+    n = g_field(g_edge_graph(e1))->num_e_slots;
+
+    if (n != g_field(g_edge_graph(e2))->num_e_slots) {
+        fail("g_copy_e_slots_static: Edges have differing numbers of slots");
+    }
+    slots1 = e1->user_data;
+    slots2 = (gGeneric *) e2->user_data;
+    if (f_copy_e == (gGeneric (*)(gGeneric)) NULL) {
+        for (n--; n >= 0; n--) {
+	    slots2[n] = ((gGeneric *) slots1)[n];
+	}
+    }
+    else {
+        FREE(slots2);
+        e2->user_data = (*f_copy_e)(slots1);
+    }
+}
+
+
+vertex_t *
+g_add_vertex_static(graph_t *g)
+{
+    g_field_t *gf;
+    vertex_t *v;
+
+    if (g == NIL(graph_t)) {
+        fail("g_add_vertex_static: Null graph");
+    }
+    gf = g_field(g);
+    v = g_add_vertex(g);
+    v->user_data = (gGeneric) ALLOC(gGeneric, gf->num_v_slots);
+    return(v);
+}
+    
+
+void
+g_delete_vertex_static(
+  vertex_t *v,
+  void (*f_free_v)(gGeneric),
+  void (*f_free_e)(gGeneric))
+{
+    edge_t *e;
+    lsGen gen;
+
+    if (v == NIL(vertex_t)) {
+        fail("g_delete_vertex_static: Null vertex");
+    }
+    foreach_in_edge(v, gen, e) {
+        if (f_free_e != (void (*)(gGeneric)) NULL) {
+	    (*f_free_e)(e->user_data);
+	}
+	FREE(e->user_data);
+    }
+    foreach_out_edge(v, gen, e) {
+        if (f_free_e != (void (*)(gGeneric)) NULL) {
+	    (*f_free_e)(e->user_data);
+	}
+	FREE(e->user_data);
+    }
+    if (f_free_v != (void (*)(gGeneric)) NULL) {
+        (*f_free_v)(v->user_data);
+    }
+    FREE(v->user_data);
+    g_delete_vertex(v, (void (*)(gGeneric)) NULL, (void (*)(gGeneric)) NULL);
+}
+
+
+void
+g_set_v_slot_static(vertex_t *v, int i, gGeneric val)
+{
+    if (v == NIL(vertex_t)) {
+        fail("g_set_v_slot_static: Null vertex");
+    }
+    ((gGeneric *) v->user_data)[i] = val;
+}
+
+
+gGeneric
+g_get_v_slot_static(vertex_t *v, int i)
+{
+    if (v == NIL(vertex_t)) {
+        fail("g_get_v_slot_static: Null vertex");
+    }
+    return ((gGeneric *) v->user_data)[i]; 
+}
+
+void
+g_copy_v_slots_static(
+  vertex_t *v1,
+  vertex_t *v2,
+  gGeneric (*f_copy_v)(gGeneric))
+{
+    int n;
+    gGeneric slots1,*slots2;
+    
+    if (v1 == NIL(vertex_t) || v2 == NIL(vertex_t)) {
+        fail("g_copy_v_slots_static: Null vertex");
+    }
+    n = g_field(g_vertex_graph(v1))->num_v_slots;
+
+    if (n != g_field(g_vertex_graph(v2))->num_v_slots) {
+        fail("g_copy_v_slots_static: Vertices have differing numbers of slots");
+    }
+    slots1 = v1->user_data;
+    slots2 = (gGeneric *) v2->user_data;
+    if (f_copy_v == (gGeneric (*)(gGeneric)) NULL) {
+        for (n--; n >= 0; n--) {
+	    slots2[n] = ((gGeneric *) slots1)[n];
+	}
+    }
+    else {
+        FREE(slots2);
+        v2->user_data = (*f_copy_v)(slots1);
+    }
+}
+
Index: /vis_dev/glu-2.1/src/graph/graph_static.h
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph_static.h	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph_static.h	(revision 8)
@@ -0,0 +1,23 @@
+/*
+ * $Id: graph_static.h,v 1.3 2002/08/27 15:28:21 fabio Exp $
+ *
+ */
+
+/******************************* graph_static.h ************************/
+
+EXTERN graph_t *g_alloc_static ARGS((int, int, int));
+EXTERN void g_free_static ARGS((graph_t *, void (*)(gGeneric), void (*)(gGeneric), void (*)(gGeneric)));
+EXTERN graph_t *g_dup_static ARGS((graph_t *, char *(*)(gGeneric), char *(*)(gGeneric), char *(*)(gGeneric)));
+EXTERN void g_set_g_slot_static ARGS((graph_t *, int, char *));
+EXTERN char *g_get_g_slot_static ARGS((graph_t *, int));
+EXTERN void g_copy_g_slots_static ARGS((graph_t *, graph_t *, char *(*)(gGeneric)));
+EXTERN vertex_t *g_add_vertex_static ARGS((graph_t *));
+EXTERN void g_delete_vertex_static ARGS((vertex_t *, void (*)(gGeneric), void (*)(gGeneric)));
+EXTERN void g_set_v_slot_static ARGS((vertex_t *, int, char *));
+EXTERN char *g_get_v_slot_static ARGS((vertex_t *, int));
+EXTERN void g_copy_v_slots_static ARGS((vertex_t *, vertex_t *, char *(*)(gGeneric)));
+EXTERN edge_t *g_add_edge_static ARGS((vertex_t *, vertex_t *));
+EXTERN void g_delete_edge_static ARGS((edge_t *, void (*)(gGeneric)));
+EXTERN void g_set_e_slot_static ARGS((edge_t *, int, char *));
+EXTERN char *g_get_e_slot_static ARGS((edge_t *, int));
+EXTERN void g_copy_e_slots_static ARGS((edge_t *, edge_t *, char *(*)(gGeneric)));
Index: /vis_dev/glu-2.1/src/graph/graph_static_int.h
===================================================================
--- /vis_dev/glu-2.1/src/graph/graph_static_int.h	(revision 8)
+++ /vis_dev/glu-2.1/src/graph/graph_static_int.h	(revision 8)
@@ -0,0 +1,13 @@
+/*
+ * $Id: graph_static_int.h,v 1.2 2002/08/27 15:29:01 fabio Exp $
+ *
+ */
+
+#include "graph_static.h"
+
+typedef struct g_field_struct {
+    int num_g_slots;
+    int num_v_slots;
+    int num_e_slots;
+    gGeneric user_data;
+} g_field_t;
Index: /vis_dev/glu-2.1/src/heap/heap.c
===================================================================
--- /vis_dev/glu-2.1/src/heap/heap.c	(revision 8)
+++ /vis_dev/glu-2.1/src/heap/heap.c	(revision 8)
@@ -0,0 +1,545 @@
+/**CFile***********************************************************************
+
+  FileName    [heap.c]
+
+  PackageName [heap]
+
+  Synopsis    [Heap-based priority queue.]
+
+  Description [This file contains the functions to maintain a priority
+  queue implemented as a heap.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "heapInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: heap.c,v 1.18 2005/05/18 19:25:43 jinh Exp $";
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void HeapHeapify ARGS((Heap_t *heap));
+static void HeapHeapifyCompare ARGS((Heap_t *heap));
+static int HeapResize ARGS((Heap_t *heap));
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a priority queue.]
+
+  Description [Initializes a priority queue. Returns a pointer to the
+  heap if successful; NULL otherwise.  The queue is implemented as a
+  heap.  The first element of the heap is the one with the smallest
+  key.]
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapFree]
+
+******************************************************************************/
+Heap_t *
+Heap_HeapInit(
+  int length)
+{
+  Heap_t *heap;
+
+  heap = ALLOC(Heap_t, 1);
+  if (heap == NIL(Heap_t)) return NIL(Heap_t);
+  heap->length = length;
+  heap->nitems = 0;
+  heap->compare = 0;
+  heap->slots = ALLOC(HeapSlot_t, length);
+  if (heap->slots == NIL(HeapSlot_t)) {
+    FREE(heap);
+    return NIL(Heap_t);
+  }
+  return heap;
+
+} /* Heap_HeapInit */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a priority queue.]
+
+  Description [Initializes a priority queue. Returns a pointer to the
+  heap if successful; NULL otherwise.  The queue is implemented as a
+  heap.  The first element of the heap is the one with the smallest
+  key.]
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapFree]
+
+******************************************************************************/
+Heap_t *
+Heap_HeapInitCompare(
+  int length, int (*compare)(const void *, const void *))
+{
+  Heap_t *heap;
+
+  heap = ALLOC(Heap_t, 1);
+  if (heap == NIL(Heap_t)) return NIL(Heap_t);
+  heap->length = length;
+  heap->nitems = 0;
+  heap->compare = compare;
+  heap->slots = ALLOC(HeapSlot_t, length);
+  if (heap->slots == NIL(HeapSlot_t)) {
+    FREE(heap);
+    return NIL(Heap_t);
+  }
+  return heap;
+
+} /* Heap_HeapInitCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a priority queue.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapInit]
+
+******************************************************************************/
+void
+Heap_HeapFree(
+  Heap_t *heap)
+{
+  FREE(heap->slots);
+  FREE(heap);
+  return;
+
+} /* Heap_HeapFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a priority queue.]
+
+  Description [Inserts an item in a priority queue.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapExtractMin]
+
+******************************************************************************/
+int
+Heap_HeapInsert(
+  Heap_t *heap,
+  void *item,
+  long key)
+{
+  HeapSlot_t *slots;
+  int i = heap->nitems;
+
+  if (i == heap->length && !HeapResize(heap)) return 0;
+  slots = heap->slots;
+  heap->nitems++;
+  while (i > 0 && KEY(slots, PARENT(i)) > key) {
+    ITEM(slots, i) = ITEM(slots, PARENT(i));
+    KEY(slots, i) = KEY(slots, PARENT(i));
+    i = PARENT(i);
+  }
+  ITEM(slots, i) = item;
+  KEY(slots, i) = key;
+  return 1;
+
+} /* Heap_HeapInsert */
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an item in a priority queue.]
+
+  Description [Inserts an item in a priority queue.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapExtractMin]
+
+******************************************************************************/
+int
+Heap_HeapInsertCompare(
+  Heap_t *heap,
+  void *item,
+  long key)
+{
+  HeapSlot_t *slots;
+  int i = heap->nitems;
+
+  if (i == heap->length && !HeapResize(heap)) return 0;
+  slots = heap->slots;
+  heap->nitems++;
+  while (i > 0 && (*(heap->compare))((char *)(long)KEY(slots, PARENT(i)), (char *)(long)key)) {
+    ITEM(slots, i) = ITEM(slots, PARENT(i));
+    KEY(slots, i) = KEY(slots, PARENT(i));
+    i = PARENT(i);
+  }
+  ITEM(slots, i) = item;
+  KEY(slots, i) = key;
+  return 1;
+
+} /* Heap_HeapInsertCompare */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extracts the element with the minimum key from a priority
+  queue.]
+
+  Description [Extracts the element with the minimum key from a
+  priority queue.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [The minimum key and the associated item are returned as
+  side effects.]
+
+  SeeAlso     [Heap_HeapInsert]
+
+******************************************************************************/
+int
+Heap_HeapExtractMin(
+  Heap_t *heap,
+  void *item,
+  long *key)
+{
+  HeapSlot_t *slots = heap->slots;
+
+  if (heap->nitems == 0) return 0;
+  *(void **)item = ITEM(slots, 0);
+  *key = KEY(slots, 0);
+  heap->nitems--;
+  /* The next three lines are redundant if the queue is empty. */
+  ITEM(slots, 0) = ITEM(slots, heap->nitems);
+  KEY(slots, 0) = KEY(slots, heap->nitems);
+  if(heap->compare) HeapHeapifyCompare(heap);
+  else              HeapHeapify(heap);
+
+  return 1;
+
+} /* Heap_HeapExtractMin */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of items in a priority queue.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Heap_HeapCount(
+  Heap_t *heap)
+{
+  return(heap->nitems);
+
+} /* Heap_HeapCount */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clones a priority queue.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapInit]
+
+******************************************************************************/
+Heap_t *
+Heap_HeapClone(
+  Heap_t *source)
+{
+  Heap_t *dest;
+  int i;
+  int nitems = source->nitems;
+  HeapSlot_t *sslots = source->slots;
+  HeapSlot_t *dslots;
+
+  dest = Heap_HeapInit(source->length);
+  if (dest == NULL) return(NULL);
+  dest->nitems = nitems;
+  dslots = dest->slots;
+  for (i = 0; i < nitems; i++) {
+    KEY(dslots, i) = KEY(sslots, i);
+    ITEM(dslots, i) = ITEM(sslots, i);
+  }
+  return(dest);
+
+} /* Heap_HeapClone */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Tests the heap property of a priority queue.]
+
+  Description [Tests the heap property of a priority queue.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Heap_HeapTest(
+  Heap_t *heap)
+{
+  HeapSlot_t *slots = heap->slots;
+  int nitems = heap->nitems;
+  int i;
+
+  for (i = 1; i < nitems; i++) {
+    if (KEY(slots,i) < KEY(slots, PARENT(i)))
+      return 0;
+  }
+  return 1;
+
+} /* Heap_HeapTest */
+
+/**Function********************************************************************
+
+  Synopsis    [Tests the heap property of a priority queue.]
+
+  Description [Tests the heap property of a priority queue.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Heap_HeapTestCompare(
+  Heap_t *heap)
+{
+  HeapSlot_t *slots = heap->slots;
+  int nitems = heap->nitems;
+  int i;
+
+  for (i = 1; i < nitems; i++) {
+    if ((*(heap->compare))((char *)(long)KEY(slots, PARENT(i)), (char *)(long)KEY(slots,i)))
+      return 0;
+  }
+  return 1;
+
+} /* Heap_HeapTest */
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Maintains the heap property of a priority queue.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapExtractMin]
+
+******************************************************************************/
+static void
+HeapHeapify(
+  Heap_t *heap)
+{
+  int nitems = heap->nitems;
+  HeapSlot_t *slots = heap->slots;
+  int i = 0;
+  int smallest = 0;
+  void *item = ITEM(slots, 0);
+  long key = KEY(slots, 0);
+
+  while (1) {
+    int left = LEFT(i);
+    int right = RIGHT(i);
+    int minkey;
+    if (left < nitems && (minkey = KEY(slots, left)) < key) {
+      smallest = left;
+    } else {
+      minkey = key;
+    }
+    if (right < nitems && KEY(slots, right) < minkey) {
+      smallest = right;
+    }
+    if (smallest == i) break;
+    KEY(slots, i) = KEY(slots, smallest);
+    ITEM(slots, i) = ITEM(slots, smallest);
+    i = smallest;
+  }
+  KEY(slots, i) = key;
+  ITEM(slots, i) = item;
+  return;
+
+} /* HeapHeapify */
+
+/**Function********************************************************************
+
+  Synopsis    [Tests the heap property of a priority queue.]
+
+  Description [Tests the heap property of a priority queue.  Returns 1 if
+  successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+HeapHeapifyCompare(
+  Heap_t *heap)
+{
+  int nitems = heap->nitems;
+  HeapSlot_t *slots = heap->slots;
+  int i = 0;
+  int smallest = 0;
+  void *item = ITEM(slots, 0);
+  int key = KEY(slots, 0);
+  int minkey;
+
+
+  while (1) {
+    int left = LEFT(i);
+    int right = RIGHT(i);
+    if (left < nitems && (*(heap->compare))((char *)(long)key, (char *)(long)(minkey = KEY(slots, left)))) {
+      smallest = left;
+    } else {
+      minkey = key;
+    }
+    if (right < nitems && (*(heap->compare))((char *)(long)minkey, (char *)(long)KEY(slots, right))) {
+      smallest = right;
+    }
+    if (smallest == i) break;
+    KEY(slots, i) = KEY(slots, smallest);
+    ITEM(slots, i) = ITEM(slots, smallest);
+    i = smallest;
+  }
+  KEY(slots, i) = key;
+  ITEM(slots, i) = item;
+  return;
+
+} /* HeapHeapifyCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes a priority queue.]
+
+  Description [Resizes a priority queue by doubling the number of
+  available slots.  Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Heap_HeapInsert]
+
+******************************************************************************/
+static int
+HeapResize(
+  Heap_t *heap)
+{
+  int oldlength = heap->length;
+  int newlength = 2 * oldlength;
+  HeapSlot_t *oldslots = heap->slots;
+  HeapSlot_t *newslots = REALLOC(HeapSlot_t, oldslots, newlength);
+  if (newslots == NIL(HeapSlot_t)) return 0;
+  heap->length = newlength;
+  heap->slots = newslots;
+  if (heap->compare) {
+    assert(Heap_HeapTestCompare(heap));
+  }
+  else {
+    assert(Heap_HeapTest(heap));
+  }
+  return 1;
+
+} /* HeapResize */
+
+/**Function********************************************************************
+
+  Synopsis    [Apply function for each element of heap.]
+
+  Description [Apply function for each element of heap. 
+               Returns 1 if successful; 0 otherwise.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+void
+Heap_HeapApplyForEachElement(Heap_t *heap, int (*compare)(const void *))
+{
+int i;
+
+  for(i=0; i<heap->nitems; i++) {
+    (*compare)(heap->slots[i].item);
+  }
+  return;
+}
Index: /vis_dev/glu-2.1/src/heap/heap.h
===================================================================
--- /vis_dev/glu-2.1/src/heap/heap.h	(revision 8)
+++ /vis_dev/glu-2.1/src/heap/heap.h	(revision 8)
@@ -0,0 +1,106 @@
+/**CFile***********************************************************************
+
+  FileName    [heap.h]
+
+  PackageName [heap]
+
+  Synopsis    [Heap-based priority queue.]
+
+  Description [This is the external header file for the heap-based
+  priority queue.  The priority of each item is determined by an
+  integer key.  The first element of the heap is the one with the
+  smallest key.  Multiple items with the same key can be inserted.
+  Refer to Chapter 7 of Cormen, Leiserson, and Rivest for the theory.
+  (The only significant difference is that the array indices start
+  from 0 in this implementation.)]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: heap.h,v 1.13 2005/05/18 19:25:43 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _HEAP
+#define _HEAP
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "util.h"
+#undef MAX
+#undef MIN
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct HeapSlot HeapSlot_t;
+
+typedef struct Heap Heap_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Iterates over the elements of a heap.]
+
+  SideEffects [none]
+
+******************************************************************************/
+#define Heap_HeapForEachItem(                                              \
+  /* Heap_t * */ heap /* heap whose element should be enumerated */,       \
+  /* int */      i    /* local variable for iterator */,                   \
+  /* void * */	 data /* heap item */                                      \
+)                                                                          \
+  for((i) = 0; (((i) < (heap)->nitems) && (data = (heap)->slots[i].item)); \
+      (i)++)
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN Heap_t * Heap_HeapInit ARGS((int length));
+EXTERN Heap_t * Heap_HeapInitCompare ARGS((int length, int (*compare)(const void *, const void *)));
+EXTERN void Heap_HeapFree ARGS((Heap_t *heap));
+EXTERN int Heap_HeapInsert ARGS((Heap_t *heap, void *item, long key));
+EXTERN int Heap_HeapInsertCompare ARGS((Heap_t *heap, void *item, long key));
+EXTERN int Heap_HeapExtractMin ARGS((Heap_t *heap, void *item, long *key));
+EXTERN int Heap_HeapCount ARGS((Heap_t *heap));
+EXTERN Heap_t * Heap_HeapClone ARGS((Heap_t *source));
+EXTERN int Heap_HeapTest ARGS((Heap_t *heap));
+EXTERN int Heap_HeapTestCompare ARGS((Heap_t *heap));
+EXTERN void Heap_HeapApplyForEachElement(Heap_t *heap, int (*compare)(const void *));
+
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _HEAP */
Index: /vis_dev/glu-2.1/src/heap/heap.make
===================================================================
--- /vis_dev/glu-2.1/src/heap/heap.make	(revision 8)
+++ /vis_dev/glu-2.1/src/heap/heap.make	(revision 8)
@@ -0,0 +1,4 @@
+CSRC += heap.c
+HEADERS += heap.h heapInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/heap/heapInt.h
===================================================================
--- /vis_dev/glu-2.1/src/heap/heapInt.h	(revision 8)
+++ /vis_dev/glu-2.1/src/heap/heapInt.h	(revision 8)
@@ -0,0 +1,144 @@
+/**CFile***********************************************************************
+
+  FileName    [heapInt.h]
+
+  PackageName [heap]
+
+  Synopsis    [Heap-based priority queue.]
+
+  Description [This is the internal header file for the heap-based priority
+  queue.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: heapInt.h,v 1.7 2005/05/18 19:25:43 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _HEAPINT
+#define _HEAPINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "heap.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Slot of a heap.]
+
+  Description [Slot of a heap.  Each slots holds a generic object and an
+  integer key.]
+
+******************************************************************************/
+struct HeapSlot {
+  long key;
+  void *item;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [Heap.]
+
+  Description []
+
+******************************************************************************/
+struct Heap {
+  int length;
+  int nitems;
+  struct HeapSlot *slots;
+  int (*compare)(const void *, const void *);
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the parent of the i-th element in a heap.]
+
+  Description [Returns the parent of the i-th element in a heap.
+  Argument <code>i</code> should be strictly positive, otherwise the
+  result is implementation dependent.]
+
+  SideEffects [none]
+
+******************************************************************************/
+#define PARENT(i)	(((i)-1)>>1)
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the left child of the i-th element in a heap.]
+
+  SideEffects [none]
+
+******************************************************************************/
+#define LEFT(i)		(((i)<<1)+1)
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the right child of the i-th element in a heap.]
+
+  SideEffects [none]
+
+******************************************************************************/
+#define RIGHT(i)	(((i)+1)<<1)
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the item stored in the i-th element in a heap.]
+
+  SideEffects [none]
+
+******************************************************************************/
+#define ITEM(p,i)	((p)[i].item)
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the key of the i-th element in a heap.]
+
+  SideEffects [none]
+
+******************************************************************************/
+#define KEY(p,i)	((p)[i].key)
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _HEAPINT */
Index: /vis_dev/glu-2.1/src/heap/semantic.cache
===================================================================
--- /vis_dev/glu-2.1/src/heap/semantic.cache	(revision 8)
+++ /vis_dev/glu-2.1/src/heap/semantic.cache	(revision 8)
@@ -0,0 +1,26 @@
+;; Object heap/
+;; SEMANTICDB Tags save file
+(semanticdb-project-database-file "heap/"
+  :tables (list 
+   (semanticdb-table "heap.h"
+    :major-mode 'c-mode
+    :tags '(("_HEAP" variable (:constant-flag t) nil [1057 1313]) ("util.h" include nil nil [1312 1329]) ("HeapSlot_t" type (:typedef ("HeapSlot" type (:type "struct") nil nil) :superclasses "HeapSlot" :type "typedef") nil [2078 2113]) ("Heap_t" type (:typedef ("Heap" type (:type "struct") nil nil) :superclasses "Heap" :type "typedef") nil [2115 2142]) ("Heap_HeapForEachItem" variable (:constant-flag t) nil [2865 3254]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapInit" type (:type "class") nil nil)) nil [3680 3713]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapInitCompare" type (:type "class") nil nil)) nil [3730 3814]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapFree" type (:type "class") nil nil)) nil [3827 3862]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapInsert" type (:type "class") nil nil)) nil [3874 3933]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapInsertCompare" type (:type "class") nil nil)) nil [3945 4011]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapExtractMin" type (:type "class") nil nil)) nil [4023 4087]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapCount" type (:type "class") nil nil)) nil [4099 4135]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapClone" type (:type "class") nil nil)) nil [4152 4190]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapTest" type (:type "class") nil nil)) nil [4202 4237]) ("ARGS" function (:prototype-flag t :type ("Heap_HeapTestCompare" type (:type "class") nil nil)) nil [4249 4291]) ("Heap_HeapApplyForEachElement" function (:prototype-flag t :arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4333 4346]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [4347 4361])) :type "void") nil [4299 4377]))
+    :file "heap.h"
+    :pointmax 4481
+    )
+   (semanticdb-table "heap.c"
+    :major-mode 'c-mode
+    :tags '(("heapInt.h" include nil nil [642 662]) ("UNUSED" variable (:default-value "\"$Id: heap.c,v 1.18 2005/05/18 19:25:43 jinh Exp $\"" :type "int") nil [1665 1726]) ("ARGS" function (:prototype-flag t :type ("HeapHeapify" type (:type "class") nil nil)) nil [2313 2346]) ("ARGS" function (:prototype-flag t :type ("HeapHeapifyCompare" type (:type "class") nil nil)) nil [2359 2399]) ("ARGS" function (:prototype-flag t :type ("HeapResize" type (:type "class") nil nil)) nil [2411 2443]) ("Heap_HeapInit" function (:pointer 1 :arguments (("length" variable (:type "int") (reparse-symbol arg-sub-list) [3272 3283])) :type ("Heap_t" type (:type "class") nil nil)) nil [3246 3587]) ("Heap_HeapInitCompare" function (:pointer 1 :arguments (("length" variable (:type "int") (reparse-symbol arg-sub-list) [4120 4131]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [4132 4146])) :type ("Heap_t" type (:type "class") nil nil)) nil [4087 4485]) ("Heap_HeapFree" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4810 4823])) :type "void") nil [4788 4873]) ("Heap_HeapInsert" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5288 5301]) ("item" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [5304 5315]) ("key" variable (:type "long") (reparse-symbol arg-sub-list) [5318 5327])) :type "int") nil [5265 5695]) ("Heap_HeapInsertCompare" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6118 6131]) ("item" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6134 6145]) ("key" variable (:type "long") (reparse-symbol arg-sub-list) [6148 6157])) :type "int") nil [6088 6572]) ("Heap_HeapExtractMin" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7122 7135]) ("item" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [7138 7149]) ("key" variable (:pointer 1 :type "long") (reparse-symbol arg-sub-list) [7152 7162])) :type "int") nil [7095 7569]) ("Heap_HeapCount" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7905 7918])) :type "int") nil [7883 7947]) ("Heap_HeapClone" function (:pointer 1 :arguments (("source" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8272 8287])) :type ("Heap_t" type (:type "class") nil nil)) nil [8245 8661]) ("Heap_HeapTest" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [9072 9085])) :type "int") nil [9051 9275]) ("Heap_HeapTestCompare" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [9691 9704])) :type "int") nil [9663 9941]) ("HeapHeapify" function (:typemodifiers ("static") :arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [10781 10794])) :type "void") nil [10754 11442]) ("HeapHeapifyCompare" function (:typemodifiers ("static") :arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [11862 11875])) :type "void") nil [11828 12615]) ("HeapResize" function (:typemodifiers ("static") :arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13053 13066])) :type "int") nil [13028 13465]) ("Heap_HeapApplyForEachElement" function (:arguments (("heap" variable (:pointer 1 :type ("Heap_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13887 13900]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [13901 13915])) :type "void") nil [13853 14027]))
+    :file "heap.c"
+    :pointmax 14028
+    )
+   (semanticdb-table "heapInt.h"
+    :major-mode 'c-mode
+    :tags 'nil
+    :file "heapInt.h"
+    )
+   )
+  :file "semantic.cache"
+  :semantic-tag-version "2.0beta3"
+  :semanticdb-version "2.0beta3"
+  )
Index: /vis_dev/glu-2.1/src/list/list.c
===================================================================
--- /vis_dev/glu-2.1/src/list/list.c	(revision 8)
+++ /vis_dev/glu-2.1/src/list/list.c	(revision 8)
@@ -0,0 +1,904 @@
+/*
+ * $Id: list.c,v 1.10 2005/04/18 05:14:28 fabio Exp $
+ *
+ */
+/*
+ * List Management Package
+ * 
+ * David Harrison
+ * University of California, Berkeley, 1985
+ *
+ * This package implements a simple generic linked list data type.  It
+ * uses a doubly linked list structure and provides some standard operations
+ * for storing and retrieving data from the list.
+ */
+
+#include "util.h"
+#include "list.h"		/* Self declaration        */
+
+
+/*
+ * The list identifier is in reality a pointer to the following list
+ * descriptor structure.  Lists are doubly linked with both top and
+ * bottom pointers stored in the list descriptor.  The length
+ * of the list is also stored in the descriptor.
+ */
+
+typedef struct list_elem {	/* One list element  */
+    struct list_desc *mainList;	/* List descriptor   */
+    struct list_elem *prevPtr;	/* Previous element  */
+    struct list_elem *nextPtr;	/* Next list element */
+    lsGeneric userData;		/* User pointer      */
+} lsElem;
+
+typedef struct list_desc {	/* List descriptor record            */
+    lsElem *topPtr, *botPtr;	/* Pointer to top and bottom of list */
+    int length;			/* Length of list                    */
+} lsDesc;
+
+
+/*
+ * Generators are in reality pointers to the generation descriptor 
+ * defined below.  A generator has a current spot which is *between*
+ * two items.  Thus,  a generator consists of two pointers:  record
+ * before spot and record after spot.  A pointer to the main list
+ * is included so the top and bottom pointers of the list can be
+ * modified if needed.
+ */
+
+typedef struct gen_desc {	/* Generator Descriptor 	*/
+    lsDesc *mainList;		/* Pointer to list descriptor   */
+    lsElem *beforeSpot;		/* Item before the current spot */
+    lsElem *afterSpot;		/* Item after the current spot  */
+} lsGenInternal;
+
+/*
+ * Handles are in reality pointers to lsElem records.  They are
+ * cheap to generate and need not be disposed.
+ */
+
+
+
+
+/*
+ * List Creation and Deletion
+ */
+
+lsList lsCreate(void)
+/*
+ * Creates a new linked list and returns its handle.  The handle is used
+ * by all other list manipulation routines and should not be discarded.
+ */
+{
+    lsDesc *newList;
+
+    newList = ALLOC(lsDesc, 1);
+    newList->topPtr = newList->botPtr = NIL(lsElem);
+    newList->length = 0;
+    return( (lsList) newList );
+}
+
+lsStatus lsDestroy(
+  lsList list			/* List to destroy              */,
+  void (*delFunc)(lsGeneric)	/* Routine to release user data */)
+/*
+ * Frees all resources associated with the specified list.  It frees memory
+ * associated with all elements of the list and then deletes the list.
+ * User data is released by calling 'delFunc' with the pointer as the
+ * argument.  Accessing a list after its destruction is a no-no.
+ */
+{
+    lsDesc *realList;
+    lsElem *index, *temp;
+
+    realList = (lsDesc *) list;
+    /* Get rid of elements */
+    index = realList->topPtr;
+    while (index != NIL(lsElem)) {
+	temp = index;  index = index->nextPtr;
+	if (delFunc)
+	  (*delFunc)(temp->userData);
+	FREE(temp);
+    }
+    /* Get rid of descriptor */
+    FREE(realList);
+    return(LS_OK);
+}
+
+
+
+/*
+ * Copying lists
+ */
+
+static lsGeneric lsIdentity(lsGeneric data)
+/* Identity copy function */
+{
+    return data;
+}
+
+lsList lsCopy(
+  lsList list				/* List to be copied         */,
+  lsGeneric (*copyFunc)(lsGeneric)	/* Routine to copy user data */)
+/*
+ * Returns a copy of list `list'.  If `copyFunc' is non-zero,
+ * it will be called for each item in `list' and the pointer it 
+ * returns will be used in place of the original user data for the 
+ * item in the newly created list.  The form of `copyFunc' should be:
+ *   lsGeneric copyFunc(data)
+ *   lsGeneric data;
+ * This is normally used to make copies of the user data in the new list.
+ * If no `copyFunc' is provided,  an identity function is used.
+ */
+{
+    lsList newList;
+    lsGen gen;
+    lsGeneric data;
+
+    if (!copyFunc) copyFunc = lsIdentity;
+    newList = lsCreate();
+    gen = lsStart(list);
+    while (lsNext(gen, &data, LS_NH) == LS_OK) {
+	(void) lsNewEnd(newList, (*copyFunc)(data), LS_NH);
+    }
+    lsFinish(gen);
+    return newList;
+}
+
+/*
+ * Change data in a Handle 
+ */
+
+lsStatus lsChangeData(
+  lsHandle itemHandle		/* Handle to data (returned) */,
+  lsGeneric data		/* Arbitrary pointer to data */)
+{
+   lsElem *realItem = (lsElem *) itemHandle;
+   realItem->userData =data;
+  return(LS_OK);
+}
+
+
+/*
+ * Adding New Elements to the Beginning and End of a List
+ */
+
+lsStatus lsNewBegin(
+  lsList list			/* List to add element to    */,
+  lsGeneric data		/* Arbitrary pointer to data */,
+  lsHandle *itemHandle		/* Handle to data (returned) */)
+/*
+ * Adds a new item to the start of a previously created linked list.
+ * If 'itemHandle' is non-zero,  it will be filled with a handle
+ * which can be used to generate a generator positioned at the
+ * item without generating through the list.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+    lsElem *newElem;
+
+    newElem = ALLOC(lsElem, 1);
+    newElem->userData = data;
+    newElem->nextPtr = realList->topPtr;
+    newElem->prevPtr = NIL(lsElem);
+    newElem->mainList = realList;
+    if (realList->topPtr == NIL(lsElem)) {
+	/* The new item is both the top and bottom element */
+	realList->botPtr = newElem;
+    } else {
+	/* There was a top element - make its prev correct */
+	realList->topPtr->prevPtr = newElem;
+    }
+    realList->topPtr = newElem;
+    realList->length += 1;
+    if (itemHandle) *itemHandle = (lsHandle) newElem;
+    return(LS_OK);
+}
+
+lsStatus lsNewEnd(
+  lsList list			/* List to append element to */,
+  lsGeneric data		/* Arbitrary pointer to data */,
+  lsHandle *itemHandle		/* Handle to data (returned) */)
+/*
+ * Adds a new item to the end of a previously created linked list.
+ * This routine appends the item in constant time and
+ * can be used freely without guilt.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+    lsElem *newElem;
+
+    newElem = ALLOC(lsElem, 1);
+    newElem->userData = data;
+    newElem->prevPtr = realList->botPtr;
+    newElem->nextPtr = NIL(lsElem);
+    newElem->mainList = realList;
+    if (realList->topPtr == NIL(lsElem))
+      realList->topPtr = newElem;
+    if (realList->botPtr != NIL(lsElem))
+      realList->botPtr->nextPtr = newElem;
+    realList->botPtr = newElem;
+    realList->length += 1;
+    if (itemHandle) *itemHandle = (lsHandle) newElem;
+    return(LS_OK);
+}
+
+/*
+ * Retrieving the first and last items of a list
+ */
+
+lsStatus lsFirstItem(
+  lsList list			/* List to get item from */,
+  lsGeneric data		/* User data (returned)  */,
+  lsHandle *itemHandle		/* Handle to data (returned) */)
+/*
+ * Returns the first item in the list.  If the list is empty,
+ * it returns LS_NOMORE.  Otherwise,  it returns LS_OK.
+ * If 'itemHandle' is non-zero,  it will be filled with a
+ * handle which may be used to generate a generator.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+
+    if (realList->topPtr != NIL(lsElem)) {
+	*(void **)data = realList->topPtr->userData;
+	if (itemHandle) *itemHandle = (lsHandle) (realList->topPtr);
+	return(LS_OK);
+    } else {
+	*(void **)data = (lsGeneric) 0;
+	if (itemHandle) *itemHandle = (lsHandle) 0;
+	return(LS_NOMORE);
+    }
+}
+
+lsStatus lsLastItem(
+  lsList list			/* List to get item from */,
+  lsGeneric data		/* User data (returned)  */,
+  lsHandle *itemHandle		/* Handle to data (returned) */)
+/*
+ * Returns the last item of a list.  If the list is empty,
+ * the routine returns LS_NOMORE.  Otherwise,  'data' will
+ * be set to the last item and the routine will return LS_OK.
+ * If 'itemHandle' is non-zero,  it will be filled with a
+ * handle which can be used to generate a generator postioned
+ * at this item.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+
+    if (realList->botPtr != NIL(lsElem)) {
+	*(void **)data = realList->botPtr->userData;
+	if (itemHandle) *itemHandle = (lsHandle) (realList->botPtr);
+	return(LS_OK);
+    } else {
+	*(void **)data = (lsGeneric) 0;
+	if (itemHandle) *itemHandle = (lsHandle) 0;
+	return(LS_NOMORE);
+    }
+}
+
+
+/* Length of a list */
+
+int lsLength(
+  lsList list			/* List to get the length of */)
+/*
+ * Returns the length of the list.  The list must have been
+ * already created using lsCreate.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+
+    return(realList->length);
+}
+
+
+/*
+ * Deleting first and last items of a list
+ */
+
+lsStatus lsDelBegin(
+  lsList list			/* List to delete item from     */,
+  lsGeneric data		/* First item (returned)        */)
+/*
+ * This routine deletes the first item of a list.  The user
+ * data associated with the item is returned so the caller
+ * may dispose of it.  Returns LS_NOMORE if there is no
+ * item to delete.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+    lsElem *temp;
+
+    if (realList->topPtr == NIL(lsElem)) {
+	/* Nothing to delete */
+	*(void **)data = (lsGeneric) 0;
+	return LS_NOMORE;
+    } else {
+	*(void **)data = realList->topPtr->userData;
+	temp = realList->topPtr;
+	realList->topPtr = realList->topPtr->nextPtr;
+	if (temp->nextPtr != NIL(lsElem)) {
+	    /* There is something after the first item */
+	    temp->nextPtr->prevPtr = NIL(lsElem);
+	} else {
+	    /* Nothing after it - bottom becomes null as well */
+	    realList->botPtr = NIL(lsElem);
+	}
+	FREE(temp);
+	realList->length -= 1;
+    }
+    return LS_OK;
+}
+
+
+lsStatus lsDelEnd(
+  lsList list			/* List to delete item from */,
+  lsGeneric data		/* Last item (returned)     */)
+/*
+ * This routine deletes the last item of a list.  The user
+ * data associated with the item is returned so the caller
+ * may dispose of it.  Returns LS_NOMORE if there is nothing
+ * to delete.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+    lsElem *temp;
+
+    if (realList->botPtr == NIL(lsElem)) {
+	/* Nothing to delete */
+	*(void **)data = (lsGeneric) 0;
+	return LS_NOMORE;
+    } else {
+	*(void **)data = realList->botPtr->userData;
+	temp = realList->botPtr;
+	realList->botPtr = realList->botPtr->prevPtr;
+	if (temp->prevPtr != NIL(lsElem)) {
+	    /* There is something before the last item */
+	    temp->prevPtr->nextPtr = NIL(lsElem);
+	} else {
+	    /* Nothing before it - top becomes null as well */
+	    realList->topPtr = NIL(lsElem);
+	}
+	FREE(temp);
+	realList->length -= 1;
+    }
+    return LS_OK;
+}
+
+
+/*
+ * List Generation Routines
+ *
+ * nowPtr is the element just before the next one to be generated
+ */
+
+lsGen lsStart(
+  lsList list			/* List to generate items from */)
+/*
+ * This routine defines a generator which is used to step through
+ * each item of the list.  It returns a generator handle which should
+ * be used when calling lsNext, lsPrev, lsInBefore, lsInAfter, lsDelete,
+ * or lsFinish.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+    lsGenInternal *newGen;
+
+    newGen = ALLOC(lsGenInternal, 1);
+    newGen->mainList = realList;
+    newGen->beforeSpot = NIL(lsElem);
+    newGen->afterSpot = realList->topPtr;
+    return ( (lsGen) newGen );
+}
+
+lsGen lsEnd(
+  lsList list			/* List to generate items from */)
+/*
+ * This routine defines a generator which is used to step through
+ * each item of a list.  The generator is initialized to the end 
+ * of the list.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+    lsGenInternal *newGen;
+
+    newGen = ALLOC(lsGenInternal, 1);
+    newGen->mainList = realList;
+    newGen->beforeSpot = realList->botPtr;
+    newGen->afterSpot = NIL(lsElem);
+    return (lsGen) newGen;
+}
+
+lsGen lsGenHandle(
+  lsHandle itemHandle		/* Handle of an item         */,
+  lsGeneric data		/* Data associated with item */,
+  int option			/* LS_BEFORE or LS_AFTER     */)
+/*
+ * This routine produces a generator given a handle.  Handles
+ * are produced whenever an item is added to a list.  The generator
+ * produced by this routine may be used when calling any of 
+ * the standard generation routines.  NOTE:  the generator
+ * should be freed using lsFinish.  The 'option' parameter
+ * determines whether the generator spot is before or after
+ * the handle item.
+ */
+{
+    lsElem *realItem = (lsElem *) itemHandle;
+    lsGenInternal *newGen;
+
+    newGen = ALLOC(lsGenInternal, 1);
+    newGen->mainList = realItem->mainList;
+    *(void **)data = realItem->userData;
+    if (option & LS_BEFORE) {
+	newGen->beforeSpot = realItem->prevPtr;
+	newGen->afterSpot = realItem;
+    } else if (option & LS_AFTER) {
+	newGen->beforeSpot = realItem;
+	newGen->afterSpot = realItem->nextPtr;
+    } else {
+	FREE(newGen);
+	newGen = (lsGenInternal *) 0;
+    }
+    return ( (lsGen) newGen );
+}
+
+
+lsStatus lsNext(
+  lsGen generator		/* Generator handle        */,
+  lsGeneric data		/* User data (return)      */,
+  lsHandle *itemHandle		/* Handle to item (return) */)
+/*
+ * Generates the item after the item previously generated by lsNext
+ * or lsPrev.   It returns a pointer to the user data structure in 'data'.  
+ * 'itemHandle' may be used to get a generation handle without
+ * generating through the list to find the item.  If there are no more 
+ * elements to generate, the routine returns  LS_NOMORE (normally it 
+ * returns LS_OK).  lsNext DOES NOT automatically clean up after all 
+ * elements have been generated.  lsFinish must be called explicitly to do this.
+ */
+{
+    register lsGenInternal *realGen = (lsGenInternal *) generator;
+
+    if (realGen->afterSpot == NIL(lsElem)) {
+	/* No more stuff to generate */
+	*(void **) data = (lsGeneric) 0;
+	if (itemHandle) *itemHandle = (lsHandle) 0;
+	return LS_NOMORE;
+    } else {
+	*(void **) data = realGen->afterSpot->userData;
+	if (itemHandle) *itemHandle = (lsHandle) (realGen->afterSpot);
+	/* Move the pointers down one */
+	realGen->beforeSpot = realGen->afterSpot;
+	realGen->afterSpot = realGen->afterSpot->nextPtr;
+	return LS_OK;
+    }
+}
+
+
+lsStatus lsPrev(
+  lsGen generator		/* Generator handle        */,
+  lsGeneric data		/* User data (return)      */,
+  lsHandle *itemHandle		/* Handle to item (return) */)
+/*
+ * Generates the item before the item previously generated by lsNext
+ * or lsPrev.   It returns a pointer to the user data structure in 'data'.  
+ * 'itemHandle' may be used to get a generation handle without
+ * generating through the list to find the item.  If there are no more 
+ * elements to generate, the routine returns  LS_NOMORE (normally it 
+ * returns LS_OK).  lsPrev DOES NOT automatically clean up after all 
+ * elements have been generated.  lsFinish must be called explicitly to do this.
+ */
+{
+    register lsGenInternal *realGen = (lsGenInternal *) generator;
+
+    if (realGen->beforeSpot == NIL(lsElem)) {
+	/* No more stuff to generate */
+	*(void **) data = (lsGeneric) 0;
+	if (itemHandle) *itemHandle = (lsHandle) 0;
+	return LS_NOMORE;
+    } else {
+	*(void **) data = realGen->beforeSpot->userData;
+	if (itemHandle) *itemHandle = (lsHandle) (realGen->beforeSpot);
+	/* Move the pointers down one */
+	realGen->afterSpot = realGen->beforeSpot;
+	realGen->beforeSpot = realGen->beforeSpot->prevPtr;
+	return LS_OK;
+    }
+
+}
+
+lsStatus lsInBefore(
+  lsGen generator		/* Generator handle          */,
+  lsGeneric data		/* Arbitrary pointer to data */,
+  lsHandle *itemHandle		/* Handle to item (return) */)
+/*
+ * Inserts an element BEFORE the current spot.  The item generated
+ * by lsNext will be unchanged;  the inserted item will be generated
+ * by lsPrev.  This modifies the list.  'itemHandle' may be used at 
+ * a later time to produce a generation handle without generating 
+ * through the list.
+ */
+{
+    lsGenInternal *realGen = (lsGenInternal *) generator;
+    lsElem *newElem;
+
+    if (realGen->beforeSpot == NIL(lsElem)) {
+	/* Item added to the beginning of the list */
+	(void) lsNewBegin((lsList) realGen->mainList, data, itemHandle);
+	realGen->beforeSpot = realGen->mainList->topPtr;
+	return LS_OK;
+    } else if (realGen->afterSpot == NIL(lsElem)) {
+	/* Item added to the end of the list */
+	(void) lsNewEnd((lsList) realGen->mainList, data, itemHandle);
+	realGen->afterSpot = realGen->mainList->botPtr;
+	return LS_OK;
+    } else {
+	/* Item added in the middle of the list */
+	newElem = ALLOC(lsElem, 1);
+	newElem->mainList = realGen->mainList;
+	newElem->prevPtr = realGen->beforeSpot;
+	newElem->nextPtr = realGen->afterSpot;
+	newElem->userData = data;
+	realGen->beforeSpot->nextPtr = newElem;
+	realGen->afterSpot->prevPtr = newElem;
+	realGen->beforeSpot = newElem;
+	realGen->mainList->length += 1;
+	if (itemHandle) *itemHandle = (lsHandle) newElem;
+	return LS_OK;
+    }
+}
+
+lsStatus lsInAfter(
+  lsGen generator		/* Generator handle          */,
+  lsGeneric data		/* Arbitrary pointer to data */,
+  lsHandle *itemHandle		/* Handle to item (return)   */)
+/*
+ * Inserts an element AFTER the current spot.  The next item generated
+ * by lsNext will be the new element.  The next  item generated by
+ * lsPrev is unchanged.  This modifies the list.  'itemHandle' may
+ * be used at a later time to generate a generation handle without
+ * searching through the list to find the item.
+ */
+{
+    lsGenInternal *realGen = (lsGenInternal *) generator;
+    lsElem *newElem;
+
+    if (realGen->beforeSpot == NIL(lsElem)) {
+	/* Item added to the beginning of the list */
+	(void) lsNewBegin((lsList) realGen->mainList, data, itemHandle);
+	realGen->beforeSpot = realGen->mainList->topPtr;
+	return LS_OK;
+    } else if (realGen->afterSpot == NIL(lsElem)) {
+	/* Item added to the end of the list */
+	(void) lsNewEnd((lsList) realGen->mainList, data, itemHandle);
+	realGen->afterSpot = realGen->mainList->botPtr;
+	return LS_OK;
+    } else {
+	/* Item added in the middle of the list */
+	newElem = ALLOC(lsElem, 1);
+	newElem->mainList = realGen->mainList;
+	newElem->prevPtr = realGen->beforeSpot;
+	newElem->nextPtr = realGen->afterSpot;
+	newElem->userData = data;
+	realGen->beforeSpot->nextPtr = newElem;
+	realGen->afterSpot->prevPtr = newElem;
+	realGen->afterSpot = newElem;
+	realGen->mainList->length += 1;
+	if (itemHandle) *itemHandle = (lsHandle) newElem;
+	return LS_OK;
+    }
+}
+	
+
+lsStatus lsDelBefore(
+  lsGen generator		/* Generator handle        */,
+  lsGeneric data		/* Deleted item (returned) */)
+/*
+ * Removes the item before the current spot.  The next call to lsPrev
+ * will return the item before the deleted item.  The next call to lsNext
+ * will be uneffected.  This modifies the list.  The routine returns 
+ * LS_BADSTATE if the user tries to call the routine and there is
+ * no item before the current spot.  This routine returns the userData
+ * of the deleted item so it may be freed (if necessary).
+ */
+{
+    lsGenInternal *realGen = (lsGenInternal *) generator;
+    lsElem *doomedItem;
+
+    if (realGen->beforeSpot == NIL(lsElem)) {
+	/* No item to delete */
+	*(void **)data = (lsGeneric) 0;
+	return LS_BADSTATE;
+    } else if (realGen->beforeSpot == realGen->mainList->topPtr) {
+	/* Delete the first item of the list */
+	realGen->beforeSpot = realGen->beforeSpot->prevPtr;
+	return lsDelBegin((lsList) realGen->mainList, data);
+    } else if (realGen->beforeSpot == realGen->mainList->botPtr) {
+	/* Delete the last item of the list */
+	realGen->beforeSpot = realGen->beforeSpot->prevPtr;
+	return lsDelEnd((lsList) realGen->mainList, data);
+    } else {
+	/* Normal mid list deletion */
+	doomedItem = realGen->beforeSpot;
+	doomedItem->prevPtr->nextPtr = doomedItem->nextPtr;
+	doomedItem->nextPtr->prevPtr = doomedItem->prevPtr;
+	realGen->beforeSpot = doomedItem->prevPtr;
+	realGen->mainList->length -= 1;
+	*(void **)data = doomedItem->userData;
+	FREE(doomedItem);
+	return LS_OK;
+    }
+}
+
+
+lsStatus lsDelAfter(
+  lsGen generator		/* Generator handle        */,
+  lsGeneric data		/* Deleted item (returned) */)
+/*
+ * Removes the item after the current spot.  The next call to lsNext
+ * will return the item after the deleted item.  The next call to lsPrev
+ * will be uneffected.  This modifies the list.  The routine returns 
+ * LS_BADSTATE if the user tries to call the routine and there is
+ * no item after the current spot.  This routine returns the userData
+ * of the deleted item so it may be freed (if necessary).
+ */
+{
+    lsGenInternal *realGen = (lsGenInternal *) generator;
+    lsElem *doomedItem;
+
+    if (realGen->afterSpot == NIL(lsElem)) {
+	/* No item to delete */
+	*(void **)data = (lsGeneric) 0;
+	return LS_BADSTATE;
+    } else if (realGen->afterSpot == realGen->mainList->topPtr) {
+	/* Delete the first item of the list */
+	realGen->afterSpot = realGen->afterSpot->nextPtr;
+	return lsDelBegin((lsList) realGen->mainList, data);
+    } else if (realGen->afterSpot == realGen->mainList->botPtr) {
+	/* Delete the last item of the list */
+	realGen->afterSpot = realGen->afterSpot->nextPtr;
+	return lsDelEnd((lsList) realGen->mainList, data);
+    } else {
+	/* Normal mid list deletion */
+	doomedItem = realGen->afterSpot;
+	doomedItem->prevPtr->nextPtr = doomedItem->nextPtr;
+	doomedItem->nextPtr->prevPtr = doomedItem->prevPtr;
+	realGen->afterSpot = doomedItem->nextPtr;
+	realGen->mainList->length -= 1;
+	*(void **)data = doomedItem->userData;
+	FREE(doomedItem);
+	return LS_OK;
+    }
+}
+
+
+lsStatus lsFinish(
+  lsGen generator		/* Generator handle */)
+/*
+ * Marks the completion of a generation of list items.  This routine should
+ * be called after calls to lsNext to free resources used by the
+ * generator.  This rule applies even if all items of a list are
+ * generated by lsNext.
+ */
+{
+    lsGenInternal *realGen = (lsGenInternal *) generator;
+
+    FREE(realGen);
+    return(LS_OK);
+}
+
+
+
+/*
+ * Functional list generation
+ *
+ * An alternate form of generating through items of a list is provided.
+ * The routines below generatae through all items of a list in a given
+ * direction and call a user provided function for each one.
+ */
+
+static lsStatus lsGenForm(lsStatus (*userFunc)(lsGeneric, lsGeneric),
+			  lsGeneric arg, lsGen gen,
+			  lsStatus (*gen_func)(lsGen, lsGeneric, lsHandle *),
+			  lsStatus (*del_func)(lsGen, lsGeneric));
+
+lsStatus lsForeach(
+  lsList list			/* List to generate through */,
+  lsStatus (*userFunc)(lsGeneric, lsGeneric) /* User provided function   */,
+  lsGeneric arg			/* User provided data       */)
+/*
+ * This routine generates all items in `list' from the first item
+ * to the last calling `userFunc' for each item.  The function
+ * should have the following form:
+ *   lsStatus userFunc(data, arg)
+ *   lsGeneric data;
+ *   lsGeneric arg;
+ * `data' will be the user data associated with the item generated.
+ * `arg' will be the same pointer provided to lsForeach.  The
+ * routine should return LS_OK to continue the generation,  LS_STOP
+ * to stop generating items,  and LS_DELETE to delete the item
+ * from the list.  If the generation was stopped prematurely,
+ * the routine will return LS_STOP.  If the user provided function
+ * does not return an appropriate value,  the routine will return
+ * LS_BADPARAM.
+ */
+{
+    return lsGenForm(userFunc, arg, lsStart(list), lsNext, lsDelBefore);
+}
+
+
+lsStatus lsBackeach(
+  lsList list			/* List to generate through */,
+  lsStatus (*userFunc)(lsGeneric, lsGeneric) /* User provided function   */,
+  lsGeneric arg			/* User provided data       */)
+/*
+ * This routine is just like lsForeach except it generates
+ * all items in `list' from the last item to the first.
+ */
+{
+    return lsGenForm(userFunc, arg, lsEnd(list), lsPrev, lsDelAfter);
+}
+
+
+static lsStatus lsGenForm(
+  lsStatus (*userFunc)(lsGeneric, lsGeneric) /* User provided function */,
+  lsGeneric arg			/* Data to pass to function       */,
+  lsGen gen			/* Generator to use               */,
+  lsStatus (*gen_func)(lsGen, lsGeneric, lsHandle *)
+				/* Generator function to use      */,
+  lsStatus (*del_func)(lsGen, lsGeneric) /* Deletion function to use */)
+/*
+ * This is the function used to implement the two functional
+ * generation interfaces to lists.
+ */
+{
+    lsGeneric data;
+
+    while ((*gen_func)(gen, &data, LS_NH) == LS_OK) {
+	switch ((*userFunc)(data, arg)) {
+	case LS_OK:
+	    /* Nothing */
+	    break;
+	case LS_STOP:
+	    (void) lsFinish(gen);
+	    return LS_STOP;
+	case LS_DELETE:
+	    (*del_func)(gen, &data);
+	    break;
+	default:
+	    return LS_BADPARAM;
+	}
+    }
+    (void) lsFinish(gen);
+    return LS_OK;
+}
+
+
+lsList lsQueryHandle(
+  lsHandle itemHandle		/* Handle of an item  */)
+/*
+ * This routine returns the associated list of the specified
+ * handle.  Returns 0 if there were problems.
+ */
+{
+    lsElem *realHandle = (lsElem *) itemHandle;
+
+    if (realHandle) {
+	return (lsList) realHandle->mainList;
+    } else {
+	return (lsList) 0;
+    }
+}
+
+lsGeneric lsFetchHandle(lsHandle itemHandle)
+/*
+ * This routine returns the user data of the item associated with
+ * `itemHandle'.
+ */
+{
+    return ((lsElem *) itemHandle)->userData;
+}
+
+lsStatus lsRemoveItem(
+  lsHandle itemHandle		/* Handle of an item */,
+  lsGeneric userData		/* Returned data     */)
+/*
+ * This routine removes the item associated with `handle' from
+ * its list and returns the user data associated with the item
+ * for reclaimation purposes.  Note this modifies the list
+ * that originally contained `item'.
+ */
+{
+    lsElem *realItem = (lsElem *) itemHandle;
+    lsGenInternal gen;
+
+    gen.mainList = realItem->mainList;
+    gen.beforeSpot = realItem->prevPtr;
+    gen.afterSpot = realItem;
+    return lsDelAfter((lsGen) &gen, userData);
+}
+
+
+/* List sorting support */
+#define TYPE		lsElem
+#define SORT		lsSortItems
+#define NEXT		nextPtr
+#define FIELD		userData
+#include "lsort.h"		/* Merge sort by R. Rudell */
+
+lsStatus lsSort(
+  lsList list				/* List to sort        */,
+  int (*compare)(lsGeneric, lsGeneric)	/* Comparison function */)
+/*
+ * This routine sorts `list' using `compare' as the comparison
+ * function between items in the list.  `compare' has the following form:
+ *   int compare(item1, item2)
+ *   lsGeneric item1, item2;
+ * The routine should return -1 if item1 is less than item2, 0 if
+ * they are equal,  and 1 if item1 is greater than item2.
+ * The routine uses a generic merge sort written by Rick Rudell.
+ */
+{
+    lsDesc *realList = (lsDesc *) list;
+    lsElem *idx, *lastElem;
+
+    realList->topPtr = lsSortItems(realList->topPtr, compare,
+				  realList->length);
+
+    /* Forward pointers are correct - fix backward pointers */
+    lastElem = (lsElem *) 0;
+    for (idx = realList->topPtr;  idx != (lsElem *) 0;  idx = idx->nextPtr) {
+	idx->prevPtr = lastElem;
+	lastElem = idx;
+    }
+    /* lastElem is last item in list */
+    realList->botPtr = lastElem;
+    return LS_OK;
+}
+
+
+lsStatus lsUniq(
+  lsList list				/* List to remove duplicates from */,
+  int (*compare)(lsGeneric, lsGeneric)	/* Item comparison function       */,
+  void (*delFunc)(lsGeneric)		/* Function to release user data  */)
+/*
+ * This routine takes a sorted list and removes all duplicates
+ * from it.  `compare' has the following form:
+ *   int compare(item1, item2)
+ *   lsGeneric item1, item2;
+ * The routine should return -1 if item1 is less than item2, 0 if
+ * they are equal,  and 1 if item1 is greater than item2. `delFunc'
+ * will be called with a pointer to a user data item for each
+ * duplicate destroyed.  `delFunc' can be zero if no clean up
+ * is required.
+ */
+{
+    lsGeneric this_item, last_item;
+    lsGenInternal realGen;
+    lsDesc *realList = (lsDesc *) list;
+
+    if (realList->length > 1) {
+	last_item = realList->topPtr->userData;
+
+	/* Inline creation of generator */
+	realGen.mainList = realList;
+	realGen.beforeSpot = realList->topPtr;
+	realGen.afterSpot = realList->topPtr->nextPtr;
+
+	while (realGen.afterSpot) {
+	    this_item = realGen.afterSpot->userData;
+	    if ((*compare)(this_item, last_item) == 0) {
+		/* Duplicate -- eliminate */
+		(void) lsDelAfter((lsGen) &realGen, &this_item);
+		if (delFunc) (*delFunc)(this_item);
+	    } else {
+		/* Move generator forward */
+		realGen.beforeSpot = realGen.afterSpot;
+		realGen.afterSpot = realGen.afterSpot->nextPtr;
+		last_item = this_item;
+	    }
+	}
+    }
+    return LS_OK;
+}
Index: /vis_dev/glu-2.1/src/list/list.h
===================================================================
--- /vis_dev/glu-2.1/src/list/list.h	(revision 8)
+++ /vis_dev/glu-2.1/src/list/list.h	(revision 8)
@@ -0,0 +1,128 @@
+/*
+ * $Id: list.h,v 1.8 2005/04/18 05:14:28 fabio Exp $
+ *
+ */
+/*
+ * List Management Package Header File
+ *
+ * David Harrison
+ * University of California, 1985
+ *
+ * This file contains public type definitions for the List Managment
+ * package implemented in list.c.  This is stand alone package.
+ */
+
+#ifndef LS_DEFINED
+#define LS_DEFINED
+
+typedef void ls_dummy;
+
+typedef ls_dummy *lsList;	/* List handle           */
+typedef ls_dummy *lsGen;	/* List generator handle */
+typedef ls_dummy *lsHandle;	/* Handle to an item     */
+typedef int lsStatus;		/* Return codes          */
+typedef void *lsGeneric;	/* Generic pointer       */
+
+#define	LS_NIL		0	/* Nil for lsList       */
+
+#define LS_BADSTATE	-3	/* Bad generator state   */
+#define LS_BADPARAM	-2	/* Bad parameter value   */
+#define LS_NOMORE	-1	/* No more items         */
+
+#define	LS_OK		0
+
+#define LS_BEFORE	1	/* Set spot before object */
+#define LS_AFTER	2	/* Set spot after object  */
+#define LS_STOP		3	/* Stop generating items  */
+#define LS_DELETE	4	/* Delete generated item  */
+
+/*
+ * For all those routines that take a handle,  this macro can be
+ * used when no handle is required.
+ */
+
+#define LS_NH		(lsHandle *) 0
+
+typedef lsGeneric (*LS_PFLSG)(lsGeneric);
+
+EXTERN lsList lsCreate ARGS((void));
+  /* Create a new list */
+EXTERN lsStatus lsDestroy ARGS((lsList, void (*)(lsGeneric)));
+  /* Delete a previously created list */
+EXTERN lsList lsCopy ARGS((lsList, LS_PFLSG));
+   /* Copies the contents of a list    */
+
+EXTERN lsStatus lsFirstItem ARGS((lsList, lsGeneric, lsHandle *));
+  /* Gets the first item of a list */
+EXTERN lsStatus lsLastItem ARGS((lsList, lsGeneric, lsHandle *));
+  /* Gets the last item of a list */
+
+EXTERN lsStatus lsNewBegin ARGS((lsList, lsGeneric, lsHandle *));
+  /* Add item to start of list */
+EXTERN lsStatus lsNewEnd ARGS((lsList, lsGeneric, lsHandle *));
+  /* Add item to end of list */
+
+EXTERN lsStatus lsDelBegin ARGS((lsList, lsGeneric));
+  /* Delete first item of a list */
+EXTERN lsStatus lsDelEnd ARGS((lsList, lsGeneric));
+  /* Delete last item of a list */
+
+EXTERN int lsLength ARGS((lsList));
+  /* Returns the length of the list */
+
+EXTERN lsGen lsStart ARGS((lsList));
+  /* Begin generation of items in a list */
+EXTERN lsGen lsEnd ARGS((lsList));
+  /* Begin generation at end of list */
+EXTERN lsGen lsGenHandle ARGS((lsHandle, lsGeneric, int));
+  /* Produces a generator given a handle */
+EXTERN lsStatus lsNext ARGS((lsGen, lsGeneric, lsHandle *));
+  /* Generate next item in sequence */
+EXTERN lsStatus lsPrev ARGS((lsGen, lsGeneric, lsHandle *));
+  /* Generate previous item in sequence */
+EXTERN lsStatus lsInBefore ARGS((lsGen, lsGeneric, lsHandle *));
+  /* Insert an item before the most recently generated by lsNext */
+EXTERN lsStatus lsInAfter ARGS((lsGen, lsGeneric, lsHandle *));
+  /* Insert an item after the most recently generated by lsNext  */
+EXTERN lsStatus lsDelBefore ARGS((lsGen, lsGeneric));
+  /* Delete the item before the current spot */
+EXTERN lsStatus lsDelAfter ARGS((lsGen, lsGeneric));
+  /* Delete the item after the current spot */
+EXTERN lsStatus lsFinish ARGS((lsGen));
+  /* End generation of items in a list */
+EXTERN lsStatus lsForeach ARGS((lsList list, lsStatus (*userFunc)(lsGeneric, lsGeneric), lsGeneric arg));
+  /* Generation of all items of a list from the first */
+EXTERN lsStatus lsBackeach ARGS((lsList list, lsStatus (*userFunc)(lsGeneric, lsGeneric), lsGeneric arg));
+  /* Generation of all items of a list from the last */
+
+EXTERN lsList lsQueryHandle ARGS((lsHandle));
+  /* Returns the list of a handle */
+EXTERN lsGeneric lsFetchHandle ARGS((lsHandle));
+  /* Returns data associated with handle */
+EXTERN lsStatus lsRemoveItem ARGS((lsHandle, lsGeneric));
+  /* Removes item associated with handle from list */
+
+EXTERN lsStatus lsSort ARGS((lsList, int (*)(lsGeneric, lsGeneric)));
+
+  /* Sorts a list */
+EXTERN lsStatus lsUniq ARGS((lsList, int (*)(lsGeneric, lsGeneric), void (*)(lsGeneric) ));
+  /* Removes duplicates from a sorted list */
+/*
+ * Macro to iterate the items of a list.Note the following:
+ * 1) in a for loop, the test is evaluate before the first time through the body
+ * 2) the logical OR operator guarantees left to right evaluation, and the second
+ *    operand is not evaluated if first operand evaluates to non-zero
+ * 3) the comma operator returns the value of its second argument.
+ */
+#define lsForEachItem(                                         \
+  list,  /* lsList, list to iterate */                         \
+  gen,   /* lsGen, local variable for iterator */              \
+  data   /* lsGeneric, variable to return data */              \
+)				                               \
+  for(gen = lsStart(list); 				       \
+      (lsNext(gen, &data, LS_NH) == LS_OK)       \
+      || ((void) lsFinish(gen), 0);                            \
+      )
+
+
+#endif
Index: /vis_dev/glu-2.1/src/list/list.make
===================================================================
--- /vis_dev/glu-2.1/src/list/list.make	(revision 8)
+++ /vis_dev/glu-2.1/src/list/list.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += list.c
+HEADERS += list.h lsort.h
+MISC += list.doc
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/list/lsort.h
===================================================================
--- /vis_dev/glu-2.1/src/list/lsort.h	(revision 8)
+++ /vis_dev/glu-2.1/src/list/lsort.h	(revision 8)
@@ -0,0 +1,157 @@
+/*
+ * $Id: lsort.h,v 1.6 2005/04/15 23:23:47 fabio Exp $
+ *
+ */
+/*
+ *  Generic linked-list sorting package
+ *  Richard Rudell, UC Berkeley, 4/1/87
+ *
+ *  Use:
+ *	#define TYPE		the linked-list type (a struct or typedef)
+ *	#define SORT		sorting routine (see below)
+ *	#include "lsort.h"
+ *
+ *  Optional:
+ *	#define NEXT		'next' field name in the linked-list structure
+ *	#define DECL_SORT	'static' or undefined
+ *	#define DECL_SORT1	'static' or undefined
+ *	#define SORT1		optional sorting routine interface
+ *	#define FIELD		select subfield of the structure for compare
+ *	#define DIRECT_COMPARE	in-line expand the compare routine
+ *
+ *  This defines up to two routines:
+ *	DECL_SORT TYPE *
+ *	SORT1(list, compare)
+ *	TYPE *list;
+ *	int (*compare)(TYPE *x, TYPE *y);
+ *	    sort the linked list 'list' according to the compare function
+ *	    'compare'
+ *
+ *	DECL_SORT1 TYPE *
+ *	SORT(list, compare, length)
+ *	TYPE *list;
+ *	int (*compare)(TYPE *x, TYPE *y);
+ *	int length;
+ *	    sort the linked list 'list' according to the compare function
+ *	    'compare'.  length is the length of the linked list.
+ *
+ *  Both routines gracefully handle length == 0 (in which case, list == 0 
+ *  is also allowed).
+ *
+ *  NEXT defines the name of the next field in the linked list.  If not
+ *  given, 'next' is assumed.
+ *
+ *  By default, both routines are declared 'static'.  This can be changed
+ *  using '#define DECL_SORT' or '#define DECL_SORT1'.
+ *
+ *  If FIELD is used, then a pointer to the particular field is passed
+ *  to the comparison function (rather than a TYPE *).  In this case,
+ *  the compare function is called with:
+ *	
+ *		if ((*compare)(x->FIELD, y->FIELD)) {
+ *
+ *  If DIRECT_COMPARE is used, then the 'FIELD' items are compared using
+ *  a simple '>' (useful for scalars to save subroutine overhead)
+ */
+
+#ifndef NEXT
+#define NEXT next
+#endif
+
+#ifndef DECL_SORT1
+#define DECL_SORT1 static
+#endif
+
+#ifndef DECL_SORT
+#define DECL_SORT static
+#endif
+
+#ifdef FIELD
+#define COMPTYPE void *
+#else
+#define COMPTYPE TYPE
+#endif
+
+DECL_SORT TYPE *SORT(TYPE *list_in,
+		     int (*compare)(COMPTYPE, COMPTYPE), int cnt);
+
+
+#ifdef SORT1
+
+DECL_SORT1 TYPE *
+SORT1(TYPE *list_in, int (*compare)(COMPTYPE, COMPTYPE))
+{
+    register int cnt;
+    register TYPE *p;
+
+    /* Find the length of the list */
+    for(p = list_in, cnt = 0; p != 0; p = p->NEXT, cnt++)
+	;
+    return SORT(list_in, compare, cnt);
+}
+
+#endif
+
+
+DECL_SORT TYPE *
+SORT(TYPE *list_in, int (*compare)(COMPTYPE, COMPTYPE), int cnt)
+{
+    register TYPE *p, **plast, *list1, *list2;
+    register int i;
+
+    if (cnt > 1) {
+	/* break the list in half */
+	for(p = list_in, i = cnt/2-1; i > 0; p = p->NEXT, i--)
+	    ;
+	list1 = list_in;
+	list2 = p->NEXT;
+	p->NEXT = 0;
+
+	/* Recursively sort the sub-lists (unless only 1 element) */
+	if ((i = cnt/2) > 1) {
+	    list1 = SORT(list1, compare, i);
+	}
+	if ((i = cnt - i) > 1) {
+	    list2 = SORT(list2, compare, i);
+	}
+
+	/* Merge the two sorted sub-lists */
+	plast = &list_in;
+	for(;;) {
+#ifdef FIELD
+#ifdef DIRECT_COMPARE
+	    if (list1->FIELD < list2->FIELD) {
+#else
+	    if ((*compare)(list1->FIELD, list2->FIELD) <= 0) {
+#endif
+#else
+	    if ((*compare)(list1, list2) <= 0) {
+#endif
+		*plast = list1;
+		plast = &(list1->NEXT);
+		if ((list1 = list1->NEXT) == 0) {
+		    *plast = list2;
+		    break;
+		}
+	    } else {
+		*plast = list2;
+		plast = &(list2->NEXT);
+		if ((list2 = list2->NEXT) == 0) {
+		    *plast = list1;
+		    break;
+		}
+	    }
+	}
+    }
+
+    return list_in;
+}
+
+#undef TYPE
+#undef SORT
+#undef SORT1
+#undef DECL_SORT
+#undef DECL_SORT1
+#undef FIELD
+#undef DIRECT_COMPARE
+#undef NEXT
Index: /vis_dev/glu-2.1/src/list/semantic.cache
===================================================================
--- /vis_dev/glu-2.1/src/list/semantic.cache	(revision 8)
+++ /vis_dev/glu-2.1/src/list/semantic.cache	(revision 8)
@@ -0,0 +1,27 @@
+;; Object list/
+;; SEMANTICDB Tags save file
+(semanticdb-project-database-file "list/"
+  :tables (list 
+   (semanticdb-table "list.c"
+    :major-mode 'c-mode
+    :tags '(("util.h" include nil nil [367 384]) ("list.h" include nil nil [385 402]) ("lsElem" type (:typedef ("list_elem" type (:members (("mainList" variable (:pointer 1 :type ("list_desc" type (:type "struct") nil nil)) (reparse-symbol classsubparts) [747 774]) ("prevPtr" variable (:pointer 1 :type ("list_elem" type (:type "struct") nil nil)) (reparse-symbol classsubparts) [803 829]) ("nextPtr" variable (:pointer 1 :type ("list_elem" type (:type "struct") nil nil)) (reparse-symbol classsubparts) [858 884]) ("userData" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol classsubparts) [913 932])) :type "struct") nil nil) :superclasses "list_elem" :type "typedef") nil [692 967]) ("lsDesc" type (:typedef ("list_desc" type (:members (("topPtr" variable (:pointer 1 :type ("lsElem" type (:type "class") nil nil)) (reparse-symbol classsubparts) [1040 1064]) ("botPtr" variable (:pointer 1 :type ("lsElem" type (:type "class") nil nil)) (reparse-symbol classsubparts) [1040 1064]) ("length" variable (:type "int") (reparse-symbol classsubparts) [1109 1120])) :type "struct") nil nil) :superclasses "list_desc" :type "typedef") nil [969 1172]) ("lsGenInternal" type (:typedef ("gen_desc" type (:members (("mainList" variable (:pointer 1 :type ("lsDesc" type (:type "class") nil nil)) (reparse-symbol classsubparts) [1600 1617]) ("beforeSpot" variable (:pointer 1 :type ("lsElem" type (:type "class") nil nil)) (reparse-symbol classsubparts) [1658 1677]) ("afterSpot" variable (:pointer 1 :type ("lsElem" type (:type "class") nil nil)) (reparse-symbol classsubparts) [1718 1736])) :type "struct") nil nil) :superclasses "gen_desc" :type "typedef") nil [1542 1789]) ("lsCreate" function (:arguments (("" variable (:type "void") (reparse-symbol arg-sub-list) [1967 1972])) :type ("lsList" type (:type "class") nil nil)) nil [1951 2292]) ("lsDestroy" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [2316 2365]) ("" variable (:type "void") (reparse-symbol arg-sub-list) [2368 2383])) :type ("lsStatus" type (:type "class") nil nil)) nil [2294 3074]) ("lsIdentity" function (:typemodifiers ("static") :arguments (("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [3131 3146])) :type ("lsGeneric" type (:type "class") nil nil)) nil [3103 3196]) ("lsCopy" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [3215 3262]) ("" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [3265 3286])) :type ("lsList" type (:type "class") nil nil)) nil [3198 4091]) ("lsChangeData" function (:arguments (("itemHandle" variable (:type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4154 4207]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4210 4258])) :type ("lsStatus" type (:type "class") nil nil)) nil [4129 4353]) ("lsNewBegin" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4445 4491]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4494 4542]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4545 4599])) :type ("lsStatus" type (:type "class") nil nil)) nil [4422 5458]) ("lsNewEnd" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5481 5527]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5530 5578]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5581 5635])) :type ("lsStatus" type (:type "class") nil nil)) nil [5460 6330]) ("lsFirstItem" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6413 6455]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6458 6502]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6505 6559])) :type ("lsStatus" type (:type "class") nil nil)) nil [6389 7124]) ("lsLastItem" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7149 7191]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7194 7238]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7241 7295])) :type ("lsStatus" type (:type "class") nil nil)) nil [7126 7948]) ("lsLength" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7991 8037])) :type "int") nil [7975 8214]) ("lsDelBegin" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8291 8340]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8343 8394])) :type ("lsStatus" type (:type "class") nil nil)) nil [8268 9210]) ("lsDelEnd" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [9234 9279]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [9282 9329])) :type ("lsStatus" type (:type "class") nil nil)) nil [9213 10142]) ("lsStart" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [10267 10315])) :type ("lsGen" type (:type "class") nil nil)) nil [10250 10801]) ("lsEnd" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [10818 10866])) :type ("lsGen" type (:type "class") nil nil)) nil [10803 11271]) ("lsGenHandle" function (:arguments (("itemHandle" variable (:type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [11294 11347]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [11350 11398]) ("option" variable (:type "int") (reparse-symbol arg-sub-list) [11401 11446])) :type ("lsGen" type (:type "class") nil nil)) nil [11273 12348]) ("lsNext" function (:arguments (("generator" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [12370 12417]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [12420 12466]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [12469 12521])) :type ("lsStatus" type (:type "class") nil nil)) nil [12351 13552]) ("lsPrev" function (:arguments (("generator" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13574 13621]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13624 13670]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13673 13725])) :type ("lsStatus" type (:type "class") nil nil)) nil [13555 14763]) ("lsInBefore" function (:arguments (("generator" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [14788 14837]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [14840 14888]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [14891 14943])) :type ("lsStatus" type (:type "class") nil nil)) nil [14765 16224]) ("lsInAfter" function (:arguments (("generator" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [16248 16297]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [16300 16348]) ("itemHandle" variable (:pointer 1 :type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [16351 16405])) :type ("lsStatus" type (:type "class") nil nil)) nil [16226 17712]) ("lsDelBefore" function (:arguments (("generator" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [17740 17787]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [17790 17836])) :type ("lsStatus" type (:type "class") nil nil)) nil [17716 19234]) ("lsDelAfter" function (:arguments (("generator" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [19260 19307]) ("data" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [19310 19356])) :type ("lsStatus" type (:type "class") nil nil)) nil [19237 20742]) ("lsFinish" function (:arguments (("generator" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [20766 20806])) :type ("lsStatus" type (:type "class") nil nil)) nil [20745 21144]) ("lsGenForm" function (:prototype-flag t :typemodifiers ("static") :arguments (("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21419 21439]) ("arg" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21468 21482]) ("gen" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21483 21493]) ("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21499 21519]) ("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21556 21576])) :type ("lsStatus" type (:type "class") nil nil)) nil [21393 21596]) ("lsForeach" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21620 21665]) ("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21668 21688]) ("arg" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21745 21792])) :type ("lsStatus" type (:type "class") nil nil)) nil [21598 22587]) ("lsBackeach" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [22613 22658]) ("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [22661 22681]) ("arg" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [22738 22785])) :type ("lsStatus" type (:type "class") nil nil)) nil [22590 22981]) ("lsGenForm" function (:typemodifiers ("static") :arguments (("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [23013 23033]) ("arg" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [23088 23141]) ("gen" variable (:type ("lsGen" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [23144 23193]) ("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [23196 23216]) ("" variable (:type ("lsStatus" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [23291 23311])) :type ("lsStatus" type (:type "class") nil nil)) nil [22984 23832]) ("lsQueryHandle" function (:arguments (("itemHandle" variable (:type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [23859 23905])) :type ("lsList" type (:type "class") nil nil)) nil [23835 24172]) ("lsFetchHandle" function (:arguments (("itemHandle" variable (:type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [24198 24218])) :type ("lsGeneric" type (:type "class") nil nil)) nil [24174 24358]) ("lsRemoveItem" function (:arguments (("itemHandle" variable (:type ("lsHandle" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [24385 24430]) ("userData" variable (:type ("lsGeneric" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [24433 24477])) :type ("lsStatus" type (:type "class") nil nil)) nil [24360 24936]) ("TYPE" variable (:constant-flag t :default-value (nil)) nil [24966 24988]) ("SORT" variable (:constant-flag t :default-value (nil)) nil [24987 25014]) ("NEXT" variable (:constant-flag t :default-value (nil)) nil [25013 25036]) ("FIELD" variable (:constant-flag t :default-value (nil)) nil [25035 25060]) ("lsort.h" include nil nil [25059 25077]) ("lsSort" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [25129 25170]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [25173 25187])) :type ("lsStatus" type (:type "class") nil nil)) nil [25110 26100]) ("lsUniq" function (:arguments (("list" variable (:type ("lsList" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [26122 26174]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [26177 26191]) ("" variable (:type "void") (reparse-symbol arg-sub-list) [26254 26269])) :type ("lsStatus" type (:type "class") nil nil)) nil [26103 27548]))
+    :file "list.c"
+    :pointmax 27549
+    :unmatched-syntax 'nil
+    )
+   (semanticdb-table "list.h"
+    :major-mode 'c-mode
+    :tags '(("LS_DEFINED" variable (:constant-flag t) nil [321 348]) ("ls_dummy" type (:typedef ("void") :superclasses "void" :type "typedef") nil [341 363]) ("lsList" type (:typedef ("ls_dummy" type (:type "class") nil nil) :pointer 1 :superclasses "ls_dummy" :type "typedef") nil [365 390]) ("lsGen" type (:typedef ("ls_dummy" type (:type "class") nil nil) :pointer 1 :superclasses "ls_dummy" :type "typedef") nil [419 443]) ("lsHandle" type (:typedef ("ls_dummy" type (:type "class") nil nil) :pointer 1 :superclasses "ls_dummy" :type "typedef") nil [472 499]) ("lsStatus" type (:typedef ("int") :superclasses "int" :type "typedef") nil [528 549]) ("lsGeneric" type (:typedef ("void") :pointer 1 :superclasses "void" :type "typedef") nil [579 603]) ("LS_NIL" variable (:constant-flag t :default-value (nil)) nil [633 650]) ("LS_BADSTATE" variable (:constant-flag t :default-value (nil)) nil [679 701]) ("LS_BADPARAM" variable (:constant-flag t :default-value (nil)) nil [730 752]) ("LS_NOMORE" variable (:constant-flag t :default-value (nil)) nil [781 801]) ("LS_OK" variable (:constant-flag t :default-value (nil)) nil [831 847]) ("LS_BEFORE" variable (:constant-flag t :default-value (nil)) nil [849 868]) ("LS_AFTER" variable (:constant-flag t :default-value (nil)) nil [898 916]) ("LS_STOP" variable (:constant-flag t :default-value (nil)) nil [946 964]) ("LS_DELETE" variable (:constant-flag t :default-value (nil)) nil [994 1013]) ("LS_NH" variable (:constant-flag t :default-value (nil)) nil [1153 1182]) ("LS_PFLSG" variable (:functionpointer-flag t :type ("lsGeneric" type (:type "class") nil nil)) nil [1192 1225]) ("ARGS" function (:prototype-flag t :type ("lsCreate" type (:type "class") nil nil)) nil [1241 1263]) ("ARGS" function (:prototype-flag t :type ("lsDestroy" type (:type "class") nil nil)) nil [1306 1352]) ("ARGS" function (:prototype-flag t :type ("lsCopy" type (:type "class") nil nil)) nil [1408 1440]) ("ARGS" function (:prototype-flag t :type ("lsFirstItem" type (:type "class") nil nil)) nil [1500 1550]) ("ARGS" function (:prototype-flag t :type ("lsLastItem" type (:type "class") nil nil)) nil [1605 1654]) ("ARGS" function (:prototype-flag t :type ("lsNewBegin" type (:type "class") nil nil)) nil [1709 1758]) ("ARGS" function (:prototype-flag t :type ("lsNewEnd" type (:type "class") nil nil)) nil [1809 1856]) ("ARGS" function (:prototype-flag t :type ("lsDelBegin" type (:type "class") nil nil)) nil [1906 1943]) ("ARGS" function (:prototype-flag t :type ("lsDelEnd" type (:type "class") nil nil)) nil [1996 2031]) ("ARGS" function (:prototype-flag t :type ("lsLength" type (:type "class") nil nil)) nil [2079 2103]) ("ARGS" function (:prototype-flag t :type ("lsStart" type (:type "class") nil nil)) nil [2157 2180]) ("ARGS" function (:prototype-flag t :type ("lsEnd" type (:type "class") nil nil)) nil [2238 2259]) ("ARGS" function (:prototype-flag t :type ("lsGenHandle" type (:type "class") nil nil)) nil [2313 2358]) ("ARGS" function (:prototype-flag t :type ("lsNext" type (:type "class") nil nil)) nil [2419 2463]) ("ARGS" function (:prototype-flag t :type ("lsPrev" type (:type "class") nil nil)) nil [2519 2563]) ("ARGS" function (:prototype-flag t :type ("lsInBefore" type (:type "class") nil nil)) nil [2623 2671]) ("ARGS" function (:prototype-flag t :type ("lsInAfter" type (:type "class") nil nil)) nil [2756 2803]) ("ARGS" function (:prototype-flag t :type ("lsDelBefore" type (:type "class") nil nil)) nil [2888 2925]) ("ARGS" function (:prototype-flag t :type ("lsDelAfter" type (:type "class") nil nil)) nil [2990 3026]) ("ARGS" function (:prototype-flag t :type ("lsFinish" type (:type "class") nil nil)) nil [3090 3113]) ("ARGS" function (:prototype-flag t :type ("lsForeach" type (:type "class") nil nil)) nil [3172 3261]) ("ARGS" function (:prototype-flag t :type ("lsBackeach" type (:type "class") nil nil)) nil [3335 3425]) ("ARGS" function (:prototype-flag t :type ("lsQueryHandle" type (:type "class") nil nil)) nil [3497 3528]) ("ARGS" function (:prototype-flag t :type ("lsFetchHandle" type (:type "class") nil nil)) nil [3583 3614]) ("ARGS" function (:prototype-flag t :type ("lsRemoveItem" type (:type "class") nil nil)) nil [3675 3716]) ("ARGS" function (:prototype-flag t :type ("lsSort" type (:type "class") nil nil)) nil [3788 3841]) ("ARGS" function (:prototype-flag t :type ("lsUniq" type (:type "class") nil nil)) nil [3880 3955]) ("lsForEachItem" variable (:constant-flag t) nil [4369 4672]))
+    :file "list.h"
+    :pointmax 4840
+    )
+   (semanticdb-table "lsort.h"
+    :major-mode 'c-mode
+    :tags 'nil
+    :file "lsort.h"
+    )
+   )
+  :file "semantic.cache"
+  :semantic-tag-version "2.0beta3"
+  :semanticdb-version "2.0beta3"
+  )
Index: /vis_dev/glu-2.1/src/mdd/mdd.h
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd.h	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd.h	(revision 8)
@@ -0,0 +1,345 @@
+/*
+ * $Id: mdd.h,v 1.29 2002/08/27 16:30:25 fabio Exp $
+ */
+
+#ifndef MDD_DEFINED
+#define MDD_DEFINED
+
+
+#include "util.h"
+#include "array.h"
+#include "st.h"
+#include "var_set.h"
+
+#include "bdd.h" 
+
+/*    #include "bdd_int.h"   */
+
+/************************************************************************/
+#define str_len         10
+#define MONITOR         0
+#define MDD_VERBOSE     0
+#define SOLUTION        0
+#define BDD_SIZE        1
+#define USE_ITE         1
+#define BYPASS          1
+/* code may not be fully debugged for interleaving */
+#define INTERLEAVE      0
+
+#define mdd_and bdd_and
+#define mdd_and_with_limit bdd_and_with_limit
+#define mdd_and_array bdd_and_array
+#define mdd_cofactor_minterm bdd_cofactor
+#define mdd_constant bdd_constant
+#define mdd_dup bdd_dup
+/* mdd_equal returns 1 if two MDD's are identical */
+/* mdd_eq is a totally different function */
+/* which returns an MDD instead */
+#define mdd_equal bdd_equal
+#define mdd_equal_mod_care_set bdd_equal_mod_care_set
+#define mdd_closest_cube bdd_closest_cube
+#define mdd_free bdd_free
+#define mdd_get_manager bdd_get_manager
+#define mdd_is_tautology bdd_is_tautology
+#define mdd_ite bdd_ite
+/* mdd_lequal checks for implication, */
+/* mdd_lequal(f,g,1,0) returns the value of (f => g') */
+/* mdd_leq is a totally different function */
+#define mdd_lequal bdd_leq
+#define mdd_lequal_mod_care_set bdd_lequal_mod_care_set
+#define mdd_lequal_array bdd_leq_array
+#define mdd_multiway_and bdd_multiway_and
+#define mdd_multiway_or bdd_multiway_or
+#define mdd_multiway_xor bdd_multiway_xor
+#define mdd_not bdd_not
+#define mdd_one bdd_one
+#define mdd_or bdd_or
+#define mdd_size bdd_size
+#define mdd_size_multiple bdd_size_multiple
+#define mdd_top_var_id bdd_top_var_id
+#define mdd_xor bdd_xor
+#define mdd_xnor bdd_xnor
+#define mdd_zero bdd_zero
+#define mdd_EMPTY bdd_EMPTY
+
+#define mdd_first_solution mdd_first_cube
+#define mdd_next_solution mdd_next_cube
+
+#define mdd_eq_c(m,a,b)  	mdd_func1c(m,a,b,eq2)
+#define mdd_geq_c(m,a,b) 	mdd_func1c(m,a,b,geq2)
+#define mdd_gt_c(m,a,b)  	mdd_func1c(m,a,b,gt2)
+#define mdd_leq_c(m,a,b) 	mdd_func1c(m,a,b,leq2)
+#define mdd_lt_c(m,a,b)  	mdd_func1c(m,a,b,lt2)
+#define mdd_neq_c(m,a,b) 	mdd_func1c(m,a,b,neq2)
+
+#define mdd_eq(m,a,b)  		mdd_func2(m,a,b,eq2)
+#define mdd_geq(m,a,b) 		mdd_func2(m,a,b,geq2)
+#define mdd_gt(m,a,b)  		mdd_func2(m,a,b,gt2)
+#define mdd_leq(m,a,b) 		mdd_func2(m,a,b,leq2)
+#define mdd_lt(m,a,b)  		mdd_func2(m,a,b,lt2)
+#define mdd_neq(m,a,b) 		mdd_func2(m,a,b,neq2)
+#define mdd_unary_minus(m,a,b) 	mdd_func2(m,a,b,unary_minus2)
+
+#define mdd_eq_plus(m,a,b,c)	mdd_func3(m,a,b,c,eq_plus3)
+#define mdd_geq_plus(m,a,b,c)	mdd_func3(m,a,b,c,geq_plus3)
+#define mdd_gt_plus(m,a,b,c)	mdd_func3(m,a,b,c,gt_plus3)
+#define mdd_leq_plus(m,a,b,c)	mdd_func3(m,a,b,c,leq_plus3)
+#define mdd_lt_plus(m,a,b,c)	mdd_func3(m,a,b,c,lt_plus3)
+#define mdd_neq_plus(m,a,b,c)	mdd_func3(m,a,b,c,neq_plus3)
+
+#define mdd_eq_minus(m,a,b,c)	mdd_func3(m,a,b,c,eq_minus3)
+#define mdd_geq_minus(m,a,b,c)	mdd_func3(m,a,b,c,geq_minus3)
+#define mdd_gt_minus(m,a,b,c)	mdd_func3(m,a,b,c,gt_minus3)
+#define mdd_leq_minus(m,a,b,c)	mdd_func3(m,a,b,c,leq_minus3)
+#define mdd_lt_minus(m,a,b,c)	mdd_func3(m,a,b,c,lt_minus3)
+#define mdd_neq_minus(m,a,b,c)	mdd_func3(m,a,b,c,neq_minus3)
+
+#define mdd_eq_plus_c(m,a,b,c)	mdd_func2c(m,a,b,c,eq_plus3)
+#define mdd_geq_plus_c(m,a,b,c)	mdd_func2c(m,a,b,c,geq_plus3)
+#define mdd_gt_plus_c(m,a,b,c)	mdd_func2c(m,a,b,c,gt_plus3)
+#define mdd_leq_plus_c(m,a,b,c)	mdd_func2c(m,a,b,c,leq_plus3)
+#define mdd_lt_plus_c(m,a,b,c)	mdd_func2c(m,a,b,c,lt_plus3)
+#define mdd_neq_plus_c(m,a,b,c)	mdd_func2c(m,a,b,c,neq_plus3)
+
+
+#define mdd_eq_plus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,eq_plus3mod)
+#define mdd_geq_plus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,geq_plus3mod)
+#define mdd_gt_plus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,gt_plus3mod)
+#define mdd_leq_plus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,leq_plus3mod)
+#define mdd_lt_plus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,lt_plus3mod)
+#define mdd_neq_plus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,neq_plus3mod)
+
+#define mdd_eq_minus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,eq_minus3mod)
+#define mdd_geq_minus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,geq_minus3mod)
+#define mdd_gt_minus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,gt_minus3mod)
+#define mdd_leq_minus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,leq_minus3mod)
+#define mdd_lt_minus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,lt_minus3mod)
+#define mdd_neq_minus_c_mod(m,a,b,c)	mdd_func2c_mod(m,a,b,c,neq_minus3mod)
+
+#define mdd_eq_s(m,a,b) 	mdd_ineq_template_s(m,a,b,0,0,1)
+#define mdd_geq_s(m,a,b) 	mdd_ineq_template_s(m,a,b,0,1,1)
+#define mdd_gt_s(m,a,b)		mdd_ineq_template_s(m,a,b,0,1,0)
+#define mdd_neq_s(m,a,b)	mdd_ineq_template_s(m,a,b,1,1,0)
+#define mdd_leq_s(m,a,b)	mdd_ineq_template_s(m,a,b,1,0,1)
+#define mdd_lt_s(m,a,b)		mdd_ineq_template_s(m,a,b,1,0,0)
+
+/**** for backward compatibility only ****/
+#define mdd_eq_g(m,a,b)  	mdd_func2(m,a,b,eq2)
+#define mdd_geq_g(m,a,b) 	mdd_func2(m,a,b,geq2)
+#define mdd_gt_g(m,a,b)  	mdd_func2(m,a,b,gt2)
+#define mdd_leq_g(m,a,b) 	mdd_func2(m,a,b,leq2)
+#define mdd_lt_g(m,a,b)  	mdd_func2(m,a,b,lt2)
+#define mdd_neq_g(m,a,b) 	mdd_func2(m,a,b,neq2)
+#define mdd_init_name(v,n,s) 	mdd_init(v,n,s)
+
+/* mdd_int.h */
+#define MDD_NOT(node)           ((bdd_node *) ((int) (node) ^ 01))
+#define MDD_REGULAR(node)       ((bdd_node *) ((int) (node) & ~01))
+#define MDD_IS_COMPLEMENT(node) ((int) (node) & 01)
+
+#define MDD_ONE(bdd)            (bdd)->one
+#define MDD_ZERO(bdd)           (MDD_NOT(MDD_ONE(bdd)))
+
+#ifndef MAX
+#define MAX(a,b) (a) > (b) ? (a) : (b)
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (a) < (b) ? (a) : (b)
+#endif
+
+    typedef bdd_t mdd_t;
+    typedef bdd_manager mdd_manager;
+
+typedef enum {
+	MDD_ACTIVE,
+	MDD_BUNDLED
+} mvar_status;
+
+struct mvar_type {
+    int mvar_id;		/* mvar id */
+    mvar_status status;         /* Whether the mvar is currently being used or 
+                                   has been bundled into another mvar */
+    char *name;			/* name of mvar */
+    int values;			/* no. of values mvar can take */
+    int encode_length;		/* no. of binary variables, bvar's, */
+				/* needed to encode mvar */
+    array_t *bvars;             /* array of bvar_id's from most significant bit to least 
+				   significant bit, has size encode_length */
+    int *encoding;		/* internal use only */
+};
+typedef struct mvar_type mvar_type;
+
+struct bvar_type {
+    mdd_t *node;
+    int mvar_id;
+};
+typedef struct bvar_type bvar_type;
+
+struct mdd_hook_type {
+    array_t *mvar_list;
+    array_t *bvar_list;	
+};
+
+typedef struct mdd_hook_type mdd_hook_type;
+
+struct mdd_gen {
+    mdd_manager *manager;
+    bdd_gen *bdd_generator;
+    bdd_gen_status status;
+    array_t *cube;		/* array of literals {0,1,2} of all vars */
+    array_t *minterm;		/* current minterm */
+    array_t *var_list;		/* list of var id's */
+    boolean out_of_range;
+}; 
+
+typedef struct mdd_gen mdd_gen;
+
+#define foreach_mdd_minterm(fn, gen, minterm, var_list)\
+  for((gen) = mdd_first_minterm(fn, &minterm, var_list);\
+      ((gen)->status != bdd_EMPTY) ? TRUE: mdd_gen_free(gen);\
+      (void) mdd_next_minterm(gen, &minterm))
+                                                                      
+
+extern mdd_hook_type mdd_hook;
+
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN mdd_manager *mdd_init ARGS((array_t *mvar_values, array_t *mvar_names, array_t *mvar_strides));
+EXTERN mdd_manager *mdd_init_empty ARGS((void));
+EXTERN unsigned int mdd_create_variables ARGS((mdd_manager *mgr, array_t *mvar_values, array_t *mvar_names, array_t *mvar_strides));
+EXTERN unsigned int mdd_create_variables_after ARGS((mdd_manager*, int, array_t*, array_t*, array_t* ));
+EXTERN unsigned int mdd_create_variables_interleaved ARGS((mdd_manager*, int, int, array_t*));
+EXTERN void mdd_quit ARGS((mdd_manager *mgr));
+EXTERN mdd_t *mdd_case ARGS((mdd_manager *mgr, int mvar, array_t *child_list));
+EXTERN mdd_t *mdd_consensus ARGS((mdd_manager *mgr, mdd_t *fn, array_t *mvars));
+EXTERN mdd_t *mdd_encode ARGS((mdd_manager *mgr, array_t *child_list, mvar_type *mv_ptr, int index));
+EXTERN mdd_t *mdd_literal ARGS((mdd_manager *mgr, int mddid, array_t *values));
+EXTERN void   mdd_search ARGS((mdd_manager *mgr, bdd_t *top, int phase, boolean minterms));
+EXTERN mdd_t *mdd_cofactor ARGS((mdd_manager *mgr, mdd_t *fn, mdd_t *cube));
+EXTERN mdd_t *mdd_smooth ARGS((mdd_manager *mgr, mdd_t *fn, array_t *mvars));
+EXTERN mdd_t *mdd_and_smooth ARGS((mdd_manager *mgr, mdd_t *f, mdd_t *g, array_t *mvars));
+EXTERN mdd_t *mdd_and_smooth_with_limit ARGS((mdd_manager *mgr, mdd_t *f, mdd_t *g, array_t *mvars, unsigned int limit));
+EXTERN mdd_t *mdd_substitute ARGS((mdd_manager *mgr, mdd_t *fn, array_t	*old_mvars, array_t *new_mvars));
+EXTERN array_t *mdd_substitute_array ARGS((mdd_manager *mgr, array_t *fn_array, array_t *old_mvars, array_t *new_mvars));
+EXTERN array_t *mdd_get_support ARGS((mdd_manager *mdd_mgr, mdd_t *f));
+EXTERN array_t *mdd_get_bdd_support_ids ARGS((mdd_manager *mdd_mgr, mdd_t *f));
+EXTERN array_t *mdd_get_bdd_support_vars ARGS((mdd_manager *mdd_mgr, mdd_t *f));
+EXTERN mdd_t *mdd_interval ARGS((mdd_manager *mgr, int mvar_id, int low, int high)); 
+EXTERN double mdd_count_onset ARGS((mdd_manager *mddMgr, mdd_t *aMdd, array_t *mddIdArr));
+EXTERN mdd_t *mdd_onset_bdd ARGS((mdd_manager *mddMgr, mdd_t *aMdd, array_t *mddIdArr));
+EXTERN int mdd_epd_count_onset ARGS((mdd_manager *mddMgr, mdd_t *aMdd, array_t *mddIdArr, EpDouble *epd));
+EXTERN array_t  * mdd_ret_bvars_of_mvar ARGS((mvar_type *mvar_ptr));
+EXTERN mdd_t *mdd_cproject ARGS((mdd_manager *mgr, mdd_t *T, array_t *mvars));
+EXTERN mdd_t *mdd_mod ARGS((mdd_manager *mgr, int a_mvar_id, int b_mvar_id, int M));
+EXTERN mdd_t *mdd_ineq_template_s ARGS((mdd_manager *mgr, int mvar1, int mvar2,	int zero_then_val, int one_else_val, int bottom_val));
+EXTERN mdd_t *mdd_add_s ARGS((mdd_manager *mgr, int sum_id, int mvar_id1, int mvar_id2 ));
+/* mdd_iter.c */
+EXTERN mdd_gen *mdd_first_minterm ARGS((mdd_t *f, array_t **minterm_p, array_t *var_list));
+EXTERN boolean mdd_next_minterm ARGS((mdd_gen *mgen, array_t **minterm_p));
+EXTERN void mdd_print_array ARGS((array_t *array));
+EXTERN int mdd_gen_free ARGS((mdd_gen *mgen));
+EXTERN mdd_t *mdd_func1c ARGS((mdd_manager *mgr, int mvar1, int mvar2, boolean (*func1c) (int, int)));
+EXTERN mdd_t *mdd_func2 ARGS((mdd_manager *mgr, int mvar1, int mvar2, boolean (*func2) (int, int)));
+/* functions of 2 variables used by mdd_func2 ARGS(()) */
+EXTERN boolean eq2 ARGS((int x, int y));
+EXTERN boolean geq2 ARGS((int x, int y));
+EXTERN boolean gt2 ARGS((int x, int y));
+EXTERN boolean leq2 ARGS((int x, int y));
+EXTERN boolean lt2 ARGS((int x, int y));
+EXTERN boolean neq2 ARGS((int x, int y));
+EXTERN boolean unary_minus2 ARGS((int x, int y));
+EXTERN mdd_t *mdd_func2c ARGS((mdd_manager *mgr,int mvar1, int mvar2, int constant, boolean (*func3)(int, int, int)));
+EXTERN mdd_t *mdd_func2c_mod ARGS((mdd_manager *mgr,int mvar1, int mvar2, int constant, boolean (*func4)(int, int, int, int)));
+
+/* should be in ../test */
+EXTERN mdd_t *mdd_func3 ARGS((mdd_manager *mgr, int mvar1, int mvar2, int mvar3, boolean (*func3)(int, int, int)));
+/* functions of 3 variables used by mdd_func3 ARGS(()) */
+EXTERN boolean eq_plus3 ARGS((int x, int y, int z));
+EXTERN boolean geq_plus3 ARGS((int x, int y, int z));
+EXTERN boolean gt_plus3 ARGS((int x, int y, int z));
+EXTERN boolean leq_plus3 ARGS((int x, int y, int z));
+EXTERN boolean lt_plus3 ARGS((int x, int y, int z));
+EXTERN boolean neq_plus3 ARGS((int x, int y, int z));
+/* actually functions below can be obtained from the set above */
+/* by just suppling the negation of the constant value */
+EXTERN boolean eq_minus3 ARGS((int x, int y, int z));
+EXTERN boolean geq_minus3 ARGS((int x, int y, int z));
+EXTERN boolean gt_minus3 ARGS((int x, int y, int z));
+EXTERN boolean leq_minus3 ARGS((int x, int y, int z));
+EXTERN boolean lt_minus3 ARGS((int x, int y, int z));
+EXTERN boolean neq_minus3 ARGS((int x, int y, int z));
+
+EXTERN array_t *mdd_id_to_bdd_id_array ARGS((mdd_manager *mddManager, int mddId));
+EXTERN array_t *mdd_id_to_bdd_array ARGS((mdd_manager *mddManager, int mddId));
+EXTERN array_t *mdd_id_array_to_bdd_array ARGS((mdd_manager *mddManager, array_t *mddIdArray));
+EXTERN array_t *mdd_id_array_to_bdd_id_array ARGS((mdd_manager *mddManager, array_t *mddIdArray));
+EXTERN mdd_t *mdd_id_array_to_bdd_cube ARGS((mdd_manager *mddManager, array_t *mddIdArray));
+EXTERN int mdd_get_number_of_bdd_vars ARGS((mdd_manager *mddManager, array_t *mddIdArray));
+EXTERN int mdd_get_number_of_bdd_support ARGS((mdd_manager *mddManager, mdd_t *f));
+EXTERN array_t *mdd_fn_array_to_bdd_rel_array ARGS((mdd_manager *mddManager, int mddId, array_t *mddFnArray));
+EXTERN array_t *mdd_fn_array_to_bdd_fn_array ARGS((mdd_manager *mddManager, int mddId, array_t *mddFnArray));
+EXTERN array_t *mdd_pick_arbitrary_minterms ARGS((mdd_manager *mgr, mdd_t *f, array_t *mddIdArr, int n));
+EXTERN mdd_t *mdd_subset_with_mask_vars ARGS((mdd_manager *mgr, mdd_t *f, array_t *mddIdArr, array_t *maskIdArr));
+EXTERN mvar_type mdd_get_var_by_id ARGS((mdd_manager *mddMgr, int id));
+EXTERN void mdd_print_support ARGS((mdd_t *f));
+EXTERN void mdd_print_support_to_file ARGS((FILE *fout, char *format, mdd_t *f));
+EXTERN char *mdd_read_var_name ARGS((mdd_t *f));
+EXTERN int mdd_read_mdd_id ARGS((mdd_t *f));
+EXTERN int mdd_check_support ARGS((mdd_manager *mddMgr, mdd_t *mdd, array_t *supportIdArray));
+EXTERN int mdd_equal_mod_care_set_array ARGS((mdd_t *aSet, mdd_t *bSet, array_t *CareSetArray));
+EXTERN int mdd_lequal_mod_care_set_array ARGS((mdd_t *aSet, mdd_t *bSet, boolean aPhase, boolean bPhase, array_t *CareSetArray));
+
+EXTERN boolean eq_plus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean geq_plus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean gt_plus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean leq_plus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean lt_plus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean neq_plus3mod ARGS((int x, int y, int z, int range));
+/* actually functions below can be obtained from the set above */
+/* by just suppling the negation of the constant value */
+EXTERN boolean eq_minus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean geq_minus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean gt_minus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean leq_minus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean lt_minus3mod ARGS((int x, int y, int z, int range));
+EXTERN boolean neq_minus3mod ARGS((int x, int y, int z, int range));
+
+/* should be in mdd_int.h */
+EXTERN int toggle ARGS((int x));
+EXTERN int no_bit_encode ARGS((int n));
+EXTERN void print_strides ARGS((array_t *mvar_strides));
+EXTERN void print_mvar_list ARGS((mdd_manager *mgr));
+EXTERN void print_bdd_list_id ARGS((array_t *bdd_list));
+EXTERN void print_bvar_list_id ARGS((mdd_manager *mgr));
+EXTERN void print_bdd ARGS((bdd_manager *mgr, bdd_t *top));
+EXTERN mvar_type find_mvar_id ARGS((mdd_manager *mgr, unsigned short id));
+EXTERN void clear_all_marks ARGS((mdd_manager *mgr));
+EXTERN void mdd_mark ARGS((mdd_manager *mgr, bdd_t *top, int phase));
+EXTERN void mdd_unmark ARGS((mdd_manager *mgr, bdd_t *top));
+EXTERN mvar_type find_mvar ARGS((mdd_manager *mgr, char *name));
+EXTERN array_t *mdd_ret_mvar_list ARGS((mdd_manager *mgr));
+EXTERN void mdd_set_mvar_list ARGS((mdd_manager *mgr, array_t *mvar_list));
+EXTERN array_t *mdd_ret_bvar_list ARGS((mdd_manager *mgr));
+EXTERN mdd_t *build_lt_c ARGS((mdd_manager *mgr, int mvar_id, int c));
+EXTERN mdd_t *build_leq_c ARGS((mdd_manager *mgr, int mvar_id, int c));
+EXTERN mdd_t *build_gt_c ARGS((mdd_manager *mgr, int mvar_id, int c));
+EXTERN mdd_t *build_geq_c ARGS((mdd_manager *mgr, int mvar_id, int c));
+EXTERN int getbit ARGS((int number, int position));
+EXTERN int integer_get_num_of_digits ARGS((int value));
+EXTERN int mdd_ret_bvar_id ARGS((mvar_type *mvar_ptr, int i));
+EXTERN bvar_type mdd_ret_bvar ARGS((mvar_type *mvar_ptr, int i, array_t *bvar_list));
+EXTERN void mdd_array_free ARGS((array_t *mddArray));
+EXTERN void mdd_array_array_free ARGS((array_t *arrayBddArray));
+EXTERN array_t *mdd_array_duplicate ARGS((array_t *mddArray));
+EXTERN boolean mdd_array_equal ARGS((array_t *array1, array_t *array2));
+EXTERN mdd_t *mdd_range_mdd ARGS((mdd_manager *mgr, array_t *support));
+
+/* unsupported */
+EXTERN int mdd_bundle_variables ARGS((mdd_manager *mgr, array_t *bundle_vars, char *mdd_var_name, int *mdd_id));
+EXTERN mdd_t * mdd_unary_minus_s ARGS((mdd_manager *mgr, int mvar1, int mvar2));
+EXTERN array_t * mvar2bdds ARGS((mdd_manager *mgr, array_t *mvars));
+#endif
Index: /vis_dev/glu-2.1/src/mdd/mdd.make
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd.make	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd.make	(revision 8)
@@ -0,0 +1,6 @@
+CSRC_mdd = mdd_add.c mdd_andsmoot.c mdd_bund.c mdd_case.c mdd_cofactor.c mdd_consensus.c mdd_func1c.c mdd_func2.c mdd_func2c.c mdd_func3.c mdd_ineq_s.c mdd_init.c mdd_intv.c mdd_iter.c mdd_literal.c mdd_mod.c mdd_quit.c mdd_search.c mdd_smooth.c mdd_substit.c mdd_support.c mdd_uminus.c mdd_util.c mvar2bdds.c mdd_func2cmod.c
+HEADERS_mdd = mdd.h
+MISC += mdd.doc
+
+
+DEPENDENCYFILES = $(CSRC_mdd)
Index: /vis_dev/glu-2.1/src/mdd/mdd_add.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_add.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_add.c	(revision 8)
@@ -0,0 +1,229 @@
+#include "mdd.h"
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void addition_block_build(mdd_manager *mgr, mdd_t **A, mdd_t **B, bvar_type *bx_ptr, bvar_type *by_ptr, bvar_type *bz_ptr);
+EXTERN void one_var_and_carry_add_block(mdd_manager *mgr, mdd_t **A, mdd_t **B, bvar_type *bz_ptr, bvar_type *blv_ptr);
+
+
+void
+addition_block_build(
+  mdd_manager *mgr,
+  mdd_t **A,
+  mdd_t **B,
+  bvar_type *bx_ptr,
+  bvar_type *by_ptr,
+  bvar_type *bz_ptr)
+{
+	mdd_t *zero;
+	mdd_t 	*C, *D, *E, *F,
+		*G, *H, *I;
+
+	zero = mdd_zero(mgr);	
+		
+	G = mdd_ite( by_ptr->node, zero , *A  ,  1, 1, 1 );
+	H = mdd_ite( by_ptr->node, *A   , *B  ,  1, 1, 1 );
+	I = mdd_ite( by_ptr->node, *B   , zero,  1, 1, 1 );
+
+	C = mdd_ite( bx_ptr->node, zero, G   ,  1, 1, 1 );
+	D = mdd_ite( bx_ptr->node, G   , H   ,  1, 1, 1 );
+	E = mdd_ite( bx_ptr->node, H   , I   ,  1, 1, 1 );
+	F = mdd_ite( bx_ptr->node, I   , zero,  1, 1, 1 );
+		
+	*A = mdd_ite( bz_ptr->node, D   , C   ,  1, 1, 1 );
+	*B = mdd_ite( bz_ptr->node, F   , E   ,  1, 1, 1 );
+
+	mdd_free(G);
+	mdd_free(H);
+	mdd_free(I);
+	mdd_free(C);
+	mdd_free(D);
+	mdd_free(E);
+	mdd_free(F);
+	mdd_free(zero);
+
+	return;
+}
+
+
+void
+one_var_and_carry_add_block(
+  mdd_manager *mgr,
+  mdd_t **A,
+  mdd_t **B,
+  bvar_type *bz_ptr,
+  bvar_type *blv_ptr)
+{
+	mdd_t *C, *D, *E;
+	mdd_t *zero;
+
+	zero = mdd_zero(mgr);	
+
+	C = mdd_ite( blv_ptr->node,  zero,   *A, 1, 1, 1);
+	D = mdd_ite( blv_ptr->node,    *A,   *B, 1, 1, 1);
+	E = mdd_ite( blv_ptr->node,    *B, zero, 1, 1, 1);
+
+	*A = mdd_ite( bz_ptr->node,    D, C, 1, 1, 1);
+	*B = mdd_ite( bz_ptr->node, zero, E, 1, 1, 1);
+
+	mdd_free(C);
+	mdd_free(D);
+	mdd_free(E);
+
+	mdd_free(zero);
+
+	return;
+}
+
+/* in1 + in2 = sum */
+mdd_t *
+mdd_add_s(
+  mdd_manager *mgr,
+  int sum_id,
+  int mvar_id1,
+  int mvar_id2)
+{
+	mdd_t *one, *zero;
+	array_t *mvar_list = mdd_ret_mvar_list(mgr);
+ 	array_t *bvar_list = mdd_ret_bvar_list(mgr);
+	int     config, 
+	    	no_common_to_all_bits, 
+	   	no_common_in_bits, i;
+
+	bvar_type bx, by, bz, z_carry, blv;
+	mvar_type x, y, z, long_var;
+	mdd_t 	*A, *B, *range_check;
+	mdd_t *result = NIL(mdd_t); /* initialize for lint */
+        
+
+	
+	x = array_fetch(mvar_type, mvar_list, mvar_id1);
+	y = array_fetch(mvar_type, mvar_list, mvar_id2);
+	z = array_fetch(mvar_type, mvar_list, sum_id);
+
+	/* Ensures that the i_th bit of x has smaller index
+	   than the i_th bit of y */
+
+	if  ( ( mdd_ret_bvar_id(&x,x.encode_length) ) >
+              ( mdd_ret_bvar_id(&y,y.encode_length) )  )  {
+			y = array_fetch(mvar_type, mvar_list, mvar_id1);
+			x = array_fetch(mvar_type, mvar_list, mvar_id2);
+			}
+
+	one = mdd_one(mgr);
+	zero = mdd_zero(mgr);	
+	
+	no_common_in_bits = MIN(x.encode_length,y.encode_length);
+	no_common_to_all_bits = MIN(no_common_in_bits, z.encode_length);
+
+	A = mdd_dup(one);
+	B = mdd_dup(zero);
+
+	for (i = 1; i <= no_common_to_all_bits; i++){
+
+		bx = mdd_ret_bvar(&x,x.encode_length-i,bvar_list); 
+		by = mdd_ret_bvar(&y,y.encode_length-i,bvar_list);
+		bz = mdd_ret_bvar(&z,z.encode_length-i,bvar_list);
+		addition_block_build( mgr, &A, &B, &bx, &by, &bz);
+	}
+
+
+	if ( z.encode_length > no_common_to_all_bits ){
+		if ( x.encode_length != y.encode_length ){
+			if ( x.encode_length == no_common_in_bits ){ 
+				long_var = y;   
+				/* short_var = x; */
+			}
+			else { 
+				long_var = x;   
+				/* short_var = y; */
+			}
+		
+			if ( z.encode_length > long_var.encode_length) {
+			config = 1;	 
+			}
+			else
+			{
+			config = 2;		
+			}
+		}
+		else 
+			config = 3;			
+	}
+	else 
+		config = 4;			
+
+
+	switch (config) {
+		
+		case 1: /* z > long_var , short_var */
+
+			for ( i = no_common_to_all_bits + 1; i <= long_var.encode_length; i++){
+
+				z_carry = mdd_ret_bvar(&z,z.encode_length-i,bvar_list);
+				blv = mdd_ret_bvar(&long_var,long_var.encode_length-i,bvar_list);
+
+				one_var_and_carry_add_block(mgr, &A, &B, &bz, &blv);
+			}
+			
+			z_carry = mdd_ret_bvar(&z,z.encode_length - long_var.encode_length - 1, bvar_list);
+
+			A = mdd_ite( z_carry.node, B, A, 1, 1, 1);
+
+			for ( i = long_var.encode_length + 2; i <= z.encode_length; i++){
+				z_carry = mdd_ret_bvar(&z,z.encode_length-i, bvar_list);
+				A = mdd_ite( z_carry.node, zero, A, 1, 1, 1);				
+			}
+			result = mdd_dup(A);
+			break;
+
+		case 2: /* short_var < z < long_var */
+
+			for ( i = no_common_to_all_bits + 1; i <= z.encode_length; i++){
+
+				z_carry = mdd_ret_bvar(&z,z.encode_length-i,bvar_list);
+				blv = mdd_ret_bvar(&long_var,long_var.encode_length-i,bvar_list);
+
+				one_var_and_carry_add_block(mgr, &A, &B, &bz, &blv);
+
+			}
+
+			result = mdd_or(A,B,1,1);
+			break;
+
+		case 3: /* z> long_var = short_var */ 
+
+			z_carry = mdd_ret_bvar(&z,z.encode_length - no_common_to_all_bits - 1,bvar_list);
+			A = mdd_ite( z_carry.node, B, A, 1, 1, 1);
+
+			for ( i = no_common_to_all_bits + 2; i <= z.encode_length; i++){
+				z_carry = mdd_ret_bvar(&z, z.encode_length - i, bvar_list);
+				A = mdd_ite( z_carry.node, zero, A, 1, 1, 1);
+			}	
+
+			result = mdd_dup(A);
+			break;
+
+		case 4: /* z <= long_var, z <= short_var */
+			result = mdd_or(A,B,1,1);
+			break;
+	}
+	
+	mdd_free(A);
+	mdd_free(B);
+
+
+	mdd_free(one);
+	mdd_free(zero);
+	
+	range_check = build_lt_c(mgr, sum_id, z.values);
+	result = mdd_and(result, range_check, 1, 1);
+
+	mdd_free(range_check);
+
+	return result;
+}
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_andsmoot.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_andsmoot.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_andsmoot.c	(revision 8)
@@ -0,0 +1,132 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_andsmoot.c,v 1.12 2002/08/27 00:55:23 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_and_smooth(
+  mdd_manager *mgr,
+  mdd_t *f,
+  mdd_t *g,
+  array_t *mvars)
+{
+    int i, j, mv_no;
+    mvar_type mv;
+    mdd_t *top;
+    bdd_t *temp;
+
+    array_t *bdd_vars = array_alloc(bdd_t *, 0);
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+
+    if ( mvars == NIL( array_t ) ) {
+	printf("\nWARNING: Empty Array of Smoothing Variables\n");
+	array_free(bdd_vars);
+	return ( bdd_and(f, g, 1, 1) ) ;
+    }
+    else if ( array_n(mvars) == 0)  {
+	printf("\nWARNING: Empty Array of Smoothing Variables\n");
+	array_free(bdd_vars);
+	return ( bdd_and(f, g, 1, 1) ) ;
+    }
+
+    for (i=0; i<array_n(mvars); i++) {
+	mv_no = array_fetch(int, mvars, i);
+	mv = array_fetch(mvar_type, mvar_list, mv_no);
+	if (mv.status == MDD_BUNDLED) {
+	    (void) fprintf(stderr, 
+		"\nmdd_andsmooth: bundled variable %s used\n",mv.name);
+	    fail("");
+	}
+
+	for (j = 0; j < mv.encode_length; j++) {
+	    temp = bdd_get_variable(mgr, mdd_ret_bvar_id(&mv,j) );
+	    array_insert_last(bdd_t *, bdd_vars, temp);
+	}
+    }
+
+    assert( array_n(bdd_vars) != 0 );
+    top = bdd_and_smooth(f, g, bdd_vars);
+
+    for (i = 0; i < array_n(bdd_vars); i++) {
+	temp = array_fetch(bdd_t *, bdd_vars, i);
+	bdd_free(temp);
+    }
+    array_free(bdd_vars);
+
+    return top;
+}
+
+
+mdd_t *
+mdd_and_smooth_with_limit(
+  mdd_manager *mgr,
+  mdd_t *f,
+  mdd_t *g,
+  array_t *mvars,
+  unsigned int limit)
+{
+    int i, j, mv_no;
+    mvar_type mv;
+    mdd_t *top;
+    bdd_t *temp;
+
+    array_t *bdd_vars = array_alloc(bdd_t *, 0);
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+
+    if ( mvars == NIL( array_t ) ) {
+	printf("\nWARNING: Empty Array of Smoothing Variables\n");
+	array_free(bdd_vars);
+	return ( bdd_and_with_limit(f, g, 1, 1, limit) ) ;
+    }
+    else if ( array_n(mvars) == 0)  {
+	printf("\nWARNING: Empty Array of Smoothing Variables\n");
+	array_free(bdd_vars);
+	return ( bdd_and_with_limit(f, g, 1, 1, limit) ) ;
+    }
+
+    for (i=0; i<array_n(mvars); i++) {
+	mv_no = array_fetch(int, mvars, i);
+	mv = array_fetch(mvar_type, mvar_list, mv_no);
+	if (mv.status == MDD_BUNDLED) {
+	    (void) fprintf(stderr, 
+		"\nmdd_andsmooth: bundled variable %s used\n",mv.name);
+	    fail("");
+	}
+
+	for (j = 0; j < mv.encode_length; j++) {
+	    temp = bdd_get_variable(mgr, mdd_ret_bvar_id(&mv,j) );
+	    array_insert_last(bdd_t *, bdd_vars, temp);
+	}
+    }
+
+    assert( array_n(bdd_vars) != 0 );
+    top = bdd_and_smooth_with_limit(f, g, bdd_vars, limit);
+
+    for (i = 0; i < array_n(bdd_vars); i++) {
+	temp = array_fetch(bdd_t *, bdd_vars, i);
+	bdd_free(temp);
+    }
+    array_free(bdd_vars);
+
+    return top;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_bund.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_bund.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_bund.c	(revision 8)
@@ -0,0 +1,68 @@
+/*
+ * $Id: mdd_bund.c,v 1.5 2002/08/27 03:24:30 fabio Exp $
+ */
+
+#include "mdd.h"
+
+int
+mdd_bundle_variables(
+  mdd_manager *mgr,
+  array_t *bundle_vars,
+  char *mdd_var_name,
+  int *mdd_id)
+{
+	array_t *mvar_list, *bvar_list;
+	mvar_type var_i, new_var;
+	int i, var_i_id;
+	bvar_type *bit_i_ptr;
+	
+	mvar_list = mdd_ret_mvar_list(mgr);
+	bvar_list = mdd_ret_bvar_list(mgr);
+
+	new_var.mvar_id = array_n(mvar_list);
+	*mdd_id = new_var.mvar_id;
+
+	new_var.name = ALLOC( char, MAX( (int) strlen(mdd_var_name),
+					 integer_get_num_of_digits(new_var.mvar_id) + 5 ) );
+
+	if ( strcmp(mdd_var_name,"") != 0)  
+		strcpy(new_var.name, mdd_var_name);
+	else {
+		strcpy(new_var.name,"");
+		sprintf(new_var.name,"mv_%d", new_var.mvar_id);
+	};
+
+	new_var.encode_length = array_n(bundle_vars);
+	new_var.status = MDD_ACTIVE;
+
+	new_var.encoding = ALLOC(int, new_var.encode_length);
+	
+	new_var.bvars = array_alloc(int, 0);
+	new_var.values = 1;
+
+	for(i=0; i<array_n(bundle_vars); i++){
+		var_i_id = array_fetch(int, bundle_vars, i);
+		var_i = array_fetch(mvar_type, mvar_list, var_i_id);
+		array_append(new_var.bvars, var_i.bvars);
+		new_var.values *= var_i.values;
+		if ( var_i.values != (int) pow(2.0, (double)var_i.encode_length) ) 
+			printf("WARNING: Variable %s has %d values which is not a power of 2 \nmdd_bundle_variables: Bundling is ambiguous \n",var_i.name, var_i.values);
+		var_i.status = MDD_BUNDLED;
+	}
+
+	array_insert_last( mvar_type, mvar_list, new_var);
+
+	for(i=0; i< array_n(new_var.bvars); i++) {
+		bit_i_ptr = array_fetch_p( bvar_type, bvar_list, mdd_ret_bvar_id(&new_var, i) );
+		bit_i_ptr->mvar_id = new_var.mvar_id;
+	}
+
+	return TRUE;
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_case.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_case.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_case.c	(revision 8)
@@ -0,0 +1,155 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_case.c,v 1.10 2002/08/24 20:44:27 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_case(
+  mdd_manager *mgr,
+  int mvar,
+  array_t *child_list)
+{
+    mvar_type mv;
+    mdd_t *mnode;
+    mdd_t *tmp;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+    mv = array_fetch(mvar_type, mvar_list, mvar);
+
+    if (mv.values != array_n(child_list)) 
+	fail("mdd_case: mvar.values different from length of child_list\n");
+
+    if (mv.status == MDD_BUNDLED) {
+	(void) fprintf(stderr, 
+	"\nmdd_andsmooth: bundled variable %s used\n",mv.name);
+	fail("");
+    }
+
+    if (mv.values == 1) {
+	tmp = array_fetch(mdd_t *, child_list, 0);
+	mnode = mdd_dup(tmp);
+    }
+    else {
+        mnode = mdd_encode(mgr, child_list, &mv, mv.encode_length-1);
+    }
+    return mnode;
+}
+
+
+mdd_t *
+mdd_encode(
+  mdd_manager *mgr,
+  array_t *child_list,
+  mvar_type *mv_ptr,
+  int index)
+{
+    array_t *new_child_list;
+    int i;
+    int child_count = 0;
+    int q = array_n(child_list);
+    bvar_type bv;
+    mdd_t *f, *g, *h, *t;
+    mdd_t *one, *zero;
+    array_t *bvar_list;
+
+    if (q == 1) {
+        f =  array_fetch(mdd_t *, child_list, 0);
+	h = mdd_dup(f);
+	if (!mdd_is_tautology(f,1) && !mdd_is_tautology(f,0)) mdd_free(f);
+        return h;
+    }
+    one = mdd_one(mgr);
+    zero = mdd_zero(mgr);
+    bvar_list = mdd_ret_bvar_list(mgr);
+
+    new_child_list = array_alloc(mdd_t *, 0);
+
+    bv = mdd_ret_bvar(mv_ptr, index, bvar_list);
+
+    for (i=0; i<(q/2); i++) {
+
+	f = mdd_dup(bv.node);
+        h = array_fetch(mdd_t *, child_list, child_count++);
+        g = array_fetch(mdd_t *, child_list, child_count++);
+#if USE_ITE
+#if BYPASS
+	/* bypasses cases 	*/
+	/* 1  = ite(F,1,1)	*/
+	/* 0  = ite(F,0,0)	*/
+	/* F  = ite(F,1,0)	*/
+	/* !F = ite(F,0,1)	*/
+	/* G  = ite(F,G,G)	*/
+    	if (mdd_is_tautology(g,0) && mdd_is_tautology(h,0)) {
+	    array_insert_last(mdd_t *, new_child_list, zero);
+	}
+    	else if (mdd_is_tautology(g,0) && mdd_is_tautology(h,1)) {
+	    t = mdd_not(f);
+	    array_insert_last(mdd_t *, new_child_list, t);
+	}
+	else if (mdd_is_tautology(g,1) && mdd_is_tautology(h,1)) {
+	    array_insert_last(mdd_t *, new_child_list, one);
+	}
+	else if (mdd_is_tautology(g,1) && mdd_is_tautology(h,0)) {
+	    t = mdd_dup(f);
+	    array_insert_last(mdd_t *, new_child_list, t);
+	}
+	else if (mdd_equal(f,g)) {
+	    t = mdd_dup(f);
+	    array_insert_last(mdd_t *, new_child_list, t);
+	}
+	else {
+    	    t = mdd_ite(f, g, h, 1, 1, 1);
+	    array_insert_last(mdd_t *, new_child_list, t);
+	}
+	if (!mdd_is_tautology(g,1) && !mdd_is_tautology(g,0)) mdd_free(g);
+	if (!mdd_is_tautology(h,1) && !mdd_is_tautology(h,0)) mdd_free(h);
+#else
+	t = mdd_ite(f, g, h, 1, 1, 1);
+	if (!mdd_is_tautology(g,1) && !mdd_is_tautology(g,0)) mdd_free(g);
+	if (!mdd_is_tautology(h,1) && !mdd_is_tautology(h,0)) mdd_free(h);
+	array_insert_last(mdd_t *, new_child_list, t);
+#endif
+#else
+	a1 = mdd_and(f,g,1,1);
+	if (!mdd_is_tautology(g,1) && !mdd_is_tautology(g,0)) mdd_free(g);
+	a2 = mdd_and(f,h,0,1);
+	if (!mdd_is_tautology(h,1) && !mdd_is_tautology(h,0)) mdd_free(h);
+	t = mdd_or(a1,a2,1,1);
+	/* t = mdd_or(mdd_and(f,g,1,1), mdd_and(f,h,0,1), 1, 1); */
+	if (!mdd_is_tautology(a1,1) && !mdd_is_tautology(a1,0)) mdd_free(a1);
+	if (!mdd_is_tautology(a2,1) && !mdd_is_tautology(a2,0)) mdd_free(a2);
+	array_insert_last(mdd_t *, new_child_list, t);
+#endif
+
+	mdd_free(f);
+    }
+
+    if (q & 1) { /* if q is odd */
+	t = array_fetch(mdd_t *, child_list, child_count);
+        array_insert_last(mdd_t *, new_child_list, t);
+    }
+    f =  mdd_encode(mgr, new_child_list, mv_ptr, index - 1);
+    array_free(new_child_list);
+    mdd_free(one);
+    mdd_free(zero);
+    return f;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_cofactor.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_cofactor.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_cofactor.c	(revision 8)
@@ -0,0 +1,115 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_cofactor.c,v 1.9 2002/08/27 16:30:26 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+static void
+mdd_traverse(
+  mdd_manager *mgr,
+  bdd_t *top,
+  boolean *mvar_present)
+{
+    bvar_type bv;
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+    int is_complemented;
+    bdd_t *uncomp_top, *child, *temp_child;
+
+    if (bdd_is_tautology(top,1)) {
+        return;
+    }
+    if (bdd_is_tautology(top,0)) {
+        return;
+    }
+
+    (void)bdd_get_node(top,&is_complemented);
+
+    bv = array_fetch(bvar_type, bvar_list, bdd_top_var_id(top));
+    mvar_present[bv.mvar_id] = 1;
+
+    if (is_complemented) uncomp_top = bdd_not(top);
+    else uncomp_top = mdd_dup(top);
+
+    child = bdd_then(uncomp_top);
+    (void) bdd_get_node(child,&is_complemented);
+    if (is_complemented) {
+        temp_child = child;
+        child = bdd_not(temp_child);
+        mdd_free(temp_child);
+    }
+    
+    mdd_traverse(mgr, child , mvar_present);
+    mdd_free(child);
+
+    child = bdd_else(uncomp_top);
+    (void) bdd_get_node(child,&is_complemented);
+    if (is_complemented) {
+        temp_child = child;
+        child = bdd_not(temp_child);
+        mdd_free(temp_child);
+    }
+
+    mdd_traverse(mgr, child, mvar_present);
+    
+ 
+    mdd_free(child);
+    mdd_free(uncomp_top);
+    return;    
+}
+
+
+static array_t *
+mvars_extract(
+  mdd_manager *mgr,
+  mdd_t *fn)
+{
+    int i, no_mvar;
+    boolean *mvar_present;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *mvars;
+                                                                          
+
+    mvars = array_alloc(int, 0);
+    no_mvar = array_n(mvar_list);
+    mvar_present = ALLOC(boolean, no_mvar);
+    for (i=0; i<no_mvar; i++) mvar_present[i] = 0;
+    mdd_traverse(mgr, fn, mvar_present);
+    for (i=0; i<no_mvar; i++) 
+	if (mvar_present[i] == 1) array_insert_last(int, mvars, i);
+    FREE(mvar_present);
+    return mvars;
+}
+
+mdd_t *
+mdd_cofactor(
+  mdd_manager *mgr,
+  mdd_t *fn,
+  mdd_t *cube)
+{
+    array_t *mvars;
+    mdd_t *top;
+
+    mvars = mvars_extract(mgr, cube);
+    top = mdd_and_smooth(mgr, fn, cube, mvars);
+    array_free(mvars);
+    return top;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_consensus.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_consensus.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_consensus.c	(revision 8)
@@ -0,0 +1,75 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_consensus.c,v 1.9 2002/08/24 20:44:27 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_consensus(
+  mdd_manager *mgr,
+  mdd_t *fn,
+  array_t *mvars)
+{
+    array_t *bdd_vars;
+    int i, j, mv_no, num;
+    mvar_type mv;
+    mdd_t *top;
+	bdd_t *tmp;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+    bdd_vars = array_alloc(bdd_t *, 0);
+
+
+    if ( mvars == NIL( array_t ) ) {
+        printf("\nWARNING: Empty Array of Consensus Variables\n");
+        array_free(bdd_vars);
+        return ( mdd_dup(fn) ) ;
+    }
+
+    else if ( array_n(mvars) == 0)  {
+        printf("\nWARNING: Empty Array of Consensus Variables\n");
+        array_free(bdd_vars);
+        return ( mdd_dup(fn) ) ;
+    }
+
+
+    for (i=0; i<array_n(mvars); i++) {
+        mv_no = array_fetch(int, mvars, i);
+	mv = array_fetch(mvar_type, mvar_list, mv_no);
+	if (mv.status == MDD_BUNDLED) {
+		(void) fprintf(stderr, 
+		"\nmdd_consensus: bundled variable %s used\n",mv.name);
+		fail("");
+	}
+
+        for (j = 0; j < mv.encode_length; j ++) {
+	    tmp = bdd_get_variable(mgr, (unsigned int) mdd_ret_bvar_id(&mv, j) );
+	    array_insert_last(bdd_t *, bdd_vars, tmp);
+	}
+    }
+    top = bdd_consensus(fn, bdd_vars);
+	num = array_n(bdd_vars);
+	for(i=0; i<num; i++){
+		bdd_free(array_fetch(bdd_t *, bdd_vars, i));
+	}
+    array_free(bdd_vars);
+    return top;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_func1c.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_func1c.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_func1c.c	(revision 8)
@@ -0,0 +1,59 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_func1c.c,v 1.11 2002/08/25 05:30:12 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_func1c(
+  mdd_manager *mgr,
+  int mvar1,
+  int constant,
+  boolean (*func2)(int, int))
+{
+    mvar_type x;
+    array_t *child_list_x;
+    int i;
+    mdd_t *tx;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    mdd_t *zero, *one;
+
+    zero = mdd_zero(mgr);
+    one = mdd_one(mgr);
+    x = array_fetch(mvar_type, mvar_list, mvar1);
+    if (x.status == MDD_BUNDLED) 
+	printf("\nWarning: mdd_func1c, bundled variable %s is used\n", x.name);
+
+    child_list_x = array_alloc(mdd_t *, x.values);
+    for (i=0; i<x.values; i++) {
+	if (func2(i,constant))
+	    array_insert_last(mdd_t *, child_list_x, one);
+        else
+            array_insert_last(mdd_t *, child_list_x, zero);
+    }
+    tx = mdd_case(mgr, mvar1, child_list_x);
+    array_free(child_list_x);
+
+    mdd_free(one);
+    mdd_free(zero);
+
+    return tx;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_func2.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_func2.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_func2.c	(revision 8)
@@ -0,0 +1,119 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_func2.c,v 1.11 2002/08/25 05:30:12 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_func2(
+  mdd_manager *mgr,
+  int mvar1,
+  int mvar2,
+  boolean (*func2)(int, int))
+{
+    mvar_type x, y;
+    array_t *child_list_x, *child_list_y;
+    int i, j;
+    mdd_t *tx, *ty;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    mdd_t *one, *zero;
+
+    one = mdd_one(mgr);
+    zero = mdd_zero(mgr);
+
+    x = array_fetch(mvar_type, mvar_list, mvar1);
+    y = array_fetch(mvar_type, mvar_list, mvar2);
+
+    if (x.status == MDD_BUNDLED) {
+	(void) fprintf(stderr, 
+		"\nWarning: mdd_func2, bundled variable %s is used\n", x.name);
+	fail("");
+    }
+
+    if (y.status == MDD_BUNDLED) {
+	(void) fprintf(stderr,
+		"\nWarning: mdd_func2 bundled variable %s is used\n", y.name);
+	fail("");
+    }
+
+    child_list_x = array_alloc(mdd_t *, 0);
+    for (i=0; i<x.values; i++) {
+	child_list_y = array_alloc(mdd_t *, 0);
+	for (j=0; j<y.values; j++) {
+	    if (func2(i,j))
+		array_insert_last(mdd_t *, child_list_y, one);
+            else
+                array_insert_last(mdd_t *, child_list_y, zero);
+	}
+	ty = mdd_case(mgr, mvar2, child_list_y);
+	array_insert_last(mdd_t *, child_list_x, ty);
+	array_free(child_list_y);
+    }
+    tx = mdd_case(mgr, mvar1, child_list_x);
+    array_free(child_list_x);
+    mdd_free(one);
+    mdd_free(zero);
+    return tx;
+}
+
+
+/***** internal functions *****/
+
+boolean
+eq2(int x, int y)
+{
+    return (x == y);
+}
+
+boolean
+geq2(int x, int y)
+{
+    return (x >= y);
+}
+
+boolean
+gt2(int x, int y)
+{
+    return (x > y);
+}
+
+boolean
+leq2(int x, int y)
+{
+    return (x <= y);
+}
+
+boolean
+lt2(int x, int y)
+{
+    return (x < y);
+}
+
+boolean
+neq2(int x, int y)
+{
+    return (x != y);
+}
+
+boolean
+unary_minus2(int x, int y)
+{
+    return (x+y == 0);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_func2c.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_func2c.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_func2c.c	(revision 8)
@@ -0,0 +1,78 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_func2c.c,v 1.10 2002/08/25 05:30:12 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_func2c(
+  mdd_manager *mgr,
+  int mvar1,
+  int mvar2,
+  int constant,
+  boolean (*func3)(int, int, int))
+{
+    mvar_type x, y;
+    array_t *child_list_x, *child_list_y;
+    int i, j;
+    mdd_t *tx, *ty;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    mdd_t *one, *zero;
+
+    x = array_fetch(mvar_type, mvar_list, mvar1);
+    y = array_fetch(mvar_type, mvar_list, mvar2);
+
+    if (x.status == MDD_BUNDLED) {
+	(void) fprintf(stderr, 
+		"\nWarning: mdd_func2c, bundled variable %s is used\n", x.name);
+	fail("");
+    }
+
+    if (y.status == MDD_BUNDLED) {
+	(void) fprintf(stderr,
+		"\nWarning: mdd_func2c, bundled variable %s is used\n", y.name);
+	fail("");
+    }
+
+
+    one = mdd_one(mgr);
+    zero = mdd_zero(mgr);
+
+    child_list_x = array_alloc(mdd_t *, 0);
+    for (i=0; i<x.values; i++) {
+	child_list_y = array_alloc(mdd_t *, 0);
+	for (j=0; j<y.values; j++) {
+	    if (func3(i,j,constant))
+		array_insert_last(mdd_t *, child_list_y, one);
+            else
+                array_insert_last(mdd_t *, child_list_y, zero);
+	}
+	ty = mdd_case(mgr, mvar2, child_list_y);
+	array_insert_last(mdd_t *, child_list_x, ty);
+	array_free(child_list_y);
+    }
+    tx = mdd_case(mgr, mvar1, child_list_x);
+    array_free(child_list_x);
+
+    mdd_free(zero);
+    mdd_free(one);
+
+    return tx;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_func2cmod.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_func2cmod.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_func2cmod.c	(revision 8)
@@ -0,0 +1,159 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_func2cmod.c,v 1.4 2002/08/25 05:30:12 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_func2c_mod(
+  mdd_manager *mgr, 
+  int mvar1,
+  int mvar2,
+  int constant,
+  boolean (*func4)(int, int, int, int))
+{
+    mvar_type x, y;
+    array_t *child_list_x, *child_list_y;
+    int i, j;
+    mdd_t *tx, *ty;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    mdd_t *one, *zero;
+
+    x = array_fetch(mvar_type, mvar_list, mvar1);
+    y = array_fetch(mvar_type, mvar_list, mvar2);
+
+    if (x.status == MDD_BUNDLED) {
+	(void) fprintf(stderr, 
+		"\nWarning: mdd_func2c, bundled variable %s is used\n", x.name);
+	fail("");
+    }
+
+    if (y.status == MDD_BUNDLED) {
+	(void) fprintf(stderr,
+		"\nWarning: mdd_func2c, bundled variable %s is used\n", y.name);
+	fail("");
+    }
+
+    if((x.values   != y.values)  || ( constant < 0) || ( constant >= x.values) ) {
+      (void) fprintf(stderr, "\n mdd_func2c_mod: Cannot operate with two different ranges\n");
+      exit(1);
+    }
+    
+
+    one = mdd_one(mgr);
+    zero = mdd_zero(mgr);
+
+    child_list_x = array_alloc(mdd_t *, 0);
+    for (i=0; i<x.values; i++) {
+	child_list_y = array_alloc(mdd_t *, 0);
+	for (j=0; j<y.values; j++) {
+	    if (func4(i,j,constant,x.values))
+		array_insert_last(mdd_t *, child_list_y, one);
+            else
+                array_insert_last(mdd_t *, child_list_y, zero);
+	}
+	ty = mdd_case(mgr, mvar2, child_list_y);
+	array_insert_last(mdd_t *, child_list_x, ty);
+	array_free(child_list_y);
+    }
+    tx = mdd_case(mgr, mvar1, child_list_x);
+    array_free(child_list_x);
+
+    mdd_free(zero);
+    mdd_free(one);
+
+    return tx;
+}
+
+
+
+/***** internal functions *****/       
+
+boolean 
+eq_plus3mod(int x, int y, int z, int range)
+{
+    return (x == (y + z) % range);
+}
+
+boolean 
+geq_plus3mod(int x, int y, int z, int range)
+{
+    return (x >= (y + z) % range);
+}
+
+boolean 
+gt_plus3mod(int x, int y, int z, int range)
+{
+    return (x > (y + z) % range);
+}
+
+boolean 
+leq_plus3mod(int x, int y, int z, int range)
+{
+    return (x <= (y + z) % range);
+}
+
+boolean 
+lt_plus3mod(int x, int y, int z, int range)
+{
+    return (x < (y + z) % range);
+}
+
+boolean 
+neq_plus3mod(int x, int y, int z, int range)
+{
+    return (x != (y + z) % range);
+}
+
+boolean 
+eq_minus3mod(int x, int y, int z, int range)
+{
+    return (x == (y - z) % range);
+}
+
+boolean 
+geq_minus3mod(int x, int y, int z, int range)
+{
+    return (x >= (y - z) % range);
+}
+
+boolean 
+gt_minus3mod(int x, int y, int z, int range)
+{
+    return (x > (y - z) % range);
+}
+
+boolean 
+leq_minus3mod(int x, int y, int z, int range)
+{
+    return (x <= (y - z) % range);
+}
+
+boolean 
+lt_minus3mod(int x, int y, int z, int range)
+{
+    return (x < (y - z) % range);
+}
+
+boolean 
+neq_minus3mod(int x, int y, int z, int range)
+{
+    return (x != (y - z) % range);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_func3.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_func3.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_func3.c	(revision 8)
@@ -0,0 +1,166 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_func3.c,v 1.10 2002/08/25 05:30:12 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_func3(
+  mdd_manager *mgr,
+  int mvar1,
+  int mvar2,
+  int mvar3,
+  boolean (*func3)(int, int, int))
+{
+    mvar_type x, y, z;
+    array_t *child_list_x, *child_list_y, *child_list_z;
+    int i, j, k;
+    mdd_t *tx, *ty, *tz;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    mdd_t *one, *zero;
+
+    one = mdd_one(mgr);
+    zero = mdd_zero(mgr);
+
+    x = array_fetch(mvar_type, mvar_list, mvar1);
+    y = array_fetch(mvar_type, mvar_list, mvar2);
+    z = array_fetch(mvar_type, mvar_list, mvar3);
+
+    if (x.status == MDD_BUNDLED) {
+	(void) fprintf(stderr, 
+		"\nWarning: mdd_func3, bundled variable %s is used\n", x.name);
+	fail("");
+    }
+
+    if (y.status == MDD_BUNDLED) {
+	(void) fprintf(stderr,
+		"\nWarning: mdd_func3, bundled variable %s is used\n", y.name);
+	fail("");
+    }
+
+    if (z.status == MDD_BUNDLED) {
+	(void) fprintf(stderr, 
+		"\nWarning: mdd_func3, bundled variable %s is used\n", z.name);
+	fail("");
+    }
+
+
+    child_list_x = array_alloc(mdd_t *, 0);
+    for (i=0; i<x.values; i++) {
+	child_list_y = array_alloc(mdd_t *, 0);
+	for (j=0; j<y.values; j++) {
+	    child_list_z = array_alloc(mdd_t *, 0);
+	    for (k=0; k<z.values; k++) {
+	        if (func3(i,j,k))
+		    array_insert_last(mdd_t *, child_list_z, one);
+                else
+                    array_insert_last(mdd_t *, child_list_z, zero);
+	    }
+	    tz = mdd_case(mgr, mvar3, child_list_z);
+	    array_insert_last(mdd_t *, child_list_y, tz);
+	    array_free(child_list_z);
+	}
+	ty = mdd_case(mgr, mvar2, child_list_y);
+	array_insert_last(mdd_t *, child_list_x, ty);
+	array_free(child_list_y);
+    }
+    tx = mdd_case(mgr, mvar1, child_list_x);
+    array_free(child_list_x);
+
+    mdd_free(one);
+    mdd_free(zero);
+
+    return tx;
+}
+
+/***** internal functions *****/       
+
+boolean 
+eq_plus3(int x, int y, int z)
+{
+    return (x == y + z);
+}
+
+boolean 
+geq_plus3(int x, int y, int z)
+{
+    return (x >= y + z);
+}
+
+boolean 
+gt_plus3(int x, int y, int z)
+{
+    return (x > y + z);
+}
+
+boolean 
+leq_plus3(int x, int y, int z)
+{
+    return (x <= y + z);
+}
+
+boolean 
+lt_plus3(int x, int y, int z)
+{
+    return (x < y + z);
+}
+
+boolean 
+neq_plus3(int x, int y, int z)
+{
+    return (x != y + z);
+}
+
+boolean 
+eq_minus3(int x, int y, int z)
+{
+    return (x == y - z);
+}
+
+boolean 
+geq_minus3(int x, int y, int z)
+{
+    return (x >= y - z);
+}
+
+boolean 
+gt_minus3(int x, int y, int z)
+{
+    return (x > y - z);
+}
+
+boolean 
+leq_minus3(int x, int y, int z)
+{
+    return (x <= y - z);
+}
+
+boolean 
+lt_minus3(int x, int y, int z)
+{
+    return (x < y - z);
+}
+
+boolean 
+neq_minus3(int x, int y, int z)
+{
+    return (x != y - z);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_ineq_s.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_ineq_s.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_ineq_s.c	(revision 8)
@@ -0,0 +1,130 @@
+/*
+ * $Id: mdd_ineq_s.c,v 1.4 2002/08/27 16:30:26 fabio Exp $
+ *
+ */
+
+#include "mdd.h"
+
+static int
+mdd_is_care_bit(
+  mvar_type mvar,
+  int index)
+{
+    return ( getbit( ( (int) pow(2.0, (double)mvar.encode_length) ) - mvar.values, mvar.encode_length-index-1));
+}
+
+
+mdd_t *
+mdd_ineq_template_s(
+  mdd_manager *mgr,
+  int mvar1,
+  int mvar2,
+  int zero_then_val /* J in Tim's thesis */,
+  int one_else_val  /* K */,
+  int bottom_val    /* A and B */)
+{
+    mvar_type x, y;
+    bvar_type bx, by;
+    mdd_t *one_top, *zero_top, *zero_then, *one_else,
+          *one_top_else = mdd_one(mgr);
+    mdd_t *one_top_then = mdd_one(mgr);
+    mdd_t *zero_top_else = mdd_one(mgr);
+    mdd_t *zero_top_then = mdd_one(mgr);
+    mdd_t *compare;
+    int i;
+
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+
+    if (zero_then_val == 0) 
+	zero_then = mdd_zero(mgr);
+    else 
+	zero_then = mdd_one(mgr);
+
+
+     if (one_else_val == 0) 
+	 one_else = mdd_zero(mgr);
+     else 
+	 one_else = mdd_one(mgr);
+
+    if (bottom_val == 0) {
+	one_top = mdd_zero(mgr);
+	zero_top = mdd_zero(mgr);
+    }
+    else {
+	one_top = mdd_one(mgr);
+	zero_top = mdd_one(mgr);
+    }
+
+
+    x = array_fetch(mvar_type, mvar_list, mvar1);
+    y = array_fetch(mvar_type, mvar_list, mvar2);
+
+    if (x.values != y.values) 
+	fail("mdd_ineq: 2 mvars have incompatible value ranges\n");
+
+    if (x.status == MDD_BUNDLED) {
+	(void) fprintf(stderr, 
+		"\nWarning: mdd_ineq, bundled variable %s is used\n", x.name);
+	fail("");
+    }
+
+    if (y.status == MDD_BUNDLED) {
+	(void) fprintf(stderr,
+		"\nWarning: mdd_ineq, bundled variable %s is used\n", y.name);
+	fail("");
+    }
+
+
+    for (i=(x.encode_length-1); i>=0; i--) {
+
+	bx = mdd_ret_bvar(&x, i, bvar_list);
+	by = mdd_ret_bvar(&y, i, bvar_list);
+
+	mdd_free(zero_top_else);
+	zero_top_else = mdd_ite(by.node, zero_then, zero_top, 1, 1, 1);
+	mdd_free(zero_top_then);
+	zero_top_then = mdd_ite(by.node, zero_top,  one_else, 1, 1, 1);
+
+	if (mdd_is_care_bit(x,i) == 0) {
+
+		mdd_free(one_top_else);
+		one_top_else = mdd_ite(by.node, zero_then, zero_top, 1, 1, 1);
+		mdd_free(one_top_then);
+		one_top_then = mdd_ite(by.node, one_top, one_else, 1, 1, 1);
+
+		mdd_free(one_top);
+
+		one_top = mdd_ite(bx.node, one_top_then, one_top_else, 1, 1, 1);
+	}
+
+	mdd_free(zero_top);
+	zero_top = mdd_ite(bx.node, zero_top_then, zero_top_else, 1, 1, 1);
+
+    }
+
+    mdd_free(zero_then);
+    mdd_free(one_else);
+
+    mdd_free(zero_top_else);
+    mdd_free(zero_top_then);
+    mdd_free(one_top_else);
+    mdd_free(one_top_then);
+
+    mdd_free(zero_top);
+
+    compare = mdd_eq(mgr, mvar1, mvar2);
+
+    if  ( ( bdd_equal(compare, one_top) == 0) && (zero_then_val == 0) && (one_else_val == 0) && (bottom_val == 1) )
+      printf("Error \n"); 
+
+    mdd_free(compare);
+    
+    return one_top;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_init.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_init.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_init.c	(revision 8)
@@ -0,0 +1,551 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_init.c,v 1.18 2005/05/14 17:30:52 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+int
+integer_get_num_of_digits(int value)
+{
+    double x;
+    int num_of_digits;
+
+    if (value > 0) 	 x = log10((double) value); 
+    else if (value == 0) x = 0;
+    else 		 fail("mdd_init: internal error, value less than 0\n");
+      
+/*
+ * Notice that floor(x) return a double, 
+ * so it needs to be cast into an integer using
+ * this following expression.
+ */
+    num_of_digits = (int) floor(x) + 1;
+
+    return num_of_digits;
+}
+
+static void
+mdd_name_variables(
+  array_t *mvar_list,
+  int no_mvars,
+  array_t **mvar_names_ptr)
+{
+
+    char *istr;
+    int i;
+
+    if (*mvar_names_ptr == NIL(array_t)) {
+	/* if no variable names are given, use generic naming */
+	/* mv_0, mv_1, ... for variable 0, 1, ... */
+	*mvar_names_ptr = array_alloc(char *, 0);
+	for (i=0; i<no_mvars; i++) {
+            /* compose a name for the mvar */
+            istr = ALLOC(char, integer_get_num_of_digits(i + array_n(mvar_list)) + 4);
+            sprintf(istr, "mv_%d", (i + array_n(mvar_list)));
+            array_insert_last(char *, *mvar_names_ptr, istr);
+
+	}
+    }
+    else {
+        if (no_mvars != array_n(*mvar_names_ptr)) 
+	    fail("mdd_init: inconsistent size of mvar_names\n");
+    }
+}
+
+
+static void
+mdd_record_variables(
+  mdd_manager *mgr,
+  int current_vertex_before,
+  int start_mvar,
+  int no_mvars,
+  array_t *mvar_names,
+  array_t *mvar_values,
+  array_t *mvar_strides)
+{
+
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+    int stride_count = 1;
+    int prev_stride = -1;
+	int current_vertex = current_vertex_before;
+    int stride, i, j, 
+        bits, n_bytes;
+    mvar_type mv;
+    bvar_type bv;
+    char *name_str, *mv_name; 
+
+#if MDD_VERBOSE
+        printf("bdd variable insertion ordering: "); 
+#endif
+
+    /* mvar_values -> mvar_list */
+    for (i=0; i<no_mvars; i++) {
+	mv.mvar_id = start_mvar + i;
+
+	/* compose a name for the mvar */
+	name_str = array_fetch(char *, mvar_names, i);
+	n_bytes = strlen (name_str) + 1;
+        mv_name = ALLOC(char, n_bytes);
+	strcpy(mv_name, name_str);
+	mv.name = mv_name;
+
+	/* register no. of values for the mvar */
+	mv.values = array_fetch(int, mvar_values, i);
+
+	/* length of ecoding bits for mvar */
+        bits = no_bit_encode(mv.values);
+	mv.encode_length = bits;
+
+	/* register the starting bdd vertex no. for the mvar */
+	mv.bvars = array_alloc(int, 0);
+
+	if (bits > 0)
+	    stride = array_fetch(int, mvar_strides, i);
+	else
+	    stride = 1;
+	for(j=0; j<bits; j++) array_insert_last(int, mv.bvars, current_vertex + (j * stride) );
+
+
+	/* create place-holder for bit-encoding of the mvar */
+        mv.encoding = ALLOC(int, bits);
+
+	/* create bdd variables and put them in bvar_list */
+	for (j=0; j<bits; j++) {
+	    bv.node = bdd_get_variable(mgr, current_vertex + stride*j);
+	    bv.mvar_id = mv.mvar_id;
+
+#if MDD_VERBOSE 
+		printf("%d ", current_vertex + stride*j);
+#endif
+
+	    array_insert(bvar_type, bvar_list, current_vertex + stride*j, bv);
+	}
+	
+	/* insert the completed mvar_type element to mvar_list */
+	mv.status = MDD_ACTIVE;
+        array_insert_last(mvar_type, mvar_list, mv);
+
+	if ((prev_stride != -1 ) && (stride != prev_stride)) {
+	    printf("mdd_record_variables: processing %s\n", mv.name);
+	    fail("mdd_record_variables: inconsistency found in mvar_stride\n");
+	}
+
+        /* register the stride for mvar interleaving */
+        /* and update current bdd vertex count */
+        if (stride_count == stride) {
+            stride_count = 1;
+	    current_vertex = current_vertex + stride*(bits-1) + 1;
+	    prev_stride = -1;
+	}
+	else {
+	    stride_count++;
+	    current_vertex++;
+	    prev_stride = stride;
+	}
+    }
+
+#if MDD_VERBOSE
+	printf("\n");
+#endif
+
+    /* init all encodings to 2's */
+    clear_all_marks(mgr);
+
+#if MONITOR
+    print_mvar_list(mgr);
+    (void) printf("%d bdd variables created\n", array_n(bvar_list));
+    print_bvar_list_id(mgr); 
+#endif
+
+}
+
+
+mdd_manager *
+mdd_init(
+  array_t *mvar_values,
+  array_t *mvar_names,
+  array_t *mvar_strides)
+{
+    array_t *mvar_list;
+    array_t *bvar_list;
+    int i, no_mvars, current_vertex;
+    int vertex_sum;
+    mdd_manager *mgr;
+    mdd_hook_type *mdd_hook;
+    bdd_external_hooks *hook;
+    boolean free_mvar_strides_flag;
+    boolean free_mvar_names_flag;
+    
+    mdd_hook = ALLOC(mdd_hook_type, 1);
+
+    /* global information about all mvar for mdd_manager */
+    mvar_list = array_alloc(mvar_type, 0);
+
+    /* global information about all bvar for mdd_manager */
+    bvar_list = array_alloc(bvar_type, 0); 
+
+    /* create the hook to the bdd_manager */
+    mdd_hook->mvar_list = mvar_list;
+    mdd_hook->bvar_list = bvar_list;
+
+    /* if some array arguments are NIL */
+    no_mvars = array_n(mvar_values);
+
+    free_mvar_names_flag = (mvar_names == NIL(array_t));
+    mdd_name_variables(mvar_list, no_mvars, &mvar_names);
+
+    /* create mdd manager */      
+    vertex_sum = 0;
+    for (i=0; i<no_mvars; i++) {
+        vertex_sum = vertex_sum + no_bit_encode(array_fetch(int,mvar_values,i));
+    }
+    mgr = bdd_start(vertex_sum);
+
+    hook =  bdd_get_external_hooks(mgr);
+
+    hook->mdd = (char *) mdd_hook;
+
+    current_vertex = 0;
+
+    if (mvar_strides == NIL(array_t)) {
+	/* if no strides are specified, the variables are not interleaved */
+	/* i.e. mvar_strides = 1 */
+        /* must set a flag to know that this array needs to be freed */
+        free_mvar_strides_flag = TRUE;
+	mvar_strides = array_alloc(int, 0);
+	for (i=0; i<no_mvars; i++) {
+	    array_insert_last(int, mvar_strides, 1);
+        }
+    }
+    else {
+        free_mvar_strides_flag = FALSE;
+	if (no_mvars != array_n(mvar_strides))
+	    fail("mdd_init: inconsistent size of mvar_strides\n");
+    }
+
+
+    mdd_record_variables(mgr, current_vertex, 0, no_mvars, mvar_names, mvar_values, mvar_strides);
+
+    if (free_mvar_strides_flag) {
+      array_free(mvar_strides);
+    }
+
+    if (free_mvar_names_flag) {
+      for (i = 0; i < array_n(mvar_names); i++) {
+        char *name = array_fetch(char *, mvar_names, i);
+        FREE(name);
+      }
+      array_free(mvar_names);
+    }
+
+    return mgr;
+}
+
+
+unsigned int
+mdd_create_variables(
+  mdd_manager *mgr,
+  array_t *mvar_values,
+  array_t *mvar_names,
+  array_t *mvar_strides)
+{
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+    int i, no_mvars, current_vertex, start_mvar;
+    int vertex_sum;
+    bdd_t *temp;
+    boolean free_mvar_strides_flag;
+    boolean free_mvar_names_flag;
+
+ 
+    /* if some array arguments are NIL */
+    no_mvars = array_n(mvar_values);
+
+    free_mvar_names_flag = (mvar_names == NIL(array_t));
+    mdd_name_variables(mvar_list, no_mvars, &mvar_names);
+
+    if (mvar_strides == NIL(array_t)) {
+	/* if no strides are specified, the variables are not interleaved */
+	/* i.e. mvar_strides = 1 */
+        /* must set a flag to know that this array needs to be freed */
+        free_mvar_strides_flag = TRUE;
+	mvar_strides = array_alloc(int, 0);
+	for (i=0; i<no_mvars; i++) {
+	    array_insert_last(int, mvar_strides, 1);
+        }
+    }
+    else {
+        free_mvar_strides_flag = FALSE;
+	if (no_mvars != array_n(mvar_strides))
+	    fail("mdd_init: inconsistent size of mvar_strides\n");
+    }
+
+    vertex_sum = 0;
+    for (i=0; i<no_mvars; i++) {
+        vertex_sum = vertex_sum + no_bit_encode(array_fetch(int,mvar_values,i));
+    }
+    for (i=0; i<vertex_sum; i++) {
+	temp =  bdd_create_variable(mgr);
+	bdd_free(temp);
+    }
+
+    current_vertex = array_n(bvar_list);
+    start_mvar = array_n(mvar_list);
+
+    mdd_record_variables(mgr, current_vertex, start_mvar, no_mvars, mvar_names, mvar_values, mvar_strides);
+
+    if (free_mvar_strides_flag) {
+      array_free(mvar_strides);
+    }
+    
+    if (free_mvar_names_flag) {
+      for (i = 0; i < array_n(mvar_names); i++) {
+        char *name = array_fetch(char *, mvar_names, i);
+        FREE(name);
+      }
+      array_free(mvar_names);
+    }
+
+    return start_mvar;
+}
+
+
+unsigned int
+mdd_create_variables_after(
+  mdd_manager *mgr,
+  int	after_mvar_id,
+  array_t *mvar_values,
+  array_t *mvar_names,
+  array_t *mvar_strides)
+{
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+    mvar_type after_mv, fol_mv;
+    int i, no_mvars, current_vertex, start_mvar;
+    int vertex_sum;
+    int after_bv_id;
+    bdd_t *temp;
+    bvar_type sec_bit_of_mv;
+    int sec_bit_level, fol_id;
+    boolean free_mvar_strides_flag;
+    boolean free_mvar_names_flag;
+
+    after_mv = array_fetch( mvar_type, mvar_list, after_mvar_id );
+
+    if (after_mv.encode_length > 1) {
+				sec_bit_of_mv = mdd_ret_bvar(&after_mv, 1, bvar_list);
+				sec_bit_level = bdd_top_var_level( mgr, sec_bit_of_mv.node );
+				/* first_bit_of_last_interleaved_mvar */
+				fol_id = bdd_get_id_from_level( mgr, sec_bit_level - 1 );
+	}
+	else
+	fol_id = mdd_ret_bvar_id(&after_mv, 0);
+
+	fol_mv = array_fetch( mvar_type, mvar_list, fol_id );
+
+    after_bv_id = mdd_ret_bvar_id(&fol_mv, fol_mv.encode_length - 1);
+
+    /* if some array arguments are NIL */
+    no_mvars = array_n(mvar_values);
+
+    free_mvar_names_flag = (mvar_names == NIL(array_t));
+    mdd_name_variables(mvar_list, no_mvars, &mvar_names);
+
+    if (mvar_strides == NIL(array_t)) {
+	/* if no strides are specified, the variables are not interleaved */
+	/* i.e. mvar_strides = 1 */
+        /* must set a flag to know that this array needs to be freed */
+        free_mvar_strides_flag = TRUE;
+	mvar_strides = array_alloc(int, 0);
+	for (i=0; i<no_mvars; i++) {
+	    array_insert_last(int, mvar_strides, 1);
+        }
+    }
+    else {
+        free_mvar_strides_flag = FALSE;
+	if (no_mvars != array_n(mvar_strides))
+	    fail("mdd_init: inconsistent size of mvar_strides\n");
+    }
+
+    vertex_sum = 0;
+    for (i=0; i<no_mvars; i++) {
+        vertex_sum = vertex_sum + no_bit_encode(array_fetch(int,mvar_values,i));
+    }
+    for (i=0; i<vertex_sum; i++) {
+	temp =  bdd_create_variable_after(mgr, after_bv_id + i);
+	bdd_free(temp);
+    }
+
+    current_vertex = array_n(bvar_list);
+    start_mvar = array_n(mvar_list);
+
+    mdd_record_variables(mgr, current_vertex, start_mvar, no_mvars, mvar_names, mvar_values, mvar_strides);
+
+    if (free_mvar_strides_flag) {
+      array_free(mvar_strides);
+    }
+    
+    if (free_mvar_names_flag) {
+      for (i = 0; i < array_n(mvar_names); i++) {
+        char *name = array_fetch(char *, mvar_names, i);
+        FREE(name);
+      }
+      array_free(mvar_names);
+    }
+
+    return start_mvar;
+
+}
+
+
+unsigned int
+mdd_create_variables_interleaved(
+  mdd_manager *mgr,
+  int inter_var_id,
+  int no_mvars,
+  array_t *mvar_names)
+{
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+    mvar_type inter_var;
+    int i, j, current_vertex, start_mvar;
+    bdd_t *temp;
+    array_t *mvar_values;
+    array_t *mvar_strides;
+    boolean free_mvar_names_flag;
+
+    inter_var = array_fetch( mvar_type, mvar_list, inter_var_id );
+
+    /* if some array arguments are NIL */
+    free_mvar_names_flag = (mvar_names == NIL(array_t));
+    mdd_name_variables(mvar_list, no_mvars, &mvar_names);
+
+
+    for (j=0; j<inter_var.encode_length; j++) {
+       for (i=0; i<no_mvars; i++) {
+		temp = bdd_create_variable_after( mgr, mdd_ret_bvar_id(&inter_var, j) );
+		bdd_free( temp );
+       }
+    }
+
+    current_vertex = array_n(bvar_list);
+    start_mvar = array_n(mvar_list);
+
+    mvar_values = array_alloc(int, 0);
+    mvar_strides = array_alloc(int, 0);
+    for(i=0; i<no_mvars; i++) {
+	array_insert_last(int, mvar_values, inter_var.values);
+	array_insert_last(int, mvar_strides, no_mvars);
+    }
+
+    mdd_record_variables(mgr, current_vertex, start_mvar, no_mvars, mvar_names, mvar_values, mvar_strides);
+
+    array_free(mvar_values);
+    array_free(mvar_strides);
+    
+    if (free_mvar_names_flag) {
+      for (i = 0; i < array_n(mvar_names); i++) {
+        char *name = array_fetch(char *, mvar_names, i);
+        FREE(name);
+      }
+      array_free(mvar_names);
+    }
+
+    return start_mvar;
+}
+
+
+void
+mdd_array_free(array_t *mddArray)
+{
+  int i;
+
+  if (mddArray != NIL(array_t)) {
+    for (i = 0; i < array_n(mddArray); i++) {
+      mdd_t *tempMdd = array_fetch(mdd_t *, mddArray, i);
+      mdd_free(tempMdd);
+    }
+    array_free(mddArray);
+  }
+}
+
+void
+mdd_array_array_free(array_t *arrayBddArray)
+{
+  int		i;
+  array_t	*bddArray;
+
+  if (arrayBddArray != NIL(array_t)) {
+    for (i = 0; i < array_n(arrayBddArray); i++) {
+      bddArray = array_fetch(array_t *, arrayBddArray, i);
+      mdd_array_free(bddArray);
+    }
+    array_free(arrayBddArray);
+  }
+}
+
+array_t *
+mdd_array_duplicate(array_t *mddArray)
+{
+  int      i;
+  int      length = array_n(mddArray);
+  array_t *result = array_alloc(mdd_t *, length);
+  for (i = 0; i < length; i++) {
+    mdd_t *tempMdd = array_fetch(mdd_t *, mddArray, i);
+    array_insert(mdd_t *, result, i, mdd_dup(tempMdd));
+  }
+
+  return (result);
+}
+
+
+/* Return true iff two arrays of mdds are identical, i.e., they contain
+   identical mdds in the same order */
+boolean
+mdd_array_equal(array_t *array1, array_t *array2)
+{
+  int i;
+  
+  assert(array1 != NIL(array_t) && array2 != NIL(array_t));
+  
+  if(array_n(array1) != array_n(array2))
+    return FALSE;
+
+  for(i = 0; i < array_n(array1); i++) {
+    mdd_t *mdd1 = array_fetch(mdd_t *, array1, i);
+    mdd_t *mdd2 = array_fetch(mdd_t *, array2, i);
+    if(!mdd_equal(mdd1, mdd2)) 
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+/* wrapper for mdd_init, to create a manager with no variables */
+mdd_manager *
+mdd_init_empty(void)
+{
+  array_t     *empty_array = array_alloc(int, 0);
+  mdd_manager *mdd_mgr = mdd_init(empty_array, NIL(array_t), NIL(array_t));
+
+  array_free(empty_array);
+  return mdd_mgr;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_intv.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_intv.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_intv.c	(revision 8)
@@ -0,0 +1,162 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_intv.c,v 1.9 2002/08/24 21:48:15 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+/* var <= c */
+mdd_t *
+build_leq_c(
+  mdd_manager *mgr,
+  int mvar_id,
+  int c)
+{
+	return build_lt_c(mgr, mvar_id, c+1);
+}
+
+mdd_t *
+build_lt_c(
+  mdd_manager *mgr,
+  int mvar_id,
+  int c)
+{
+/*	mdd_t *A, *one, *zero;
+	array_t *mvar_list = mdd_ret_mvar_list(mgr);
+	array_t *bvar_list = mdd_ret_bvar_list(mgr);
+	mvar_type a_mv;
+	int i;
+	bvar_type bit_i;
+        mdd_t *temp_A;
+
+	one = mdd_one(mgr);
+	zero = mdd_zero(mgr);
+
+	a_mv = array_fetch( mvar_type, mvar_list, mvar_id);
+
+
+	if ( a_mv.values <= c ) {
+		mdd_free(zero);
+		return one;
+	}
+
+	A = mdd_zero(mgr);
+
+	for(i=1; i <= a_mv.encode_length; i++){
+		bit_i = mdd_ret_bvar(&a_mv, (a_mv.encode_length - i), bvar_list);
+                temp_A = A;
+		if ( getbit(c,i-1) == 0 ) {
+			A = mdd_ite(bit_i.node, zero, temp_A, 1, 1, 1);
+                }
+		else {
+			A = mdd_ite(bit_i.node, temp_A, one, 1, 1, 1);
+                }
+                bdd_free(temp_A);
+	}
+
+	mdd_free(one);
+	mdd_free(zero);
+		
+	return A;
+    */
+
+/* Temporary fix until the routines are rewritten taking care of don't cares. */    
+
+    return mdd_lt_c(mgr, mvar_id, c);
+} 
+
+
+mdd_t *
+build_geq_c(
+  mdd_manager *mgr,
+  int mvar_id,
+  int c)
+{
+/*
+  mdd_t *A, *one, *zero;
+	array_t *bvar_list = mdd_ret_bvar_list(mgr),
+	        *mvar_list = mdd_ret_mvar_list(mgr);
+	mvar_type a_mv;
+	int i;
+	bvar_type bit_i;
+        mdd_t *temp_A;
+
+	one = mdd_one(mgr);
+	zero = mdd_zero(mgr);
+
+	a_mv = array_fetch( mvar_type, mvar_list, mvar_id);
+
+	if ( a_mv.values <= c ) { 
+		mdd_free( one );
+		return zero;
+	}
+
+
+	A = mdd_one(mgr);
+
+	for(i=1; i <= a_mv.encode_length; i++){
+		bit_i = mdd_ret_bvar(&a_mv, (a_mv.encode_length - i), bvar_list );
+                temp_A = A;
+		if ( getbit(c,i-1) == 0 ) {
+			A = mdd_ite(bit_i.node, one, temp_A, 1, 1, 1);
+                }
+		else {
+			A = mdd_ite(bit_i.node, temp_A, zero, 1, 1, 1);
+                     }
+        	bdd_free(temp_A);	
+	}
+
+	mdd_free(one);
+	mdd_free(zero);
+		
+	return A;
+    */
+    return mdd_geq_c(mgr, mvar_id, c);
+}
+
+
+mdd_t *
+build_gt_c(
+  mdd_manager *mgr,
+  int mvar_id,
+  int c)
+{
+	return build_geq_c(mgr, mvar_id, c+1);
+}
+
+/* low <= var <= high */
+mdd_t *
+mdd_interval(
+  mdd_manager *mgr,
+  int mvar_id,
+  int low,
+  int high)
+{
+	mdd_t *HIGH_MDD, *LOW_MDD, *result;
+
+
+    LOW_MDD = build_geq_c(mgr,mvar_id,low);
+	HIGH_MDD = build_leq_c(mgr,mvar_id,high);
+
+	result = mdd_and(HIGH_MDD, LOW_MDD, 1, 1);
+
+	mdd_free(LOW_MDD);
+	mdd_free(HIGH_MDD);
+
+	return result;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_iter.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_iter.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_iter.c	(revision 8)
@@ -0,0 +1,332 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_iter.c,v 1.8 2002/08/27 16:30:26 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+/* this routine returns the first minterm (2's in cube becomes 0's), */
+/* given an mdd generator, containing a cube and a list of variables */
+/* to be included in the minterm */
+   
+static array_t *
+first_minterm(mdd_gen *mgen)
+{
+    array_t *minterm;
+    bdd_literal literal;
+    int i, j;
+
+    array_t *mvar_list = mdd_ret_mvar_list(mgen->manager);
+    int mv_id;
+    mvar_type mv;
+    boolean out_of_range;  /* a minterm is out of range if one variable is */
+    array_t *solution;
+    int value;
+
+    out_of_range = 0;
+                                                                                
+    minterm = array_alloc(bdd_literal, 0);
+    solution = array_alloc(int, 0);
+    /* loop once for each mvar */
+    for (i=0; i<array_n(mgen->var_list); i++) {
+	mv_id = array_fetch(int, mgen->var_list, i);
+	mv = array_fetch(mvar_type, mvar_list, mv_id);
+	/* loop for each bvar */
+        value = 0;
+        for (j=0; j<mv.encode_length; j++) {
+	    literal = array_fetch(bdd_literal, mgen->cube, mdd_ret_bvar_id(&mv, j) ); 
+            if (literal == 0) {
+		array_insert_last(bdd_literal, minterm, 0);
+		value = value*2 + 0;
+	    }
+	    else if (literal == 1) {
+		array_insert_last(bdd_literal, minterm, 1);
+		value = value*2 + 1;
+	    }
+	    else { /*if (literal == 2) */
+		array_insert_last(bdd_literal, minterm, 0);
+		value = value*2 + 0;
+            }
+	}
+	(void) array_insert_last(int, solution, value);
+	if (value >= mv.values) out_of_range = 1;
+    }
+    mgen->minterm = minterm;
+    mgen->out_of_range = out_of_range;
+
+    return (solution);
+}
+
+
+/* this routine returns the next minterm, given a current minterm, */
+/* a cube and a list of variables to be included in the minterm */
+/* if no more, return NIL(array_t). */
+
+static array_t *
+next_minterm(mdd_gen *mgen)
+{
+    int carry;
+    int i, j, k;
+    array_t *minterm;
+    bdd_literal literal;
+    bdd_literal prev_literal;
+    array_t *mvar_list = mdd_ret_mvar_list(mgen->manager);
+    int mv_id;
+    mvar_type mv;
+    boolean out_of_range;
+    array_t *solution;
+    int value;
+
+    out_of_range = 0;
+
+    carry = 1;
+    k = 0;
+
+    minterm = array_alloc(bdd_literal, array_n(mgen->minterm)); 
+    solution = array_alloc(int, 0);
+    /* loop once for each mvar */
+    for (i=0; i<array_n(mgen->var_list); i++) {
+	mv_id = array_fetch(int, mgen->var_list, i);
+	mv = array_fetch(mvar_type, mvar_list, mv_id);
+	value = 0;
+	/* loop for each bvar */
+        for (j=0; j<mv.encode_length; j++) {
+            literal = array_fetch(bdd_literal, mgen->cube, mdd_ret_bvar_id(&mv, j) );
+
+	    prev_literal = array_fetch(bdd_literal, mgen->minterm, k);
+            if ((literal == 2) && (carry == 1)) {
+		if (prev_literal == 0) {
+		    array_insert(bdd_literal, minterm, k, 1);
+		    carry = 0;
+		    value = value*2 + 1;
+		}
+		else if (prev_literal == 1) {
+		    array_insert(bdd_literal, minterm, k, 0);
+		    carry = 1;
+		    value = value*2 + 0;
+		}
+	    }
+	    else if ((literal == 2) && (carry == 0)) {
+		    array_insert(bdd_literal, minterm, k, prev_literal);
+		    value = value*2 + prev_literal;
+	    }
+	    else { /* if literal == 0 or 1 */
+                    array_insert(bdd_literal, minterm, k, literal);
+		    value = value*2 + literal;
+	    }
+	    k++;
+	}
+	array_insert_last(int, solution, value);
+	if (value >= mv.values) out_of_range = 1;
+    }
+
+    if (carry == 1) {
+	/* no more minterms */
+	array_free(minterm);
+	minterm = NIL(array_t);
+	array_free(solution);
+	solution = NIL(array_t);
+    }
+    array_free(mgen->minterm);
+    mgen->minterm = minterm;
+    mgen->out_of_range = out_of_range;
+
+    return (solution);
+}
+
+
+static array_t *
+next_valid_minterm(mdd_gen *mgen)
+{
+    array_t *solution;
+    array_t *cube;
+
+    solution = next_minterm(mgen);
+
+    /* check if done with current cube */
+    if (mgen->minterm == NIL(array_t)) {
+	(void) bdd_next_cube(mgen->bdd_generator, &cube);
+        mgen->status = bdd_gen_read_status(mgen->bdd_generator);
+	mgen->cube = cube;
+	if (mgen->status != bdd_EMPTY) {
+	    if (solution != NIL(array_t) ) array_free(solution);
+	    solution = first_minterm(mgen);
+	}
+	else {
+	    mgen->minterm = NIL(array_t);
+	    mgen->cube = NIL(array_t);
+	}
+    }
+    return (solution);
+}
+
+
+mdd_gen *
+mdd_first_minterm(
+  mdd_t *f,
+  array_t **solution_p   /* minterm = array of values */,
+  array_t *variable_list)
+{
+    mdd_gen *mgen;	/* mdd generator */
+    bdd_gen *bgen;	/* bdd generator for bdd_first_cube, bdd_next_cube */
+    array_t *cube;	/* array of literals {0,1,2} */
+    array_t *allvar_list; 
+    array_t *mvar_list;
+    array_t *smoothing_list;
+    int i, j, k;
+    array_t *solution = NIL(array_t); /* initialize for lint */
+    array_t *var_list;
+    boolean i_is_present;
+    mdd_t *mdd_tmp, *f_copy;
+    bdd_manager *mgr;
+
+    if ( f != NIL(mdd_t) ) {
+	/* new code added by Timothy */
+	/* f is first smoothed by all variables NOT present in var_list */
+
+	f_copy = mdd_dup(f); 
+
+	smoothing_list = array_alloc(int, 0);
+    
+    
+	mgr = bdd_get_manager(f_copy);
+	mvar_list = mdd_ret_mvar_list(mgr);                                                                           
+
+	for (i = 0; i < array_n(mvar_list); i++) {
+	    i_is_present = FALSE;
+	    for (j = 0; j < array_n(variable_list); j++) {
+		k = array_fetch(int, variable_list, j);
+		if (k == i) i_is_present = TRUE;
+	    }
+	    if (i_is_present == FALSE) array_insert_last(int, smoothing_list, i);
+	}
+	if (array_n(smoothing_list) > 0) {
+	    mdd_tmp = mdd_smooth(mgr, f_copy, smoothing_list);
+	    (void) mdd_free(f_copy);
+	    f_copy = mdd_dup(mdd_tmp);
+	    (void) mdd_free(mdd_tmp);
+    
+	}
+
+	(void) array_free(smoothing_list);
+
+	bgen = bdd_first_cube(f_copy, &cube);
+	(void) mdd_free(f_copy);
+    
+	mgen = ALLOC(mdd_gen, 1);
+	mgen->manager = mgr;
+	mgen->bdd_generator = bgen;
+	mgen->status = bdd_gen_read_status(mgen->bdd_generator);
+	mgen->cube = cube; 		/* store in mdd gen for later use */
+	mgen->out_of_range = 0;
+	if (mgen->status != bdd_EMPTY) {
+	    if (variable_list != NIL(array_t)) {
+		var_list = array_dup(variable_list);
+		mgen->var_list = var_list;
+	    }
+	    else {
+		allvar_list = array_alloc(int, 0);
+		for (i=0; i<array_n(mvar_list); i++) 
+		    array_insert_last(int, allvar_list, i);
+		mgen->var_list = allvar_list;
+	    }
+	    solution = first_minterm(mgen);
+	    while (mgen->out_of_range) {
+		array_free(solution);
+		solution = next_valid_minterm(mgen);
+	    }
+	}
+	else {
+
+	    /* mgen->status == bdd_EMPTY */
+	    if (variable_list != NIL(array_t)) {
+                var_list = array_dup(variable_list);
+                mgen->var_list = var_list;
+            }
+            else {
+                allvar_list = array_alloc(int, 0);
+                for (i=0; i<array_n(mvar_list); i++)
+                    array_insert_last(int, allvar_list, i);
+                mgen->var_list = allvar_list;
+            }
+
+	    mgen->minterm = NIL(array_t);
+	    mgen->cube = NIL(array_t);
+	    /* previous solution will not be freed here */
+	    /* but by the calling procedure */
+	}
+	*solution_p = solution;
+    }
+    else /* f = NIL */{
+      mgen = ALLOC(mdd_gen, 1);
+      mgen->manager = NIL(mdd_manager);
+      mgen->bdd_generator = NIL(bdd_gen);
+      mgen->status = bdd_EMPTY;
+      mgen->cube = NIL(array_t);
+      mgen->minterm = NIL(array_t);
+      mgen->out_of_range = 0;
+      mgen->var_list = NIL(array_t);
+    }
+
+    return (mgen);
+}
+
+
+boolean
+mdd_next_minterm(
+  mdd_gen *mgen,
+  array_t **solution_p 	/* minterm = array of values */)
+{
+    array_t *solution;
+    solution = next_valid_minterm(mgen);
+    while ((mgen->out_of_range) && (mgen->status != bdd_EMPTY)) {
+	array_free(solution);
+	solution = next_valid_minterm(mgen);
+    }
+    *solution_p = solution;
+    if (mgen->status != bdd_EMPTY)
+	return (1);
+    else
+	return (0);
+}
+
+
+void
+mdd_print_array(array_t *array)
+{
+    int i, value;
+    for (i=0; i<array_n(array); i++) {
+	value = array_fetch(int, array, i);
+        printf("%d ",value);
+    }
+    printf("\n");
+}
+
+
+int
+mdd_gen_free(mdd_gen *mgen)
+{
+    if (mgen->minterm != NIL(array_t)) array_free(mgen->minterm);
+/*  if (mgen->cube != NIL(array_t)) array_free(mgen->cube); */
+/*  mgen->cube gets freed in bdd_gen_free(mgen->bdd_generator) below */
+    if (mgen->var_list != NIL(array_t)) array_free(mgen->var_list);
+    bdd_gen_free(mgen->bdd_generator);
+    FREE(mgen);
+
+    return (0);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_literal.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_literal.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_literal.c	(revision 8)
@@ -0,0 +1,60 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_literal.c,v 1.10 2002/08/24 21:48:15 fabio Exp $
+ *
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+/* Returns \/_{i in values}(mddid == i) */
+/* Algorithm used to be quadratic.  Is linear now */
+mdd_t *
+mdd_literal(
+  mdd_manager *mgr,
+  int mddid,
+  array_t *values)
+{
+  mvar_type mvar;
+  mdd_t *one, *zero;
+  array_t *allValues;    /* Holds one in pos i iff value i is allowed */
+  int i;                 /* iterator                                  */   
+  int value;             /* iterates over values                      */
+  mdd_t *result;
+  
+  mvar = mdd_get_var_by_id(mgr, mddid);
+  one = mdd_one(mgr);
+  zero = mdd_zero(mgr);
+  allValues = array_alloc(mdd_t *, mvar.values);
+
+  /* first set every value to zero */
+  for(i = 0; i < mvar.values; i++)
+    array_insert(mdd_t *, allValues, i, zero);
+  
+  /* then set requested values to one */
+  arrayForEachItem(int, values, i, value)
+    array_insert(mdd_t *, allValues, value, one);
+  
+  result = mdd_case(mgr, mddid, allValues);
+  array_free(allValues);
+
+  mdd_free(one);
+  mdd_free(zero);
+  
+  return result;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_mod.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_mod.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_mod.c	(revision 8)
@@ -0,0 +1,130 @@
+/*
+ * $Id: mdd_mod.c,v 1.5 2002/08/27 16:30:26 fabio Exp $
+ *
+ */
+
+#include "mdd.h"
+
+static void mod_block_build (mdd_t ****, int, bvar_type *, bvar_type *);
+static void assert_zero (mdd_manager *, mdd_t **, bvar_type *);
+static void single_var_block_build (mdd_t ****, bvar_type *, int);
+
+int
+getbit(int number, int position)
+{
+return ( (number >> position) & 1);
+}
+
+static void
+assert_zero(
+  mdd_manager *mgr,
+  mdd_t **PINS_00_ptr,
+  bvar_type *a_bit_i_ptr)
+{
+	mdd_t *zero;
+
+	zero = mdd_zero(mgr);
+
+	(*PINS_00_ptr) = mdd_ite( a_bit_i_ptr->node,  zero, (*PINS_00_ptr) , 1, 1, 1);		
+
+	mdd_free(zero);
+
+	return;
+}
+
+static void
+single_var_block_build(
+  mdd_t ****PINS_ptr,
+  bvar_type *b_bit_i_ptr,
+  int M)
+{
+	int i;
+
+	for (i=0; i < M; i++)
+		(*PINS_ptr)[0][i] = mdd_ite( b_bit_i_ptr->node, (*PINS_ptr)[0][(2*i+1)%M], (*PINS_ptr)[0][(2*i)%M], 1, 1, 1);
+
+}
+
+/* a = b (mod M) */
+static void
+mod_block_build(
+  mdd_t ****PINS_ptr,
+  int M /* modulus */,
+  bvar_type *a_bit_i_ptr,
+  bvar_type *b_bit_i_ptr)  
+{
+	int i, j;
+	mdd_t *THEN, *ELSE;
+
+	for(i=0; i<M; i++)
+		for (j=0; j<M; j++){
+			THEN = mdd_ite(b_bit_i_ptr->node, (*PINS_ptr)[(2*i+1)%M][(2*j+1)%M], 
+							   (*PINS_ptr)[(2*i+1)%M][(2*j)%M],   1, 1, 1);
+			
+			ELSE = mdd_ite(b_bit_i_ptr->node, (*PINS_ptr)[(2*i)%M][(2*j+1)%M], 
+							   (*PINS_ptr)[(2*i)%M][(2*j)%M],     1, 1, 1);
+		
+			(*PINS_ptr)[i][j] = mdd_ite(a_bit_i_ptr->node, THEN, ELSE, 1, 1, 1);
+		}			
+}
+
+/* a = b (mod M) */
+mdd_t *
+mdd_mod(
+  mdd_manager *mgr,
+  int a_mvar_id,
+  int b_mvar_id,
+  int M /* Modulus */ )
+{
+	mdd_t ***PINS; 		/* Two dimensional array of mdd_t*'s used in forming the mdd */
+	int i, j;
+	mvar_type a, b;
+	array_t *mvar_list = mdd_ret_mvar_list(mgr);
+ 	array_t *bvar_list = mdd_ret_bvar_list(mgr);
+	bvar_type a_bit_i, b_bit_i;
+	mdd_t *result, *less_than;
+
+	a = array_fetch ( mvar_type, mvar_list, a_mvar_id);
+	b = array_fetch ( mvar_type, mvar_list, b_mvar_id);
+
+	/* Allocate two dimensional array PINS[0..M-1][0..M-1] of mdd_t *'s */
+	PINS = ALLOC(mdd_t **, M);		
+	for(i=0; i<M; i++) PINS[i] = ALLOC(mdd_t *, M);
+	
+	for(i=0; i< M; i++) 
+		for(j=0; j< M; j++) PINS[i][j] = mdd_zero(mgr);
+
+	for(i=0; i< M; i++) PINS[i][i] = mdd_one(mgr);
+
+	for( i = 1 ; i <= (MIN(a.encode_length, b.encode_length)); i++){ 
+		a_bit_i = mdd_ret_bvar( &a, (a.encode_length - i), bvar_list);
+		b_bit_i = mdd_ret_bvar( &b, (b.encode_length - i), bvar_list);
+
+		mod_block_build(&PINS, M,  &a_bit_i, &b_bit_i);	 
+	}
+
+	if ( a.encode_length > b.encode_length ) 
+		for ( i = MIN(a.encode_length, b.encode_length)+1; i <= a.encode_length; i++){
+			a_bit_i = mdd_ret_bvar( &a, (a.encode_length - i), bvar_list);
+			assert_zero( mgr, &(PINS[0][0]), &a_bit_i);
+		}
+
+	if ( b.encode_length > a.encode_length )
+		for ( i = MIN(a.encode_length, b.encode_length)+1; i <= b.encode_length; i++){
+			b_bit_i = mdd_ret_bvar( &b, (b.encode_length - i), bvar_list);
+			single_var_block_build( &PINS, &b_bit_i, M);
+		}
+
+	less_than = build_lt_c(mgr, a_mvar_id, M);
+
+	result = mdd_and(PINS[0][0], less_than, 1, 1);
+		
+	return result;	
+
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_quit.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_quit.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_quit.c	(revision 8)
@@ -0,0 +1,51 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_quit.c,v 1.10 2002/08/24 21:48:15 fabio Exp $
+ *
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+void
+mdd_quit(mdd_manager *mgr)
+{
+    int i;
+    mvar_type one_mvar_struct;
+    bvar_type one_bvar_struct;
+    bdd_external_hooks *hook;  
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+
+
+    for (i=0; i<array_n(mvar_list); i++) {
+	one_mvar_struct = array_fetch(mvar_type, mvar_list, i);
+        FREE(one_mvar_struct.name);
+        FREE(one_mvar_struct.encoding);
+	array_free(one_mvar_struct.bvars);
+    }
+    array_free(mvar_list); 
+    for (i=0; i<array_n(bvar_list); i++) {
+	one_bvar_struct = array_fetch(bvar_type, bvar_list, i);
+        mdd_free(one_bvar_struct.node);
+    }
+    array_free(bvar_list); 
+
+    hook = bdd_get_external_hooks(mgr);
+    FREE(hook->mdd);
+
+    bdd_end(mgr);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_search.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_search.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_search.c	(revision 8)
@@ -0,0 +1,107 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_search.c,v 1.10 2002/08/27 16:30:26 fabio Exp $
+ *
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+static void
+mdd_pr_cubes(mdd_manager *mgr)
+{
+    int i, j;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    mvar_type mv;
+
+    for (i=0; i<array_n(mvar_list); i++) {
+        mv = array_fetch(mvar_type, mvar_list, i);
+        (void) printf("\n%s = ", mv.name);
+        for (j=0; j<mv.encode_length; j++)
+            (void) printf("%d",mv.encoding[j]);
+    }
+    (void) printf("\n");
+}
+
+static void
+mdd_pr_minterms(mdd_manager *mgr)
+{
+	/* not implemented yet */
+
+    int i, j;
+    mvar_type mv;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+    for (i=0; i<array_n(mvar_list); i++) {
+        mv = array_fetch(mvar_type, mvar_list, i);
+        (void) printf("\n%s = ", mv.name);
+        for (j=0; j<mv.encode_length; j++)
+            (void) printf("%d",mv.encoding[j]);
+    }
+    (void) printf("\n");
+}
+
+void
+mdd_search(
+  mdd_manager *mgr,
+  bdd_t *top,
+  int phase,
+  boolean minterms)
+{
+    int is_complemented;
+    bdd_t *child, *top_uncomp;
+    
+    if (mdd_is_tautology(top,1)) {
+	if (phase == 1) {
+	    if (minterms == 1) mdd_pr_minterms(mgr);	
+	    else mdd_pr_cubes(mgr);	
+	}
+        return;
+    }
+    if (mdd_is_tautology(top,0)) {
+	if (phase == 0) {
+	    if (minterms == 1) mdd_pr_minterms(mgr);	
+	    else mdd_pr_cubes(mgr);	
+	}
+        return;
+    }
+
+    (void)bdd_get_node(top,&is_complemented);
+
+    if (is_complemented != 0) { 
+	phase = toggle(phase);
+    }
+
+    (void) mdd_mark(mgr, top, 1);
+
+    if (is_complemented) top_uncomp = bdd_not(top); 
+    else top_uncomp = mdd_dup(top);
+
+    child = bdd_then(top_uncomp);
+    mdd_search(mgr, child, phase, minterms);
+    mdd_free(child);
+
+
+    child = bdd_else(top_uncomp);
+    (void) mdd_mark(mgr, top, 0);
+    mdd_search(mgr, child, phase, minterms);
+    mdd_unmark(mgr, top);
+
+    mdd_free(top_uncomp);
+    mdd_free(child);
+    return;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_smooth.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_smooth.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_smooth.c	(revision 8)
@@ -0,0 +1,74 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_smooth.c,v 1.10 2002/08/27 03:17:38 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_smooth(
+  mdd_manager *mgr,
+  mdd_t *fn,
+  array_t *mvars)
+{
+    array_t *bdd_vars;
+    int i, j, mv_no;
+    mvar_type mv;
+    mdd_t *top;
+    bdd_t *temp;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+	
+	
+    if ( mvars == NIL(array_t) ) {
+	top = bdd_dup(fn);
+	printf("\nWARNING: Empty Array of Smoothing Variables\n");
+	return top;
+    }
+    else if ( array_n(mvars) == 0) {
+	top = bdd_dup(fn);
+	printf("\nWARNING: Empty Array of Smoothing Variables\n");
+	return top;
+    }
+		
+	
+    bdd_vars = array_alloc(bdd_t *, 0);	
+    for (i=0; i<array_n(mvars); i++) {
+	mv_no = array_fetch(int, mvars, i);
+	mv = array_fetch(mvar_type, mvar_list, mv_no);
+	if (mv.status == MDD_BUNDLED) {
+	    (void) fprintf(stderr, 
+			"\nmdd_smooth: bundled variable %s used\n",mv.name);
+	    fail("");
+        }
+
+	for (j=0; j<mv.encode_length; j++) {
+	    temp = bdd_get_variable(mgr, mdd_ret_bvar_id(&mv,j) );
+	    array_insert_last(bdd_t *, bdd_vars, temp);
+	}
+    }
+	
+    top = bdd_smooth(fn, bdd_vars);
+  
+    for (i=0; i<array_n(bdd_vars); i++) {
+	temp = array_fetch(bdd_t *, bdd_vars, i);
+	bdd_free(temp);
+    }
+    array_free(bdd_vars);
+
+    return top;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_substit.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_substit.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_substit.c	(revision 8)
@@ -0,0 +1,106 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_substit.c,v 1.10 2002/08/24 21:48:15 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+array_t *
+mdd_substitute_array(
+  mdd_manager	*mgr,
+  array_t	*fn_array,
+  array_t	*old_mvars,
+  array_t	*new_mvars)
+{
+    array_t	*new_fn_array;
+    mdd_t	*new_fn, *fn;
+    int		i;
+
+    new_fn_array = array_alloc(mdd_t *, 0);
+    arrayForEachItem(mdd_t *, fn_array, i, fn) {
+	new_fn = mdd_substitute(mgr, fn, old_mvars, new_mvars);
+	array_insert(mdd_t *, new_fn_array, i, new_fn);
+    }
+
+    return(new_fn_array);
+}
+
+mdd_t *
+mdd_substitute(
+  mdd_manager	*mgr,
+  mdd_t		*fn,
+  array_t	*old_mvars,
+  array_t	*new_mvars)
+{
+    array_t 		*old_bdd_vars, *new_bdd_vars;
+    int 		i, j, old_mv_no, new_mv_no, no_mvar;
+    mvar_type 		old_mv, new_mv;
+    mdd_t 		*top;
+    array_t 		*mvar_list = mdd_ret_mvar_list(mgr);
+    bdd_t		*varBdd;
+
+    old_bdd_vars = array_alloc( bdd_t *, 0);
+    new_bdd_vars = array_alloc( bdd_t *, 0);
+
+    no_mvar = array_n(old_mvars);
+    if (no_mvar != array_n(new_mvars)) 
+        fail("mdd_substitute: arrays contains different no. of mvars.\n");
+
+    for (i=0; i<no_mvar; i++) {
+        old_mv_no = array_fetch(int, old_mvars, i);
+	old_mv = array_fetch(mvar_type, mvar_list, old_mv_no);
+	if (old_mv.status == MDD_BUNDLED) {
+		(void) fprintf(stderr, 
+		   "\nmdd_substitute: bundled variable %s used\n",old_mv.name);
+		fail("");
+	}
+
+        new_mv_no = array_fetch(int, new_mvars, i);
+	new_mv = array_fetch(mvar_type, mvar_list, new_mv_no);
+	if (new_mv.status == MDD_BUNDLED) {
+		(void) fprintf(stderr, 
+		   "\nmdd_substitute: bundled variable %s used\n",new_mv.name);
+		fail("");
+	}
+
+	if (old_mv.values != new_mv.values) 
+            fail("mdd_substitute: mvars have different no. of values\n");
+
+	for (j=0; j<old_mv.encode_length; j++) {	
+	    varBdd = bdd_get_variable( mgr, mdd_ret_bvar_id(&old_mv,j) );
+	    array_insert_last( bdd_t *, old_bdd_vars, varBdd );
+
+	    varBdd = bdd_get_variable( mgr, mdd_ret_bvar_id(&new_mv, j) );
+	    array_insert_last( bdd_t *, new_bdd_vars, varBdd);
+	}
+    }
+    top = bdd_substitute(fn, old_bdd_vars, new_bdd_vars);
+
+    for(j=0; j<array_n(old_bdd_vars); j++) {
+        varBdd = array_fetch(bdd_t*,old_bdd_vars,j);
+        bdd_free(varBdd);
+    }
+    array_free(old_bdd_vars);
+    for(j=0; j<array_n(new_bdd_vars); j++) {
+        varBdd = array_fetch(bdd_t*,new_bdd_vars,j);
+        bdd_free(varBdd);
+    }
+    array_free(new_bdd_vars);
+
+    return top;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_support.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_support.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_support.c	(revision 8)
@@ -0,0 +1,104 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_support.c,v 1.12 2002/08/24 21:48:15 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+array_t *
+mdd_get_support(mdd_manager *mdd_mgr, mdd_t *f)
+{
+    array_t *full_list, *support_list;
+    array_t *mvar_list = mdd_ret_mvar_list(mdd_mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mdd_mgr);
+    var_set_t *vset;
+    int i, list_length;
+    bvar_type bv;
+    boolean present;
+
+
+    /* initialize full list of mvar id's */
+    list_length = array_n(mvar_list);
+    full_list = array_alloc(boolean, list_length);
+    for (i = 0; i < array_n(mvar_list); i++) {
+	array_insert(boolean, full_list, i, 0);
+    }
+
+    vset = bdd_get_support(f);
+    for (i = 0; i < array_n(bvar_list); i++) {
+	if (var_set_get_elt(vset, i) == 1) {
+	    bv = array_fetch(bvar_type, bvar_list, i);
+	    (void) array_insert(boolean, full_list, bv.mvar_id, 1);
+	}
+    }
+
+    support_list = array_alloc(int, 0);
+    for (i = 0; i < array_n(mvar_list); i++) {
+	present = array_fetch(boolean, full_list, i);
+	if (present) array_insert_last(int, support_list, i);
+    }
+
+    (void) array_free(full_list);
+    (void) var_set_free(vset);
+
+    return support_list;
+}
+
+array_t *
+mdd_get_bdd_support_ids(mdd_manager *mdd_mgr, mdd_t *f)
+{
+    array_t *bdd_support_list;
+    array_t *bvar_list = mdd_ret_bvar_list(mdd_mgr);
+    var_set_t *vset;
+    int i;
+
+    bdd_support_list = array_alloc(int, 0);
+
+    vset = bdd_get_support(f);
+    for (i = 0; i < array_n(bvar_list); i++) {
+	if (var_set_get_elt(vset, i) == 1) {
+	    array_insert_last(int, bdd_support_list, i);
+	}
+    }
+
+    (void) var_set_free(vset);
+    return bdd_support_list;
+}
+
+array_t *
+mdd_get_bdd_support_vars(mdd_manager *mdd_mgr, mdd_t *f)
+{
+    array_t *bdd_support_list;
+    array_t *bvar_list = mdd_ret_bvar_list(mdd_mgr);
+    var_set_t *vset;
+    mdd_t *var;
+    int i;
+
+    bdd_support_list = array_alloc(mdd_t *, 0);
+    
+    vset = bdd_get_support(f);
+    for (i = 0; i < array_n(bvar_list); i++) {
+	if (var_set_get_elt(vset, i) == 1) {
+	    var = bdd_var_with_index(mdd_mgr, i);
+	    array_insert_last(mdd_t *, bdd_support_list, var);
+	}
+    }
+
+    (void) var_set_free(vset);
+    return bdd_support_list;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_uminus.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_uminus.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_uminus.c	(revision 8)
@@ -0,0 +1,30 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_uminus.c,v 1.9 2002/08/24 21:48:15 fabio Exp $
+ *
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+mdd_t *
+mdd_unary_minus_s(
+  mdd_manager *mgr,
+  int mvar1,
+  int mvar2)
+{
+    return (mdd_unary_minus(mgr, mvar1, mvar2));
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/mdd_util.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mdd_util.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mdd_util.c	(revision 8)
@@ -0,0 +1,1434 @@
+#include <stdio.h>
+#include <math.h>
+#include "util.h"
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mdd_util.c,v 1.38 2002/09/21 20:41:33 fabio Exp $
+ *
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+static	bdd_t*	mddRetOnvalBdd(mdd_manager *mddMgr, int mddId);
+static	bdd_t*	mddIntRetOnvalBdd(mdd_manager *mddMgr, int valNum, int low, int hi, int level, array_t *bddVarArr);
+static	void	mddFreeBddArr(array_t *bddArr);
+	
+/************************************************************************/
+#define		mddGetVarById( mgr, id )	\
+    array_fetch(mvar_type, mdd_ret_mvar_list((mgr)),(id))
+
+
+int
+toggle(int x)
+{
+    if (x == 0) return 1;
+    else {
+	if (x == 1) return 0;
+	else {
+	    fail("toggle: invalid boolean value\n");
+	    return -1;
+	}
+    }
+}
+
+int
+no_bit_encode(int n)
+{
+    int i = 0;
+    int j = 1;
+
+    if (n < 2) return 1; /* Takes care of mv.values <= 1 */
+
+    while (j < n) {
+	j = j * 2;
+	i++;
+    }
+    return i;
+}
+
+void
+print_mvar_list(mdd_manager *mgr)
+{
+    mvar_type mv;
+    int i;
+    int no_mvar;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+    no_mvar = array_n(mvar_list);
+    printf("print_mvar_list:\n");
+    printf("id\tname\tvalues\tbits\tstride\tstart_vertex\n");
+    for (i=0; i<no_mvar; i++) {
+        mv = array_fetch(mvar_type, mvar_list, i);
+        (void) printf("%d\t%s\t%d\t%d\n", 
+		mv.mvar_id, mv.name, mv.values, 
+		mv.encode_length);
+    }
+}
+
+void
+print_strides(array_t *mvar_strides)
+{
+    int i, s;
+
+    (void) printf("mvar_strides: ");
+    for (i=0; i<array_n(mvar_strides); i++) {
+        s = array_fetch(int, mvar_strides, i);
+        (void) printf("%d ", s);
+    }
+    (void) printf("\n");
+}
+
+void
+print_bdd_list_id(array_t *bdd_list)
+{
+    bdd_t *b;
+    int i, is_complemented;
+
+    (void) printf("bdd_list id's: ");
+    for (i=0; i<array_n(bdd_list); i++) {
+        b = array_fetch(bdd_t *, bdd_list, i);
+        (void)bdd_get_node(b, &is_complemented);
+        if (is_complemented) (void) printf("!");
+        (void) printf("%d ", bdd_top_var_id(b));
+    }
+    (void) printf("\n");
+}
+
+void
+print_bvar_list_id(mdd_manager *mgr)
+{
+    bvar_type bv;
+    int i, is_complemented;
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+ 
+    (void) printf("bvar_list id's: ");
+    for (i=0; i<array_n(bvar_list); i++) {
+        bv = array_fetch(bvar_type, bvar_list, i);
+        (void)bdd_get_node(bv.node,&is_complemented);
+        if (is_complemented) (void) printf("!");
+	(void) printf("%d ", bdd_top_var_id(bv.node));
+    }
+    (void) printf("\n");
+}
+
+void
+print_bdd(bdd_manager *mgr, bdd_t *top)
+{
+
+    int is_complemented;
+    bdd_t *child, *top_uncomp;
+
+    if (bdd_is_tautology(top,1)) {
+	(void) printf("ONE ");
+        return;
+    }
+    if (bdd_is_tautology(top,0)) {
+	(void) printf("ZERO ");
+        return;
+    }
+    (void)bdd_get_node(top, &is_complemented);
+    if (is_complemented != 0) (void) printf("!");
+    (void) printf("%d ", bdd_top_var_id(top));
+    (void) printf("v ");
+    (void) printf("< ");
+
+    if (is_complemented) top_uncomp = bdd_not(top);
+    else top_uncomp = mdd_dup(top);
+
+    child = bdd_then(top);
+
+    print_bdd(mgr, child);
+    (void) printf("> ");
+
+    mdd_free(child);
+    child = bdd_else(top);
+
+    print_bdd(mgr, child);
+    (void) printf("^ ");
+    
+    mdd_free(top_uncomp);
+    mdd_free(child);
+
+    return;
+}
+
+
+
+mvar_type 
+find_mvar_id(mdd_manager *mgr, unsigned short id)
+{
+    mvar_type mv;
+    bvar_type bv;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    array_t *bvar_list = mdd_ret_bvar_list(mgr);
+
+    if (id >= array_n(bvar_list))
+    	fail("find_mvar_id: invalid parameter range for id\n");
+    bv = array_fetch(bvar_type, bvar_list, id);
+    if ((bv.mvar_id < 0) || (bv.mvar_id >= array_n(mvar_list)))
+    	fail("find_mvar_id: bvar contains invalid mvar_id\n");
+    mv = array_fetch(mvar_type, mvar_list, bv.mvar_id);
+    return mv;
+}
+
+void
+clear_all_marks(mdd_manager *mgr)
+{
+    int i, j;
+    mvar_type mv;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+
+    for (i=0; i<array_n(mvar_list); i++) {
+	mv = array_fetch(mvar_type, mvar_list, i);
+	for (j=0; j<mv.encode_length; j++)
+	    mv.encoding[j] = 2;
+    }
+}
+
+void
+mdd_mark(
+  mdd_manager *mgr,
+  bdd_t *top /**** was bdd_node *bnode; --- changed by Serdar ***/,
+  int phase)
+{
+    int i, top_id, found = 0;
+    int bit_position = 0; /* initialize for lint */
+    mvar_type mv;
+
+    top_id = bdd_top_var_id(top);
+    mv = find_mvar_id(mgr, top_id);
+
+    for (i=0; i<(mv.encode_length); i++){
+		if ( mdd_ret_bvar_id( &mv, i) == top_id ){
+			bit_position = i;
+			found = 1;
+			break;
+		};
+    };
+   
+    
+    if (found == 0)
+	fail("mdd_mark: interleaving error\n");
+
+    mv.encoding[bit_position] = phase;
+    
+}
+
+void
+mdd_unmark(mdd_manager *mgr, bdd_t *top)
+{
+    int i, top_id, found = 0;
+    int bit_position = 0; /* initialize for lint */
+    mvar_type mv;
+
+
+    top_id = bdd_top_var_id(top);
+    mv = find_mvar_id(mgr, top_id);
+
+    for (i=0; i<mv.encode_length; i++) 
+		if ( mdd_ret_bvar_id( &mv, i) == top_id ){
+			bit_position = i;
+			found = 1;
+			break;
+		};
+
+    if (found == 0)
+	fail("mdd_unmark: interleaving error\n");
+    mv.encoding[bit_position] = 2;
+}
+
+mvar_type 
+find_mvar(mdd_manager *mgr, char *name)
+{
+    int i;
+    mvar_type mv;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+    for (i=0; i<array_n(mvar_list); i++) {
+	mv = array_fetch(mvar_type, mvar_list, i);
+        if (strcmp(mv.name, name) == 0) return mv;
+    }
+    fail("find_mvar: cannot find name in mvar_list\n");
+    return mv;
+}
+
+array_t *
+mdd_ret_mvar_list(mdd_manager *mgr)
+{
+    bdd_external_hooks *hook;    
+    array_t *mvar_list;
+
+    hook =  bdd_get_external_hooks(mgr);
+    mvar_list = ((mdd_hook_type *)(hook->mdd))->mvar_list;
+
+    return mvar_list;
+}
+
+void
+mdd_set_mvar_list(mdd_manager *mgr, array_t *mvar_list)
+{
+    bdd_external_hooks *hook;    
+
+    hook =  bdd_get_external_hooks(mgr);
+    ((mdd_hook_type *)(hook->mdd))->mvar_list = mvar_list;
+}
+
+
+array_t *
+mdd_ret_bvar_list(mdd_manager *mgr)
+{
+    bdd_external_hooks *hook;    
+    array_t *bvar_list;
+
+    hook =  bdd_get_external_hooks(mgr);
+    bvar_list = ((mdd_hook_type *)(hook->mdd))->bvar_list;
+
+    return bvar_list;
+}
+
+
+int
+mdd_ret_bvar_id(mvar_type *mvar_ptr, int i)
+{
+	
+	return ( array_fetch(int, mvar_ptr->bvars, i) );
+}
+
+bvar_type
+mdd_ret_bvar(mvar_type *mvar_ptr, int i, array_t *bvar_list)
+{
+	int bvar_id;
+	
+	bvar_id = array_fetch(int, mvar_ptr->bvars, i);
+	
+	return array_fetch(bvar_type, bvar_list, bvar_id);
+}
+
+/************************************************************************/
+/* Given an Mdd, returns the num of onset points.  By construction of	*/
+/* Mdd's, some points not in the range of Mdd vars may be included 	*/
+/* in the onset. These fake points must first be removed.		*/
+/************************************************************************/
+
+double
+mdd_count_onset(
+  mdd_manager	*mddMgr,
+  mdd_t		*aMdd,
+  array_t	*mddIdArr)
+{
+	bdd_t		*onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd;
+	double		onsetNum;
+	array_t		*bddVarArr;
+	int		i, arrSize, mddId;
+
+	arrSize = array_n( mddIdArr );
+	onvalBdd = bdd_one( mddMgr );
+
+	for ( i = 0 ; i < arrSize ; i++ ) {
+	    mddId = array_fetch( int, mddIdArr, i );
+	    aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId );
+
+	    tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 );
+	    bdd_free( onvalBdd );
+	    bdd_free( aOnvalBdd );
+	    onvalBdd = tmpBdd;
+	}
+	onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 );
+	bdd_free( onvalBdd );
+
+	bddVarArr = mdd_id_array_to_bdd_array( mddMgr, mddIdArr );
+	onsetNum = bdd_count_onset( onsetBdd, bddVarArr );
+	bdd_free( onsetBdd );
+	mddFreeBddArr( bddVarArr );
+	return( onsetNum );
+}		/* mdd_count_onset */
+
+mdd_t *
+mdd_onset_bdd(
+  mdd_manager	*mddMgr,
+  mdd_t		*aMdd,
+  array_t	*mddIdArr)
+{
+	bdd_t		*onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd;
+	int		i, arrSize, mddId;
+
+	arrSize = array_n( mddIdArr );
+	onvalBdd = bdd_one( mddMgr );
+
+	for ( i = 0 ; i < arrSize ; i++ ) {
+	    mddId = array_fetch( int, mddIdArr, i );
+	    aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId );
+
+	    tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 );
+	    bdd_free( onvalBdd );
+	    bdd_free( aOnvalBdd );
+	    onvalBdd = tmpBdd;
+	}
+	onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 );
+	bdd_free( onvalBdd );
+	return( onsetBdd );
+}		/* mdd_onset_bdd */
+
+int
+mdd_epd_count_onset(
+  mdd_manager	*mddMgr,
+  mdd_t		*aMdd,
+  array_t	*mddIdArr,
+  EpDouble	*epd)
+{
+	bdd_t		*onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd;
+	array_t		*bddVarArr;
+	int		i, arrSize, mddId;
+	int		status;
+
+	arrSize = array_n( mddIdArr );
+	onvalBdd = bdd_one( mddMgr );
+
+	for ( i = 0 ; i < arrSize ; i++ ) {
+	    mddId = array_fetch( int, mddIdArr, i );
+	    aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId );
+
+	    tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 );
+	    bdd_free( onvalBdd );
+	    bdd_free( aOnvalBdd );
+	    onvalBdd = tmpBdd;
+	}
+	onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 );
+	bdd_free( onvalBdd );
+
+	bddVarArr = mdd_id_array_to_bdd_array( mddMgr, mddIdArr );
+	status = bdd_epd_count_onset( onsetBdd, bddVarArr, epd );
+	if (status)
+	    return(status);
+	bdd_free( onsetBdd );
+	mddFreeBddArr( bddVarArr );
+	return(0);
+}		/* mdd_epd_count_onset */
+
+/************************************************************************/
+static	bdd_t*
+mddRetOnvalBdd(
+  mdd_manager	*mddMgr,
+  int		mddId)
+{
+	bdd_t		*onvalBdd;
+	mvar_type	mVar;
+	int		valNum, high;
+	array_t		*bddVarArr;	
+	
+	mVar = mddGetVarById( mddMgr, mddId );
+	valNum = mVar.values;
+	high = (int) pow( (double) 2, (double) mVar.encode_length ); 
+	assert( (valNum == 1)  || ( (valNum <= high) && (valNum > high/2) ));
+	if ( valNum == high )
+	    onvalBdd = bdd_one( mddMgr );
+	else {
+	    bddVarArr = mdd_id_to_bdd_array( mddMgr, mddId );
+	    onvalBdd = mddIntRetOnvalBdd( mddMgr, valNum, 0, high, 
+					  0, bddVarArr );
+	    mddFreeBddArr( bddVarArr );
+	}
+	return( onvalBdd );
+}		/* mddRetOnvalBdd */	
+
+/************************************************************************/
+static	bdd_t*
+mddIntRetOnvalBdd(
+  mdd_manager *mddMgr,
+  int valNum,
+  int low,
+  int hi,
+  int level,
+  array_t *bddVarArr)
+{
+	int		mid;
+	bdd_t		*curVar, *recBdd;
+	bdd_t		*onvalBdd = NIL(bdd_t); /* initialized for lint */
+
+	mid = (low + hi) / 2;
+	curVar = array_fetch( bdd_t *, bddVarArr, level );
+
+	if 	( valNum > mid ) {
+	    recBdd = mddIntRetOnvalBdd( mddMgr, valNum, mid, hi, 
+					level+1, bddVarArr );
+	    onvalBdd = bdd_or( recBdd, curVar, 1, 0 );
+	    bdd_free( recBdd );
+	}
+	else if ( valNum < mid ) {
+	    recBdd = mddIntRetOnvalBdd( mddMgr, valNum, low, mid, 
+					level+1, bddVarArr );
+	    onvalBdd = bdd_and( recBdd, curVar, 1, 0 );
+	    bdd_free( recBdd );
+	}
+	else if ( valNum == mid ) 
+	    onvalBdd = bdd_not( curVar );
+	return( onvalBdd );
+}		/* mddIntRetOnvalBdd */
+
+/************************************************************************/
+/* Given an array of bdd nodes, frees the array.			*/
+
+static void
+mddFreeBddArr(array_t *bddArr)
+{
+	int	i, arrSize;
+
+	arrSize = array_n( bddArr );
+	for ( i = 0 ; i < arrSize ; i++ ) 
+	    bdd_free( array_fetch( bdd_t *, bddArr, i ) );
+	array_free( bddArr );
+}		/* mddFreeBddArr */
+
+array_t  *
+mdd_ret_bvars_of_mvar(mvar_type *mvar_ptr)
+{
+	return mvar_ptr->bvars;
+}
+
+/************************************************************************/
+/* mdd_get_care_set returns the care set of the mdd manager */ 
+
+static mdd_t *mdd_get_care_set(mdd_manager *mdd_mgr)
+{
+    mdd_t *temp;
+    mvar_type mv;
+    mdd_manager *bdd_mgr;
+
+    int mvar_id,i,j,val_j,value;
+    array_t *mvar_list;
+    bdd_t *care_set, *care_val, *care_cube,*bit_j;
+    
+    mvar_list = mdd_ret_mvar_list(mdd_mgr);
+    bdd_mgr = mdd_mgr;
+    
+    care_set = bdd_one(bdd_mgr);
+    
+    for (mvar_id =0; mvar_id < array_n(mvar_list); mvar_id++)
+        {
+            mv = array_fetch(mvar_type, mvar_list, mvar_id);
+            care_val = bdd_zero(bdd_mgr);
+                
+            for (i=0; i< (mv.values); i++)
+                {
+                    value = i;
+                    care_cube = bdd_one(bdd_mgr);
+                    for(j=0; j< mv.encode_length; j++ )
+                        {
+                            bit_j = bdd_get_variable(bdd_mgr,mdd_ret_bvar_id(&mv, j));
+                            val_j = value % 2;
+                            value = value/2;
+                            temp = care_cube;
+                            care_cube = bdd_and(temp,bit_j,1,val_j);
+                            bdd_free(temp);
+                        }
+                    temp = care_val;
+                    care_val = bdd_or(temp,care_cube,1,1);
+                    bdd_free(temp);
+                    bdd_free(care_cube);
+                }
+            temp = care_set;
+            care_set = bdd_and(temp,care_val,1,1);
+            bdd_free(care_val);
+            bdd_free(temp);
+        }
+    return care_set;
+}
+
+/* Corrected mdd_cproject */
+/* returns only valid carepoints */
+
+mdd_t *mdd_cproject(
+  mdd_manager *mgr,
+  mdd_t *T,
+  array_t *mvars)
+{
+    mdd_t *care_set, *new_T, *T_proj;
+     array_t *bdd_vars;
+    int i, j, mv_no;
+    mvar_type mv;
+    bdd_t *temp;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+
+    care_set = mdd_get_care_set(mgr);
+    new_T = bdd_and(T,care_set,1,1);
+    bdd_free(care_set);
+
+      if ( mvars == NIL(array_t) ) {
+        T_proj = bdd_dup(T);
+        printf("\nWARNING: Empty Array of Smoothing Variables\n");
+        return T_proj;
+    }
+    else if ( array_n(mvars) == 0) {
+        T_proj = bdd_dup(T);
+        printf("\nWARNING: Empty Array of Smoothing Variables\n");
+        return T_proj;
+    }
+                
+        
+    bdd_vars = array_alloc(bdd_t*, 0);     
+    for (i=0; i<array_n(mvars); i++) {
+        mv_no = array_fetch(int, mvars, i);
+        mv = array_fetch(mvar_type, mvar_list, mv_no);
+        if (mv.status == MDD_BUNDLED) {
+            (void) fprintf(stderr, 
+                        "\nmdd_smooth: bundled variable %s used\n",mv.name);
+            fail("");
+        }
+
+        for (j = 0;j < mv.encode_length; j ++) {
+            temp = bdd_get_variable(mgr, mdd_ret_bvar_id(&mv,j) );
+            array_insert_last(bdd_t *, bdd_vars, temp);
+        }
+    }
+        
+  
+    T_proj = bdd_cproject(new_T,bdd_vars);
+    bdd_free(new_T);
+
+    for (i=0; i<array_n(bdd_vars); i++) {
+        temp = array_fetch(bdd_t *, bdd_vars, i);
+        bdd_free(temp);
+    }
+    array_free(bdd_vars);
+
+    
+    return T_proj;
+}
+
+void
+mdd_print_support(mdd_t *f)
+{
+    mdd_manager *mgr = bdd_get_manager(f);
+    array_t *support_list = mdd_get_support(mgr, f);
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    int nSupports = array_n(support_list);
+    int i, j;
+    mvar_type mv;
+    int id;
+
+    for (i = 0; i < nSupports; i++) {
+	id = array_fetch(int, support_list, i);
+	mv = array_fetch(mvar_type, mvar_list, id);
+	if (id == mv.mvar_id)
+	    printf("[%d] = %s\n", i, mv.name);
+	else { /* needs to be checked */
+	    for (j = 0; j < array_n(mvar_list); j++) {
+		mv = array_fetch(mvar_type, mvar_list, j);
+		if (id == mv.mvar_id) {
+		    printf(" [%d] = %s\n", i, mv.name);
+		    break;
+		}
+	    }
+	}
+    }
+
+    array_free(support_list);
+}
+
+void
+mdd_print_support_to_file(FILE *fout, char *format, mdd_t *f)
+{
+    mdd_manager *mgr = bdd_get_manager(f);
+    array_t *support_list = mdd_get_support(mgr, f);
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+    int nSupports = array_n(support_list);
+    int i, j;
+    mvar_type mv;
+    int id;
+
+    for (i = 0; i < nSupports; i++) {
+	id = array_fetch(int, support_list, i);
+	mv = array_fetch(mvar_type, mvar_list, id);
+	if (id == mv.mvar_id)
+	    fprintf(fout, format, mv.name);
+	else { /* needs to be checked */
+	    for (j = 0; j < array_n(mvar_list); j++) {
+		mv = array_fetch(mvar_type, mvar_list, j);
+		if (id == mv.mvar_id) {
+		    fprintf(fout, format, mv.name);
+		    break;
+		}
+	    }
+	}
+    }
+
+    array_free(support_list);
+}
+
+char *
+mdd_read_var_name(mdd_t *f)
+{
+    mdd_manager *mgr;
+    array_t *support_list;
+    array_t *mvar_list;
+    int i, id;
+    mvar_type mv;
+
+    if (bdd_size(f) != 2) {
+	fprintf(stderr,
+	  "** mdd error: mdd_read_var_name can be called for a variable\n");
+	return(NIL(char));
+    }
+
+    mgr = bdd_get_manager(f);
+    support_list = mdd_get_support(mgr, f);
+    mvar_list = mdd_ret_mvar_list(mgr);
+
+    id = array_fetch(int, support_list, 0);
+    mv = array_fetch(mvar_type, mvar_list, id);
+    if (id == mv.mvar_id) {
+	array_free(support_list);
+	return(mv.name);
+    } else { /* needs to be checked */
+	for (i = 0; i < array_n(mvar_list); i++) {
+	    mv = array_fetch(mvar_type, mvar_list, i);
+	    if (id == mv.mvar_id) {
+		array_free(support_list);
+		return(mv.name);
+	    }
+	}
+    }
+
+    array_free(support_list);
+    return(NIL(char));
+}
+
+int
+mdd_read_mdd_id(mdd_t *f)
+{
+    mdd_manager *mgr;
+    array_t *support_list;
+    int id;
+
+    if (bdd_size(f) != 2) {
+	fprintf(stderr,
+	  "** mdd error: mdd_read_mdd_id can be called for a variable\n");
+	return(0);
+    }
+
+    mgr = bdd_get_manager(f);
+    support_list = mdd_get_support(mgr, f);
+    id = array_fetch(int, support_list, 0);
+    array_free(support_list);
+    return(id);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of BDD ids corresponding to a MDD variable.]
+
+  Description [This function takes an MddId. It returns an array of BDD ids
+  corresponding to the bits.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+mdd_id_to_bdd_id_array(mdd_manager *mddManager, int mddId)
+{
+  array_t     *bddIdArray;
+  mvar_type   mddVar;
+  array_t     *mvar_list;
+  int         i, j;
+
+  mvar_list = mdd_ret_mvar_list(mddManager);
+  mddVar = array_fetch(mvar_type, mvar_list, mddId);
+  bddIdArray = array_alloc(int, mddVar.encode_length);
+  
+  for (i=0; i<mddVar.encode_length; i++){
+    j = mdd_ret_bvar_id(&mddVar, i);
+    array_insert_last(int, bddIdArray, j);
+  }
+  return bddIdArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of Bdd_t's corresponding to a Mdd variable.]
+
+  Description [This function takes an MddId. It returns an array of bdd_t's
+  corresponding to the bits.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+mdd_id_to_bdd_array(mdd_manager *mddManager, int mddId)
+{
+  array_t	*bddArray;
+  mvar_type	mddVar;
+  int		i, id;
+  
+  mddVar = mddGetVarById(mddManager, mddId);
+  bddArray = array_alloc(bdd_t*, mddVar.encode_length);
+  
+  for (i = 0; i < mddVar.encode_length; i++) {
+    id = mdd_ret_bvar_id(&mddVar, i);
+    array_insert_last(bdd_t*, bddArray, bdd_get_variable(mddManager, id));
+  }
+  return bddArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of binary vars(bdd_t *) for a given mdd
+  id array.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+mdd_id_array_to_bdd_array(mdd_manager *mddManager, array_t *mddIdArray)
+{
+  array_t	*bddArray;
+  int		i, j;
+  int		id, size;
+  mvar_type	mddVar;
+
+  bddArray = array_alloc(bdd_t*, 0);
+  size = array_n(mddIdArray);
+
+  for (i = 0; i < size; i++) {
+    id = array_fetch(int, mddIdArray, i);
+    mddVar = mddGetVarById(mddManager, id);
+    for (j = 0; j < mddVar.encode_length; j++) {
+      id = mdd_ret_bvar_id(&mddVar, j);
+      array_insert_last(bdd_t *, bddArray, bdd_get_variable(mddManager, id));
+    }
+  }
+  return bddArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of bddId's corresponding to an array of Mdd
+  ids.] 
+
+  Description [This function takes an array of MddId's. For each MddId it
+  returns an array of bddId's corresponding to the bits. These arrays of bddId's
+  are concatenated together and returned.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+mdd_id_array_to_bdd_id_array(mdd_manager *mddManager, array_t *mddIdArray)
+{
+  array_t *bddIdArray;
+  int i;
+
+  bddIdArray = array_alloc(int, 0);
+  for (i=0; i<array_n(mddIdArray); i++){
+    int mddId;
+    array_t *tmpBddIdArray;
+    mddId = array_fetch(int, mddIdArray, i);
+    tmpBddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
+    array_append(bddIdArray, tmpBddIdArray);
+    array_free(tmpBddIdArray);
+  }
+  return bddIdArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a bdd cube from a given mdd id array.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+mdd_id_array_to_bdd_cube(mdd_manager *mddManager, array_t *mddIdArray)
+{
+  int		i, j;
+  int		id, size;
+  mvar_type	mddVar;
+  mdd_t		*cube, *var, *tmp;
+  int		nVars;
+  char		*vars;
+
+  size = array_n(mddIdArray);
+  nVars = bdd_num_vars(mddManager);
+  vars = ALLOC(char, sizeof(char) * nVars);
+  memset(vars, 0, sizeof(char) * nVars);
+
+  for (i = 0; i < size; i++) {
+    id = array_fetch(int, mddIdArray, i);
+    mddVar = mddGetVarById(mddManager, id);
+    for (j = 0; j < mddVar.encode_length; j++) {
+      id = mdd_ret_bvar_id(&mddVar, j);
+      vars[bdd_get_level_from_id(mddManager, id)] = 1;
+    }
+  }
+  cube = mdd_one(mddManager);
+  for (i = nVars - 1; i >= 0; i--) {
+    if (vars[i] == 0)
+      continue;
+    id = (int)bdd_get_id_from_level(mddManager, (long)i);
+    var = bdd_get_variable(mddManager, id);
+    tmp = mdd_and(cube, var, 1, 1);
+    mdd_free(cube);
+    mdd_free(var);
+    cube = tmp;
+  }
+  FREE(vars);
+  return cube;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of bdd variables from mdd id array.]
+
+  Description [Returns the number of bdd variables from mdd id array.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+mdd_get_number_of_bdd_vars(mdd_manager *mddManager, array_t *mddIdArray)
+{
+  int i, n;
+
+  n = 0;
+  for (i=0; i<array_n(mddIdArray); i++){
+    int mddId;
+    array_t *tmpBddIdArray;
+    mddId = array_fetch(int, mddIdArray, i);
+    tmpBddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
+    n += array_n(tmpBddIdArray);
+    array_free(tmpBddIdArray);
+  }
+  return n;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of bdd support of a mdd.]
+
+  Description [Returns the number of bdd support of a mdd.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+mdd_get_number_of_bdd_support(mdd_manager *mddManager, mdd_t *f)
+{
+    array_t *bvar_list = mdd_ret_bvar_list(mddManager);
+    var_set_t *vset;
+    int i, number = 0;
+
+    vset = bdd_get_support(f);
+    for (i = 0; i < array_n(bvar_list); i++) {
+	if (var_set_get_elt(vset, i) == 1) {
+	    number++;
+	}
+    }
+
+    (void) var_set_free(vset);
+    return number;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Given an Mvf representing the functionality of a multi-valued
+  variable, it returns an array of Bdd's representing the characteristic
+  function of the relation of the various bits of the multi-valued variable.] 
+
+  Description [Suppose y is a k-valued variable and takes values
+              0,1,..,k-1. Then the input to this function is an array with k
+              Mdds each representing the onset of the respective value of the
+              variable (the ith Mdd representing the onset when y takes the
+              value (i-1). Suppose m bits are needed to encode the k values of
+              y. Then internally y is represented as y_0, y_1, ...,
+              y_(m-1). Now the functionality of each bit of y can be computed
+              by proper boolean operation on the functions representing the
+              onsets of various values of y. For instance if y is a 4-valued
+              variable. To achieve that we do the following:
+              For each bit b{
+                relation = 0;
+                For each value j of the variable{
+                  Ej = Encoding function of the jth value
+                  Fj = Onset function of the jth value
+                  If (b appears in the positive phase in Ej) then
+                     relation += b * Fj 
+                  else if (b appears in the negative phase in Ej) then
+                     relation += b'* Fj
+                  else if (b does not appear in Ej) then
+                     relation += Fj
+                }
+              }
+              Note that the above algorithm does not handle the case when a
+              bit appears in both phases in the encoding of any value of the
+              variable. Hence the assumption behind the above algorithm is that
+              the values are encoded as cubes.
+              The case when the encoding are functions can be handled by more
+              complex algorithm. In that case, we will not be able to build the
+              relation for each bit separately. Something to be dealt with in
+              the later work.
+              ]              
+  SideEffects []
+
+******************************************************************************/
+array_t *
+mdd_fn_array_to_bdd_rel_array(
+  mdd_manager *mddManager,
+  int mddId,
+  array_t *mddFnArray)
+{
+  array_t *bddRelationArray, *mddLiteralArray, *valueArray, *bddArray;
+  mvar_type mddVar;
+  int i, j, numValues, numEncodingBits;
+  bdd_t *bdd, *bddRelation, *bddNot;
+  bdd_t *mddFn, *posCofactor, *negCofactor, *tmpBddRelation;
+  mdd_t *mddLiteral, *literalRelation;
+  array_t *mvar_list;
+  
+  numValues = array_n(mddFnArray);
+  /* simple binary case */
+  if (numValues == 2) {
+    bdd_t *onRelation, *offRelation;
+
+    bddArray = mdd_id_to_bdd_array(mddManager, mddId);
+    bdd = array_fetch(bdd_t *, bddArray, 0);
+    array_free(bddArray);
+    mddFn = array_fetch(mdd_t *, mddFnArray, 0);
+    offRelation = bdd_and(bdd, mddFn, 0, 1);
+    mddFn = array_fetch(mdd_t *, mddFnArray, 1);
+    onRelation = bdd_and(bdd, mddFn, 1, 1);
+    bdd_free(bdd);
+    bddRelation = bdd_or(onRelation, offRelation, 1, 1);
+    bdd_free(onRelation);
+    bdd_free(offRelation);
+    bddRelationArray = array_alloc(bdd_t *, 0);
+    array_insert_last(bdd_t *, bddRelationArray, bddRelation);
+    return bddRelationArray;
+  }
+  mvar_list = mdd_ret_mvar_list(mddManager);
+  mddVar = array_fetch(mvar_type, mvar_list, mddId);
+  assert(mddVar.values == numValues);
+
+  /*
+   * The following is to check whether each encoding is cube or not.
+   * Since Berkeley MDD package always does the cube encoding this checking has
+   * been turned off currently.
+   */
+  
+  valueArray = array_alloc(int, 1);
+  mddLiteralArray = array_alloc(mdd_t*, 0);
+  for (i=0; i<numValues; i++){
+    array_insert(int, valueArray, 0, i);
+    /* Form the Mdd corresponding to this value */
+    mddLiteral = mdd_literal(mddManager, mddId, valueArray);
+    /* Check if this is a cube */
+    if (bdd_is_cube(mddLiteral) == FALSE){ 
+      fprintf(stderr,
+	"The encoding of the variable %s for the value %d isnot a cube.\n",
+	mddVar.name, i); 
+      fprintf(stderr, "It can result in wrong answers.\n");
+    } 
+    array_insert_last(mdd_t*, mddLiteralArray, mddLiteral);
+  }
+  array_free(valueArray);
+
+  bddRelationArray = array_alloc(bdd_t*, 0);
+  numEncodingBits = mddVar.encode_length;
+  bddArray = mdd_id_to_bdd_array(mddManager, mddId);
+  for (i=0; i<numEncodingBits; i++) {
+    bddRelation = bdd_zero((bdd_manager *)mddManager);
+    bdd = array_fetch(bdd_t*, bddArray, i);
+    bddNot = bdd_not(bdd);
+    for (j=0; j<numValues; j++){
+      mddLiteral = array_fetch(mdd_t*, mddLiteralArray, j);
+      mddFn = array_fetch(mdd_t*, mddFnArray, j);
+      posCofactor = bdd_cofactor(mddLiteral, bdd);
+      if (bdd_is_tautology(posCofactor, 0)) {
+	literalRelation = bdd_and(bddNot, mddFn, 1, 1);
+	bdd_free(posCofactor);
+      } else {
+	negCofactor = bdd_cofactor(mddLiteral, bddNot);
+	if (bdd_is_tautology(negCofactor, 0)) {
+	  literalRelation = bdd_and(bdd, mddFn, 1, 1);
+        } else {
+	  assert(bdd_equal(posCofactor, negCofactor));
+	  literalRelation = bdd_dup(mddFn);
+	}
+	bdd_free(posCofactor);
+	bdd_free(negCofactor);
+      }
+      tmpBddRelation = bdd_or(bddRelation, literalRelation, 1, 1);
+      bdd_free(literalRelation);
+      bdd_free(bddRelation);
+      bddRelation = tmpBddRelation;
+    }
+    array_insert_last(bdd_t*, bddRelationArray, bddRelation);
+    bdd_free(bdd);
+    bdd_free(bddNot);
+  }
+  /* Free stuff */
+  mdd_array_free(mddLiteralArray);
+  array_free(bddArray);
+  return bddRelationArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Given an Mvf representing the functionality of a multi-valued
+  variable, it returns an array of Bdd's representing the characteristic
+  function of the relation of the various bits of the multi-valued variable.] 
+
+  Description [Suppose y is a k-valued variable and takes values
+              0,1,..,k-1. Then the input to this function is an array with k
+              Mdds each representing the onset of the respective value of the
+              variable (the ith Mdd representing the onset when y takes the
+              value (i-1). Suppose m bits are needed to encode the k values of
+              y. Then internally y is represented as y_0, y_1, ...,
+              y_(m-1). Now the functionality of each bit of y can be computed
+              by proper boolean operation on the functions representing the
+              onsets of various values of y. For instance if y is a 4-valued
+              variable. To achieve that we do the following:
+              For each bit b{
+                relation = 0;
+                For each value j of the variable{
+                  Ej = Encoding function of the jth value
+                  Fj = Onset function of the jth value
+                  If (b appears in the positive phase in Ej) then
+                     relation += b * Fj 
+                  else if (b appears in the negative phase in Ej) then
+                     relation += b'* Fj
+                  else if (b does not appear in Ej) then
+                     relation += Fj
+                }
+              }
+              Note that the above algorithm does not handle the case when a
+              bit appears in both phases in the encoding of any value of the
+              variable. Hence the assumption behind the above algorithm is that
+              the values are encoded as cubes.
+              The case when the encoding are functions can be handled by more
+              complex algorithm. In that case, we will not be able to build the
+              relation for each bit separately. Something to be dealt with in
+              the later work.
+              ]              
+  SideEffects []
+
+******************************************************************************/
+array_t *
+mdd_fn_array_to_bdd_fn_array(
+  mdd_manager *mddManager,
+  int mddId,
+  array_t *mddFnArray)
+{
+  array_t *bddFunctionArray, *mddLiteralArray, *valueArray, *bddArray;
+  mvar_type mddVar;
+  int i, j, numValues, numEncodingBits;
+  bdd_t *bdd, *bddFunction, *bddNot;
+  bdd_t *onSet, *offSet, *dcSet, *lower, *upper;
+  bdd_t *mddFn, *posCofactor, *negCofactor, *tmp;
+  mdd_t *mddLiteral;
+  array_t *mvar_list;
+  
+  numValues = array_n(mddFnArray);
+  /* simple binary case */
+  if (numValues == 2) {
+    bddFunctionArray = array_alloc(bdd_t *, 0);
+    mddFn = array_fetch(mdd_t *, mddFnArray, 1);
+    bddFunction = mdd_dup(mddFn);
+    array_insert_last(bdd_t *, bddFunctionArray, bddFunction);
+    return bddFunctionArray;
+  }
+  mvar_list = mdd_ret_mvar_list(mddManager);
+  mddVar = array_fetch(mvar_type, mvar_list, mddId);
+  assert(mddVar.values == numValues);
+
+  /*
+   * The following is to check whether each encoding is cube or not.
+   * Since Berkeley MDD package always does the cube encoding this checking has
+   * been turned off currently.
+   */
+  
+  valueArray = array_alloc(int, 1);
+  mddLiteralArray = array_alloc(mdd_t*, 0);
+  for (i=0; i<numValues; i++){
+    array_insert(int, valueArray, 0, i);
+    /* Form the Mdd corresponding to this value */
+    mddLiteral = mdd_literal(mddManager, mddId, valueArray);
+    /* Check if this is a cube */
+    if (bdd_is_cube(mddLiteral) == FALSE) {
+      fprintf(stderr,
+	"The encoding of the variable %s for the value %d isnot a cube.\n",
+	mddVar.name, i); 
+      fprintf(stderr, "It can result in wrong answers.\n");
+    } 
+    array_insert_last(mdd_t*, mddLiteralArray, mddLiteral);
+  }
+  array_free(valueArray);
+
+  bddFunctionArray = array_alloc(bdd_t*, 0);
+  numEncodingBits = mddVar.encode_length;
+  bddArray = mdd_id_to_bdd_array(mddManager, mddId);
+  for (i=0; i<numEncodingBits; i++) {
+    onSet = bdd_zero((bdd_manager *)mddManager);
+    offSet = bdd_zero((bdd_manager *)mddManager);
+    dcSet = bdd_zero((bdd_manager *)mddManager);
+    bdd = array_fetch(bdd_t*, bddArray, i);
+    bddNot = bdd_not(bdd);
+    for (j=0; j<numValues; j++) {
+      mddLiteral = array_fetch(mdd_t*, mddLiteralArray, j);
+      posCofactor = bdd_cofactor(mddLiteral, bdd);
+      mddFn = array_fetch(mdd_t*, mddFnArray, j);
+
+      if (bdd_is_tautology(posCofactor, 0)) {
+	tmp = bdd_or(offSet, mddFn, 1, 1);
+	bdd_free(offSet);
+	offSet = tmp;
+	bdd_free(posCofactor);
+	continue;
+      }
+
+      negCofactor = bdd_cofactor(mddLiteral, bddNot);
+      if (bdd_is_tautology(negCofactor, 0)) {
+	tmp = bdd_or(onSet, mddFn, 1, 1);
+	bdd_free(onSet);
+	onSet = tmp;
+	bdd_free(posCofactor);
+	bdd_free(negCofactor);
+	continue;
+      }
+
+      assert(bdd_equal(posCofactor, negCofactor));
+      bdd_free(posCofactor);
+      bdd_free(negCofactor);
+
+      tmp = bdd_or(dcSet, mddFn, 1, 1);
+      bdd_free(dcSet);
+      dcSet = tmp;
+    }
+    bdd_free(bdd);
+    bdd_free(bddNot);
+    lower = bdd_and(onSet, offSet, 1, 0);
+    bdd_free(offSet);
+    upper = bdd_or(onSet, dcSet, 1, 1);
+    bdd_free(onSet);
+    bdd_free(dcSet);
+    bddFunction = bdd_between(lower, upper);
+    bdd_free(lower);
+    bdd_free(upper);
+    array_insert_last(bdd_t*, bddFunctionArray, bddFunction);
+  }
+  /* Free stuff */
+  mdd_array_free(mddLiteralArray);
+  array_free(bddArray);
+  return bddFunctionArray;
+}
+
+
+array_t *
+mdd_pick_arbitrary_minterms(
+  mdd_manager	*mddMgr,
+  mdd_t		*aMdd,
+  array_t	*mddIdArr,
+  int		n)
+{
+    bdd_t	*onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd;
+    array_t	*bddVarArr;
+    int		i, arrSize, mddId;
+    array_t	*mintermArray;
+
+    arrSize = array_n( mddIdArr );
+    onvalBdd = bdd_one( mddMgr );
+
+    for ( i = 0 ; i < arrSize ; i++ ) {
+	mddId = array_fetch( int, mddIdArr, i );
+	aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId );
+
+	tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 );
+	bdd_free( onvalBdd );
+	bdd_free( aOnvalBdd );
+	onvalBdd = tmpBdd;
+    }
+    onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 );
+    bdd_free( onvalBdd );
+
+    bddVarArr = mdd_id_array_to_bdd_array(mddMgr, mddIdArr);
+    mintermArray = bdd_bdd_pick_arbitrary_minterms(onsetBdd, bddVarArr,
+	array_n(bddVarArr), n);
+    bdd_free(onsetBdd);
+    mddFreeBddArr(bddVarArr);
+    return(mintermArray);
+}
+
+
+mdd_t *
+mdd_subset_with_mask_vars(
+  mdd_manager	*mddMgr,
+  mdd_t		*aMdd,
+  array_t	*mddIdArr,
+  array_t	*maskIdArr)
+{
+    bdd_t	*onvalBdd, *aOnvalBdd, *onsetBdd, *tmpBdd;
+    array_t	*bddVarArr, *maskVarArr;
+    int		i, arrSize, mddId;
+    mdd_t	*subset;
+
+    arrSize = array_n( mddIdArr );
+    onvalBdd = bdd_one( mddMgr );
+
+    for ( i = 0 ; i < arrSize ; i++ ) {
+	mddId = array_fetch( int, mddIdArr, i );
+	aOnvalBdd = mddRetOnvalBdd( mddMgr, mddId );
+
+	tmpBdd = bdd_and( onvalBdd, aOnvalBdd, 1, 1 );
+	bdd_free( onvalBdd );
+	bdd_free( aOnvalBdd );
+	onvalBdd = tmpBdd;
+    }
+    onsetBdd = bdd_and( onvalBdd, aMdd, 1, 1 );
+    bdd_free( onvalBdd );
+
+    bddVarArr = mdd_id_array_to_bdd_array(mddMgr, mddIdArr);
+    maskVarArr = mdd_id_array_to_bdd_array(mddMgr, maskIdArr);
+
+    subset = bdd_subset_with_mask_vars(onsetBdd, bddVarArr, maskVarArr);
+    bdd_free(onsetBdd);
+    mddFreeBddArr(bddVarArr);
+    mddFreeBddArr(maskVarArr);
+    return(subset);
+}
+
+
+/* Internal macro to access the mvar_type structure for each MDD variable. */
+mvar_type
+mdd_get_var_by_id(mdd_manager *mddMgr, int id)
+{
+    return(mddGetVarById(mddMgr, id));
+}
+
+
+/* checks whether all support variables of mdd appear in supportIdArray. */
+int
+mdd_check_support(
+  mdd_manager	*mddMgr,
+  mdd_t		*mdd,
+  array_t	*supportIdArray)
+{
+  int		i, mddId;
+  st_table	*supportTable = st_init_table(st_numcmp, st_numhash);
+  array_t	*tmpIdArray;
+  int		allSupportFlag = 1;
+
+  for (i = 0; i < array_n(supportIdArray); i++) {
+    mddId = array_fetch(int, supportIdArray, i);
+    st_insert(supportTable, (char *)(long)mddId, NULL);
+  }
+
+  tmpIdArray = mdd_get_support(mddMgr, mdd);
+  for (i = 0; i < array_n(tmpIdArray); i++) {
+    mddId = array_fetch(int, tmpIdArray, i);
+    if (!st_lookup(supportTable, (char *)(long)mddId, NULL)) {
+      allSupportFlag = 0;
+      break;
+    }
+  }
+
+  st_free_table(supportTable);
+  array_free(tmpIdArray);
+  return(allSupportFlag);
+}
+
+
+boolean
+mdd_equal_mod_care_set_array(mdd_t *aSet, mdd_t *bSet, array_t *careSetArray)
+{
+  mdd_t	*tmpMdd1, *tmpMdd2;
+  mdd_t	*careSet;
+  int i;
+  boolean result;
+
+  if (mdd_equal(aSet, bSet))
+    return 1;
+
+  arrayForEachItem(mdd_t *, careSetArray, i, careSet) {
+    tmpMdd1 = mdd_and(aSet, careSet, 1, 1);
+    tmpMdd2 = mdd_and(bSet, careSet, 1, 1);
+
+    result = mdd_equal(tmpMdd1, tmpMdd2);
+    mdd_free(tmpMdd1);
+    mdd_free(tmpMdd2);
+    if (result == 1)
+      return 1;
+  }
+
+  return 0;
+}
+
+
+boolean
+mdd_lequal_mod_care_set_array(mdd_t *aSet, mdd_t *bSet,
+			      boolean aPhase, boolean bPhase,
+			      array_t *careSetArray)
+{
+  mdd_t	*tmpMdd, *careSet;
+  int	i, result;
+
+  if (mdd_lequal(aSet, bSet, aPhase, bPhase))
+    return 1;
+
+  arrayForEachItem(mdd_t *, careSetArray, i, careSet) {
+    tmpMdd = mdd_and(aSet, careSet, aPhase, 1);
+
+    result = mdd_lequal(tmpMdd, bSet, 1, bPhase);
+    mdd_free(tmpMdd);
+    if (result == 1)
+      return 1;
+  }
+
+  return 0;
+}
+
+
+/* Return the mdd that represents all valid assignments to the
+   variables in the support.  Support is an array of mdd_ids. */
+mdd_t *
+mdd_range_mdd(
+  mdd_manager *mgr,
+  array_t *support
+  )
+{
+  int var, varIndex;      /* iterates over support */
+  mdd_t *range;
+
+  range = mdd_one(mgr);
+  arrayForEachItem(int, support, varIndex, var){
+    mdd_t *rangeForVar;
+    mdd_t *tmp;
+
+    rangeForVar = mddRetOnvalBdd(mgr, var);
+    tmp = mdd_and( rangeForVar, range, 1, 1);
+    mdd_free(rangeForVar);
+    mdd_free(range);
+    range = tmp;
+  }
+  
+  return range;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
Index: /vis_dev/glu-2.1/src/mdd/mvar2bdds.c
===================================================================
--- /vis_dev/glu-2.1/src/mdd/mvar2bdds.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/mvar2bdds.c	(revision 8)
@@ -0,0 +1,42 @@
+#include "mdd.h"
+
+/*
+ * MDD Package
+ *
+ * $Id: mvar2bdds.c,v 1.10 2002/08/27 03:16:56 fabio Exp $
+ * 
+ * Author: Timothy Kam
+ *
+ * Copyright 1992 by the Regents of the University of California.
+ *
+ * All rights reserved.  Permission to use, copy, modify and distribute
+ * this software is hereby granted, provided that the above copyright
+ * notice and this permission notice appear in all copies.  This software
+ * is made available as is, with no warranties.
+ */
+
+array_t *
+mvar2bdds(mdd_manager *mgr, array_t *mvars)
+{
+    array_t *bdd_vars;
+    int i, j, mv_no;
+    mvar_type mv;
+    bdd_t *temp;
+    array_t *mvar_list = mdd_ret_mvar_list(mgr);
+
+    bdd_vars = array_alloc(bdd_t *, 0);	
+    for (i=0; i<array_n(mvars); i++) {
+        mv_no = array_fetch(int, mvars, i);
+	mv = array_fetch(mvar_type, mvar_list, mv_no);
+        for (j = 0; j < mv.encode_length; j ++) {
+	    temp = bdd_get_variable(mgr, mdd_ret_bvar_id(&mv,j) );
+	    array_insert_last(bdd_t *, bdd_vars, temp);
+	}
+    }
+    return (bdd_vars);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mdd/semantic.cache
===================================================================
--- /vis_dev/glu-2.1/src/mdd/semantic.cache	(revision 8)
+++ /vis_dev/glu-2.1/src/mdd/semantic.cache	(revision 8)
@@ -0,0 +1,20 @@
+;; Object mdd/
+;; SEMANTICDB Tags save file
+(semanticdb-project-database-file "mdd/"
+  :tables (list 
+   (semanticdb-table "mdd_util.c"
+    :major-mode 'c-mode
+    :tags '(("stdio.h" include (:system-flag t) nil [1 19]) ("math.h" include (:system-flag t) nil [20 37]) ("util.h" include nil nil [38 55]) ("mdd.h" include nil nil [56 72]) ("mddRetOnvalBdd" function (:prototype-flag t :pointer 1 :typemodifiers ("static") :arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [549 569]) ("mddId" variable (:type "int") (reparse-symbol arg-sub-list) [570 580])) :type ("bdd_t" type (:type "class") nil nil)) nil [520 581]) ("mddIntRetOnvalBdd" function (:prototype-flag t :pointer 1 :typemodifiers ("static") :arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [614 634]) ("valNum" variable (:type "int") (reparse-symbol arg-sub-list) [635 646]) ("low" variable (:type "int") (reparse-symbol arg-sub-list) [647 655]) ("hi" variable (:type "int") (reparse-symbol arg-sub-list) [656 663]) ("level" variable (:type "int") (reparse-symbol arg-sub-list) [664 674]) ("bddVarArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [675 694])) :type ("bdd_t" type (:type "class") nil nil)) nil [582 695]) ("mddFreeBddArr" function (:prototype-flag t :typemodifiers ("static") :arguments (("bddArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [722 738])) :type "void") nil [696 739]) ("mddGetVarById" variable (:constant-flag t :default-value (nil)) nil [817 910]) ("toggle" function (:arguments (("x" variable (:type "int") (reparse-symbol arg-sub-list) [924 930])) :type "int") nil [913 1073]) ("no_bit_encode" function (:arguments (("n" variable (:type "int") (reparse-symbol arg-sub-list) [1093 1099])) :type "int") nil [1075 1253]) ("print_mvar_list" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [1276 1293])) :type "void") nil [1255 1711]) ("print_strides" function (:arguments (("mvar_strides" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [1732 1754])) :type "void") nil [1713 1967]) ("print_bdd_list_id" function (:arguments (("bdd_list" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [1992 2010])) :type "void") nil [1969 2362]) ("print_bvar_list_id" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [2388 2405])) :type "void") nil [2364 2821]) ("print_bdd" function (:arguments (("mgr" variable (:pointer 1 :type ("bdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [2838 2855]) ("top" variable (:pointer 1 :type ("bdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [2856 2867])) :type "void") nil [2823 3623]) ("find_mvar_id" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [3651 3668]) ("id" variable (:type "unsigned short") (reparse-symbol arg-sub-list) [3669 3687])) :type ("mvar_type" type (:type "class") nil nil)) nil [3627 4164]) ("clear_all_marks" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4187 4204])) :type "void") nil [4166 4445]) ("mdd_mark" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4464 4481]) ("top" variable (:pointer 1 :type ("bdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [4484 4549]) ("phase" variable (:type "int") (reparse-symbol arg-sub-list) [4552 4562])) :type "void") nil [4447 4997]) ("mdd_unmark" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5015 5032]) ("top" variable (:pointer 1 :type ("bdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5033 5044])) :type "void") nil [4999 5455]) ("find_mvar" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5478 5495]) ("name" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [5496 5507])) :type ("mvar_type" type (:type "class") nil nil)) nil [5457 5805]) ("mdd_ret_mvar_list" function (:pointer 1 :arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5835 5852])) :type ("array_t" type (:type "class") nil nil)) nil [5807 6038]) ("mdd_set_mvar_list" function (:arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6063 6080]) ("mvar_list" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6081 6100])) :type "void") nil [6040 6239]) ("mdd_ret_bvar_list" function (:pointer 1 :arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6270 6287])) :type ("array_t" type (:type "class") nil nil)) nil [6242 6473]) ("mdd_ret_bvar_id" function (:arguments (("mvar_ptr" variable (:pointer 1 :type ("mvar_type" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6496 6516]) ("i" variable (:type "int") (reparse-symbol arg-sub-list) [6517 6523])) :type "int") nil [6476 6579]) ("mdd_ret_bvar" function (:arguments (("mvar_ptr" variable (:pointer 1 :type ("mvar_type" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6604 6624]) ("i" variable (:type "int") (reparse-symbol arg-sub-list) [6625 6631]) ("bvar_list" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6632 6651])) :type ("bvar_type" type (:type "class") nil nil)) nil [6581 6774]) ("mdd_count_onset" function (:arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7159 7179]) ("aMdd" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7182 7195]) ("mddIdArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7198 7216])) :type "double") nil [7133 7924]) ("mdd_onset_bdd" function (:pointer 1 :arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7974 7994]) ("aMdd" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [7997 8010]) ("mddIdArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8013 8031])) :type ("mdd_t" type (:type "class") nil nil)) nil [7949 8533]) ("mdd_epd_count_onset" function (:arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8583 8603]) ("aMdd" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8606 8619]) ("mddIdArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8622 8640]) ("epd" variable (:pointer 1 :type ("EpDouble" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8643 8657])) :type "int") nil [8556 9392]) ("mddRetOnvalBdd" function (:pointer 1 :typemodifiers ("static") :arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [9528 9548]) ("mddId" variable (:type "int") (reparse-symbol arg-sub-list) [9551 9562])) :type ("bdd_t" type (:type "class") nil nil)) nil [9496 10106]) ("mddIntRetOnvalBdd" function (:pointer 1 :typemodifiers ("static") :arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [10241 10261]) ("valNum" variable (:type "int") (reparse-symbol arg-sub-list) [10264 10275]) ("low" variable (:type "int") (reparse-symbol arg-sub-list) [10278 10286]) ("hi" variable (:type "int") (reparse-symbol arg-sub-list) [10289 10296]) ("level" variable (:type "int") (reparse-symbol arg-sub-list) [10299 10309]) ("bddVarArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [10312 10331])) :type ("bdd_t" type (:type "class") nil nil)) nil [10206 10970]) ("mddFreeBddArr" function (:typemodifiers ("static") :arguments (("bddArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [11153 11169])) :type "void") nil [11127 11332]) ("mdd_ret_bvars_of_mvar" function (:pointer 1 :arguments (("mvar_ptr" variable (:pointer 1 :type ("mvar_type" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [11388 11408])) :type ("array_t" type (:type "class") nil nil)) nil [11355 11437]) ("mdd_get_care_set" function (:pointer 1 :typemodifiers ("static") :arguments (("mdd_mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [11610 11631])) :type ("mdd_t" type (:type "class") nil nil)) nil [11579 13062]) ("mdd_cproject" function (:pointer 1 :arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13153 13170]) ("T" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13173 13182]) ("mvars" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [13185 13200])) :type ("mdd_t" type (:type "class") nil nil)) nil [13130 14629]) ("mdd_print_support" function (:arguments (("f" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [14654 14663])) :type "void") nil [14631 15346]) ("mdd_print_support_to_file" function (:arguments (("fout" variable (:pointer 1 :type ("FILE" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [15379 15390]) ("format" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [15391 15404]) ("f" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [15405 15414])) :type "void") nil [15348 16090]) ("mdd_read_var_name" function (:pointer 1 :arguments (("f" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [16117 16126])) :type "char") nil [16092 16936]) ("mdd_read_mdd_id" function (:arguments (("f" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [16958 16967])) :type "int") nil [16938 17329]) ("mdd_id_to_bdd_id_array" function (:pointer 1 :arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [17728 17752]) ("mddId" variable (:type "int") (reparse-symbol arg-sub-list) [17753 17763])) :type ("array_t" type (:type "class") nil nil)) nil [17695 18166]) ("mdd_id_to_bdd_array" function (:pointer 1 :arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [18562 18586]) ("mddId" variable (:type "int") (reparse-symbol arg-sub-list) [18587 18597])) :type ("array_t" type (:type "class") nil nil)) nil [18532 18946]) ("mdd_id_array_to_bdd_array" function (:pointer 1 :arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [19268 19292]) ("mddIdArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [19293 19313])) :type ("array_t" type (:type "class") nil nil)) nil [19232 19770]) ("mdd_id_array_to_bdd_id_array" function (:pointer 1 :arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [20275 20299]) ("mddIdArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [20300 20320])) :type ("array_t" type (:type "class") nil nil)) nil [20236 20686]) ("mdd_id_array_to_bdd_cube" function (:pointer 1 :arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [20982 21006]) ("mddIdArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [21007 21027])) :type ("mdd_t" type (:type "class") nil nil)) nil [20949 21893]) ("mdd_get_number_of_bdd_vars" function (:arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [22249 22273]) ("mddIdArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [22274 22294])) :type "int") nil [22218 22592]) ("mdd_get_number_of_bdd_support" function (:arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [22929 22953]) ("f" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [22954 22963])) :type "int") nil [22895 23259]) ("mdd_fn_array_to_bdd_rel_array" function (:pointer 1 :arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [25589 25613]) ("mddId" variable (:type "int") (reparse-symbol arg-sub-list) [25616 25626]) ("mddFnArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [25629 25649])) :type ("array_t" type (:type "class") nil nil)) nil [25546 28912]) ("mdd_fn_array_to_bdd_fn_array" function (:pointer 1 :arguments (("mddManager" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [31241 31265]) ("mddId" variable (:type "int") (reparse-symbol arg-sub-list) [31268 31278]) ("mddFnArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [31281 31301])) :type ("array_t" type (:type "class") nil nil)) nil [31199 34504]) ("mdd_pick_arbitrary_minterms" function (:pointer 1 :arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [34548 34568]) ("aMdd" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [34571 34584]) ("mddIdArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [34587 34605]) ("n" variable (:type "int") (reparse-symbol arg-sub-list) [34608 34615])) :type ("array_t" type (:type "class") nil nil)) nil [34507 35385]) ("mdd_subset_with_mask_vars" function (:pointer 1 :arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [35425 35445]) ("aMdd" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [35448 35461]) ("mddIdArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [35464 35482]) ("maskIdArr" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [35485 35504])) :type ("mdd_t" type (:type "class") nil nil)) nil [35388 36344]) ("mdd_get_var_by_id" function (:arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [36453 36473]) ("id" variable (:type "int") (reparse-symbol arg-sub-list) [36474 36481])) :type ("mvar_type" type (:type "class") nil nil)) nil [36425 36524]) ("mdd_check_support" function (:arguments (("mddMgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [36628 36648]) ("mdd" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [36651 36663]) ("supportIdArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [36666 36690])) :type "int") nil [36603 37319]) ("mdd_equal_mod_care_set_array" function (:arguments (("aSet" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37359 37371]) ("bSet" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37372 37384]) ("careSetArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37385 37407])) :type ("boolean" type (:type "class") nil nil)) nil [37322 37816]) ("mdd_lequal_mod_care_set_array" function (:arguments (("aSet" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37857 37869]) ("bSet" variable (:pointer 1 :type ("mdd_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37870 37882]) ("aPhase" variable (:type ("boolean" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37892 37907]) ("bPhase" variable (:type ("boolean" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37908 37923]) ("careSetArray" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [37933 37955])) :type ("boolean" type (:type "class") nil nil)) nil [37819 38296]) ("mdd_range_mdd" function (:pointer 1 :arguments (("mgr" variable (:pointer 1 :type ("mdd_manager" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [38452 38469]) ("support" variable (:pointer 1 :type ("array_t" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [38472 38492])) :type ("mdd_t" type (:type "class") nil nil)) nil [38427 38859]))
+    :file "mdd_util.c"
+    :pointmax 39103
+    )
+   (semanticdb-table "mdd.h"
+    :major-mode 'c-mode
+    :tags 'nil
+    :file "mdd.h"
+    )
+   )
+  :file "semantic.cache"
+  :semantic-tag-version "2.0beta3"
+  :semanticdb-version "2.0beta3"
+  )
Index: /vis_dev/glu-2.1/src/mem/mem.3
===================================================================
--- /vis_dev/glu-2.1/src/mem/mem.3	(revision 8)
+++ /vis_dev/glu-2.1/src/mem/mem.3	(revision 8)
@@ -0,0 +1,174 @@
+.\" Storage management library man page
+.TH MEM 3 "16 November 1993"
+.SH NAME
+mem \- a memory management package
+.SH SYNOPSIS
+.B #include <memuser.h>
+.SH DESCRIPTION
+The
+.B libmem
+library provides a set of routines for allocating storage.  Programs
+designed to be used with the library should use the
+.B -lmem
+options to
+.B cc
+when linking.
+.SH "LIST OF FUNCTIONS"
+.nf
+.ta 3in
+\fIName\fP	\fIFunction\fP
+mem_get_block	Allocate a block of memory
+mem_free_block	Free a block of memory
+mem_resize_block	Resize a block of memory
+mem_copy	Copy a block of memory
+mem_zero	Initialize a block of memory to all zeros
+mem_allocation	Get total memory allocation
+mem_new_rec_mgr	Create a record manager
+mem_free_rec_mgr	Destroy a record manager
+mem_new_rec	Get a record from a record manager
+mem_free_rec	Return a record to a record manager
+.fi
+.SH "OVERVIEW"
+The library includes routines for handling blocks of memory and for
+dealing with fixed size records.  The block manipulation routines use
+a binary buddy scheme, so fragmentation generally is not a problem.
+The record manager routines are designed for handling many small,
+fixed size records.  There is essentially no storage overhead when
+using these routines, and allocation and deallocation are particularly
+fast.
+.SH "DETAILED DESCRIPTION"
+.B pointer
+.br
+.B mem_get_block(size)
+.br
+.B long size;
+.in +4
+Allocate a block of storage
+.B size
+bytes long.  The type
+.B pointer
+is defined to be either a character pointer or a void pointer,
+depending on whether the C compiler is ANSI-standard.
+.LP
+.B void
+.br
+.B mem_free_block(p)
+.br
+.B pointer p;
+.in +4
+Free the block of storage pointed to by \fBp\fR.
+.LP
+.B pointer
+.br
+.B mem_resize_block(p, size)
+.br
+.B pointer p;
+.br
+.B long size;
+.in +4
+Try to resize the block of memory pointed to by
+.B p
+to be
+.B size
+bytes long.  If this is not possible, a new block is allocated and the
+contents of the old block are copied.  A pointer to the expanded block
+is returned.
+.LP
+.B void
+.br
+.B mem_copy(p, q, size)
+.br
+.B pointer p;
+.br
+.B pointer q;
+.br
+.B long size;
+.in +4
+Copy
+.B size
+bytes from the location given by
+.B q
+to the location give by \fBp\fR.
+.LP
+.LP
+.B void
+.br
+.B mem_zero(p, size)
+.br
+.B pointer p;
+.br
+.B long size;
+.in +4
+Fill
+.B size
+bytes at the location given by
+.B p
+with zero.
+.LP
+.B long
+.br
+.B mem_allocation()
+.in +4
+Returns the total memory allocation in bytes.
+.LP
+.B rec_mgr
+.br
+.B mem_new_rec_mgr(size)
+.br
+.B int size;
+.in +4
+Returns a new record manager for handling record of
+.B size
+bytes.  The size is limited to approximately 4K, but is really
+intended to be smaller.
+.LP
+.B void
+.br
+.B mem_free_rec_mgr(m)
+.br
+.B rec_mgr m;
+.in +4
+Free the record manager given by
+.B m
+and all of its associated storage.
+.LP
+.B pointer
+.br
+.B mem_new_rec(m)
+.br
+.B rec_mgr m;
+.in +4
+Return a pointer to a new record.
+.LP
+.B void
+.br
+.B mem_free_rec(m, p)
+.br
+.B rec_mgr m;
+.br
+.B pointer p;
+.in +4
+Return the record pointed to by
+.B p
+to the record manager \fBm\fR.
+.SH "PORTABILITY NOTES"
+The library is fairly UNIX specific; it calls
+.B sbrk
+directly.  If you don't have something similar, you may have to
+rewrite parts of it.  The storage management routines need to be able
+to move and clear blocks of memory whose size is given by a long.  You
+may have to fiddle with these, especially if you have a machine where
+int and long are different.  If you encounter portability problems,
+let me know; maybe the next release will be able to accommodate your
+machine.  For non-UNIX people, or if you are using malloc elsewhere
+and it is unhappy about other routines calling sbrk, you can try
+defining the symbol USE_MALLOC_FREE in memint.h.  It turns calls to
+the memory management library routines into calls to malloc, free, and
+cousins.  This has not been tested extensively.
+.SH BUGS
+It's a feature.
+.SH AUTHOR
+David E. Long
+.br
+long@research.att.com
+
Index: /vis_dev/glu-2.1/src/mem/mem.make
===================================================================
--- /vis_dev/glu-2.1/src/mem/mem.make	(revision 8)
+++ /vis_dev/glu-2.1/src/mem/mem.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += memblock.c memrec.c
+HEADERS += memint.h memuser.h
+MISC += mem.3
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/mem/memblock.c
===================================================================
--- /vis_dev/glu-2.1/src/mem/memblock.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mem/memblock.c	(revision 8)
@@ -0,0 +1,487 @@
+/* Memory block management routines */
+
+
+#include "memint.h"
+
+
+#if STDC_HEADERS
+#  include <stdlib.h>
+#else
+#  if defined(__STDC__)
+extern void exit(int);
+#  else
+extern void exit();
+#  endif
+#endif
+
+
+/* Amount of memory allocated */
+
+static SIZE_T block_allocation;
+
+
+/* mem_copy(dest, src, size) copies a block of memory. */
+
+void
+#if defined(__STDC__)
+mem_copy(pointer dest, pointer src, SIZE_T size)
+#else
+mem_copy(dest, src, size)
+     pointer dest;
+     pointer src;
+     SIZE_T size;
+#endif
+{
+  MEM_COPY(dest, src, size);
+}
+
+
+/* mem_zero(ptr, size) zeros a block of memory. */
+
+void
+#if defined(__STDC__)
+mem_zero(pointer ptr, SIZE_T size)
+#else
+mem_zero(ptr, size)
+     pointer ptr;
+     SIZE_T size;
+#endif
+{
+  MEM_ZERO(ptr, size);
+}
+
+
+/* mem_fatal(message) prints an error message and exits. */
+
+void
+#if defined(__STDC__)
+mem_fatal(char *message)
+#else
+mem_fatal(message)
+     char *message;
+#endif
+{
+  fprintf(stderr, "Memory management library: error: %s\n", message);
+  exit(1);
+}
+
+
+SIZE_T
+#if defined(__STDC__)
+mem_allocation(void)
+#else
+mem_allocation()
+#endif
+{
+  /* This will always returns zero when we're using malloc and free, */
+  /* but you can maybe change it depending on your system. */
+  return (block_allocation);
+}
+
+
+/* This code used if we're going to do our own memory management. */
+
+#if !defined(USE_MALLOC_FREE)
+/* Free lists of various sizes */
+
+static block avail[MAX_SIZE_INDEX+1];
+
+
+/* Bogus segment for initialization */
+
+static struct segment_ dummy_seg={(pointer)0, (SIZE_T)0};
+
+
+/* Current segment */
+
+static segment curr_seg= &dummy_seg;
+
+
+static
+int
+#if defined(__STDC__)
+ceiling_log_2(SIZE_T i)
+#else
+ceiling_log_2(i)
+     SIZE_T i;
+#endif
+{
+  SIZE_T j;
+  int result;
+
+  for (result=0, j=1; j < i; ++result, j*=2);
+  return (result);
+}
+
+
+/* block_size_index(size) return the coded size for a block. */
+
+static
+int
+#if defined(__STDC__)
+block_size_index(SIZE_T size)
+#else
+block_size_index(size)
+     SIZE_T size;
+#endif
+{
+  if (size < 1)
+    return (-1);
+  if (size > MAX_SIZE)
+    mem_fatal("block_size_index: block size too large");
+  else
+    size+=HEADER_SIZE;
+  return (ceiling_log_2(size));
+}
+
+
+/* add_to_free_list(b) adds b to the appropriate free list. */
+
+static
+void
+#if defined(__STDC__)
+add_to_free_list(block b)
+#else
+add_to_free_list(b)
+     block b;
+#endif
+{
+  int i;
+
+  i=b->size_index;
+  if (!avail[i])
+    {
+      b->next=b;
+      b->prev=b;
+      avail[i]=b;
+    }
+  else
+    {
+      b->next=avail[i]->next;
+      avail[i]->next->prev=b;
+      avail[i]->next=b;
+      b->prev=avail[i];
+    }
+  b->used=0;
+}
+
+
+/* remove_from_free_list(b) removes b from the free list which it */
+/* is on. */
+
+static
+block
+#if defined(__STDC__)
+remove_from_free_list(block b)
+#else
+remove_from_free_list(b)
+     block b;
+#endif
+{
+  int i;
+
+  i=b->size_index;
+  if (b->next == b)
+    avail[i]=0;
+  else
+    {
+      b->next->prev=b->prev;
+      b->prev->next=b->next;
+      if (avail[i] == b)
+	avail[i]=b->next;
+    }
+  b->used=1;
+  return (b);
+}
+
+
+/* buddy(b) returns the buddy block of b, or null if there is no */
+/* buddy. */
+
+static
+block
+#if defined(__STDC__)
+buddy(block b)
+#else
+buddy(b)
+     block b;
+#endif
+{
+  SIZE_T buddy_offset;
+
+  buddy_offset=(SIZE_T)(((INT_PTR)b-(INT_PTR)b->seg->base_address) ^ ((SIZE_T)1 << b->size_index));
+  if (buddy_offset < b->seg->limit)
+    return ((block)((INT_PTR)b->seg->base_address+buddy_offset));
+  else
+    return ((block)0);
+}
+
+
+/* trim_to_size(b, size_index) repeatedly splits b until it has */
+/* the indicated size.  Blocks which are split off are added to the */
+/* appropriate free list. */
+
+static
+void
+#if defined(__STDC__)
+trim_to_size(block b, int size_index)
+#else
+trim_to_size(b, size_index)
+     block b;
+     int size_index;
+#endif
+{
+  block bb;
+
+  while (b->size_index > size_index)
+    {
+      b->size_index--;
+      bb=buddy(b);
+      bb->size_index=b->size_index;
+      bb->seg=b->seg;
+      add_to_free_list(bb);
+    }
+}
+
+
+/* merge_and_free(b) repeatedly merges b its buddy until b has no */
+/* buddy or the buddy isn't free, then adds the result to the */
+/* appropriate free list. */
+
+static
+void
+#if defined(__STDC__)
+merge_and_free(block b)
+#else
+merge_and_free(b)
+     block b;
+#endif
+{
+  block bb;
+
+  for (bb=buddy(b); bb && !bb->used && bb->size_index == b->size_index; bb=buddy(b))
+    {
+      remove_from_free_list(bb);
+      if ((INT_PTR)bb < (INT_PTR)b)
+	b=bb;
+      b->size_index++;
+    }
+  add_to_free_list(b);
+}
+
+
+/* mem_get_block(size) allocates a new block of the specified size. */
+
+pointer
+#if defined(__STDC__)
+mem_get_block(SIZE_T size)
+#else
+mem_get_block(size)
+     SIZE_T size;
+#endif
+{
+  int i;
+  int size_index;
+  int alloc_size_index;
+  int new_seg;
+  SIZE_T alloc_size;
+  pointer sbrk_ret;
+  block b;
+
+  if ((size_index=block_size_index(size)) < 0)
+    return ((pointer)0);
+  /* Find smallest free block which is large enough. */
+  for (i=size_index; i <= MAX_SIZE_INDEX && !avail[i]; ++i);
+  if (i > MAX_SIZE_INDEX)
+    {
+      /* We must get more storage; don't allocate less than */
+      /* 2^MIN_ALLOC_SIZE_INDEX. */
+      if (size_index < MIN_ALLOC_SIZE_INDEX)
+	alloc_size_index=MIN_ALLOC_SIZE_INDEX;
+      else
+	alloc_size_index=size_index;
+      alloc_size=((SIZE_T)1 << alloc_size_index);
+      /* Pad current segment to be a multiple of 2^alloc_size_index in */
+      /* length. */
+      alloc_size+=((curr_seg->limit+alloc_size-1) & ~(alloc_size-1))-curr_seg->limit;
+      if ((sbrk_ret=(pointer)SBRK(0)) != (pointer)((INT_PTR)curr_seg->base_address+curr_seg->limit) ||
+	  alloc_size+curr_seg->limit > MAX_SEG_SIZE)
+	{
+	  /* Segment is too large or someone else has moved the break. */
+	  /* Pad to get to appropriate boundary. */
+	  alloc_size=ROUNDUP((INT_PTR)sbrk_ret)-(INT_PTR)sbrk_ret;
+	  /* Pad allocation request with storage for new segment */
+	  /* information and indicate that a new segment must be */
+	  /* created. */
+	  alloc_size+=((SIZE_T)1 << alloc_size_index)+ROUNDUP(sizeof(struct segment_));
+	  new_seg=1;
+	}
+      else
+	new_seg=0;
+      sbrk_ret=(pointer)SBRK(alloc_size);
+      if (sbrk_ret == (pointer)-1)
+	mem_fatal("mem_get_block: allocation failed");
+      block_allocation+=alloc_size;
+      if (new_seg)
+	{
+	  curr_seg=(segment)ROUNDUP((INT_PTR)sbrk_ret);
+	  curr_seg->base_address=(pointer)((INT_PTR)curr_seg+ROUNDUP(sizeof(struct segment_)));
+	  curr_seg->limit=0;
+	  /* Readjust allocation size. */
+	  alloc_size=(1l << alloc_size_index);
+	}
+      /* Carve allocated space up into blocks and add to free lists. */
+      while (alloc_size)
+	{
+	  size=alloc_size-(alloc_size & (alloc_size-1));
+	  b=(block)((INT_PTR)curr_seg->base_address+curr_seg->limit);
+	  b->size_index=ceiling_log_2(size);
+	  b->seg=curr_seg;
+	  add_to_free_list(b);
+	  curr_seg->limit+=size;
+	  alloc_size-=size;
+	}
+      /* Find free block of appropriate size. */
+      for (i=size_index; i <= MAX_SIZE_INDEX && !avail[i]; ++i);
+    }
+  b=remove_from_free_list(avail[i]);
+  trim_to_size(b, size_index);
+  return ((pointer)((INT_PTR)b+HEADER_SIZE));
+}
+
+
+/* mem_free_block(p) frees the block indicated by p. */
+
+void
+#if defined(__STDC__)
+mem_free_block(pointer p)
+#else
+mem_free_block(p)
+     pointer p;
+#endif
+{
+  block b;
+
+  if (!p)
+    return;
+  b=(block)((INT_PTR)p-HEADER_SIZE);
+  if (!b->used)
+    mem_fatal("mem_free_block: block not in use");
+  if (b->size_index < 0 || b->size_index > MAX_SIZE_INDEX)
+    mem_fatal("mem_free_block: invalid block header");
+  merge_and_free(b);
+}
+
+
+/* mem_resize_block(p, new_size) expands or contracts the block */
+/* indicated by p to a new size.  We try to avoid moving the block if */
+/* possible. */
+
+pointer
+#if defined(__STDC__)
+mem_resize_block(pointer p, SIZE_T new_size)
+#else
+mem_resize_block(p, new_size)
+     pointer p;
+     SIZE_T new_size;
+#endif
+{
+  int new_size_index;
+  block b;
+  block bb;
+  pointer q;
+  SIZE_T old_size;
+
+  if (!p)
+    return (mem_get_block(new_size));
+  b=(block)((INT_PTR)p-HEADER_SIZE);
+  if (!b->used)
+    mem_fatal("mem_resize_block: block not in use");
+  if (b->size_index < 0 || b->size_index > MAX_SIZE_INDEX)
+    mem_fatal("mem_resize_block: invalid block header");
+  if ((new_size_index=block_size_index(new_size)) < 0)
+    {
+      mem_free_block(p);
+      return ((pointer)0);
+    }
+  if (b->size_index >= new_size_index)
+    {
+      /* Shrink block. */
+      trim_to_size(b, new_size_index);
+      return (p);
+    }
+  old_size=(1l << b->size_index)-HEADER_SIZE;
+  /* Try to expand by adding buddies at higher addresses. */
+  for (bb=buddy(b);
+       bb && (INT_PTR)b < (INT_PTR)bb && !bb->used && bb->size_index == b->size_index;
+       bb=buddy(b))
+    {
+      remove_from_free_list(bb);
+      if (++(b->size_index) == new_size_index)
+	return (p);
+    }
+  /* Couldn't expand all the way to needed size; allocate a new block */
+  /* and move the contents of the old one. */
+  q=mem_get_block(new_size);
+  mem_copy(q, p, old_size);
+  merge_and_free(b);
+  return (q);
+}
+#endif
+
+
+/* This code used if we're using malloc and free. */
+
+#if defined(USE_MALLOC_FREE)
+pointer
+#if defined(__STDC__)
+mem_get_block(SIZE_T size)
+#else
+mem_get_block(size)
+     SIZE_T size;
+#endif
+{
+  pointer result;
+
+  if (size <= 0)
+    return ((pointer)0);
+  result=MALLOC(size);
+  if (!result)
+    mem_fatal("mem_get_block: allocation failed");
+  return (result);
+}
+
+
+void
+#if defined(__STDC__)
+mem_free_block(pointer p)
+#else
+mem_free_block(p)
+     pointer p;
+#endif
+{
+  if (!p)
+    return;
+  FREE(p);
+}
+
+
+pointer
+#if defined(__STDC__)
+mem_resize_block(pointer p, SIZE_T new_size)
+#else
+mem_resize_block(p, new_size)
+     pointer p;
+     SIZE_T new_size;
+#endif
+{
+  if (!p)
+    return (mem_get_block(new_size));
+  if (new_size <= 0)
+    {
+      mem_free_block(p);
+      return ((pointer)0);
+    }
+  return (REALLOC(p, new_size));
+}
+#endif
Index: /vis_dev/glu-2.1/src/mem/memint.h
===================================================================
--- /vis_dev/glu-2.1/src/mem/memint.h	(revision 8)
+++ /vis_dev/glu-2.1/src/mem/memint.h	(revision 8)
@@ -0,0 +1,126 @@
+/* Memory management internal definitions */
+
+
+#if !defined(_MEMINTH)
+#define _MEMINTH
+
+
+/* All user-visible stuff */
+
+#include "memuser.h"
+
+
+/* >>> Potentially system dependent configuration stuff */
+/* See memuser.h as well. */
+
+/* The storage management library can either use system-provided */
+/* versions of malloc, free and friends, or it can implement a buddy */
+/* scheme based on something like sbrk.  If you want to do the former, */
+/* define USE_MALLOC_FREE. */
+
+/* #define USE_MALLOC_FREE */
+
+/* Now we need macros for routines to copy and zero-fill blocks of */
+/* memory, and to either do malloc/free/whatever or to do an sbrk.  Since */
+/* different systems have different types that these routines expect, we */
+/* wrap everything in macros. */
+
+#if defined(USE_MALLOC_FREE)
+#if defined(__STDC__)
+extern void *malloc(unsigned long);
+extern void free(void *);
+extern void *realloc(void *, unsigned long);
+#define MALLOC(size) ((pointer)malloc((unsigned long)(size)))
+#define FREE(p) (free((void *)(p)))
+#define REALLOC(p, size) ((pointer)realloc((void *)(p), (unsigned long)(size)))
+#else
+extern char *malloc();
+extern void free();
+extern char *realloc();
+#define MALLOC(size) ((pointer)malloc((int)(size)))
+#define FREE(p) (free((char *)(p)))
+#define REALLOC(p, size) ((pointer)realloc((char *)(p), (int)(size)))
+#endif
+#else
+#if defined(__STDC__)
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#else
+extern char *sbrk(int);
+#endif
+#define SBRK(size) ((pointer)sbrk((int)(size)))
+#else
+extern char *sbrk();
+#define SBRK(size) ((pointer)sbrk((int)(size)))
+#endif
+#endif
+
+/* You may need to muck with these depending on whether you have */
+/* bcopy or memcpy. */
+
+#if defined(__STDC__)
+#if STDC_HEADERS
+#include <string.h>
+#else
+extern void *memcpy(); /* TRS, 6/17/94: removed arg types to suppress warning on mips/gcc */
+/* extern void *memcpy(void *, const void *, unsigned long); */
+
+extern void *memset(); /* SPK 3/01/01: removed arg types to suppress
+			  warning on linux-rh-6.2/egcs-2.91/66 */
+/* extern void *memset(void *, int, unsigned long); */
+#endif
+#define MEM_COPY(dest, src, size) (void)memcpy((void *)(dest), (const void *)(src), (unsigned long)(size))
+#define MEM_ZERO(ptr, size) (void)memset((void *)(ptr), 0, (unsigned long)(size))
+#else
+extern void bcopy();
+extern void bzero();
+#define MEM_COPY(dest, src, size) bcopy((char *)(src), (char *)(dest), (int)(size))
+#define MEM_ZERO(ptr, size) bzero((char *)(ptr), (int)(size))
+#endif
+
+
+#if defined(__STDC__)
+#define ARGS(args) args
+#else
+#define ARGS(args) ()
+#endif
+
+
+/* >>> System independent stuff here. */
+
+struct segment_
+{
+  pointer base_address;
+  SIZE_T limit;
+};
+
+typedef struct segment_ *segment;
+
+
+struct block_
+{
+  int used;
+  int size_index;
+  struct block_ *next;
+  struct block_ *prev;
+  segment seg;
+};
+
+typedef struct block_ *block;
+
+
+#define HEADER_SIZE ((SIZE_T)ROUNDUP(sizeof(struct block_)))
+#define MAX_SIZE_INDEX (8*sizeof(SIZE_T)-2)
+#define MAX_SEG_SIZE ((SIZE_T)1 << MAX_SIZE_INDEX)
+#define MAX_SIZE ((SIZE_T)(MAX_SEG_SIZE-HEADER_SIZE))
+#define MIN_ALLOC_SIZE_INDEX 15
+
+#define NICE_BLOCK_SIZE ((SIZE_T)4096-ROUNDUP(sizeof(struct block_)))
+
+
+extern void mem_fatal ARGS((char *));
+
+
+#undef ARGS
+
+#endif
Index: /vis_dev/glu-2.1/src/mem/memrec.c
===================================================================
--- /vis_dev/glu-2.1/src/mem/memrec.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mem/memrec.c	(revision 8)
@@ -0,0 +1,156 @@
+/* Record manager routines */
+
+
+#include "memint.h"
+
+
+#define ALLOC_SIZE NICE_BLOCK_SIZE
+
+
+/* #define DEBUG_MEM */
+#define MAGIC_COOKIE 0x34f21ab3l
+#define MAGIC_COOKIE1 0x432fa13bl
+
+
+struct list_
+{
+  struct list_ *next;
+};
+
+typedef struct list_ *list;
+
+
+struct rec_mgr_
+{
+  int size;
+  int recs_per_block;
+  list free;
+  list blocks;
+};
+
+
+/* mem_new_rec(mgr) allocates a record from the specified record */
+/* manager. */
+
+pointer
+#if defined(__STDC__)
+mem_new_rec(rec_mgr mgr)
+#else
+mem_new_rec(mgr)
+     rec_mgr mgr;
+#endif
+{
+  int i;
+  pointer p;
+  list new_;
+
+  if (!mgr->free)
+    {
+      /* Allocate a new block. */
+      new_=(list)mem_get_block(ALLOC_SIZE);
+      new_->next=mgr->blocks;
+      mgr->blocks=new_;
+      mgr->free=(list)((INT_PTR)new_+ROUNDUP(sizeof(struct list_)));
+      p=(pointer)(mgr->free);
+      /* Carve the block into pieces. */
+      for (i=1; i < mgr->recs_per_block; ++i)
+	{
+	  ((list)p)->next=(list)((INT_PTR)p+mgr->size);
+#if defined(DEBUG_MEM)
+	  if (mgr->size >= sizeof(long)+sizeof(struct list_))
+	    *(long *)(sizeof(struct list_)+(INT_PTR)p)=MAGIC_COOKIE;
+#endif
+	  p=(pointer)((INT_PTR)p+mgr->size);
+	}
+      ((list)p)->next=0;
+#if defined(DEBUG_MEM)
+      if (mgr->size >= sizeof(long)+sizeof(struct list_))
+	*(long *)(sizeof(struct list_)+(INT_PTR)p)=MAGIC_COOKIE;
+#endif
+    }
+  new_=mgr->free;
+#if defined(DEBUG_MEM)
+  if (mgr->size >= sizeof(long)+sizeof(struct list_))
+    if (*(long *)(sizeof(struct list_)+(INT_PTR)new_) != MAGIC_COOKIE)
+      fprintf(stderr, "record at 0x%lx may be in use\n", (INT_PTR)new_);
+    else
+      *(long *)(sizeof(struct list_)+(INT_PTR)new_)=MAGIC_COOKIE1;
+#endif
+  mgr->free=mgr->free->next;
+  return ((pointer)new_);
+}
+
+
+/* mem_free_rec(mgr, rec) frees a record managed by the indicated */
+/* record manager. */
+
+void
+#if defined(__STDC__)
+mem_free_rec(rec_mgr mgr, pointer rec)
+#else
+mem_free_rec(mgr, rec)
+     rec_mgr mgr;
+     pointer rec;
+#endif
+{
+#if defined(DEBUG_MEM)
+  if (mgr->size >= sizeof(long)+sizeof(struct list_))
+    if (*(long *)(sizeof(struct list_)+(INT_PTR)rec) == MAGIC_COOKIE)
+      fprintf(stderr, "record at 0x%lx may already be freed\n", (INT_PTR)rec);
+#endif
+  ((list)rec)->next=mgr->free;
+#if defined(DEBUG_MEM)
+  if (mgr->size >= sizeof(long)+sizeof(struct list_))
+    *(long *)(sizeof(struct list_)+(INT_PTR)rec)=MAGIC_COOKIE;
+#endif
+  mgr->free=(list)rec;
+}
+
+
+/* mem_new_rec_mgr(size) creates a new record manager with the given */
+/* record size. */
+
+rec_mgr
+#if defined(__STDC__)
+mem_new_rec_mgr(int size)
+#else
+mem_new_rec_mgr(size)
+     int size;
+#endif
+{
+  rec_mgr mgr;
+
+  if (size < sizeof(struct list_))
+    size=sizeof(struct list_);
+  size=ROUNDUP(size);
+  if (size > ALLOC_SIZE-ROUNDUP(sizeof(struct list_)))
+    mem_fatal("mem_new_rec_mgr: record size too large");
+  mgr=(rec_mgr)mem_get_block((SIZE_T)sizeof(struct rec_mgr_));
+  mgr->size=size;
+  mgr->recs_per_block=(ALLOC_SIZE-ROUNDUP(sizeof(struct list_)))/size;
+  mgr->free=0;
+  mgr->blocks=0;
+  return (mgr);
+}
+
+
+/* mem_free_rec_mgr(mgr) frees all the storage associated with the */
+/* specified record manager. */
+
+void
+#if defined(__STDC__)
+mem_free_rec_mgr(rec_mgr mgr)
+#else
+mem_free_rec_mgr(mgr)
+     rec_mgr mgr;
+#endif
+{
+  list p, q;
+
+  for (p=mgr->blocks; p; p=q)
+    {
+      q=p->next;
+      mem_free_block((pointer)p);
+    }
+  mem_free_block((pointer)mgr);
+}
Index: /vis_dev/glu-2.1/src/mem/memuser.h
===================================================================
--- /vis_dev/glu-2.1/src/mem/memuser.h	(revision 8)
+++ /vis_dev/glu-2.1/src/mem/memuser.h	(revision 8)
@@ -0,0 +1,89 @@
+/*
+ * $Id: memuser.h,v 1.3 2002/08/27 15:47:48 fabio Exp $
+ *
+ */
+
+/* Memory management user-visible definitions */
+
+
+#if !defined(_MEMUSERH)
+#define _MEMUSERH
+
+#ifndef ARGS
+#  ifdef __STDC__
+#    define ARGS(args)	args
+#  else
+#    define ARGS(args)  ()
+#  endif
+#endif
+
+#ifdef __cplusplus
+#  define EXTERN	extern "C"
+#else
+#  define EXTERN	extern
+#endif
+
+#include <stdio.h>
+
+
+
+/* >>> Potentially machine dependent stuff */
+/* See memint.h as well. */
+
+typedef unsigned long INT_PTR;	/* Integral type that can hold a pointer */
+typedef unsigned long SIZE_T;	/* Integral type that can hold the maximum */
+				/* size of an object */
+
+/* REQUIRED_ALIGNMENT is the alignment required by the machine hardware; */
+/* it is provided for user use. */
+
+#define REQUIRED_ALIGNMENT 4
+
+
+/* Types */
+
+#if defined(__STDC__)
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+
+typedef struct rec_mgr_ *rec_mgr;
+
+
+/* ALLOC_ALIGNMENT is the alignment for all storage returned by the */
+/* storage allocation routines. */
+
+#define ALLOC_ALIGNMENT 8
+
+
+/* Round a size up for alignment */
+
+#define ROUNDUP(size) ((((size)+ALLOC_ALIGNMENT-1)/ALLOC_ALIGNMENT)*ALLOC_ALIGNMENT)
+#define ALIGN(size) ((((size)+REQUIRED_ALIGNMENT-1)/REQUIRED_ALIGNMENT)*REQUIRED_ALIGNMENT)
+
+
+/* Block storage management routines */
+
+EXTERN pointer mem_get_block ARGS((SIZE_T));
+EXTERN void mem_free_block ARGS((pointer));
+EXTERN pointer mem_resize_block ARGS((pointer, SIZE_T));
+EXTERN void mem_copy ARGS((pointer, pointer, SIZE_T));
+EXTERN void mem_zero ARGS((pointer, SIZE_T));
+EXTERN void mem_fatal ARGS((char *));
+EXTERN SIZE_T mem_allocation ARGS((void));
+
+
+/* Record manager routines */
+
+EXTERN pointer mem_new_rec ARGS((rec_mgr));
+EXTERN void mem_free_rec ARGS((rec_mgr, pointer));
+EXTERN rec_mgr mem_new_rec_mgr ARGS((int));
+EXTERN void mem_free_rec_mgr ARGS((rec_mgr));
+
+
+#undef ARGS
+#undef EXTERN
+
+#endif
Index: /vis_dev/glu-2.1/src/mtr/mtr.h
===================================================================
--- /vis_dev/glu-2.1/src/mtr/mtr.h	(revision 8)
+++ /vis_dev/glu-2.1/src/mtr/mtr.h	(revision 8)
@@ -0,0 +1,191 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mtr.h]
+
+  PackageName [mtr]
+
+  Synopsis    [Multiway-branch tree manipulation]
+
+  Description [This package provides two layers of functions. Functions
+  of the lower level manipulate multiway-branch trees, implemented
+  according to the classical scheme whereby each node points to its
+  first child and its previous and next siblings. These functions are
+  collected in mtrBasic.c.<p>
+  Functions of the upper layer deal with group trees, that is the trees
+  used by group sifting to represent the grouping of variables. These
+  functions are collected in mtrGroup.c.]
+
+  SeeAlso     [The CUDD package documentation; specifically on group
+  sifting.]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: mtr.h,v 1.13 2004/08/13 18:15:11 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef __MTR
+#define __MTR
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef SIZEOF_VOID_P
+#define SIZEOF_VOID_P 4
+#endif
+#ifndef SIZEOF_INT
+#define SIZEOF_INT 4
+#endif
+
+#undef CONST
+#if defined(__STDC__) || defined(__cplusplus)
+#define CONST           const
+#else /* !(__STDC__ || __cplusplus) */
+#define CONST
+#endif /* !(__STDC__ || __cplusplus) */
+
+#if defined(__GNUC__)
+#define MTR_INLINE __inline__
+# if (__GNUC__ >2 || __GNUC_MINOR__ >=7)
+#   define MTR_UNUSED __attribute__ ((unused))
+# else
+#   define MTR_UNUSED
+# endif
+#else
+#define MTR_INLINE
+#define MTR_UNUSED
+#endif
+ 
+/* Flag definitions */
+#define MTR_DEFAULT	0x00000000
+#define MTR_TERMINAL 	0x00000001
+#define MTR_SOFT	0x00000002
+#define MTR_FIXED	0x00000004
+#define MTR_NEWNODE	0x00000008
+
+/* MTR_MAXHIGH is defined in such a way that on 32-bit and 64-bit
+** machines one can cast a value to (int) without generating a negative
+** number.
+*/
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+#define MTR_MAXHIGH	(((MtrHalfWord) ~0) >> 1)
+#else
+#define MTR_MAXHIGH	((MtrHalfWord) ~0)
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
+typedef unsigned int   MtrHalfWord;
+#else
+typedef unsigned short MtrHalfWord;
+#endif
+
+typedef struct MtrNode {
+    MtrHalfWord flags;
+    MtrHalfWord low;
+    MtrHalfWord size;
+    MtrHalfWord index;
+    struct MtrNode *parent;
+    struct MtrNode *child;
+    struct MtrNode *elder;
+    struct MtrNode *younger;
+} MtrNode;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/* Flag manipulation macros */
+#define MTR_SET(node, flag)		(node->flags |= (flag))
+#define MTR_RESET(node, flag)	(node->flags &= ~ (flag))
+#define MTR_TEST(node, flag)	(node->flags & (flag))
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern MtrNode * Mtr_AllocNode (void);
+extern void Mtr_DeallocNode (MtrNode *node);
+extern MtrNode * Mtr_InitTree (void);
+extern void Mtr_FreeTree (MtrNode *node);
+extern MtrNode * Mtr_CopyTree (MtrNode *node, int expansion);
+extern void Mtr_MakeFirstChild (MtrNode *parent, MtrNode *child);
+extern void Mtr_MakeLastChild (MtrNode *parent, MtrNode *child);
+extern MtrNode * Mtr_CreateFirstChild (MtrNode *parent);
+extern MtrNode * Mtr_CreateLastChild (MtrNode *parent);
+extern void Mtr_MakeNextSibling (MtrNode *first, MtrNode *second);
+extern void Mtr_PrintTree (MtrNode *node);
+extern MtrNode * Mtr_InitGroupTree (int lower, int size);
+extern MtrNode * Mtr_MakeGroup (MtrNode *root, unsigned int low, unsigned int high, unsigned int flags);
+extern MtrNode * Mtr_DissolveGroup (MtrNode *group);
+extern MtrNode * Mtr_FindGroup (MtrNode *root, unsigned int low, unsigned int high);
+extern int Mtr_SwapGroups (MtrNode *first, MtrNode *second);
+extern void Mtr_PrintGroups (MtrNode *root, int silent);
+extern MtrNode * Mtr_ReadGroups (FILE *fp, int nleaves);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MTR */
Index: /vis_dev/glu-2.1/src/mtr/mtr.make
===================================================================
--- /vis_dev/glu-2.1/src/mtr/mtr.make	(revision 8)
+++ /vis_dev/glu-2.1/src/mtr/mtr.make	(revision 8)
@@ -0,0 +1,4 @@
+CSRC += mtrBasic.c mtrGroup.c
+HEADERS += mtr.h mtrInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/mtr/mtrBasic.c
===================================================================
--- /vis_dev/glu-2.1/src/mtr/mtrBasic.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mtr/mtrBasic.c	(revision 8)
@@ -0,0 +1,451 @@
+/**CFile***********************************************************************
+
+  FileName    [mtrBasic.c]
+
+  PackageName [mtr]
+
+  Synopsis    [Basic manipulation of multiway branching trees.]
+
+  Description [External procedures included in this module:
+	    <ul>
+	    <li> Mtr_AllocNode()
+	    <li> Mtr_DeallocNode()
+	    <li> Mtr_InitTree()
+	    <li> Mtr_FreeTree()
+	    <li> Mtr_CopyTree()
+	    <li> Mtr_MakeFirstChild()
+	    <li> Mtr_MakeLastChild()
+	    <li> Mtr_CreateFirstChild()
+	    <li> Mtr_CreateLastChild()
+	    <li> Mtr_MakeNextSibling()
+	    <li> Mtr_PrintTree()
+	    </ul>
+	    ]
+
+  SeeAlso     [cudd package]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "mtrInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] MTR_UNUSED = "$Id: mtrBasic.c,v 1.12 2004/08/13 18:15:11 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates new tree node.]
+
+  Description [Allocates new tree node. Returns pointer to node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_DeallocNode]
+
+******************************************************************************/
+MtrNode *
+Mtr_AllocNode(void)
+{
+    MtrNode *node;
+
+    node = ALLOC(MtrNode,1);
+    return node;
+
+} /* Mtr_AllocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deallocates tree node.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_AllocNode]
+
+******************************************************************************/
+void
+Mtr_DeallocNode(
+  MtrNode * node /* node to be deallocated */)
+{
+    FREE(node);
+    return;
+
+} /* end of Mtr_DeallocNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes tree with one node.]
+
+  Description [Initializes tree with one node. Returns pointer to node.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_FreeTree Mtr_InitGroupTree]
+
+******************************************************************************/
+MtrNode *
+Mtr_InitTree(void)
+{
+    MtrNode *node;
+
+    node = Mtr_AllocNode();
+    if (node == NULL) return(NULL);
+
+    node->parent = node->child = node->elder = node->younger = NULL;
+    node->flags = 0;
+
+    return(node);
+
+} /* end of Mtr_InitTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Disposes of tree rooted at node.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitTree]
+
+******************************************************************************/
+void
+Mtr_FreeTree(
+  MtrNode * node)
+{
+    if (node == NULL) return;
+    if (! MTR_TEST(node,MTR_TERMINAL)) Mtr_FreeTree(node->child);
+    Mtr_FreeTree(node->younger);
+    Mtr_DeallocNode(node);
+    return;
+
+} /* end of Mtr_FreeTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a copy of tree.]
+
+  Description [Makes a copy of tree. If parameter expansion is greater
+  than 1, it will expand the tree by that factor. It is an error for
+  expansion to be less than 1. Returns a pointer to the copy if
+  successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitTree]
+
+******************************************************************************/
+MtrNode *
+Mtr_CopyTree(
+  MtrNode * node,
+  int  expansion)
+{
+    MtrNode *copy;
+
+    if (node == NULL) return(NULL);
+    if (expansion < 1) return(NULL);
+    copy = Mtr_AllocNode();
+    if (copy == NULL) return(NULL);
+    copy->parent = copy->elder = copy->child = copy->younger = NULL;
+    if (node->child != NULL) {
+	copy->child = Mtr_CopyTree(node->child, expansion);
+	if (copy->child == NULL) {
+	    Mtr_DeallocNode(copy);
+	    return(NULL);
+	}
+    }
+    if (node->younger != NULL) {
+	copy->younger = Mtr_CopyTree(node->younger, expansion);
+	if (copy->younger == NULL) {
+	    Mtr_FreeTree(copy);
+	    return(NULL);
+	}
+    }
+    copy->flags = node->flags;
+    copy->low = node->low * expansion;
+    copy->size = node->size * expansion;
+    copy->index = node->index * expansion;
+    if (copy->younger) copy->younger->elder = copy;
+    if (copy->child) {
+	MtrNode *auxnode = copy->child;
+	while (auxnode != NULL) {
+	    auxnode->parent = copy;
+	    auxnode = auxnode->younger;
+	}
+    }
+    return(copy);
+    
+} /* end of Mtr_CopyTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes child the first child of parent.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeLastChild Mtr_CreateFirstChild]
+
+******************************************************************************/
+void
+Mtr_MakeFirstChild(
+  MtrNode * parent,
+  MtrNode * child)
+{
+    child->parent = parent;
+    child->younger = parent->child;
+    child->elder = NULL;
+    if (parent->child != NULL) {
+#ifdef MTR_DEBUG
+	assert(parent->child->elder == NULL);
+#endif
+	parent->child->elder = child;
+    }
+    parent->child = child;
+    return;
+
+} /* end of Mtr_MakeFirstChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes child the last child of parent.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeFirstChild Mtr_CreateLastChild]
+
+******************************************************************************/
+void
+Mtr_MakeLastChild(
+  MtrNode * parent,
+  MtrNode * child)
+{
+    MtrNode *node;
+
+    child->younger = NULL;
+
+    if (parent->child == NULL) {
+	parent->child = child;
+	child->elder = NULL;
+    } else {
+	for (node = parent->child;
+	     node->younger != NULL;
+	     node = node->younger);
+	node->younger = child;
+	child->elder = node;
+    }
+    child->parent = parent;
+    return;
+
+} /* end of Mtr_MakeLastChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new node and makes it the first child of parent.]
+
+  Description [Creates a new node and makes it the first child of
+  parent. Returns pointer to new child.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeFirstChild Mtr_CreateLastChild]
+
+******************************************************************************/
+MtrNode *
+Mtr_CreateFirstChild(
+  MtrNode * parent)
+{
+    MtrNode *child;
+
+    child = Mtr_AllocNode();
+    if (child == NULL) return(NULL);
+
+    child->child = child->younger = child-> elder = NULL;
+    child->flags = 0;
+    Mtr_MakeFirstChild(parent,child);
+    return(child);
+
+} /* end of Mtr_CreateFirstChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new node and makes it the last child of parent.]
+
+  Description [Creates a new node and makes it the last child of parent.
+  Returns pointer to new child.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeLastChild Mtr_CreateFirstChild]
+
+******************************************************************************/
+MtrNode *
+Mtr_CreateLastChild(
+  MtrNode * parent)
+{
+    MtrNode *child;
+
+    child = Mtr_AllocNode();
+    if (child == NULL) return(NULL);
+
+    child->child = child->younger = child->elder = NULL;
+    child->flags = 0;
+    Mtr_MakeLastChild(parent,child);
+    return(child);
+
+} /* end of Mtr_CreateLastChild */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes second the next sibling of first.]
+
+  Description [Makes second the next sibling of first. Second becomes a
+  child of the parent of first.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Mtr_MakeNextSibling(
+  MtrNode * first,
+  MtrNode * second)
+{
+    second->younger = first->younger;
+    if (first->younger != NULL) {
+	first->younger->elder = second;
+    }
+    second->parent = first->parent;
+    first->younger = second;
+    second->elder = first;
+    return;
+
+} /* end of Mtr_MakeNextSibling */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a tree, one node per line.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_PrintGroups]
+
+******************************************************************************/
+void
+Mtr_PrintTree(
+  MtrNode * node)
+{
+    if (node == NULL) return;
+    (void) fprintf(stdout,
+#if SIZEOF_VOID_P == 8
+    "N=0x%-8lx C=0x%-8lx Y=0x%-8lx E=0x%-8lx P=0x%-8lx F=%x L=%d S=%d\n",
+    (unsigned long) node, (unsigned long) node->child,
+    (unsigned long) node->younger, (unsigned long) node->elder,
+    (unsigned long) node->parent, node->flags, node->low, node->size);
+#else
+    "N=0x%-8x C=0x%-8x Y=0x%-8x E=0x%-8x P=0x%-8x F=%x L=%d S=%d\n",
+    (unsigned) node, (unsigned) node->child,
+    (unsigned) node->younger, (unsigned) node->elder,
+    (unsigned) node->parent, node->flags, node->low, node->size);
+#endif
+    if (!MTR_TEST(node,MTR_TERMINAL)) Mtr_PrintTree(node->child);
+    Mtr_PrintTree(node->younger);
+    return;
+
+} /* end of Mtr_PrintTree */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: /vis_dev/glu-2.1/src/mtr/mtrGroup.c
===================================================================
--- /vis_dev/glu-2.1/src/mtr/mtrGroup.c	(revision 8)
+++ /vis_dev/glu-2.1/src/mtr/mtrGroup.c	(revision 8)
@@ -0,0 +1,716 @@
+/**CFile***********************************************************************
+
+  FileName    [mtrGroup.c]
+
+  PackageName [mtr]
+
+  Synopsis    [Functions to support group specification for reordering.]
+
+  Description [External procedures included in this module:
+	    <ul>
+	    <li> Mtr_InitGroupTree()
+	    <li> Mtr_MakeGroup()
+	    <li> Mtr_DissolveGroup()
+	    <li> Mtr_FindGroup()
+	    <li> Mtr_SwapGroups()
+	    <li> Mtr_PrintGroups()
+	    <li> Mtr_ReadGroups()
+	    </ul>
+	Static procedures included in this module:
+	    <ul>
+	    <li> mtrShiftHL
+	    </ul>
+	    ]
+
+  SeeAlso     [cudd package]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+******************************************************************************/
+
+#include "util.h"
+#include "mtrInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.16 2004/08/13 18:15:11 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int mtrShiftHL (MtrNode *node, int shift);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate new tree.]
+
+  Description [Allocate new tree with one node, whose low and size
+  fields are specified by the lower and size parameters.
+  Returns pointer to tree root.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitTree Mtr_FreeTree]
+
+******************************************************************************/
+MtrNode *
+Mtr_InitGroupTree(
+  int  lower,
+  int  size)
+{
+    MtrNode *root;
+
+    root = Mtr_InitTree();
+    if (root == NULL) return(NULL);
+    root->flags = MTR_DEFAULT;
+    root->low = lower;
+    root->size = size;
+    return(root);
+
+} /* end of Mtr_InitGroupTree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a new group with size leaves starting at low.]
+
+  Description [Makes a new group with size leaves starting at low.
+  If the new group intersects an existing group, it must
+  either contain it or be contained by it.  This procedure relies on
+  the low and size fields of each node. It also assumes that the
+  children of each node are sorted in order of increasing low.  In
+  case of a valid request, the flags of the new group are set to the
+  value passed in `flags.' This can also be used to change the flags
+  of an existing group.  Returns the pointer to the root of the new
+  group upon successful termination; NULL otherwise. If the group
+  already exists, the pointer to its root is returned.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup]
+
+******************************************************************************/
+MtrNode *
+Mtr_MakeGroup(
+  MtrNode * root /* root of the group tree */,
+  unsigned int  low /* lower bound of the group */,
+  unsigned int  size /* upper bound of the group */,
+  unsigned int  flags /* flags for the new group */)
+{
+    MtrNode *node,
+	    *first,
+	    *last,
+	    *previous,
+	    *newn;
+
+    /* Sanity check. */
+    if (size == 0)
+	return(NULL);
+
+    /* Check whether current group includes new group.  This check is
+    ** necessary at the top-level call.  In the subsequent calls it is
+    ** redundant. */
+    if (low < (unsigned int) root->low ||
+	low + size > (unsigned int) (root->low + root->size))
+	return(NULL);
+
+    /* Trying to create an existing group has the effect of updating
+    ** the flags. */
+    if (root->size == size && root->low == low) {
+	root->flags = flags;
+	return(root);
+    }
+
+    /* At this point we know that the new group is properly contained
+    ** in the group of root. We have two possible cases here: - root
+    ** is a terminal node; - root has children. */
+
+    /* Root has no children: create a new group. */
+    if (root->child == NULL) {
+	newn = Mtr_AllocNode();
+	if (newn == NULL) return(NULL);	/* out of memory */
+	newn->low = low;
+	newn->size = size;
+	newn->flags = flags;
+	newn->parent = root;
+	newn->elder = newn->younger = newn->child = NULL;
+	root->child = newn;
+	return(newn);
+    }
+
+    /* Root has children: Find all chidren of root that are included
+    ** in the new group. If the group of any child entirely contains
+    ** the new group, call Mtr_MakeGroup recursively. */
+    previous = NULL;
+    first = root->child; /* guaranteed to be non-NULL */
+    while (first != NULL && low >= (unsigned int) (first->low + first->size)) {
+	previous = first;
+	first = first->younger;
+    }
+    if (first == NULL) {
+	/* We have scanned the entire list and we need to append a new
+	** child at the end of it.  Previous points to the last child
+	** of root. */
+	newn = Mtr_AllocNode();
+	if (newn == NULL) return(NULL);	/* out of memory */
+	newn->low = low;
+	newn->size = size;
+	newn->flags = flags;
+	newn->parent = root;
+	newn->elder = previous;
+	previous->younger = newn;
+	newn->younger = newn->child = NULL;
+	return(newn);
+    }
+    /* Here first is non-NULL and low < first->low + first->size. */
+    if (low >= (unsigned int) first->low &&
+	low + size <= (unsigned int) (first->low + first->size)) {
+	/* The new group is contained in the group of first. */
+	newn = Mtr_MakeGroup(first, low, size, flags);
+	return(newn);
+    } else if (low + size <= first->low) {
+	/* The new group is entirely contained in the gap between
+	** previous and first. */
+	newn = Mtr_AllocNode();
+	if (newn == NULL) return(NULL);	/* out of memory */
+	newn->low = low;
+	newn->size = size;
+	newn->flags = flags;
+	newn->child = NULL;
+	newn->parent = root;
+	newn->elder = previous;
+	newn->younger = first;
+	first->elder = newn;
+	if (previous != NULL) {
+	    previous->younger = newn;
+	} else {
+	    root->child = newn;
+	}
+	return(newn);
+    } else if (low < (unsigned int) first->low &&
+	       low + size < (unsigned int) (first->low + first->size)) {
+	/* Trying to cut an existing group: not allowed. */
+	return(NULL);
+    } else if (low > first->low) {
+	/* The new group neither is contained in the group of first
+	** (this was tested above) nor contains it. It is therefore
+	** trying to cut an existing group: not allowed. */
+	return(NULL);
+    }
+
+    /* First holds the pointer to the first child contained in the new
+    ** group. Here low <= first->low and low + size >= first->low +
+    ** first->size.  One of the two inequalities is strict. */
+    last = first->younger;
+    while (last != NULL &&
+	   (unsigned int) (last->low + last->size) < low + size) {
+	last = last->younger;
+    }
+    if (last == NULL) {
+	/* All the chilren of root from first onward become children
+	** of the new group. */
+	newn = Mtr_AllocNode();
+	if (newn == NULL) return(NULL);	/* out of memory */
+	newn->low = low;
+	newn->size = size;
+	newn->flags = flags;
+	newn->child = first;
+	newn->parent = root;
+	newn->elder = previous;
+	newn->younger = NULL;
+	first->elder = NULL;
+	if (previous != NULL) {
+	    previous->younger = newn;
+	} else {
+	    root->child = newn;
+	}
+	last = first;
+	while (last != NULL) {
+	    last->parent = newn;
+	    last = last->younger;
+	}
+	return(newn);
+    }
+
+    /* Here last != NULL and low + size <= last->low + last->size. */
+    if (low + size - 1 >= (unsigned int) last->low &&
+	low + size < (unsigned int) (last->low + last->size)) {
+	/* Trying to cut an existing group: not allowed. */
+	return(NULL);
+    }
+
+    /* First and last point to the first and last of the children of
+    ** root that are included in the new group. Allocate a new node
+    ** and make all children of root between first and last chidren of
+    ** the new node.  Previous points to the child of root immediately
+    ** preceeding first. If it is NULL, then first is the first child
+    ** of root. */
+    newn = Mtr_AllocNode();
+    if (newn == NULL) return(NULL);	/* out of memory */
+    newn->low = low;
+    newn->size = size;
+    newn->flags = flags;
+    newn->child = first;
+    newn->parent = root;
+    if (previous == NULL) {
+	root->child = newn;
+    } else {
+	previous->younger = newn;
+    }
+    newn->elder = previous;
+    newn->younger = last->younger;
+    if (last->younger != NULL) {
+	last->younger->elder = newn;
+    }
+    last->younger = NULL;
+    first->elder = NULL;
+    for (node = first; node != NULL; node = node->younger) {
+	node->parent = newn;
+    }
+
+    return(newn);
+
+} /* end of Mtr_MakeGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges the children of `group' with the children of its
+  parent.]
+
+  Description [Merges the children of `group' with the children of its
+  parent. Disposes of the node pointed by group. If group is the
+  root of the group tree, this procedure leaves the tree unchanged.
+  Returns the pointer to the parent of `group' upon successful
+  termination; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_MakeGroup]
+
+******************************************************************************/
+MtrNode *
+Mtr_DissolveGroup(
+  MtrNode * group /* group to be dissolved */)
+{
+    MtrNode *parent;
+    MtrNode *last;
+
+    parent = group->parent;
+
+    if (parent == NULL) return(NULL);
+    if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL);
+
+    /* Make all children of group children of its parent, and make
+    ** last point to the last child of group. */
+    for (last = group->child; last->younger != NULL; last = last->younger) {
+	last->parent = parent;
+    }
+    last->parent = parent;
+
+    last->younger = group->younger;
+    if (group->younger != NULL) {
+	group->younger->elder = last;
+    }
+
+    group->child->elder = group->elder;
+    if (group == parent->child) {
+	parent->child = group->child;
+    } else {
+	group->elder->younger = group->child;
+    }
+
+    Mtr_DeallocNode(group);
+    return(parent);
+
+} /* end of Mtr_DissolveGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a group with size leaves starting at low, if it exists.]
+
+  Description [Finds a group with size leaves starting at low, if it
+  exists.  This procedure relies on the low and size fields of each
+  node. It also assumes that the children of each node are sorted in
+  order of increasing low.  Returns the pointer to the root of the
+  group upon successful termination; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+MtrNode *
+Mtr_FindGroup(
+  MtrNode * root /* root of the group tree */,
+  unsigned int  low /* lower bound of the group */,
+  unsigned int  size /* upper bound of the group */)
+{
+    MtrNode *node;
+
+#ifdef MTR_DEBUG
+    /* We cannot have a non-empty proper subgroup of a singleton set. */
+    assert(!MTR_TEST(root,MTR_TERMINAL));
+#endif
+
+    /* Sanity check. */
+    if (size < 1) return(NULL);
+
+    /* Check whether current group includes the group sought.  This
+    ** check is necessary at the top-level call.  In the subsequent
+    ** calls it is redundant. */
+    if (low < (unsigned int) root->low ||
+	low + size > (unsigned int) (root->low + root->size))
+	return(NULL);
+
+    if (root->size == size && root->low == low)
+	return(root);
+
+    if (root->child == NULL)
+	return(NULL);
+
+    /* Find all chidren of root that are included in the new group. If
+    ** the group of any child entirely contains the new group, call
+    ** Mtr_MakeGroup recursively.  */
+    node = root->child;
+    while (low >= (unsigned int) (node->low + node->size)) {
+	node = node->younger;
+    }
+    if (low + size <= (unsigned int) (node->low + node->size)) {
+	/* The group is contained in the group of node. */
+	node = Mtr_FindGroup(node, low, size);
+	return(node);
+    } else {
+	return(NULL);
+    }
+
+} /* end of Mtr_FindGroup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Swaps two children of a tree node.]
+
+  Description [Swaps two children of a tree node. Adjusts the high and
+  low fields of the two nodes and their descendants.  The two children
+  must be adjacent. However, first may be the younger sibling of second.
+  Returns 1 in case of success; 0 otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Mtr_SwapGroups(
+  MtrNode * first /* first node to be swapped */,
+  MtrNode * second /* second node to be swapped */)
+{
+    MtrNode *node;
+    MtrNode *parent;
+    int sizeFirst;
+    int sizeSecond;
+
+    if (second->younger == first) { /* make first first */
+	node = first;
+	first = second;
+	second = node;
+    } else if (first->younger != second) { /* non-adjacent */
+	return(0);
+    }
+
+    sizeFirst = first->size;
+    sizeSecond = second->size;
+
+    /* Swap the two nodes. */
+    parent = first->parent;
+    if (parent == NULL || second->parent != parent) return(0);
+    if (parent->child == first) {
+	parent->child = second;
+    } else { /* first->elder != NULL */
+	first->elder->younger = second;
+    }
+    if (second->younger != NULL) {
+	second->younger->elder = first;
+    }
+    first->younger = second->younger;
+    second->elder = first->elder;
+    first->elder = second;
+    second->younger = first;
+
+    /* Adjust the high and low fields. */
+    if (!mtrShiftHL(first,sizeSecond)) return(0);
+    if (!mtrShiftHL(second,-sizeFirst)) return(0);
+
+    return(1);
+
+} /* end of Mtr_SwapGroups */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the groups as a parenthesized list.]
+
+  Description [Prints the groups as a parenthesized list. After each
+  group, the group's flag are printed, preceded by a `|'.  For each
+  flag (except MTR_TERMINAL) a character is printed.
+  <ul>
+  <li>F: MTR_FIXED
+  <li>N: MTR_NEWNODE
+  <li>S: MTR_SOFT
+  </ul>
+  The second argument, silent, if different from 0, causes
+  Mtr_PrintGroups to only check the syntax of the group tree.
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_PrintTree]
+
+******************************************************************************/
+void
+Mtr_PrintGroups(
+  MtrNode * root /* root of the group tree */,
+  int  silent /* flag to check tree syntax only */)
+{
+    MtrNode *node;
+
+    assert(root != NULL);
+    assert(root->younger == NULL || root->younger->elder == root);
+    assert(root->elder == NULL || root->elder->younger == root);
+    if (!silent) (void) printf("(%d",root->low);
+    if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
+	if (!silent) (void) printf(",");
+    } else {
+	node = root->child;
+	while (node != NULL) {
+	    assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
+	    assert(node->parent == root);
+	    Mtr_PrintGroups(node,silent);
+	    node = node->younger;
+	}
+    }
+    if (!silent) {
+	(void) printf("%d", root->low + root->size - 1);
+	if (root->flags != MTR_DEFAULT) {
+	    (void) printf("|");
+	    if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
+	    if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
+	    if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
+	}
+	(void) printf(")");
+	if (root->parent == NULL) (void) printf("\n");
+    }
+    assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
+    return;
+
+} /* end of Mtr_PrintGroups */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads groups from a file and creates a group tree.]
+
+  Description [Reads groups from a file and creates a group tree.
+  Each group is specified by three fields:
+  <xmp>
+       low size flags.
+  </xmp>
+  Low and size are (short) integers. Flags is a string composed of the
+  following characters (with associated translation):
+  <ul>
+  <li>D: MTR_DEFAULT
+  <li>F: MTR_FIXED
+  <li>N: MTR_NEWNODE
+  <li>S: MTR_SOFT
+  <li>T: MTR_TERMINAL
+  </ul>
+  Normally, the only flags that are needed are D and F.  Groups and
+  fields are separated by white space (spaces, tabs, and newlines).
+  Returns a pointer to the group tree if successful; NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mtr_InitGroupTree Mtr_MakeGroup]
+
+******************************************************************************/
+MtrNode *
+Mtr_ReadGroups(
+  FILE * fp /* file pointer */,
+  int  nleaves /* number of leaves of the new tree */)
+{
+    int low;
+    int size;
+    int err;
+    unsigned int flags;
+    MtrNode *root;
+    MtrNode *node;
+    char attrib[8*sizeof(unsigned int)+1];
+    char *c;
+
+    root = Mtr_InitGroupTree(0,nleaves);
+    if (root == NULL) return NULL;
+
+    while (! feof(fp)) {
+	/* Read a triple and check for consistency. */
+	err = fscanf(fp, "%d %d %s", &low, &size, attrib);
+	if (err == EOF) {
+	    break;
+	} else if (err != 3) {
+	    return(NULL);
+	} else if (low < 0 || low+size > nleaves || size < 1) {
+	    return(NULL);
+	} else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) {
+	    /* Not enough bits in the flags word to store these many
+	    ** attributes. */
+	    return(NULL);
+	}
+
+	/* Parse the flag string. Currently all flags are permitted,
+	** to make debugging easier. Normally, specifying NEWNODE
+	** wouldn't be allowed. */
+	flags = MTR_DEFAULT;
+	for (c=attrib; *c != 0; c++) {
+	    switch (*c) {
+	    case 'D':
+		break;
+	    case 'F':
+		flags |= MTR_FIXED;
+		break;
+	    case 'N':
+		flags |= MTR_NEWNODE;
+		break;
+	    case 'S':
+		flags |= MTR_SOFT;
+		break;
+	    case 'T':
+		flags |= MTR_TERMINAL;
+		break;
+	    default:
+		return NULL;
+	    }
+	}
+	node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size,
+			     flags);
+	if (node == NULL) return(NULL);
+    }
+
+    return(root);
+
+} /* end of Mtr_ReadGroups */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adjusts the low fields of a node and its descendants.]
+
+  Description [Adjusts the low fields of a node and its
+  descendants. Adds shift to low of each node. Checks that no
+  out-of-bounds values result.  Returns 1 in case of success; 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+mtrShiftHL(
+  MtrNode * node /* group tree node */,
+  int  shift /* amount by which low should be changed */)
+{
+    MtrNode *auxnode;
+    int low;
+
+    low = (int) node->low;
+
+
+    low += shift;
+
+    if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0);
+
+    node->low = (MtrHalfWord) low;
+
+    if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) {
+	auxnode = node->child;
+	do {
+	    if (!mtrShiftHL(auxnode,shift)) return(0);
+	    auxnode = auxnode->younger;
+	} while (auxnode != NULL);
+    }
+
+    return(1);
+
+} /* end of mtrShiftHL */
Index: /vis_dev/glu-2.1/src/mtr/mtrInt.h
===================================================================
--- /vis_dev/glu-2.1/src/mtr/mtrInt.h	(revision 8)
+++ /vis_dev/glu-2.1/src/mtr/mtrInt.h	(revision 8)
@@ -0,0 +1,92 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mtrInt.h]
+
+  PackageName [mtr]
+
+  Synopsis    [Internal data structures of the mtr package]
+
+  Description [In this package all definitions are external.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+  Neither the name of the University of Colorado nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.]
+
+  Revision    [$Id: mtrInt.h,v 1.2 2004/08/13 18:15:12 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _MTRINT
+#define _MTRINT
+
+#include "mtr.h"
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MTRINT */
Index: /vis_dev/glu-2.1/src/sparse/cols.c
===================================================================
--- /vis_dev/glu-2.1/src/sparse/cols.c	(revision 8)
+++ /vis_dev/glu-2.1/src/sparse/cols.c	(revision 8)
@@ -0,0 +1,294 @@
+/*
+ * $Id: cols.c,v 1.3 2002/09/10 00:00:12 fabio Exp $
+ *
+ */
+#include <stdio.h>
+#include "sparse_int.h"
+
+
+/*
+ *  allocate a new col vector 
+ */
+sm_col *
+sm_col_alloc(void)
+{
+    register sm_col *pcol;
+
+#ifdef FAST_AND_LOOSE
+    if (sm_col_freelist == NIL(sm_col)) {
+	pcol = ALLOC(sm_col, 1);
+    } else {
+	pcol = sm_col_freelist;
+	sm_col_freelist = pcol->next_col;
+    }
+#else
+    pcol = ALLOC(sm_col, 1);
+#endif
+
+    pcol->col_num = 0;
+    pcol->length = 0;
+    pcol->first_row = pcol->last_row = NIL(sm_element);
+    pcol->next_col = pcol->prev_col = NIL(sm_col);
+    pcol->flag = 0;
+    pcol->user_word = NIL(char);		/* for our user ... */
+    return pcol;
+}
+
+
+/*
+ *  free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols;
+ *  however, freeing a rowumn must still walk down the rowumn discarding
+ *  the elements one-by-one; that is the only use for the extra '-DCOLS'
+ *  compile flag ...
+ */
+void
+sm_col_free(sm_col *pcol)
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+    if (pcol->first_row != NIL(sm_element)) {
+	/* Add the linked list of col items to the free list */
+	pcol->last_row->next_row = sm_element_freelist;
+	sm_element_freelist = pcol->first_row;
+    }
+
+    /* Add the col to the free list of cols */
+    pcol->next_col = sm_col_freelist;
+    sm_col_freelist = pcol;
+#else
+    register sm_element *p, *pnext;
+
+    for(p = pcol->first_row; p != 0; p = pnext) {
+	pnext = p->next_row;
+	sm_element_free(p);
+    }
+    FREE(pcol);
+#endif
+}
+
+
+/*
+ *  duplicate an existing col
+ */
+sm_col *
+sm_col_dup(sm_col *pcol)
+{
+    register sm_col *pnew;
+    register sm_element *p;
+
+    pnew = sm_col_alloc();
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	(void) sm_col_insert(pnew, p->row_num);
+    }
+    return pnew;
+}
+
+
+/*
+ *  insert an element into a col vector 
+ */
+sm_element *
+sm_col_insert(sm_col *pcol, int row)
+{
+    register sm_element *test, *element;
+
+    /* get a new item, save its address */
+    sm_element_alloc(element);
+    test = element;
+    sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, 
+		    next_row, prev_row, row_num, row, test);
+
+    /* if item was not used, free it */
+    if (element != test) {
+	sm_element_free(element);
+    }
+
+    /* either way, return the current new value */
+    return test;
+}
+
+
+/*
+ *  remove an element from a col vector 
+ */
+void
+sm_col_remove(sm_col *pcol, int row)
+{
+    register sm_element *p;
+
+    for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+	;
+    if (p != 0 && p->row_num == row) {
+	dll_unlink(p, pcol->first_row, pcol->last_row, 
+			    next_row, prev_row, pcol->length);
+	sm_element_free(p);
+    }
+}
+
+
+/*
+ *  find an element (if it is in the col vector)
+ */
+sm_element *
+sm_col_find(sm_col *pcol, int row)
+{
+    register sm_element *p;
+
+    for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+	;
+    if (p != 0 && p->row_num == row) {
+	return p;
+    } else {
+	return NIL(sm_element);
+    }
+}
+
+
+/*
+ *  return 1 if col p2 contains col p1; 0 otherwise
+ */
+int 
+sm_col_contains(sm_col *p1, sm_col *p2)
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    while (q1 != 0) {
+	if (q2 == 0 || q1->row_num < q2->row_num) {
+	    return 0;
+	} else if (q1->row_num == q2->row_num) {
+	    q1 = q1->next_row;
+	    q2 = q2->next_row;
+	} else {
+	    q2 = q2->next_row;
+	}
+    }
+    return 1;
+}
+
+
+/*
+ *  return 1 if col p1 and col p2 share an element in common
+ */
+int 
+sm_col_intersects(sm_col *p1, sm_col *p2)
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    if (q1 == 0 || q2 == 0) return 0;
+    for(;;) {
+	if (q1->row_num < q2->row_num) {
+	    if ((q1 = q1->next_row) == 0) {
+		return 0;
+	    }
+	} else if (q1->row_num > q2->row_num) {
+	    if ((q2 = q2->next_row) == 0) {
+		return 0;
+	    }
+	} else {
+	    return 1;
+	}
+    }
+}
+
+
+/*
+ *  compare two cols, lexical ordering
+ */
+int 
+sm_col_compare(sm_col *p1, sm_col *p2)
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    while(q1 != 0 && q2 != 0) {
+	if (q1->row_num != q2->row_num) {
+	    return q1->row_num - q2->row_num;
+	}
+	q1 = q1->next_row;
+	q2 = q2->next_row;
+    }
+
+    if (q1 != 0) {
+	return 1;
+    } else if (q2 != 0) {
+	return -1;
+    } else {
+	return 0;
+    }
+}
+
+
+/*
+ *  return the intersection
+ */
+sm_col *
+sm_col_and(sm_col *p1, sm_col *p2)
+{
+    register sm_element *q1, *q2;
+    register sm_col *result;
+
+    result = sm_col_alloc();
+    q1 = p1->first_row;
+    q2 = p2->first_row;
+    if (q1 == 0 || q2 == 0) return result;
+    for(;;) {
+	if (q1->row_num < q2->row_num) {
+	    if ((q1 = q1->next_row) == 0) {
+		return result;
+	    }
+	} else if (q1->row_num > q2->row_num) {
+	    if ((q2 = q2->next_row) == 0) {
+		return result;
+	    }
+	} else {
+	    (void) sm_col_insert(result, q1->row_num);
+	    if ((q1 = q1->next_row) == 0) {
+		return result;
+	    }
+	    if ((q2 = q2->next_row) == 0) {
+		return result;
+	    }
+	}
+    }
+}
+
+
+int 
+sm_col_hash(sm_col *pcol, int modulus)
+{
+    register int sum;
+    register sm_element *p;
+
+    sum = 0;
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	sum = (sum*17 + p->row_num) % modulus;
+    }
+    return sum;
+}
+
+
+/*
+ *  remove an element from a col vector (given a pointer to the element) 
+ */
+void
+sm_col_remove_element(sm_col *pcol, sm_element *p)
+{
+    dll_unlink(p, pcol->first_row, pcol->last_row, 
+			next_row, prev_row, pcol->length);
+    sm_element_free(p);
+}
+
+
+void
+sm_col_print(FILE *fp, sm_col *pcol)
+{
+    sm_element *p;
+
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	(void) fprintf(fp, " %d", p->row_num);
+    }
+}
Index: /vis_dev/glu-2.1/src/sparse/matrix.c
===================================================================
--- /vis_dev/glu-2.1/src/sparse/matrix.c	(revision 8)
+++ /vis_dev/glu-2.1/src/sparse/matrix.c	(revision 8)
@@ -0,0 +1,540 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: matrix.c,v 1.4 2002/09/10 00:01:02 fabio Exp $
+ *
+ */
+#include <stdio.h>
+#include "sparse_int.h"
+
+/*
+ *  free-lists are only used if 'FAST_AND_LOOSE' is set; this is because
+ *  we lose the debugging capability of libmm_t which trashes objects when
+ *  they are free'd.  However, FAST_AND_LOOSE is much faster if matrices
+ *  are created and freed frequently.
+ */
+
+#ifdef FAST_AND_LOOSE
+sm_element *sm_element_freelist;
+sm_row *sm_row_freelist;
+sm_col *sm_col_freelist;
+#endif
+
+sm_matrix *
+sm_allocate(void)
+{
+    register sm_matrix *A;
+
+    A = ALLOC(sm_matrix, 1);
+    A->rows = NIL(sm_row *);
+    A->cols = NIL(sm_col *);
+    A->nrows = A->ncols = 0;
+    A->rows_size = A->cols_size = 0;
+    A->first_row = A->last_row = NIL(sm_row);
+    A->first_col = A->last_col = NIL(sm_col);
+    A->user_word = NIL(char);		/* for our user ... */
+    return A;
+}
+
+
+sm_matrix *
+sm_alloc_size(int row, int col)
+{
+    register sm_matrix *A;
+
+    A = sm_alloc();
+    sm_resize(A, row, col);
+    return A;
+}
+
+
+void
+sm_free_space(sm_matrix *A)
+{
+#ifdef FAST_AND_LOOSE
+    register sm_row *prow;
+
+    if (A->first_row != 0) {
+	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	    /* add the elements to the free list of elements */
+	    prow->last_col->next_col = sm_element_freelist;
+	    sm_element_freelist = prow->first_col;
+	}
+
+	/* Add the linked list of rows to the row-free-list */
+	A->last_row->next_row = sm_row_freelist;
+	sm_row_freelist = A->first_row;
+
+	/* Add the linked list of cols to the col-free-list */
+	A->last_col->next_col = sm_col_freelist;
+	sm_col_freelist = A->first_col;
+    }
+#else
+    register sm_row *prow, *pnext_row;
+    register sm_col *pcol, *pnext_col;
+
+    for(prow = A->first_row; prow != 0; prow = pnext_row) {
+	pnext_row = prow->next_row;
+	sm_row_free(prow);
+    }
+    for(pcol = A->first_col; pcol != 0; pcol = pnext_col) {
+	pnext_col = pcol->next_col;
+	pcol->first_row = pcol->last_row = NIL(sm_element);
+	sm_col_free(pcol);
+    }
+#endif
+
+    /* Free the arrays to map row/col numbers into pointers */
+    FREE(A->rows);
+    FREE(A->cols);
+    FREE(A);
+}
+
+
+sm_matrix *
+sm_dup(sm_matrix *A)
+{
+    register sm_row *prow;
+    register sm_element *p;
+    register sm_matrix *B;
+
+    B = sm_alloc();
+    if (A->last_row != 0) {
+	sm_resize(B, A->last_row->row_num, A->last_col->col_num);
+	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	    for(p = prow->first_col; p != 0; p = p->next_col) {
+		(void) sm_insert(B, p->row_num, p->col_num);
+	    }
+	}
+    }
+    return B;
+}
+
+
+void 
+sm_resize(sm_matrix *A, int row, int col)
+{
+    register int i, new_size;
+
+    if (row >= A->rows_size) {
+	new_size = MAX(A->rows_size*2, row+1);
+	A->rows = REALLOC(sm_row *, A->rows, new_size);
+	for(i = A->rows_size; i < new_size; i++) {
+	    A->rows[i] = NIL(sm_row);
+	}
+	A->rows_size = new_size;
+    }
+
+    if (col >= A->cols_size) {
+	new_size = MAX(A->cols_size*2, col+1);
+	A->cols = REALLOC(sm_col *, A->cols, new_size);
+	for(i = A->cols_size; i < new_size; i++) {
+	    A->cols[i] = NIL(sm_col);
+	}
+	A->cols_size = new_size;
+    }
+}
+
+
+/*  
+ *  insert -- insert a value into the matrix
+ */
+sm_element *
+sm_insert(sm_matrix *A, int row, int col)
+{
+    register sm_row *prow;
+    register sm_col *pcol;
+    register sm_element *element;
+    sm_element *save_element;
+
+    if (row >= A->rows_size || col >= A->cols_size) {
+	sm_resize(A, row, col);
+    }
+
+    prow = A->rows[row];
+    if (prow == NIL(sm_row)) {
+	prow = A->rows[row] = sm_row_alloc();
+	prow->row_num = row;
+	sorted_insert(sm_row, A->first_row, A->last_row, A->nrows, 
+			next_row, prev_row, row_num, row, prow);
+    }
+
+    pcol = A->cols[col];
+    if (pcol == NIL(sm_col)) {
+	pcol = A->cols[col] = sm_col_alloc();
+	pcol->col_num = col;
+	sorted_insert(sm_col, A->first_col, A->last_col, A->ncols, 
+			next_col, prev_col, col_num, col, pcol);
+    }
+
+    /* get a new item, save its address */
+    sm_element_alloc(element);
+    save_element = element;
+
+    /* insert it into the row list */
+    sorted_insert(sm_element, prow->first_col, prow->last_col, 
+		prow->length, next_col, prev_col, col_num, col, element);
+
+    /* if it was used, also insert it into the column list */
+    if (element == save_element) {
+	sorted_insert(sm_element, pcol->first_row, pcol->last_row, 
+		pcol->length, next_row, prev_row, row_num, row, element);
+    } else {
+	/* otherwise, it was already in matrix -- free element we allocated */
+	sm_element_free(save_element);
+    }
+    return element;
+}
+
+
+sm_element *
+sm_find(sm_matrix *A, int rownum, int colnum)
+{
+    sm_row *prow;
+    sm_col *pcol;
+
+    prow = sm_get_row(A, rownum);
+    if (prow == NIL(sm_row)) {
+	return NIL(sm_element);
+    } else {
+	pcol = sm_get_col(A, colnum);
+	if (pcol == NIL(sm_col)) {
+	    return NIL(sm_element);
+	}
+	if (prow->length < pcol->length) {
+	    return sm_row_find(prow, colnum);
+	} else {
+	    return sm_col_find(pcol, rownum);
+	}
+    }
+}
+
+
+void
+sm_remove(sm_matrix *A, int rownum, int colnum)
+{
+    sm_remove_element(A, sm_find(A, rownum, colnum));
+}
+
+
+
+void
+sm_remove_element(sm_matrix *A, sm_element *p)
+{
+    register sm_row *prow;
+    register sm_col *pcol;
+
+    if (p == 0) return;
+
+    /* Unlink the element from its row */
+    prow = sm_get_row(A, p->row_num);
+    dll_unlink(p, prow->first_col, prow->last_col, 
+			next_col, prev_col, prow->length);
+
+    /* if no more elements in the row, discard the row header */
+    if (prow->first_col == NIL(sm_element)) {
+	sm_delrow(A, p->row_num);
+    }
+
+    /* Unlink the element from its column */
+    pcol = sm_get_col(A, p->col_num);
+    dll_unlink(p, pcol->first_row, pcol->last_row, 
+			next_row, prev_row, pcol->length);
+
+    /* if no more elements in the column, discard the column header */
+    if (pcol->first_row == NIL(sm_element)) {
+	sm_delcol(A, p->col_num);
+    }
+
+    sm_element_free(p);
+}
+
+
+void 
+sm_delrow(sm_matrix *A, int i)
+{
+    register sm_element *p, *pnext;
+    sm_col *pcol;
+    sm_row *prow;
+
+    prow = sm_get_row(A, i);
+    if (prow != NIL(sm_row)) {
+	/* walk across the row */
+	for(p = prow->first_col; p != 0; p = pnext) {
+	    pnext = p->next_col;
+
+	    /* unlink the item from the column (and delete it) */
+	    pcol = sm_get_col(A, p->col_num);
+	    sm_col_remove_element(pcol, p);
+
+	    /* discard the column if it is now empty */
+	    if (pcol->first_row == NIL(sm_element)) {
+		sm_delcol(A, pcol->col_num);
+	    }
+	}
+
+	/* discard the row -- we already threw away the elements */ 
+	A->rows[i] = NIL(sm_row);
+	dll_unlink(prow, A->first_row, A->last_row, 
+				next_row, prev_row, A->nrows);
+	prow->first_col = prow->last_col = NIL(sm_element);
+	sm_row_free(prow);
+    }
+}
+
+
+void 
+sm_delcol(sm_matrix *A, int i)
+{
+    register sm_element *p, *pnext;
+    sm_row *prow;
+    sm_col *pcol;
+
+    pcol = sm_get_col(A, i);
+    if (pcol != NIL(sm_col)) {
+	/* walk down the column */
+	for(p = pcol->first_row; p != 0; p = pnext) {
+	    pnext = p->next_row;
+
+	    /* unlink the element from the row (and delete it) */
+	    prow = sm_get_row(A, p->row_num);
+	    sm_row_remove_element(prow, p);
+
+	    /* discard the row if it is now empty */
+	    if (prow->first_col == NIL(sm_element)) {
+		sm_delrow(A, prow->row_num);
+	    }
+	}
+
+	/* discard the column -- we already threw away the elements */ 
+	A->cols[i] = NIL(sm_col);
+	dll_unlink(pcol, A->first_col, A->last_col, 
+			    next_col, prev_col, A->ncols);
+	pcol->first_row = pcol->last_row = NIL(sm_element);
+	sm_col_free(pcol);
+    }
+}
+
+
+void
+sm_copy_row(sm_matrix *dest, int dest_row, sm_row *prow)
+{
+    register sm_element *p;
+
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	(void) sm_insert(dest, dest_row, p->col_num);
+    }
+}
+
+
+void
+sm_copy_col(sm_matrix *dest, int dest_col, sm_col *pcol)
+{
+    register sm_element *p;
+
+    for(p = pcol->first_row; p != 0; p = p->next_row) {
+	(void) sm_insert(dest, dest_col, p->row_num);
+    }
+}
+
+
+sm_row *
+sm_longest_row(sm_matrix *A)
+{
+    register sm_row *large_row, *prow;
+    register int max_length;
+
+    max_length = 0;
+    large_row = NIL(sm_row);
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	if (prow->length > max_length) {
+	    max_length = prow->length;
+	    large_row = prow;
+	}
+    }
+    return large_row;
+}
+
+
+sm_col *
+sm_longest_col(sm_matrix *A)
+{
+    register sm_col *large_col, *pcol;
+    register int max_length;
+
+    max_length = 0;
+    large_col = NIL(sm_col);
+    for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	if (pcol->length > max_length) {
+	    max_length = pcol->length;
+	    large_col = pcol;
+	}
+    }
+    return large_col;
+}
+
+
+int
+sm_num_elements(sm_matrix *A)
+{
+    register sm_row *prow;
+    register int num;
+
+    num = 0;
+    sm_foreach_row(A, prow) {
+	num += prow->length;
+    }
+    return num;
+}
+
+
+int 
+sm_read(FILE *fp, sm_matrix **A)
+{
+    int i, j, err;
+
+    *A = sm_alloc();
+    while (! feof(fp)) {
+	err = fscanf(fp, "%d %d", &i, &j);
+	if (err == EOF) {
+	    return 1;
+	} else if (err != 2) {
+	    return 0;
+	}
+	(void) sm_insert(*A, i, j);
+    }
+    return 1;
+}
+
+
+int 
+sm_read_compressed(FILE *fp, sm_matrix **A)
+{
+    int i, j, k, nrows, ncols;
+    unsigned long x;
+
+    *A = sm_alloc();
+    if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) {
+	return 0;
+    }
+    sm_resize(*A, nrows, ncols);
+
+    for(i = 0; i < nrows; i++) {
+	if (fscanf(fp, "%lx", &x) != 1) {
+	    return 0;
+	}
+	for(j = 0; j < ncols; j += 32) {
+	    if (fscanf(fp, "%lx", &x) != 1) {
+		return 0;
+	    }
+	    for(k = j; x != 0; x >>= 1, k++) {
+		if (x & 1) {
+		    (void) sm_insert(*A, i, k);
+		}
+	    }
+	}
+    }
+    return 1;
+}
+
+
+void 
+sm_write(FILE *fp, sm_matrix *A)
+{
+    register sm_row *prow;
+    register sm_element *p;
+
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	for(p = prow->first_col; p != 0; p = p->next_col) {
+	    (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num);
+	}
+    }
+}
+
+
+void 
+sm_print(FILE *fp, sm_matrix *A)
+{
+    register sm_row *prow;
+    register sm_col *pcol;
+    int c;
+
+    if (A->last_col->col_num >= 100) {
+	(void) fprintf(fp, "    ");
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	    (void) fprintf(fp, "%d", (pcol->col_num / 100)%10);
+	}
+	putc('\n', fp);
+    }
+
+    if (A->last_col->col_num >= 10) {
+	(void) fprintf(fp, "    ");
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	    (void) fprintf(fp, "%d", (pcol->col_num / 10)%10);
+	}
+	putc('\n', fp);
+    }
+
+    (void) fprintf(fp, "    ");
+    for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	(void) fprintf(fp, "%d", pcol->col_num % 10);
+    }
+    putc('\n', fp);
+
+    (void) fprintf(fp, "    ");
+    for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	(void) fprintf(fp, "-");
+    }
+    putc('\n', fp);
+
+    for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+	(void) fprintf(fp, "%3d:", prow->row_num);
+
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+	    c = sm_row_find(prow, pcol->col_num) ? '1' : '.';
+	    putc(c, fp);
+	}
+	putc('\n', fp);
+    }
+}
+
+
+void 
+sm_dump(sm_matrix *A, char *s, int max)
+{
+    FILE *fp = stdout;
+
+    (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols);
+    if (A->nrows < max) {
+	sm_print(fp, A);
+    }
+}
+
+
+void
+sm_cleanup(void)
+{
+#ifdef FAST_AND_LOOSE
+    register sm_element *p, *pnext;
+    register sm_row *prow, *pnextrow;
+    register sm_col *pcol, *pnextcol;
+
+    for(p = sm_element_freelist; p != 0; p = pnext) {
+	pnext = p->next_col;
+	FREE(p);
+    }
+    sm_element_freelist = 0;
+
+    for(prow = sm_row_freelist; prow != 0; prow = pnextrow) {
+	pnextrow = prow->next_row;
+	FREE(prow);
+    }
+    sm_row_freelist = 0;
+
+    for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) {
+	pnextcol = pcol->next_col;
+	FREE(pcol);
+    }
+    sm_col_freelist = 0;
+#endif
+}
Index: /vis_dev/glu-2.1/src/sparse/rows.c
===================================================================
--- /vis_dev/glu-2.1/src/sparse/rows.c	(revision 8)
+++ /vis_dev/glu-2.1/src/sparse/rows.c	(revision 8)
@@ -0,0 +1,294 @@
+/*
+ * $Id: rows.c,v 1.3 2002/09/10 00:02:02 fabio Exp $
+ *
+ */
+#include <stdio.h>
+#include "sparse_int.h"
+
+
+/*
+ *  allocate a new row vector 
+ */
+sm_row *
+sm_row_alloc(void)
+{
+    register sm_row *prow;
+
+#ifdef FAST_AND_LOOSE
+    if (sm_row_freelist == NIL(sm_row)) {
+	prow = ALLOC(sm_row, 1);
+    } else {
+	prow = sm_row_freelist;
+	sm_row_freelist = prow->next_row;
+    }
+#else
+    prow = ALLOC(sm_row, 1);
+#endif
+
+    prow->row_num = 0;
+    prow->length = 0;
+    prow->first_col = prow->last_col = NIL(sm_element);
+    prow->next_row = prow->prev_row = NIL(sm_row);
+    prow->flag = 0;
+    prow->user_word = NIL(char);		/* for our user ... */
+    return prow;
+}
+
+
+/*
+ *  free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows;
+ *  however, freeing a column must still walk down the column discarding
+ *  the elements one-by-one; that is the only use for the extra '-DCOLS'
+ *  compile flag ...
+ */
+void
+sm_row_free(sm_row *prow)
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+    if (prow->first_col != NIL(sm_element)) {
+	/* Add the linked list of row items to the free list */
+	prow->last_col->next_col = sm_element_freelist;
+	sm_element_freelist = prow->first_col;
+    }
+
+    /* Add the row to the free list of rows */
+    prow->next_row = sm_row_freelist;
+    sm_row_freelist = prow;
+#else
+    register sm_element *p, *pnext;
+
+    for(p = prow->first_col; p != 0; p = pnext) {
+	pnext = p->next_col;
+	sm_element_free(p);
+    }
+    FREE(prow);
+#endif
+}
+
+
+/*
+ *  duplicate an existing row
+ */
+sm_row *
+sm_row_dup(sm_row *prow)
+{
+    register sm_row *pnew;
+    register sm_element *p;
+
+    pnew = sm_row_alloc();
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	(void) sm_row_insert(pnew, p->col_num);
+    }
+    return pnew;
+}
+
+
+/*
+ *  insert an element into a row vector 
+ */
+sm_element *
+sm_row_insert(sm_row *prow, int col)
+{
+    register sm_element *test, *element;
+
+    /* get a new item, save its address */
+    sm_element_alloc(element);
+    test = element;
+    sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, 
+		    next_col, prev_col, col_num, col, test);
+
+    /* if item was not used, free it */
+    if (element != test) {
+	sm_element_free(element);
+    }
+
+    /* either way, return the current new value */
+    return test;
+}
+
+
+/*
+ *  remove an element from a row vector 
+ */
+void
+sm_row_remove(sm_row *prow, int col)
+{
+    register sm_element *p;
+
+    for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+	;
+    if (p != 0 && p->col_num == col) {
+	dll_unlink(p, prow->first_col, prow->last_col, 
+			    next_col, prev_col, prow->length);
+	sm_element_free(p);
+    }
+}
+
+
+/*
+ *  find an element (if it is in the row vector)
+ */
+sm_element *
+sm_row_find(sm_row *prow, int col)
+{
+    register sm_element *p;
+
+    for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+	;
+    if (p != 0 && p->col_num == col) {
+	return p;
+    } else {
+	return NIL(sm_element);
+    }
+}
+
+
+/*
+ *  return 1 if row p2 contains row p1; 0 otherwise
+ */
+int 
+sm_row_contains(sm_row *p1, sm_row *p2)
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    while (q1 != 0) {
+	if (q2 == 0 || q1->col_num < q2->col_num) {
+	    return 0;
+	} else if (q1->col_num == q2->col_num) {
+	    q1 = q1->next_col;
+	    q2 = q2->next_col;
+	} else {
+	    q2 = q2->next_col;
+	}
+    }
+    return 1;
+}
+
+
+/*
+ *  return 1 if row p1 and row p2 share an element in common
+ */
+int 
+sm_row_intersects(sm_row *p1, sm_row *p2)
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    if (q1 == 0 || q2 == 0) return 0;
+    for(;;) {
+	if (q1->col_num < q2->col_num) {
+	    if ((q1 = q1->next_col) == 0) {
+		return 0;
+	    }
+	} else if (q1->col_num > q2->col_num) {
+	    if ((q2 = q2->next_col) == 0) {
+		return 0;
+	    }
+	} else {
+	    return 1;
+	}
+    }
+}
+
+
+/*
+ *  compare two rows, lexical ordering
+ */
+int 
+sm_row_compare(sm_row *p1, sm_row *p2)
+{
+    register sm_element *q1, *q2;
+
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    while(q1 != 0 && q2 != 0) {
+	if (q1->col_num != q2->col_num) {
+	    return q1->col_num - q2->col_num;
+	}
+	q1 = q1->next_col;
+	q2 = q2->next_col;
+    }
+
+    if (q1 != 0) {
+	return 1;
+    } else if (q2 != 0) {
+	return -1;
+    } else {
+	return 0;
+    }
+}
+
+
+/*
+ *  return the intersection
+ */
+sm_row *
+sm_row_and(sm_row *p1, sm_row *p2)
+{
+    register sm_element *q1, *q2;
+    register sm_row *result;
+
+    result = sm_row_alloc();
+    q1 = p1->first_col;
+    q2 = p2->first_col;
+    if (q1 == 0 || q2 == 0) return result;
+    for(;;) {
+	if (q1->col_num < q2->col_num) {
+	    if ((q1 = q1->next_col) == 0) {
+		return result;
+	    }
+	} else if (q1->col_num > q2->col_num) {
+	    if ((q2 = q2->next_col) == 0) {
+		return result;
+	    }
+	} else {
+	    (void) sm_row_insert(result, q1->col_num);
+	    if ((q1 = q1->next_col) == 0) {
+		return result;
+	    }
+	    if ((q2 = q2->next_col) == 0) {
+		return result;
+	    }
+	}
+    }
+}
+
+
+int 
+sm_row_hash(sm_row *prow, int modulus)
+{
+    register int sum;
+    register sm_element *p;
+
+    sum = 0;
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	sum = (sum*17 + p->col_num) % modulus;
+    }
+    return sum;
+}
+
+
+/*
+ *  remove an element from a row vector (given a pointer to the element) 
+ */
+void
+sm_row_remove_element(sm_row *prow, sm_element *p)
+{
+    dll_unlink(p, prow->first_col, prow->last_col, 
+			next_col, prev_col, prow->length);
+    sm_element_free(p);
+}
+
+
+void
+sm_row_print(FILE *fp, sm_row *prow)
+{
+    sm_element *p;
+
+    for(p = prow->first_col; p != 0; p = p->next_col) {
+	(void) fprintf(fp, " %d", p->col_num);
+    }
+}
Index: /vis_dev/glu-2.1/src/sparse/sparse.h
===================================================================
--- /vis_dev/glu-2.1/src/sparse/sparse.h	(revision 8)
+++ /vis_dev/glu-2.1/src/sparse/sparse.h	(revision 8)
@@ -0,0 +1,159 @@
+#ifndef SPARSE_H
+#define SPARSE_H
+
+#include "util.h"
+
+/* hack to fix conflict with libX11.a */
+#define sm_alloc sm_allocate
+#define sm_free sm_free_space
+
+/*
+ *  sparse.h -- sparse matrix package header file
+ */
+
+typedef struct sm_element_struct sm_element;
+typedef struct sm_row_struct sm_row;
+typedef struct sm_col_struct sm_col;
+typedef struct sm_matrix_struct sm_matrix;
+
+
+/*
+ *  sparse matrix element
+ */
+struct sm_element_struct {
+    int row_num;		/* row number of this element */
+    int col_num;		/* column number of this element */
+    sm_element *next_row;	/* next row in this column */
+    sm_element *prev_row;	/* previous row in this column */
+    sm_element *next_col;	/* next column in this row */
+    sm_element *prev_col;	/* previous column in this row */
+    char *user_word;		/* user-defined word */
+};
+
+
+/*
+ *  row header
+ */
+struct sm_row_struct {
+    int row_num;		/* the row number */
+    int length;			/* number of elements in this row */
+    int flag;			/* user-defined word */
+    sm_element *first_col;	/* first element in this row */
+    sm_element *last_col;	/* last element in this row */
+    sm_row *next_row;		/* next row (in sm_matrix linked list) */
+    sm_row *prev_row;		/* previous row (in sm_matrix linked list) */
+    char *user_word;		/* user-defined word */
+};
+
+
+/*
+ *  column header
+ */
+struct sm_col_struct {
+    int col_num;		/* the column number */
+    int length;			/* number of elements in this column */
+    int flag;			/* user-defined word */
+    sm_element *first_row;	/* first element in this column */
+    sm_element *last_row;	/* last element in this column */
+    sm_col *next_col;		/* next column (in sm_matrix linked list) */
+    sm_col *prev_col;		/* prev column (in sm_matrix linked list) */
+    char *user_word;		/* user-defined word */
+};
+
+
+/*
+ *  A sparse matrix
+ */
+struct sm_matrix_struct {
+    sm_row **rows;		/* pointer to row headers (by row #) */
+    int rows_size;		/* alloc'ed size of above array */
+    sm_col **cols;		/* pointer to column headers (by col #) */
+    int cols_size;		/* alloc'ed size of above array */
+    sm_row *first_row;		/* first row (linked list of all rows) */
+    sm_row *last_row;		/* last row (linked list of all rows) */
+    int nrows;			/* number of rows */
+    sm_col *first_col;		/* first column (linked list of columns) */
+    sm_col *last_col;		/* last column (linked list of columns) */
+    int ncols;			/* number of columns */
+    char *user_word;		/* user-defined word */
+};
+
+
+#define sm_get_col(A, colnum)	\
+    (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \
+	(A)->cols[colnum] : (sm_col *) 0)
+
+#define sm_get_row(A, rownum)	\
+    (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \
+	(A)->rows[rownum] : (sm_row *) 0)
+
+#define sm_foreach_row(A, prow)	\
+	for(prow = A->first_row; prow != 0; prow = prow->next_row)
+
+#define sm_foreach_col(A, pcol)	\
+	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col)
+
+#define sm_foreach_row_element(prow, p)	\
+	for(p = (prow == 0) ? 0 : prow->first_col; p != 0; p = p->next_col)
+
+#define sm_foreach_col_element(pcol, p) \
+	for(p = (pcol == 0) ? 0 : pcol->first_row; p != 0; p = p->next_row)
+
+#define sm_put(x, val) \
+	(x->user_word = (char *) val)
+
+#define sm_get(type, x) \
+	((type) (x->user_word))
+
+EXTERN sm_matrix *sm_allocate ARGS((void));
+EXTERN sm_matrix *sm_alloc_size ARGS((int, int));
+EXTERN void sm_free_space ARGS((sm_matrix *));
+EXTERN sm_matrix *sm_dup ARGS((sm_matrix *));
+EXTERN void sm_resize ARGS((sm_matrix *, int, int));
+EXTERN sm_element *sm_insert ARGS((sm_matrix *, int, int));
+EXTERN sm_element *sm_find ARGS((sm_matrix *, int, int));
+EXTERN void sm_remove ARGS((sm_matrix *, int, int));
+EXTERN void sm_remove_element ARGS((sm_matrix *, sm_element *));
+EXTERN void sm_delrow ARGS((sm_matrix *, int));
+EXTERN void sm_delcol ARGS((sm_matrix *, int));
+EXTERN void sm_copy_row ARGS((sm_matrix *, int, sm_row *));
+EXTERN void sm_copy_col ARGS((sm_matrix *, int, sm_col *));
+EXTERN sm_row *sm_longest_row ARGS((sm_matrix *));
+EXTERN sm_col *sm_longest_col ARGS((sm_matrix *));
+EXTERN int sm_num_elements ARGS((sm_matrix *));
+EXTERN int sm_read ARGS((FILE *, sm_matrix **));
+EXTERN int sm_read_compressed ARGS((FILE *, sm_matrix **));
+EXTERN void sm_write ARGS((FILE *, sm_matrix *));
+EXTERN void sm_print ARGS((FILE *, sm_matrix *));
+EXTERN void sm_dump ARGS((sm_matrix *, char *, int));
+EXTERN void sm_cleanup ARGS((void));
+
+EXTERN sm_col *sm_col_alloc ARGS((void));
+EXTERN void sm_col_free ARGS((sm_col *));
+EXTERN sm_col *sm_col_dup ARGS((sm_col *));
+EXTERN sm_element *sm_col_insert ARGS((sm_col *, int));
+EXTERN void sm_col_remove ARGS((sm_col *, int));
+EXTERN sm_element *sm_col_find ARGS((sm_col *, int));
+EXTERN int sm_col_contains ARGS((sm_col *, sm_col *));
+EXTERN int sm_col_intersects ARGS((sm_col *, sm_col *));
+EXTERN int sm_col_compare ARGS((sm_col *, sm_col *));
+EXTERN sm_col *sm_col_and ARGS((sm_col *, sm_col *));
+EXTERN int sm_col_hash ARGS((sm_col *, int));
+EXTERN void sm_col_remove_element ARGS((sm_col *, sm_element *));
+EXTERN void sm_col_print ARGS((FILE *, sm_col *));
+
+EXTERN sm_row *sm_row_alloc ARGS((void));
+EXTERN void sm_row_free ARGS((sm_row *));
+EXTERN sm_row *sm_row_dup ARGS((sm_row *));
+EXTERN sm_element *sm_row_insert ARGS((sm_row *, int));
+EXTERN void sm_row_remove ARGS((sm_row *, int));
+EXTERN sm_element *sm_row_find ARGS((sm_row *, int));
+EXTERN int sm_row_contains ARGS((sm_row *, sm_row *));
+EXTERN int sm_row_intersects ARGS((sm_row *, sm_row *));
+EXTERN int sm_row_compare ARGS((sm_row *, sm_row *));
+EXTERN sm_row *sm_row_and ARGS((sm_row *, sm_row *));
+EXTERN int sm_row_hash ARGS((sm_row *, int));
+EXTERN void sm_row_remove_element ARGS((sm_row *, sm_element *));
+EXTERN void sm_row_print ARGS((FILE *, sm_row *));
+
+#endif
Index: /vis_dev/glu-2.1/src/sparse/sparse.make
===================================================================
--- /vis_dev/glu-2.1/src/sparse/sparse.make	(revision 8)
+++ /vis_dev/glu-2.1/src/sparse/sparse.make	(revision 8)
@@ -0,0 +1,6 @@
+CSRC += cols.c matrix.c rows.c
+HEADERS += sparse.h sparse_int.h
+MISC += sparse.doc
+
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/sparse/sparse_int.h
===================================================================
--- /vis_dev/glu-2.1/src/sparse/sparse_int.h	(revision 8)
+++ /vis_dev/glu-2.1/src/sparse/sparse_int.h	(revision 8)
@@ -0,0 +1,108 @@
+#include "sparse.h"
+#include "util.h"
+
+
+/*
+ *  sorted, double-linked list insertion
+ *
+ *  type: object type
+ *
+ *  first, last: fields (in header) to head and tail of the list
+ *  count: field (in header) of length of the list
+ *
+ *  next, prev: fields (in object) to link next and previous objects
+ *  value: field (in object) which controls the order
+ *
+ *  newval: value field for new object
+ *  e: an object to use if insertion needed (set to actual value used)
+ */
+
+#define sorted_insert(type, first, last, count, next, prev, value, newval, e) \
+    if (last == 0) { \
+	e->value = newval; \
+	first = e; \
+	last = e; \
+	e->next = 0; \
+	e->prev = 0; \
+	count++; \
+    } else if (last->value < newval) { \
+	e->value = newval; \
+	last->next = e; \
+	e->prev = last; \
+	last = e; \
+	e->next = 0; \
+	count++; \
+    } else if (first->value > newval) { \
+	e->value = newval; \
+	first->prev = e; \
+	e->next = first; \
+	first = e; \
+	e->prev = 0; \
+	count++; \
+    } else { \
+	type *p; \
+	for(p = first; p->value < newval; p = p->next) \
+	    ; \
+	if (p->value > newval) { \
+	    e->value = newval; \
+	    p = p->prev; \
+	    p->next->prev = e; \
+	    e->next = p->next; \
+	    p->next = e; \
+	    e->prev = p; \
+	    count++; \
+	} else { \
+	    e = p; \
+	} \
+    }
+
+
+/*
+ *  double linked-list deletion
+ */
+#define dll_unlink(p, first, last, next, prev, count) { \
+    if (p->prev == 0) { \
+	first = p->next; \
+    } else { \
+	p->prev->next = p->next; \
+    } \
+    if (p->next == 0) { \
+	last = p->prev; \
+    } else { \
+	p->next->prev = p->prev; \
+    } \
+    count--; \
+}
+
+
+#ifdef FAST_AND_LOOSE
+extern sm_element *sm_element_freelist;
+extern sm_row *sm_row_freelist;
+extern sm_col *sm_col_freelist;
+
+#define sm_element_alloc(newobj) \
+    if (sm_element_freelist == NIL(sm_element)) { \
+	newobj = ALLOC(sm_element, 1); \
+    } else { \
+	newobj = sm_element_freelist; \
+	sm_element_freelist = sm_element_freelist->next_col; \
+    } \
+    newobj->user_word = NIL(char); \
+
+#define sm_element_free(e) \
+    (e->next_col = sm_element_freelist, sm_element_freelist = e)
+
+#else
+
+#define sm_element_alloc(newobj)	\
+    newobj = ALLOC(sm_element, 1);	\
+    newobj->user_word = NIL(char);
+#define sm_element_free(e)		\
+    FREE(e)
+#endif
+
+
+EXTERN void sm_row_remove_element(sm_row *, sm_element *);
+EXTERN void sm_col_remove_element(sm_col *, sm_element *);
+
+/* LINTLIBRARY */
Index: /vis_dev/glu-2.1/src/st/semantic.cache
===================================================================
--- /vis_dev/glu-2.1/src/st/semantic.cache	(revision 8)
+++ /vis_dev/glu-2.1/src/st/semantic.cache	(revision 8)
@@ -0,0 +1,22 @@
+;; Object st/
+;; SEMANTICDB Tags save file
+(semanticdb-project-database-file "st/"
+  :tables (list 
+   (semanticdb-table "st.h"
+    :major-mode 'c-mode
+    :tags '(("ST_INCLUDED" variable (:constant-flag t) nil [482 769]) ("st_free_gen" function (:type "void" :arguments (("" variable (:pointer 1 :type ("st_generator" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6955 6970])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6930 6971]) ("st_gen_int" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_generator" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6898 6913]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6914 6921]) ("" variable (:pointer 1 :type "int") (reparse-symbol arg-sub-list) [6922 6928])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6875 6929]) ("st_gen" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_generator" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6842 6857]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6858 6865]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6866 6873])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6823 6874]) ("st_init_gen" function (:type ("st_generator" type (:type "class") nil nil) :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6810 6821])) :typemodifiers ("extern" "\"C\"" "extern") :pointer 1 :prototype-flag t) (reparse-symbol extern-c-contents) [6776 6822]) ("st_ptrcmp" function (:type "int" :arguments (("" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [6747 6760]) ("" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [6761 6774])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6725 6775]) ("st_numcmp" function (:type "int" :arguments (("" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [6696 6709]) ("" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [6710 6723])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6674 6724]) ("st_ptrhash" function (:type "int" :arguments (("" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [6660 6667]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [6668 6672])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6637 6673]) ("st_numhash" function (:type "int" :arguments (("" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [6623 6630]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [6631 6635])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6600 6636]) ("st_strhash" function (:type "int" :arguments (("" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [6586 6593]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [6594 6598])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6563 6599]) ("st_foreach" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6533 6544]) ("" variable (:type ("ST_PFSR" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6545 6553]) ("" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [6554 6561])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6510 6562]) ("st_delete_int" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6482 6493]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6494 6501]) ("" variable (:pointer 1 :type "int") (reparse-symbol arg-sub-list) [6502 6508])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6456 6509]) ("st_delete" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6427 6438]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6439 6446]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6447 6454])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6405 6455]) ("st_copy" function (:type ("st_table" type (:type "class") nil nil) :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6392 6403])) :typemodifiers ("extern" "\"C\"" "extern") :pointer 1 :prototype-flag t) (reparse-symbol extern-c-contents) [6366 6404]) ("st_find" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6337 6348]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6349 6356]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6357 6364])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6317 6365]) ("st_find_or_add" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6288 6299]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6300 6307]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6308 6315])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6261 6316]) ("st_add_direct" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6232 6243]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6244 6251]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6252 6259])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6206 6260]) ("st_insert" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6177 6188]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6189 6196]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6197 6204])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6155 6205]) ("st_lookup_int" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6127 6138]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6139 6146]) ("" variable (:pointer 1 :type "int") (reparse-symbol arg-sub-list) [6147 6153])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6101 6154]) ("st_lookup" function (:type "int" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6072 6083]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6084 6091]) ("" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [6092 6099])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6050 6100]) ("st_free_table" function (:type "void" :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6037 6048])) :typemodifiers ("extern" "\"C\"" "extern") :prototype-flag t) (reparse-symbol extern-c-contents) [6010 6049]) ("st_init_table" function (:type ("st_table" type (:type "class") nil nil) :arguments (("" variable (:type ("ST_PFICPCP" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5985 5996]) ("" variable (:type ("ST_PFICPI" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5997 6007])) :typemodifiers ("extern" "\"C\"" "extern") :pointer 1 :prototype-flag t) (reparse-symbol extern-c-contents) [5953 6008]) ("st_init_table_with_params" function (:type ("st_table" type (:type "class") nil nil) :arguments (("" variable (:type ("ST_PFICPCP" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5906 5917]) ("" variable (:type ("ST_PFICPI" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5918 5928]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [5929 5933]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [5934 5938]) ("" variable (:type "double") (reparse-symbol arg-sub-list) [5939 5946]) ("" variable (:type "int") (reparse-symbol arg-sub-list) [5947 5951])) :typemodifiers ("extern" "\"C\"" "extern") :pointer 1 :prototype-flag t) (reparse-symbol extern-c-contents) [5862 5952]) ("st_foreach_item_int" variable (:typemodifiers ("extern" "\"C\"") :constant-flag t) (reparse-symbol extern-c-contents) [5401 5462]) ("st_foreach_item" variable (:typemodifiers ("extern" "\"C\"") :constant-flag t) (reparse-symbol extern-c-contents) [4484 4541]) ("st_count" variable (:typemodifiers ("extern" "\"C\"") :default-value (nil) :constant-flag t) (reparse-symbol extern-c-contents) [3724 3770]) ("st_is_member" variable (:typemodifiers ("extern" "\"C\"") :default-value (nil) :constant-flag t) (reparse-symbol extern-c-contents) [3318 3382]) ("ST_PFICPI" variable (:typemodifiers ("extern" "\"C\"") :type "int" :functionpointer-flag t) (reparse-symbol extern-c-contents) [2419 2449]) ("ST_PFICPCP" variable (:typemodifiers ("extern" "\"C\"") :type "int" :functionpointer-flag t) (reparse-symbol extern-c-contents) [2328 2374]) ("ST_PFSR" variable (:typemodifiers ("extern" "\"C\"") :type ("st_retval" type (:type "class") nil nil) :functionpointer-flag t) (reparse-symbol extern-c-contents) [2273 2318]) ("st_retval" type (:typemodifiers ("extern" "\"C\"") :type "enum" :members (("ST_CONTINUE" variable (:constant-flag t :type "int") (reparse-symbol enumsubparts) [2225 2237]) ("ST_STOP" variable (:constant-flag t :type "int") (reparse-symbol enumsubparts) [2238 2246]) ("ST_DELETE" variable (:constant-flag t :type "int") (reparse-symbol enumsubparts) [2247 2257]))) (reparse-symbol extern-c-contents) [2209 2258]) ("st_generator" type (:typemodifiers ("extern" "\"C\"") :type "struct" :members (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol classsubparts) [2146 2162]) ("entry" variable (:pointer 1 :type ("st_table_entry" type (:type "class") nil nil)) (reparse-symbol classsubparts) [2167 2189]) ("index" variable (:type "int") (reparse-symbol classsubparts) [2194 2204]))) (reparse-symbol extern-c-contents) [2120 2207]) ("st_generator" type (:typemodifiers ("extern" "\"C\"") :type "typedef" :superclasses "st_generator" :typedef ("st_generator" type (:type "struct") nil nil)) (reparse-symbol extern-c-contents) [2078 2119]) ("st_table" type (:typemodifiers ("extern" "\"C\"") :type "struct" :members (("compare" variable (:functionpointer-flag t :type "int") (reparse-symbol classsubparts) [1867 1910]) ("hash" variable (:functionpointer-flag t :type "int") (reparse-symbol classsubparts) [1915 1940]) ("num_bins" variable (:type "int") (reparse-symbol classsubparts) [1945 1958]) ("num_entries" variable (:type "int") (reparse-symbol classsubparts) [1963 1979]) ("max_density" variable (:type "int") (reparse-symbol classsubparts) [1984 2000]) ("reorder_flag" variable (:type "int") (reparse-symbol classsubparts) [2005 2022]) ("grow_factor" variable (:type "double") (reparse-symbol classsubparts) [2027 2046]) ("bins" variable (:pointer 2 :type ("st_table_entry" type (:type "class") nil nil)) (reparse-symbol classsubparts) [2051 2073]))) (reparse-symbol extern-c-contents) [1845 2076]) ("st_table" type (:typemodifiers ("extern" "\"C\"") :type "typedef" :superclasses "st_table" :typedef ("st_table" type (:type "struct") nil nil)) (reparse-symbol extern-c-contents) [1811 1844]) ("st_table_entry" type (:typemodifiers ("extern" "\"C\"") :type "struct" :members (("key" variable (:pointer 1 :type "char") (reparse-symbol classsubparts) [1752 1762]) ("record" variable (:pointer 1 :type "char") (reparse-symbol classsubparts) [1767 1780]) ("next" variable (:pointer 1 :type ("st_table_entry" type (:type "class") nil nil)) (reparse-symbol classsubparts) [1785 1806]))) (reparse-symbol extern-c-contents) [1724 1809]) ("st_table_entry" type (:typemodifiers ("extern" "\"C\"") :type "typedef" :superclasses "st_table_entry" :typedef ("st_table_entry" type (:type "struct") nil nil)) (reparse-symbol extern-c-contents) [1678 1723]) ("ST_OUT_OF_MEM" variable (:typemodifiers ("extern" "\"C\"") :default-value (nil) :constant-flag t) (reparse-symbol extern-c-contents) [1165 1193]) ("ST_DEFAULT_REORDER_FLAG" variable (:typemodifiers ("extern" "\"C\"") :default-value (nil) :constant-flag t) (reparse-symbol extern-c-contents) [1131 1164]) ("ST_DEFAULT_GROW_FACTOR" variable (:typemodifiers ("extern" "\"C\"") :default-value (nil) :constant-flag t) (reparse-symbol extern-c-contents) [1096 1130]) ("ST_DEFAULT_INIT_TABLE_SIZE" variable (:typemodifiers ("extern" "\"C\"") :default-value (nil) :constant-flag t) (reparse-symbol extern-c-contents) [1058 1095]) ("ST_DEFAULT_MAX_DENSITY" variable (:typemodifiers ("extern" "\"C\"") :default-value (nil) :constant-flag t) (reparse-symbol extern-c-contents) [1025 1057]))
+    :file "st.h"
+    :pointmax 7132
+    :unmatched-syntax 'nil
+    )
+   (semanticdb-table "st.c"
+    :major-mode 'c-mode
+    :tags '(("util.h" include nil nil [397 414]) ("st.h" include nil nil [415 430]) ("UNUSED" variable (:default-value "\" $Id: st.c,v 1.8 2005/04/13 05:02:20 fabio Exp $\"" :type "int") nil [1429 1489]) ("ST_NUMCMP" variable (:constant-flag t :default-value (nil)) nil [1739 1774]) ("ST_NUMHASH" variable (:constant-flag t :default-value (nil)) nil [1776 1824]) ("st_shift" variable (:constant-flag t :default-value (nil)) nil [1849 1867]) ("st_shift" variable (:constant-flag t :default-value (nil)) nil [1874 1892]) ("ST_PTRHASH" variable (:constant-flag t :default-value (nil)) nil [1901 1979]) ("EQUAL" variable (:constant-flag t :default-value (nil)) nil [1981 2125]) ("do_hash" variable (:constant-flag t :default-value (nil)) nil [2127 2382]) ("PTR_NOT_EQUAL" variable (:constant-flag t :default-value (nil)) nil [2384 2513]) ("FIND_ENTRY" variable (:constant-flag t :default-value (nil)) nil [2515 2579]) ("bins" variable (:dereference 1 :type "int") nil [2592 2607]) ("ADD_DIRECT" variable (:constant-flag t :default-value (nil)) nil [2986 3381]) ("rehash" function (:prototype-flag t :typemodifiers ("static") :arguments (("" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [3724 3735])) :type "int") nil [3705 3736]) ("st_init_table" function (:pointer 1 :arguments (("compare" variable (:type ("ST_PFICPCP" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5591 5610]) ("hash" variable (:type ("ST_PFICPI" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [5611 5626])) :type ("st_table" type (:type "class") nil nil)) nil [5566 5812]) ("st_init_table_with_params" function (:pointer 1 :arguments (("compare" variable (:type ("ST_PFICPCP" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6867 6886]) ("hash" variable (:type ("ST_PFICPI" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [6889 6904]) ("size" variable (:type "int") (reparse-symbol arg-sub-list) [6907 6916]) ("density" variable (:type "int") (reparse-symbol arg-sub-list) [6919 6931]) ("grow_factor" variable (:type "double") (reparse-symbol arg-sub-list) [6934 6953]) ("reorder_flag" variable (:type "int") (reparse-symbol arg-sub-list) [6956 6973])) :type ("st_table" type (:type "class") nil nil)) nil [6827 7568]) ("st_free_table" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8104 8120])) :type "void") nil [8085 8379]) ("st_lookup" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [8936 8952]) ("key" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [8953 8963]) ("value" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [8964 8976])) :type "int") nil [8922 9265]) ("st_lookup_int" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [9827 9843]) ("key" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [9844 9854]) ("value" variable (:pointer 1 :type "int") (reparse-symbol arg-sub-list) [9855 9866])) :type "int") nil [9809 10162]) ("st_insert" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [10732 10748]) ("key" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [10749 10759]) ("value" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [10760 10772])) :type "int") nil [10718 11478]) ("st_add_direct" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [12136 12152]) ("key" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [12153 12163]) ("value" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [12164 12176])) :type "int") nil [12118 12729]) ("st_find_or_add" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [14035 14051]) ("key" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [14052 14062]) ("slot" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [14063 14074])) :type "int") nil [14016 14843]) ("st_find" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [15226 15242]) ("key" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [15243 15253]) ("slot" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [15254 15265])) :type "int") nil [15214 15554]) ("st_copy" function (:pointer 1 :arguments (("old_table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [16001 16021])) :type ("st_table" type (:type "class") nil nil)) nil [15982 17060]) ("st_delete" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [17744 17760]) ("keyp" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [17761 17772]) ("value" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [17773 17785])) :type "int") nil [17730 18189]) ("st_delete_int" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [18915 18931]) ("keyp" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [18932 18943]) ("value" variable (:pointer 1 :type "int") (reparse-symbol arg-sub-list) [18944 18955])) :type "int") nil [18897 19365]) ("st_foreach" function (:arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [20401 20417]) ("func" variable (:type ("ST_PFSR" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [20418 20431]) ("arg" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [20432 20442])) :type "int") nil [20386 20951]) ("st_strhash" function (:arguments (("string" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [21278 21291]) ("modulus" variable (:type "int") (reparse-symbol arg-sub-list) [21292 21304])) :type "int") nil [21263 21452]) ("st_numhash" function (:arguments (("x" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [21797 21805]) ("size" variable (:type "int") (reparse-symbol arg-sub-list) [21806 21815])) :type "int") nil [21782 21852]) ("st_ptrhash" function (:arguments (("x" variable (:pointer 1 :type "char") (reparse-symbol arg-sub-list) [22191 22199]) ("size" variable (:type "int") (reparse-symbol arg-sub-list) [22200 22209])) :type "int") nil [22176 22246]) ("st_numcmp" function (:arguments (("x" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [22603 22617]) ("y" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [22618 22632])) :type "int") nil [22589 22665]) ("st_ptrcmp" function (:arguments (("x" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [23015 23029]) ("y" variable (:pointer 1 :constant-flag t :type "char") (reparse-symbol arg-sub-list) [23030 23044])) :type "int") nil [23001 23077]) ("st_init_gen" function (:pointer 1 :arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [23518 23534])) :type ("st_generator" type (:type "class") nil nil)) nil [23491 23764]) ("st_gen" function (:arguments (("gen" variable (:pointer 1 :type ("st_generator" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [24601 24619]) ("key_p" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [24620 24632]) ("value_p" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [24633 24647])) :type "int") nil [24590 25182]) ("st_gen_int" function (:arguments (("gen" variable (:pointer 1 :type ("st_generator" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [25850 25868]) ("key_p" variable (:pointer 1 :type "void") (reparse-symbol arg-sub-list) [25869 25881]) ("value_p" variable (:pointer 1 :type "int") (reparse-symbol arg-sub-list) [25882 25895])) :type "int") nil [25834 26436]) ("st_free_gen" function (:arguments (("gen" variable (:pointer 1 :type ("st_generator" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [26898 26916])) :type "void") nil [26881 26936]) ("rehash" function (:typemodifiers ("static") :arguments (("table" variable (:pointer 1 :type ("st_table" type (:type "class") nil nil)) (reparse-symbol arg-sub-list) [27751 27767])) :type "int") nil [27733 28867]))
+    :file "st.c"
+    :pointmax 28881
+    )
+   )
+  :file "semantic.cache"
+  :semantic-tag-version "2.0beta3"
+  :semanticdb-version "2.0beta3"
+  )
Index: /vis_dev/glu-2.1/src/st/st.c
===================================================================
--- /vis_dev/glu-2.1/src/st/st.c	(revision 8)
+++ /vis_dev/glu-2.1/src/st/st.c	(revision 8)
@@ -0,0 +1,1065 @@
+/**CFile***********************************************************************
+
+  FileName    [st.c]
+
+  PackageName [st]
+
+  Synopsis    [Symbol table package.]
+
+  Description [The st library provides functions to create, maintain,
+  and query symbol tables.]
+
+  SeeAlso     []
+
+  Author      []
+
+  Copyright   []
+
+******************************************************************************/
+
+#include "util.h"
+#include "st.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] UNUSED = " $Id: st.c,v 1.8 2005/04/13 05:02:20 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define ST_NUMCMP(x,y) ((x) != (y))
+
+#define ST_NUMHASH(x,size) (ABS((long)x)%(size))
+
+#if SIZEOF_VOID_P == 8
+#define st_shift 3
+#else
+#define st_shift 2
+#endif
+
+#define ST_PTRHASH(x,size) ((unsigned int)((unsigned long)(x)>>st_shift)%size)
+
+#define EQUAL(func, x, y) \
+    ((((func) == st_numcmp) || ((func) == st_ptrcmp)) ?\
+      (ST_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0))
+
+#define do_hash(key, table)\
+    ((int)((table->hash == st_ptrhash) ? ST_PTRHASH((char *)(key),(table)->num_bins) :\
+     (table->hash == st_numhash) ? ST_NUMHASH((char *)(key), (table)->num_bins) :\
+     (*table->hash)((char *)(key), (table)->num_bins)))
+
+#define PTR_NOT_EQUAL(table, ptr, user_key)\
+(ptr != NIL(st_table_entry) && !EQUAL(table->compare, (char *)user_key, (ptr)->key))
+
+#define FIND_ENTRY(table, hash_val, key, ptr, last) \
+    (last) = &(table)->bins[hash_val];\
+    (ptr) = *(last);\
+    while (PTR_NOT_EQUAL((table), (ptr), (key))) {\
+	(last) = &(ptr)->next; (ptr) = *(last);\
+    }\
+    if ((ptr) != NIL(st_table_entry) && (table)->reorder_flag) {\
+	*(last) = (ptr)->next;\
+	(ptr)->next = (table)->bins[hash_val];\
+	(table)->bins[hash_val] = (ptr);\
+    }
+
+/* This macro does not check if memory allocation fails. Use at you own risk */
+#define ADD_DIRECT(table, key, value, hash_val, newt)\
+{\
+    if (table->num_entries/table->num_bins >= table->max_density) {\
+	rehash(table);\
+	hash_val = do_hash(key,table);\
+    }\
+    \
+    newt = ALLOC(st_table_entry, 1);\
+    \
+    newt->key = (char *)key;\
+    newt->record = value;\
+    newt->next = table->bins[hash_val];\
+    table->bins[hash_val] = newt;\
+    table->num_entries++;\
+}
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int rehash (st_table *);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Create and initialize a table.]
+
+  Description [Create and initialize a table with the comparison function
+  compare_fn and hash function hash_fn. compare_fn is
+  <pre>
+	int compare_fn(const char *key1, const char *key2)
+  </pre>
+  It returns <,=,> 0 depending on whether key1 <,=,> key2 by some measure.<p>
+  hash_fn is
+  <pre>
+	int hash_fn(char *key, int modulus)
+  </pre>
+  It returns a integer between 0 and modulus-1 such that if
+  compare_fn(key1,key2) == 0 then hash_fn(key1) == hash_fn(key2).<p>
+  There are five predefined hash and comparison functions in st.
+  For keys as numbers:
+  <pre>
+	 st_numhash(key, modulus) { return (unsigned int) key % modulus; }
+  </pre>
+  <pre>
+	 st_numcmp(x,y) { return (int) x - (int) y; }
+  </pre>
+  For keys as pointers:
+  <pre>
+	 st_ptrhash(key, modulus) { return ((unsigned int) key/4) % modulus }
+  </pre>
+  <pre>
+	 st_ptrcmp(x,y) { return (int) x - (int) y; }
+  </pre>
+  For keys as strings:
+  <pre>
+         st_strhash(x,y) - a reasonable hashing function for strings
+  </pre>
+  <pre>
+	 strcmp(x,y) - the standard library function
+  </pre>
+  It is recommended to use these particular functions if they fit your 
+  needs, since st will recognize certain of them and run more quickly
+  because of it.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table_with_params st_free_table]
+
+******************************************************************************/
+st_table *
+st_init_table(ST_PFICPCP compare, ST_PFICPI hash)
+{
+    return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE,
+				     ST_DEFAULT_MAX_DENSITY,
+				     ST_DEFAULT_GROW_FACTOR,
+				     ST_DEFAULT_REORDER_FLAG);
+
+} /* st_init_table */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create a table with given parameters.]
+
+  Description [The full blown table initializer.  compare and hash are
+  the same as in st_init_table. density is the largest the average
+  number of entries per hash bin there should be before the table is
+  grown.  grow_factor is the factor the table is grown by when it
+  becomes too full. size is the initial number of bins to be allocated
+  for the hash table.  If reorder_flag is non-zero, then every time an
+  entry is found, it is moved to the top of the chain.<p>
+  st_init_table(compare, hash) is equivelent to
+  <pre>
+  st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE,
+			    ST_DEFAULT_MAX_DENSITY,
+			    ST_DEFAULT_GROW_FACTOR,
+			    ST_DEFAULT_REORDER_FLAG);
+  </pre>
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table st_free_table]
+
+******************************************************************************/
+st_table *
+st_init_table_with_params(
+  ST_PFICPCP compare,
+  ST_PFICPI hash,
+  int size,
+  int density,
+  double grow_factor,
+  int reorder_flag)
+{
+    int i;
+    st_table *newt;
+
+    newt = ALLOC(st_table, 1);
+    if (newt == NIL(st_table)) {
+	return NIL(st_table);
+    }
+    newt->compare = compare;
+    newt->hash = hash;
+    newt->num_entries = 0;
+    newt->max_density = density;
+    newt->grow_factor = grow_factor;
+    newt->reorder_flag = reorder_flag;
+    if (size <= 0) {
+	size = 1;
+    }
+    newt->num_bins = size;
+    newt->bins = ALLOC(st_table_entry *, size);
+    if (newt->bins == NIL(st_table_entry *)) {
+	FREE(newt);
+	return NIL(st_table);
+    }
+    for(i = 0; i < size; i++) {
+	newt->bins[i] = 0;
+    }
+    return newt;
+
+} /* st_init_table_with_params */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free a table.]
+
+  Description [Any internal storage associated with table is freed.
+  It is the user's responsibility to free any storage associated
+  with the pointers he placed in the table (by perhaps using
+  st_foreach).]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table st_init_table_with_params]
+
+******************************************************************************/
+void
+st_free_table(st_table *table)
+{
+    st_table_entry *ptr, *next;
+    int i;
+
+    for(i = 0; i < table->num_bins ; i++) {
+	ptr = table->bins[i];
+	while (ptr != NIL(st_table_entry)) {
+	    next = ptr->next;
+	    FREE(ptr);
+	    ptr = next;
+	}
+    }
+    FREE(table->bins);
+    FREE(table);
+
+} /* st_free_table */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Lookup up `key' in `table'.]
+
+  Description [Lookup up `key' in `table'. If an entry is found, 1 is
+  returned and if `value' is not nil, the variable it points to is set
+  to the associated value.  If an entry is not found, 0 is returned
+  and the variable pointed by value is unchanged.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_lookup_int]
+
+******************************************************************************/
+int
+st_lookup(st_table *table, void *key, void *value)
+{
+    int hash_val;
+    st_table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+
+    if (ptr == NIL(st_table_entry)) {
+	return 0;
+    } else {
+	if (value != NIL(void)) {
+	    *(char **)value = ptr->record;
+	}
+	return 1;
+    }
+
+} /* st_lookup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Lookup up `key' in `table'.]
+
+  Description [Lookup up `key' in `table'.  If an entry is found, 1 is
+  returned and if `value' is not nil, the variable it points to is
+  set to the associated integer value.  If an entry is not found, 0 is
+  return and the variable pointed by `value' is unchanged.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_lookup]
+
+******************************************************************************/
+int
+st_lookup_int(st_table *table, void *key, int *value)
+{
+    int hash_val;
+    st_table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+    
+    if (ptr == NIL(st_table_entry)) {
+	return 0;
+    } else {
+	if (value != NIL(int)) {
+	    *value = (int) (long) ptr->record;
+	}
+	return 1;
+    }
+
+} /* st_lookup_int */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Insert value in table under the key 'key'.]
+
+  Description [Insert value in table under the key 'key'.  Returns 1
+  if there was an entry already under the key; 0 if there was no entry
+  under the key and insertion was successful; ST_OUT_OF_MEM otherwise.
+  In either of the first two cases the new value is added.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+st_insert(st_table *table, void *key, void *value)
+{
+    int hash_val;
+    st_table_entry *newt;
+    st_table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+
+    if (ptr == NIL(st_table_entry)) {
+	if (table->num_entries/table->num_bins >= table->max_density) {
+	    if (rehash(table) == ST_OUT_OF_MEM) {
+		return ST_OUT_OF_MEM;
+	    }
+	    hash_val = do_hash(key, table);
+	}
+	newt = ALLOC(st_table_entry, 1);
+	if (newt == NIL(st_table_entry)) {
+	    return ST_OUT_OF_MEM;
+	}
+	newt->key = (char *)key;
+	newt->record = (char *)value;
+	newt->next = table->bins[hash_val];
+	table->bins[hash_val] = newt;
+	table->num_entries++;
+	return 0;
+    } else {
+	ptr->record = (char *)value;
+	return 1;
+    }
+
+} /* st_insert */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Place 'value' in 'table' under the key 'key'.]
+
+  Description [Place 'value' in 'table' under the key 'key'.  This is
+  done without checking if 'key' is in 'table' already.  This should
+  only be used if you are sure there is not already an entry for
+  'key', since it is undefined which entry you would later get from
+  st_lookup or st_find_or_add. Returns 1 if successful; ST_OUT_OF_MEM
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+st_add_direct(st_table *table, void *key, void *value)
+{
+    int hash_val;
+    st_table_entry *newt;
+    
+    hash_val = do_hash(key, table);
+    if (table->num_entries / table->num_bins >= table->max_density) {
+	if (rehash(table) == ST_OUT_OF_MEM) {
+	    return ST_OUT_OF_MEM;
+	}
+    }
+    hash_val = do_hash(key, table);
+    newt = ALLOC(st_table_entry, 1);
+    if (newt == NIL(st_table_entry)) {
+	return ST_OUT_OF_MEM;
+    }
+    newt->key = (char *)key;
+    newt->record = (char *)value;
+    newt->next = table->bins[hash_val];
+    table->bins[hash_val] = newt;
+    table->num_entries++;
+    return 1;
+
+} /* st_add_direct */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Lookup `key' in `table'.]
+
+  Description [Lookup `key' in `table'.  If not found, create an
+  entry.  In either case set slot to point to the field in the entry
+  where the value is stored.  The value associated with `key' may then
+  be changed by accessing directly through slot.  Returns 1 if an
+  entry already existed, 0 if it did not exist and creation was
+  successful; ST_OUT_OF_MEM otherwise.  As an example:
+  <pre>
+      char **slot;
+  </pre>
+  <pre>
+      char *key;
+  </pre>
+  <pre>
+      char *value = (char *) item_ptr <-- ptr to a malloc'd structure
+  </pre>
+  <pre>
+      if (st_find_or_add(table, key, &slot) == 1) {
+  </pre>
+  <pre>
+	 FREE(*slot); <-- free the old value of the record
+  </pre>
+  <pre>
+      }
+  </pre>
+  <pre>
+      *slot = value;  <-- attach the new value to the record
+  </pre>
+  This replaces the equivelent code:
+  <pre>
+      if (st_lookup(table, key, &ovalue) == 1) {
+  </pre>
+  <pre>
+         FREE(ovalue);
+  </pre>
+  <pre>
+      }
+  </pre>
+  <pre>
+      st_insert(table, key, value);
+  </pre>
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [st_find]
+
+******************************************************************************/
+int
+st_find_or_add(st_table *table, void *key, void *slot)
+{
+    int hash_val;
+    st_table_entry *newt, *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+
+    if (ptr == NIL(st_table_entry)) {
+	if (table->num_entries / table->num_bins >= table->max_density) {
+	    if (rehash(table) == ST_OUT_OF_MEM) {
+		return ST_OUT_OF_MEM;
+	    }
+	    hash_val = do_hash(key, table);
+	}
+	newt = ALLOC(st_table_entry, 1);
+	if (newt == NIL(st_table_entry)) {
+	    return ST_OUT_OF_MEM;
+	}
+	newt->key = (char *)key;
+	newt->record = (char *) 0;
+	newt->next = table->bins[hash_val];
+	table->bins[hash_val] = newt;
+	table->num_entries++;
+	if (slot != NIL(void)) *(char ***)slot = &newt->record;
+	return 0;
+    } else {
+	if (slot != NIL(void)) *(char ***)slot = &ptr->record;
+	return 1;
+    }
+
+} /* st_find_or_add */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Lookup `key' in `table'.]
+
+  Description [Like st_find_or_add, but does not create an entry if
+  one is not found.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_find_or_add]
+
+******************************************************************************/
+int
+st_find(st_table *table, void *key, void *slot)
+{
+    int hash_val;
+    st_table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr, last);
+
+    if (ptr == NIL(st_table_entry)) {
+	return 0;
+    } else {
+	if (slot != NIL(void)) {
+	    *(char ***)slot = &ptr->record;
+	}
+	return 1;
+    }
+
+} /* st_find */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return a copy of old_table and all its members.]
+
+  Description [Return a copy of old_table and all its members.
+  (st_table *) 0 is returned if there was insufficient memory to do
+  the copy.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+st_copy(st_table *old_table)
+{
+    st_table *new_table;
+    st_table_entry *ptr, *newptr, *next, *newt;
+    int i, j, num_bins = old_table->num_bins;
+
+    new_table = ALLOC(st_table, 1);
+    if (new_table == NIL(st_table)) {
+	return NIL(st_table);
+    }
+    
+    *new_table = *old_table;
+    new_table->bins = ALLOC(st_table_entry *, num_bins);
+    if (new_table->bins == NIL(st_table_entry *)) {
+	FREE(new_table);
+	return NIL(st_table);
+    }
+    for(i = 0; i < num_bins ; i++) {
+	new_table->bins[i] = NIL(st_table_entry);
+	ptr = old_table->bins[i];
+	while (ptr != NIL(st_table_entry)) {
+	    newt = ALLOC(st_table_entry, 1);
+	    if (newt == NIL(st_table_entry)) {
+		for (j = 0; j <= i; j++) {
+		    newptr = new_table->bins[j];
+		    while (newptr != NIL(st_table_entry)) {
+			next = newptr->next;
+			FREE(newptr);
+			newptr = next;
+		    }
+		}
+		FREE(new_table->bins);
+		FREE(new_table);
+		return NIL(st_table);
+	    }
+	    *newt = *ptr;
+	    newt->next = new_table->bins[i];
+	    new_table->bins[i] = newt;
+	    ptr = ptr->next;
+	}
+    }
+    return new_table;
+
+} /* st_copy */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Delete the entry with the key pointed to by `keyp'.]
+
+  Description [Delete the entry with the key pointed to by `keyp'.  If
+  the entry is found, 1 is returned, the variable pointed by `keyp' is
+  set to the actual key and the variable pointed by `value' is set to
+  the corresponding entry.  (This allows the freeing of the associated
+  storage.)  If the entry is not found, then 0 is returned and nothing
+  is changed.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_delete_int]
+
+******************************************************************************/
+int
+st_delete(st_table *table, void *keyp, void *value)
+{
+    int hash_val;
+    char *key = *(char **)keyp;
+    st_table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr ,last);
+    
+    if (ptr == NIL(st_table_entry)) {
+	return 0;
+    }
+
+    *last = ptr->next;
+    if (value != NIL(void)) *(char **)value = ptr->record;
+    *(char **)keyp = ptr->key;
+    FREE(ptr);
+    table->num_entries--;
+    return 1;
+
+} /* st_delete */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Delete the entry with the key pointed to by `keyp'.]
+
+  Description [Delete the entry with the key pointed to by `keyp'.
+  `value' must be a pointer to an integer.  If the entry is found, 1
+  is returned, the variable pointed by `keyp' is set to the actual key
+  and the variable pointed by `value' is set to the corresponding
+  entry.  (This allows the freeing of the associated storage.) If the
+  entry is not found, then 0 is returned and nothing is changed.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_delete]
+
+******************************************************************************/
+int
+st_delete_int(st_table *table, void *keyp, int *value)
+{
+    int hash_val;
+    char *key = *(char **)keyp;
+    st_table_entry *ptr, **last;
+
+    hash_val = do_hash(key, table);
+
+    FIND_ENTRY(table, hash_val, key, ptr ,last);
+
+    if (ptr == NIL(st_table_entry)) {
+        return 0;
+    }
+
+    *last = ptr->next;
+    if (value != NIL(int)) *value = (int) (long) ptr->record;
+    *(char **)keyp = ptr->key;
+    FREE(ptr);
+    table->num_entries--;
+    return 1;
+
+} /* st_delete_int */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Iterates over the elements of a table.]
+
+  Description [For each (key, value) record in `table', st_foreach
+  call func with the arguments
+  <pre>
+	  (*func)(key, value, arg)
+  </pre>
+  If func returns ST_CONTINUE, st_foreach continues processing
+  entries.  If func returns ST_STOP, st_foreach stops processing and
+  returns immediately. If func returns ST_DELETE, then the entry is
+  deleted from the symbol table and st_foreach continues.  In the case
+  of ST_DELETE, it is func's responsibility to free the key and value,
+  if necessary.<p>
+
+  The routine returns 1 if all items in the table were generated and 0
+  if the generation sequence was aborted using ST_STOP.  The order in
+  which the records are visited will be seemingly random.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_foreach_item st_foreach_item_int]
+
+******************************************************************************/
+int
+st_foreach(st_table *table, ST_PFSR func, char *arg)
+{
+    st_table_entry *ptr, **last;
+    enum st_retval retval;
+    int i;
+
+    for(i = 0; i < table->num_bins; i++) {
+	last = &table->bins[i]; ptr = *last;
+	while (ptr != NIL(st_table_entry)) {
+	    retval = (*func)(ptr->key, ptr->record, arg);
+	    switch (retval) {
+	    case ST_CONTINUE:
+		last = &ptr->next; ptr = *last;
+		break;
+	    case ST_STOP:
+		return 0;
+	    case ST_DELETE:
+		*last = ptr->next;
+		table->num_entries--;	/* cstevens@ic */
+		FREE(ptr);
+		ptr = *last;
+	    }
+	}
+    }
+    return 1;
+
+} /* st_foreach */
+
+
+/**Function********************************************************************
+
+  Synopsis    [String hash function.]
+
+  Description [String hash function.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table]
+
+******************************************************************************/
+int
+st_strhash(char *string, int modulus)
+{
+    int val = 0;
+    int c;
+    
+    while ((c = *string++) != '\0') {
+	val = val*997 + c;
+    }
+
+    return ((val < 0) ? -val : val)%modulus;
+
+} /* st_strhash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Number hash function.]
+
+  Description [Integer number hash function.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table st_numcmp]
+
+******************************************************************************/
+int
+st_numhash(char *x, int size)
+{
+    return ST_NUMHASH(x, size);
+
+} /* st_numhash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Pointer hash function.]
+
+  Description [Pointer hash function.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table st_ptrcmp]
+
+******************************************************************************/
+int
+st_ptrhash(char *x, int size)
+{
+    return ST_PTRHASH(x, size);
+
+} /* st_ptrhash */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Number comparison function.]
+
+  Description [integer number comparison function.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table st_numhash]
+
+******************************************************************************/
+int
+st_numcmp(const char *x, const char *y)
+{
+    return ST_NUMCMP(x, y);
+
+} /* st_numcmp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Pointer comparison function.]
+
+  Description [Pointer comparison function.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_table st_ptrhash]
+
+******************************************************************************/
+int
+st_ptrcmp(const char *x, const char *y)
+{
+    return ST_NUMCMP(x, y);
+
+} /* st_ptrcmp */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a generator.]
+
+  Description [Returns a generator handle which when used with
+  st_gen() will progressively return each (key, value) record in
+  `table'.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_free_gen]
+
+******************************************************************************/
+st_generator *
+st_init_gen(st_table *table)
+{
+    st_generator *gen;
+
+    gen = ALLOC(st_generator, 1);
+    if (gen == NIL(st_generator)) {
+	return NIL(st_generator);
+    }
+    gen->table = table;
+    gen->entry = NIL(st_table_entry);
+    gen->index = 0;
+    return gen;
+
+} /* st_init_gen */
+
+
+/**Function********************************************************************
+
+  Synopsis [returns the next (key, value) pair in the generation
+  sequence. ]
+
+  Description [Given a generator returned by st_init_gen(), this
+  routine returns the next (key, value) pair in the generation
+  sequence.  The pointer `value_p' can be zero which means no value
+  will be returned.  When there are no more items in the generation
+  sequence, the routine returns 0.
+
+  While using a generation sequence, deleting any (key, value) pair
+  other than the one just generated may cause a fatal error when
+  st_gen() is called later in the sequence and is therefore not
+  recommended.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_gen_int]
+
+******************************************************************************/
+int
+st_gen(st_generator *gen, void *key_p, void *value_p)
+{
+    int i;
+
+    if (gen->entry == NIL(st_table_entry)) {
+	/* try to find next entry */
+	for(i = gen->index; i < gen->table->num_bins; i++) {
+	    if (gen->table->bins[i] != NIL(st_table_entry)) {
+		gen->index = i+1;
+		gen->entry = gen->table->bins[i];
+		break;
+	    }
+	}
+	if (gen->entry == NIL(st_table_entry)) {
+	    return 0;		/* that's all folks ! */
+	}
+    }
+    *(char **)key_p = gen->entry->key;
+    if (value_p != NIL(void)) {
+	*(char **)value_p = gen->entry->record;
+    }
+    gen->entry = gen->entry->next;
+    return 1;
+
+} /* st_gen */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the next (key, value) pair in the generation
+  sequence.]
+
+  Description [Given a generator returned by st_init_gen(), this
+  routine returns the next (key, value) pair in the generation
+  sequence.  `value_p' must be a pointer to an integer.  The pointer
+  `value_p' can be zero which means no value will be returned.  When
+  there are no more items in the generation sequence, the routine
+  returns 0.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_gen]
+
+******************************************************************************/
+int 
+st_gen_int(st_generator *gen, void *key_p, int *value_p)
+{
+    int i;
+
+    if (gen->entry == NIL(st_table_entry)) {
+	/* try to find next entry */
+	for(i = gen->index; i < gen->table->num_bins; i++) {
+	    if (gen->table->bins[i] != NIL(st_table_entry)) {
+		gen->index = i+1;
+		gen->entry = gen->table->bins[i];
+		break;
+	    }
+	}
+	if (gen->entry == NIL(st_table_entry)) {
+	    return 0;		/* that's all folks ! */
+	}
+    }
+    *(char **)key_p = gen->entry->key;
+    if (value_p != NIL(int)) {
+   	*value_p = (int) (long) gen->entry->record;
+    }
+    gen->entry = gen->entry->next;
+    return 1;
+
+} /* st_gen_int */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reclaims the resources associated with `gen'.]
+
+  Description [After generating all items in a generation sequence,
+  this routine must be called to reclaim the resources associated with
+  `gen'.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_init_gen]
+
+******************************************************************************/
+void
+st_free_gen(st_generator *gen)
+{
+    FREE(gen);
+
+} /* st_free_gen */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Rehashes a symbol table.]
+
+  Description [Rehashes a symbol table.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_insert]
+
+******************************************************************************/
+static int
+rehash(st_table *table)
+{
+    st_table_entry *ptr, *next, **old_bins;
+    int             i, old_num_bins, hash_val, old_num_entries;
+
+    /* save old values */
+    old_bins = table->bins;
+    old_num_bins = table->num_bins;
+    old_num_entries = table->num_entries;
+
+    /* rehash */
+    table->num_bins = (int) (table->grow_factor * old_num_bins);
+    if (table->num_bins % 2 == 0) {
+	table->num_bins += 1;
+    }
+    table->num_entries = 0;
+    table->bins = ALLOC(st_table_entry *, table->num_bins);
+    if (table->bins == NIL(st_table_entry *)) {
+	table->bins = old_bins;
+	table->num_bins = old_num_bins;
+	table->num_entries = old_num_entries;
+	return ST_OUT_OF_MEM;
+    }
+    /* initialize */
+    for (i = 0; i < table->num_bins; i++) {
+	table->bins[i] = 0;
+    }
+
+    /* copy data over */
+    for (i = 0; i < old_num_bins; i++) {
+	ptr = old_bins[i];
+	while (ptr != NIL(st_table_entry)) {
+	    next = ptr->next;
+	    hash_val = do_hash(ptr->key, table);
+	    ptr->next = table->bins[hash_val];
+	    table->bins[hash_val] = ptr;
+	    table->num_entries++;
+	    ptr = next;
+	}
+    }
+    FREE(old_bins);
+
+    return 1;
+
+} /* rehash */
Index: /vis_dev/glu-2.1/src/st/st.h
===================================================================
--- /vis_dev/glu-2.1/src/st/st.h	(revision 8)
+++ /vis_dev/glu-2.1/src/st/st.h	(revision 8)
@@ -0,0 +1,232 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [st.h]
+
+  PackageName [st]
+
+  Synopsis    [Symbol table package.]
+
+  Description [The st library provides functions to create, maintain,
+  and query symbol tables.]
+
+  SeeAlso     []
+
+  Author      []
+
+  Copyright   []
+
+  Revision    [$Id: st.h,v 1.4 2005/04/13 05:02:20 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef ST_INCLUDED
+#define ST_INCLUDED
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define ST_DEFAULT_MAX_DENSITY 5
+#define ST_DEFAULT_INIT_TABLE_SIZE 11
+#define ST_DEFAULT_GROW_FACTOR 2.0
+#define ST_DEFAULT_REORDER_FLAG 0
+#define ST_OUT_OF_MEM -10000
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct st_table_entry st_table_entry;
+struct st_table_entry {
+    char *key;
+    char *record;
+    st_table_entry *next;
+};
+
+typedef struct st_table st_table;
+struct st_table {
+    int (*compare)(const char *, const char *);
+    int (*hash)(char *, int);
+    int num_bins;
+    int num_entries;
+    int max_density;
+    int reorder_flag;
+    double grow_factor;
+    st_table_entry **bins;
+};
+
+typedef struct st_generator st_generator;
+struct st_generator {
+    st_table *table;
+    st_table_entry *entry;
+    int index;
+};
+
+enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
+
+typedef enum st_retval (*ST_PFSR)(char *, char *, char *);
+
+typedef int (*ST_PFICPCP)(const char *, const char *); /* type for comparison function */
+
+typedef int (*ST_PFICPI)(char *, int);     /* type for hash function */
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Checks whethere `key' is in `table'.]
+
+  Description [Returns 1 if there is an entry under `key' in `table', 0
+  otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     [st_lookup]
+
+******************************************************************************/
+#define st_is_member(table,key) st_lookup(table,key,(char **) 0)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns the number of entries in the table `table'.]
+
+  Description [Returns the number of entries in the table `table'.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define st_count(table) ((table)->num_entries)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Iteration macro.]
+
+  Description [An iteration macro which loops over all the entries in
+  `table', setting `key' to point to the key and `value' to the
+  associated value (if it is not nil). `gen' is a generator variable
+  used internally. Sample usage:
+  <pre>
+     	char *key, *value;
+  </pre>
+  <pre>
+	st_generator *gen;
+  </pre>
+  <pre>
+
+	st_foreach_item(table, gen, &key, &value) {
+  </pre>
+  <pre>
+	    process_item(value);
+  </pre>
+  <pre>
+	}
+  </pre>
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [st_foreach_item_int st_foreach]
+
+******************************************************************************/
+#define st_foreach_item(table, gen, key, value) \
+    for(gen=st_init_gen(table); st_gen(gen,key,value) || (st_free_gen(gen),0);)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Iteration macro.]
+
+  Description [An iteration macro which loops over all the entries in
+  `table', setting `key' to point to the key and `value' to the
+  associated value (if it is not nil). `value' is assumed to be a
+  pointer to an integer.  `gen' is a generator variable used
+  internally. Sample usage:
+  <pre>
+     	char *key;
+  </pre>
+  <pre>
+	int value;
+  </pre>
+  <pre>
+	st_generator *gen;
+  </pre>
+  <pre>
+
+	st_foreach_item_int(table, gen, &key, &value) {
+  </pre>
+  <pre>
+	    process_item(value);
+  </pre>
+  <pre>
+	}
+  </pre>
+  ]
+
+  SideEffects [None]
+
+  SeeAlso     [st_foreach_item st_foreach]
+
+******************************************************************************/
+#define st_foreach_item_int(table, gen, key, value) \
+    for(gen=st_init_gen(table); st_gen_int(gen,key,value) || (st_free_gen(gen),0);)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+extern st_table *st_init_table_with_params (ST_PFICPCP, ST_PFICPI, int, int, double, int);
+extern st_table *st_init_table (ST_PFICPCP, ST_PFICPI); 
+extern void st_free_table (st_table *);
+extern int st_lookup (st_table *, void *, void *);
+extern int st_lookup_int (st_table *, void *, int *);
+extern int st_insert (st_table *, void *, void *);
+extern int st_add_direct (st_table *, void *, void *);
+extern int st_find_or_add (st_table *, void *, void *);
+extern int st_find (st_table *, void *, void *);
+extern st_table *st_copy (st_table *);
+extern int st_delete (st_table *, void *, void *);
+extern int st_delete_int (st_table *, void *, int *);
+extern int st_foreach (st_table *, ST_PFSR, char *);
+extern int st_strhash (char *, int);
+extern int st_numhash (char *, int);
+extern int st_ptrhash (char *, int);
+extern int st_numcmp (const char *, const char *);
+extern int st_ptrcmp (const char *, const char *);
+extern st_generator *st_init_gen (st_table *);
+extern int st_gen (st_generator *, void *, void *);
+extern int st_gen_int (st_generator *, void *, int *);
+extern void st_free_gen (st_generator *);
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* ST_INCLUDED */
Index: /vis_dev/glu-2.1/src/st/st.make
===================================================================
--- /vis_dev/glu-2.1/src/st/st.make	(revision 8)
+++ /vis_dev/glu-2.1/src/st/st.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += st.c
+HEADERS += st.h
+MISC += st.doc
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/util/cpu_stats.c
===================================================================
--- /vis_dev/glu-2.1/src/util/cpu_stats.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/cpu_stats.c	(revision 8)
@@ -0,0 +1,105 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: cpu_stats.c,v 1.12 2005/05/16 16:25:24 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+#include <stdio.h>
+#include "util.h"
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#  include <sys/resource.h>
+#endif
+
+#if defined(_IBMR2)
+#define etext _etext
+#define edata _edata
+#define end _end
+#endif
+
+#ifndef __CYGWIN32__
+extern int end, etext, edata;
+#endif
+
+void
+util_print_cpu_stats(FILE *fp)
+{
+#if HAVE_SYS_RESOURCE_H && !defined(__CYGWIN32__)
+    struct rusage rusage;
+#ifdef RLIMIT_DATA
+    struct rlimit rlp;
+    long vm_limit, vm_soft_limit;
+#endif
+    long text, data;
+    double user, system, scale;
+    char hostname[257];
+    long vm_text, vm_init_data, vm_uninit_data, vm_sbrk_data;
+
+    /* Get the hostname */
+    (void) gethostname(hostname, 256);
+    hostname[256] = '\0';		/* just in case */
+
+    /* Get the virtual memory sizes */
+    vm_text = (long) (((long) (&etext)) / 1024.0 + 0.5);
+    vm_init_data = (long) (((&edata) - (&etext)) / 1024.0 + 0.5);
+    vm_uninit_data = (long) (((&end) - (&edata)) / 1024.0 + 0.5);
+    vm_sbrk_data = (long) ((sizeof(char) * ((char *) sbrk(0) - (char *) (&end))) / 1024.0 + 0.5); 
+
+    /* Get virtual memory limits */
+#ifdef RLIMIT_DATA /* In HP-UX, with cc, this constant does not exist */
+    (void) getrlimit(RLIMIT_DATA, &rlp);
+    vm_limit = (long) (rlp.rlim_max / 1024.0 + 0.5);
+    vm_soft_limit = (long) (rlp.rlim_cur / 1024.0 + 0.5);
+#endif
+
+    /* Get usage stats */
+    (void) getrusage(RUSAGE_SELF, &rusage);
+    user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec/1.0e6;
+    system = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6;
+    scale = (user + system)*100.0;
+    if (scale == 0.0) scale = 0.001;
+
+    (void) fprintf(fp, "Runtime Statistics\n");
+    (void) fprintf(fp, "------------------\n");
+    (void) fprintf(fp, "Machine name: %s\n", hostname);
+    (void) fprintf(fp, "User time   %6.1f seconds\n", user);
+    (void) fprintf(fp, "System time %6.1f seconds\n\n", system);
+
+    text = (long) (rusage.ru_ixrss / scale + 0.5);
+    data = (long) ((rusage.ru_idrss + rusage.ru_isrss) / scale + 0.5);
+    (void) fprintf(fp, "Average resident text size       = %5ldK\n", text);
+    (void) fprintf(fp, "Average resident data+stack size = %5ldK\n", data);
+    (void) fprintf(fp, "Maximum resident size            = %5ldK\n\n", 
+	rusage.ru_maxrss/2);
+    (void) fprintf(fp, "Virtual text size                = %5ldK\n", 
+	vm_text);
+    (void) fprintf(fp, "Virtual data size                = %5ldK\n", 
+	vm_init_data + vm_uninit_data + vm_sbrk_data);
+    (void) fprintf(fp, "    data size initialized        = %5ldK\n", 
+	vm_init_data);
+    (void) fprintf(fp, "    data size uninitialized      = %5ldK\n", 
+	vm_uninit_data);
+    (void) fprintf(fp, "    data size sbrk               = %5ldK\n", 
+	vm_sbrk_data);
+    /* In some platforms, this constant does not exist */
+#ifdef RLIMIT_DATA 
+    (void) fprintf(fp, "Virtual memory limit             = %5ldK (%ldK)\n\n", 
+	vm_soft_limit, vm_limit);
+#endif
+    (void) fprintf(fp, "Major page faults = %ld\n", rusage.ru_majflt);
+    (void) fprintf(fp, "Minor page faults = %ld\n", rusage.ru_minflt);
+    (void) fprintf(fp, "Swaps = %ld\n", rusage.ru_nswap);
+    (void) fprintf(fp, "Input blocks = %ld\n", rusage.ru_inblock);
+    (void) fprintf(fp, "Output blocks = %ld\n", rusage.ru_oublock);
+    (void) fprintf(fp, "Context switch (voluntary) = %ld\n", rusage.ru_nvcsw);
+    (void) fprintf(fp, "Context switch (involuntary) = %ld\n", rusage.ru_nivcsw);
+#else /* Do not have sys/resource.h */
+    (void) fprintf(fp, "Usage statistics not available\n");
+#endif
+}
+
Index: /vis_dev/glu-2.1/src/util/cpu_time.c
===================================================================
--- /vis_dev/glu-2.1/src/util/cpu_time.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/cpu_time.c	(revision 8)
@@ -0,0 +1,189 @@
+/**CFile***********************************************************************
+
+  FileName    [ cpu_time.c ]
+
+  PackageName [ util ]
+
+  Synopsis    [ System time calls ]
+
+  Description [ The problem is that all unix systems have a different notion
+		of how fast time goes (i.e., the units returned by).  This
+		returns a consistent result. ]
+
+  Author      [ Stephen Edwards <sedwards@eecs.berkeley.edu> and others ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "util.h"
+
+#if HAVE_SYS_TYPES_H
+#  include<sys/types.h>
+#endif
+
+#if HAVE_SYS_TIMES_H
+#  include<sys/times.h>
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/**Function********************************************************************
+
+  Synopsis           [ Return elapsed time in milliseconds ]
+
+  Description        [ Return a long which represents the elapsed time in
+		       milliseconds since some constant reference. <P>
+
+		       There are two possibilities:
+		       <OL>
+		       <LI> The system is non-POSIX compliant, so unistd.h
+		            and hence sysconf() can't tell us the clock tick
+			    speed.  At this point, we have to resort to
+			    using the user-settable CLOCK_RESOLUTION definition
+			    to get the right speed
+		       <LI> The system is POSIX-compliant.  unistd.h gives
+		            us sysconf(), which tells us the clock rate.
+		       </OL>
+ ]
+
+  SideEffects        [ none ]
+
+******************************************************************************/
+long 
+util_cpu_time(void)
+{
+    long t = 0;
+
+#if HAVE_SYSCONF == 1
+
+    /* Code for POSIX systems */
+
+    struct tms buffer;
+    long nticks;                /* number of clock ticks per second */
+
+    nticks = sysconf(_SC_CLK_TCK);
+    times(&buffer);
+    t = (long) (buffer.tms_utime * (1000.0/nticks));
+
+#else
+#  ifndef vms
+
+    /* Code for non-POSIX systems */
+
+    struct tms buffer;
+
+    time(&buffer);
+    t = buffer.tms_utime * 1000.0 / CLOCK_RESOLUTION;
+
+#  else
+
+    /* Code for VMS (?) */
+
+    struct {int p1, p2, p3, p4;} buffer;
+    static long ref_time;
+    times(&buffer);
+    t = buffer.p1 * 10;
+    if (ref_time == 0)
+      ref_time = t;
+    t = t - ref_time;
+
+#  endif /* vms */
+#endif /* _POSIX_VERSION */
+
+    return t;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [ Return elapsed time in milliseconds. It includes waited-
+                       for terminated children. ]
+
+  Description        [ Return a long which represents the elapsed time in
+		       milliseconds since some constant reference. This time
+                       includes the CPU time spent executing instructions of
+		       the calling process and the time this process waited
+		       for its children to be terminated<P>
+
+		       There are two possibilities:
+		       <OL>
+		       <LI> The system is non-POSIX compliant, so unistd.h
+		            and hence sysconf() can't tell us the clock tick
+			    speed.  At this point, we have to resort to
+			    using the user-settable CLOCK_RESOLUTION definition
+			    to get the right speed
+		       <LI> The system is POSIX-compliant.  unistd.h gives
+		            us sysconf(), which tells us the clock rate.
+		       </OL>
+ ]
+
+  SideEffects        [ none ]
+
+******************************************************************************/
+long 
+util_cpu_ctime(void)
+{
+    long t = 0;
+
+#if HAVE_SYSCONF == 1
+
+    /* Code for POSIX systems */
+
+    struct tms buffer;
+    long nticks;                /* number of clock ticks per second */
+
+    nticks = sysconf(_SC_CLK_TCK);
+    times(&buffer);
+    t = (long) ((buffer.tms_utime + buffer.tms_cutime) * (1000.0/nticks));
+
+#else
+#  ifndef vms
+
+    /* Code for non-POSIX systems */
+
+    struct tms buffer;
+
+    time(&buffer);
+    t = (buffer.tms_utime + buffer.tms_cutime) * 1000.0 / CLOCK_RESOLUTION;
+
+#  else
+
+    /* Code for VMS (?) */
+
+    struct {int p1, p2, p3, p4;} buffer;
+    static long ref_time;
+    times(&buffer);
+    t = (buffer.p1 + buffer.p3) * 10;
+    if (ref_time == 0)
+      ref_time = t;
+    t = t - ref_time;
+
+#  endif /* vms */
+#endif /* _POSIX_VERSION */
+
+    return t;
+}
+
Index: /vis_dev/glu-2.1/src/util/datalimit.c
===================================================================
--- /vis_dev/glu-2.1/src/util/datalimit.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/datalimit.c	(revision 8)
@@ -0,0 +1,95 @@
+/**CFile************************************************************************
+
+  FileName    [datalimit.c]
+
+  PackageName [util]
+
+  Synopsis [Routine to obtain the maximum data size available to a program. The
+  routine is based on "getrlimit". If the system does not have this function,
+  the default value RLIMIT_DATA_DEFAULT is assumed. This function provides an
+  informative value, it does not restrict the size of the program in any way.]
+
+  Author      [Fabio Somenzi <fabio@colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "util.h"
+
+static char rcsid[] UNUSED = "$Id: datalimit.c,v 1.5 2003/08/01 15:42:30 fabio Exp $";
+
+#if HAVE_SYS_RESOURCE_H
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#ifndef RLIMIT_DATA_DEFAULT
+#define RLIMIT_DATA_DEFAULT 67108864	/* assume 64MB by default */
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Function that computes the data limit of the process.]
+
+  SideEffects        []
+
+******************************************************************************/
+long
+getSoftDataLimit(void)
+{
+#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && defined(RLIMIT_DATA)
+    struct rlimit rl;
+    int result;
+
+    result = getrlimit(RLIMIT_DATA, &rl);
+    if (result != 0 || rl.rlim_cur == RLIM_INFINITY)
+	return((long) RLIMIT_DATA_DEFAULT);
+    else
+	return((long) rl.rlim_cur);
+#else
+    return((long) RLIMIT_DATA_DEFAULT);
+#endif
+
+} /* end of getSoftDataLimit */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: /vis_dev/glu-2.1/src/util/getopt.c
===================================================================
--- /vis_dev/glu-2.1/src/util/getopt.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/getopt.c	(revision 8)
@@ -0,0 +1,78 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: getopt.c,v 1.4 2002/09/10 00:04:35 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+#include <stdio.h>
+#include "util.h"
+
+
+/*  File   : getopt.c
+ *  Author : Henry Spencer, University of Toronto
+ *  Updated: 28 April 1984
+ *
+ *  Changes: (R Rudell)
+ *	changed index() to strchr();
+ *	added getopt_reset() to reset the getopt argument parsing
+ *
+ *  Purpose: get option letter from argv.
+ */
+
+char *util_optarg;	/* Global argument pointer. */
+int util_optind = 0;	/* Global argv index. */
+static char *scan;
+
+
+void
+util_getopt_reset(void)
+{
+    util_optarg = 0;
+    util_optind = 0;
+    scan = 0;
+}
+
+
+
+int 
+util_getopt(int argc, char *argv[], char *optstring)
+{
+    register int c;
+    register char *place;
+
+    util_optarg = NIL(char);
+
+    if (scan == NIL(char) || *scan == '\0') {
+	if (util_optind == 0) util_optind++;
+	if (util_optind >= argc) return EOF;
+	place = argv[util_optind];
+	if (place[0] != '-' || place[1] == '\0') return EOF;
+	util_optind++;
+	if (place[1] == '-' && place[2] == '\0') return EOF;
+	scan = place+1;
+    }
+
+    c = *scan++;
+    place = strchr(optstring, c);
+    if (place == NIL(char) || c == ':') {
+	(void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+	return '?';
+    }
+    if (*++place == ':') {
+	if (*scan != '\0') {
+	    util_optarg = scan;
+	    scan = NIL(char);
+	} else {
+	    if (util_optind >= argc) {
+		(void) fprintf(stderr, "%s: %c requires an argument\n", 
+		    argv[0], c);
+		return '?';
+	    }
+	    util_optarg = argv[util_optind];
+	    util_optind++;
+	}
+    }
+    return c;
+}
Index: /vis_dev/glu-2.1/src/util/pathsearch.c
===================================================================
--- /vis_dev/glu-2.1/src/util/pathsearch.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/pathsearch.c	(revision 8)
@@ -0,0 +1,124 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: pathsearch.c,v 1.7 2005/04/30 22:38:11 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+#if HAVE_SYS_FILE_H
+#  include <sys/file.h>
+#endif
+
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+
+#include "util.h"
+
+/**Function********************************************************************
+
+  Synopsis           [ Check that a given file is present and accessible ]
+
+  SideEffects        [none]
+******************************************************************************/
+int
+util_check_file(char *filename, char *mode)
+{
+#if defined(HAVE_SYS_STAT_H)
+    struct stat stat_rec;
+    int access_char = mode[0];
+    int access_mode = R_OK;
+
+    /* First check that the file is a regular file. */
+
+    if (stat(filename,&stat_rec) == 0 && S_ISREG(stat_rec.st_mode)) {
+	if (access_char == 'w') {
+	    access_mode = W_OK;
+	} else if (access_char == 'x') {
+	    access_mode = X_OK;
+	}
+	return access(filename,access_mode) == 0;
+    }
+    return 0;
+
+#else
+
+    FILE *fp;
+    int got_file;
+
+    if (strcmp(mode, "x") == 0) {
+	mode = "r";
+    }
+    fp = fopen(filename, mode);
+    got_file = (fp != 0);
+    if (fp != 0) {
+	(void) fclose(fp);
+    }
+    return got_file;
+
+#endif
+}
+
+/**Function********************************************************************
+
+  Synopsis           [ Search for a program in all possible paths ]
+
+  SideEffects        [none]
+
+******************************************************************************/
+char *
+util_path_search(char *prog)
+{
+#ifdef HAVE_GETENV
+    return util_file_search(prog, getenv("PATH"), "x");
+#else
+    return util_file_search(prog, NIL(char), "x");
+#endif
+}
+
+char *
+util_file_search(
+  char *file	/* file we're looking for */,
+  char *path	/* search path, colon separated */,
+  char *mode	/* "r", "w", or "x" */)
+{
+    int quit;
+    char *buffer, *filename, *save_path, *cp;
+
+    if (path == 0 || strcmp(path, "") == 0) {
+	path = ".";		/* just look in the current directory */
+    }
+
+    save_path = path = util_strsav(path);
+    quit = 0;
+    do {
+	cp = strchr(path, ':');
+	if (cp != 0) {
+	    *cp = '\0';
+	} else {
+	    quit = 1;
+	}
+
+	/* cons up the filename out of the path and file name */
+	if (strcmp(path, ".") == 0) {
+	    buffer = util_strsav(file);
+	} else {
+	    buffer = ALLOC(char, strlen(path) + strlen(file) + 4);
+	    (void) sprintf(buffer, "%s/%s", path, file);
+	}
+	filename = util_tilde_expand(buffer);
+	FREE(buffer);
+
+	/* see if we can access it */
+	if (util_check_file(filename, mode)) {
+	    FREE(save_path);
+	    return filename;
+	}
+	FREE(filename);
+	path = ++cp;
+    } while (! quit); 
+
+    FREE(save_path);
+    return 0;
+}
Index: /vis_dev/glu-2.1/src/util/prtime.c
===================================================================
--- /vis_dev/glu-2.1/src/util/prtime.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/prtime.c	(revision 8)
@@ -0,0 +1,27 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: prtime.c,v 1.3 2002/08/25 02:37:11 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+#include <stdio.h>
+#include "util.h"
+
+
+/*
+ *  util_print_time -- massage a long which represents a time interval in
+ *  milliseconds, into a string suitable for output 
+ *
+ *  Hack for IBM/PC -- avoids using floating point
+ */
+
+char *
+util_print_time(long t)
+{
+    static char s[40];
+
+    (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10);
+    return s;
+}
Index: /vis_dev/glu-2.1/src/util/qsort.c
===================================================================
--- /vis_dev/glu-2.1/src/util/qsort.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/qsort.c	(revision 8)
@@ -0,0 +1,251 @@
+/**CFile***********************************************************************
+
+  FileName    [qsort.c]
+
+  PackageName [util]
+
+  Synopsis    [Our own qsort routine.]
+
+  Author      []
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "util.h"
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: qsort.c,v 1.5 2002/08/25 05:30:13 fabio Exp $";
+#endif
+
+#define		THRESH		4		/* threshold for insertion */
+#define		MTHRESH		6		/* threshold for median */
+
+static  int		(*qcmp)(const void *, const void *);
+						/* the comparison routine */
+static  int		qsz;			/* size of each record */
+static  int		thresh;			/* THRESHold in chars */
+static  int		mthresh;		/* MTHRESHold in chars */
+static	void		qst ARGS((char *base, char *max));
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+#undef min
+#undef max
+/**Function********************************************************************
+
+  Synopsis           [Own version of the system qsort routine.]
+
+  Description [The THRESHold below is the insertion sort threshold, and has
+  been adjusted for records of size 48 bytes.  The MTHREShold is where we stop
+  finding a better median. First, set up some global parameters for qst to
+  share.  Then, quicksort with qst(), and then a cleanup insertion sort
+  ourselves.  Sound simple?  It's not...]
+
+  SideEffects        []
+
+  SeeAlso            [qst]
+
+******************************************************************************/
+void
+qsort(
+  void *vbase,
+  size_t n,
+  size_t size,
+  int (*compar)(const void *, const void *))
+{
+	register char c, *i, *j, *lo, *hi;
+	char *min, *max, *base;
+
+	if (n <= 1)
+		return;
+	base = (char *) vbase;
+	qsz = size;
+	qcmp = compar;
+	thresh = qsz * THRESH;
+	mthresh = qsz * MTHRESH;
+	max = base + n * qsz;
+	if (n >= THRESH) {
+		qst(base, max);
+		hi = base + thresh;
+	} else {
+		hi = max;
+	}
+	/*
+	 * First put smallest element, which must be in the first THRESH, in
+	 * the first position as a sentinel.  This is done just by searching
+	 * the first THRESH elements (or the first n if n < THRESH), finding
+	 * the min, and swapping it into the first position.
+	 */
+	for (j = lo = base; (lo += qsz) < hi; )
+		if ((*qcmp)(j, lo) > 0)
+			j = lo;
+	if (j != base) {
+		/* swap j into place */
+		for (i = base, hi = base + qsz; i < hi; ) {
+			c = *j;
+			*j++ = *i;
+			*i++ = c;
+		}
+	}
+	/*
+	 * With our sentinel in place, we now run the following hyper-fast
+	 * insertion sort. For each remaining element, min, from [1] to [n-1],
+	 * set hi to the index of the element AFTER which this one goes.
+	 * Then, do the standard insertion sort shift on a character at a time
+	 * basis for each element in the frob.
+	 */
+	for (min = base; (hi = min += qsz) < max; ) {
+		while ((*qcmp)(hi -= qsz, min) > 0)
+			/* void */;
+		if ((hi += qsz) != min) {
+			for (lo = min + qsz; --lo >= min; ) {
+				c = *lo;
+				for (i = j = lo; (j -= qsz) >= hi; i = j)
+					*i = *j;
+				*i = c;
+			}
+		}
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Effectively perform qsort]
+
+  Description [First, find the median element, and put that one in the first
+  place as the discriminator.  (This "median" is just the median of the first,
+  last and middle elements).  (Using this median instead of the first element
+  is a big win).  Then, the usual partitioning/swapping, followed by moving the
+  discriminator into the right place.  Then, figure out the sizes of the two
+  partions, do the smaller one recursively and the larger one via a repeat of
+  this code.  Stopping when there are less than THRESH elements in a partition
+  and cleaning up with an insertion sort (in our caller) is a huge win.  All
+  data swaps are done in-line, which is space-losing but time-saving.  (And
+  there are only three places where this is done).]
+
+  SideEffects        []
+
+  SeeAlso            [qsort]
+
+******************************************************************************/
+static void
+qst(char *base, char *max)
+{
+	register char c, *i, *j, *jj;
+	register int ii;
+	char *mid, *tmp;
+	int lo, hi;
+
+	/*
+	 * At the top here, lo is the number of characters of elements in the
+	 * current partition.  (Which should be max - base).
+	 * Find the median of the first, last, and middle element and make
+	 * that the middle element.  Set j to largest of first and middle.
+	 * If max is larger than that guy, then it's that guy, else compare
+	 * max with loser of first and take larger.  Things are set up to
+	 * prefer the middle, then the first in case of ties.
+	 */
+	lo = max - base;		/* number of elements as chars */
+	do	{
+		mid = i = base + qsz * ((lo / qsz) >> 1);
+		if (lo >= mthresh) {
+			j = ((*qcmp)((jj = base), i) > 0 ? jj : i);
+			if ((*qcmp)(j, (tmp = max - qsz)) > 0) {
+				/* switch to first loser */
+				j = (j == jj ? i : jj);
+				if ((*qcmp)(j, tmp) < 0)
+					j = tmp;
+			}
+			if (j != i) {
+				ii = qsz;
+				do	{
+					c = *i;
+					*i++ = *j;
+					*j++ = c;
+				} while (--ii);
+			}
+		}
+		/*
+		 * Semi-standard quicksort partitioning/swapping
+		 */
+		for (i = base, j = max - qsz; ; ) {
+			while (i < mid && (*qcmp)(i, mid) <= 0)
+				i += qsz;
+			while (j > mid) {
+				if ((*qcmp)(mid, j) <= 0) {
+					j -= qsz;
+					continue;
+				}
+				tmp = i + qsz;	/* value of i after swap */
+				if (i == mid) {
+					/* j <-> mid, new mid is j */
+					mid = jj = j;
+				} else {
+					/* i <-> j */
+					jj = j;
+					j -= qsz;
+				}
+				goto swap;
+			}
+			if (i == mid) {
+				break;
+			} else {
+				/* i <-> mid, new mid is i */
+				jj = mid;
+				tmp = mid = i;	/* value of i after swap */
+				j -= qsz;
+			}
+		swap:
+			ii = qsz;
+			do	{
+				c = *i;
+				*i++ = *jj;
+				*jj++ = c;
+			} while (--ii);
+			i = tmp;
+		}
+		/*
+		 * Look at sizes of the two partitions, do the smaller
+		 * one first by recursion, then do the larger one by
+		 * making sure lo is its size, base and max are update
+		 * correctly, and branching back.  But only repeat
+		 * (recursively or by branching) if the partition is
+		 * of at least size THRESH.
+		 */
+		i = (j = mid) + qsz;
+		if ((lo = j - base) <= (hi = max - i)) {
+			if (lo >= thresh)
+				qst(base, j);
+			base = i;
+			lo = hi;
+		} else {
+			if (hi >= thresh)
+				qst(i, max);
+			max = j;
+		}
+	} while (lo >= thresh);
+}
Index: /vis_dev/glu-2.1/src/util/random.c
===================================================================
--- /vis_dev/glu-2.1/src/util/random.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/random.c	(revision 8)
@@ -0,0 +1,198 @@
+/**CFile***********************************************************************
+
+  FileName    [random.c]
+
+  PackageName [util]
+
+  Synopsis    [Our own portable random number generator.]
+
+  Author      [Fabio Somenzi <Fabio@Colorado.EDU>]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  \"AS IS\" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "util.h" 
+
+static char rcsid[] UNUSED = "$Id: random.c,v 1.4 2002/09/10 00:05:33 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Random generator constants. */
+#define MODULUS1 2147483563
+#define LEQA1 40014
+#define LEQQ1 53668
+#define LEQR1 12211
+#define MODULUS2 2147483399
+#define LEQA2 40692
+#define LEQQ2 52774
+#define LEQR2 3791
+#define STAB_SIZE 64
+#define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static long utilRand = 0;
+static long utilRand2;
+static long shuffleSelect;
+static long shuffleTable[STAB_SIZE];
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializer for the portable random number generator.]
+
+  Description [Initializer for the portable number generator based on
+  ran2 in "Numerical Recipes in C." The input is the seed for the
+  generator. If it is negative, its absolute value is taken as seed.
+  If it is 0, then 1 is taken as seed. The initialized sets up the two
+  recurrences used to generate a long-period stream, and sets up the
+  shuffle table.]
+
+  SideEffects [None]
+
+  SeeAlso     [util_random]
+
+******************************************************************************/
+void
+util_srandom(long seed)
+{
+    int i;
+
+    if (seed < 0)       utilRand = -seed;
+    else if (seed == 0) utilRand = 1;
+    else                utilRand = seed;
+    utilRand2 = utilRand;
+    /* Load the shuffle table (after 11 warm-ups). */
+    for (i = 0; i < STAB_SIZE + 11; i++) {
+	long int w;
+	w = utilRand / LEQQ1;
+	utilRand = LEQA1 * (utilRand - w * LEQQ1) - w * LEQR1;
+	utilRand += (utilRand < 0) * MODULUS1;
+	shuffleTable[i % STAB_SIZE] = utilRand;
+    }
+    shuffleSelect = shuffleTable[1 % STAB_SIZE];
+} /* end of util_srandom */
+
+/**Function********************************************************************
+
+  Synopsis    [Portable random number generator.]
+
+  Description [Portable number generator based on ran2 from "Numerical
+  Recipes in C." It is a long period (> 2 * 10^18) random number generator
+  of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly
+  distributed between 0 and 2147483561 (inclusive of the endpoint values).
+  The random generator can be explicitly initialized by calling
+  util_srandom. If no explicit initialization is performed, then the
+  seed 1 is assumed.]
+
+  SideEffects []
+
+  SeeAlso     [util_srandom]
+
+******************************************************************************/
+long
+util_random(void)
+{
+    int i;	/* index in the shuffle table */
+    long int w; /* work variable */
+
+    /* utilRand == 0 if the geneartor has not been initialized yet. */
+    if (utilRand == 0) util_srandom(1);
+
+    /* Compute utilRand = (utilRand * LEQA1) % MODULUS1 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = utilRand / LEQQ1;
+    utilRand   = LEQA1 * (utilRand - w * LEQQ1) - w * LEQR1;
+    utilRand  += (utilRand < 0) * MODULUS1;
+
+    /* Compute utilRand2 = (utilRand2 * LEQA2) % MODULUS2 avoiding
+    ** overflows by Schrage's method.
+    */
+    w          = utilRand2 / LEQQ2;
+    utilRand2  = LEQA2 * (utilRand2 - w * LEQQ2) - w * LEQR2;
+    utilRand2 += (utilRand2 < 0) * MODULUS2;
+
+    /* utilRand is shuffled with the Bays-Durham algorithm.
+    ** shuffleSelect and utilRand2 are combined to generate the output.
+    */
+
+    /* Pick one element from the shuffle table; "i" will be in the range
+    ** from 0 to STAB_SIZE-1.
+    */
+    i = shuffleSelect / STAB_DIV;
+    /* Mix the element of the shuffle table with the current iterate of
+    ** the second sub-generator, and replace the chosen element of the
+    ** shuffle table with the current iterate of the first sub-generator.
+    */
+    shuffleSelect   = shuffleTable[i] - utilRand2;
+    shuffleTable[i] = utilRand;
+    shuffleSelect  += (shuffleSelect < 1) * (MODULUS1 - 1);
+    /* Since shuffleSelect != 0, and we want to be able to return 0,
+    ** here we subtract 1 before returning.
+    */
+    return(shuffleSelect - 1);
+
+} /* end of util_random */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
Index: /vis_dev/glu-2.1/src/util/safe_mem.c
===================================================================
--- /vis_dev/glu-2.1/src/util/safe_mem.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/safe_mem.c	(revision 8)
@@ -0,0 +1,89 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: safe_mem.c,v 1.7 2002/09/14 22:59:31 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+#include "util.h"
+
+/*
+ *  These are interface routines to be placed between a program and the
+ *  system memory allocator.  
+ *
+ *  It forces well-defined semantics for several 'borderline' cases:
+ *
+ *	malloc() of a 0 size object is guaranteed to return something
+ *	    which is not 0, and can safely be freed (but not dereferenced)
+ *	free() accepts (silently) an 0 pointer
+ *	realloc of a 0 pointer is allowed, and is equiv. to malloc()
+ *	For the IBM/PC it forces no object > 64K; note that the size argument
+ *	    to malloc/realloc is a 'long' to catch this condition
+ *
+ *  The function pointer MMoutOfMemory() contains a vector to handle a
+ *  'out-of-memory' error (which, by default, points at a simple wrap-up 
+ *  and exit routine).
+ */
+
+void (*MMoutOfMemory)(unsigned long) = MMout_of_memory;
+
+
+/* MMout_of_memory -- out of memory for lazy people, flush and exit */
+void
+MMout_of_memory(unsigned long size)
+{
+  (void) fflush(stdout);
+  (void) fprintf(stderr, "\nout of memory allocating %lu bytes\n", size);
+  exit(1);
+}
+
+
+void *
+MMalloc(unsigned long size)
+{
+  void *p;
+
+#ifdef IBMPC
+  if (size > 65000L) {
+    if (MMoutOfMemory != (void (*)(unsigned long)) 0) (*MMoutOfMemory)(size);
+    return NIL(void);
+  }
+#endif
+  if (size == 0) size = sizeof(long);
+  if ((p = malloc(size)) == NIL(void)) {
+    if (MMoutOfMemory != (void (*)(unsigned long)) 0) (*MMoutOfMemory)(size);
+    return NIL(void);
+  }
+  return p;
+}
+
+
+void *
+MMrealloc(void *obj, unsigned long size)
+{
+  void *p;
+
+#ifdef IBMPC
+  if (size > 65000L) {
+    if (MMoutOfMemory != (void (*)(unsigned long)) 0) (*MMoutOfMemory)(size);
+    return NIL(void);
+  }
+#endif
+  if (obj == NIL(void)) return MMalloc(size);
+  if (size <= 0) size = sizeof(long);
+  if ((p = realloc(obj, size)) == NIL(void)) {
+    if (MMoutOfMemory != (void (*)(unsigned long)) 0) (*MMoutOfMemory)(size);
+    return NIL(void);
+  }
+  return p;
+}
+
+
+void
+MMfree(void *obj)
+{
+  if (obj != 0) {
+    free(obj);
+  }
+}
Index: /vis_dev/glu-2.1/src/util/strsav.c
===================================================================
--- /vis_dev/glu-2.1/src/util/strsav.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/strsav.c	(revision 8)
@@ -0,0 +1,151 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: strsav.c,v 1.6 2002/08/27 07:47:03 fabio Exp $
+ *
+ */
+/* LINTLIBRARY */
+
+#include <stdio.h>
+#include "util.h"
+
+
+/*
+ *  util_strsav -- save a copy of a string
+ */
+char *
+util_strsav(char *s)
+{
+    if(s == NIL(char)) {  /* added 7/95, for robustness */
+       return s;
+    }
+    else {
+       return strcpy(ALLOC(char, strlen(s)+1), s);
+    }
+}
+
+/*
+ * util_inttostr -- converts an integer into a string
+ */
+char *
+util_inttostr(int i)
+{
+  unsigned int mod, len;
+  char *s;
+  
+  if (i == 0)
+    len = 1;
+  else {
+    if (i < 0) {
+      len = 1;
+      mod = -i;
+    }
+    else {
+      len = 0;
+      mod = i;
+    }
+    len += (unsigned) floor(log10(mod)) + 1;
+  }
+
+  s = ALLOC(char, len + 1);
+  sprintf(s, "%d", i);
+  
+  return s;
+}
+
+/*
+ * util_strcat3 -- Creates a new string which is the concatenation of 3
+ *    strings. It is the responsibility of the caller to free this string
+ *    using FREE.
+ */
+char *
+util_strcat3(
+  char * str1,
+  char * str2,
+  char * str3)
+{
+  char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) + 1);
+  
+  (void) strcpy(str, str1);
+  (void) strcat(str, str2);
+  (void) strcat(str, str3);
+
+  return (str);
+}
+
+/*
+ * util_strcat4 -- Creates a new string which is the concatenation of 4
+ *    strings. It is the responsibility of the caller to free this string
+ *    using FREE.
+ */
+char *
+util_strcat4(
+  char * str1,
+  char * str2,
+  char * str3,
+  char * str4)
+{
+  char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) +
+                    strlen(str4) + 1);
+  
+  (void) strcpy(str, str1);
+  (void) strcat(str, str2);
+  (void) strcat(str, str3);
+  (void) strcat(str, str4);
+
+  return (str);
+}
+
+
+#if !HAVE_STRSTR
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+char *
+strstr(
+  const char * s,
+  const char * pat)
+{
+  int len;
+
+  len = strlen(pat);
+  for (; *s != '\0'; ++s)
+    if (*s == *pat && memcmp(s, pat, len) ==  0) {
+      return (char *)s; /* UGH */
+    }
+  return NULL;
+}
+#endif /* !HAVE_STRSTR */
+
+#if !HAVE_STRCHR
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+char *
+strchr(const char * s, int c)
+{
+   for (; *s != '\0'; s++) {
+     if (*s == c) {
+       return (char *)s;
+     }
+   }
+   return NULL;
+   
+}
+#endif /* !HAVE_STRCHR */
Index: /vis_dev/glu-2.1/src/util/texpand.c
===================================================================
--- /vis_dev/glu-2.1/src/util/texpand.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/texpand.c	(revision 8)
@@ -0,0 +1,62 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: texpand.c,v 1.3 2002/08/25 02:37:11 fabio Exp $
+ *
+ */
+
+#include "util.h"
+
+#if HAVE_PWD_H
+#  include <pwd.h>
+#endif
+
+
+char *
+util_tilde_expand(char *fname)
+{
+#if HAVE_PWD_H
+    struct passwd *userRecord;
+    char username[256], *filename, *dir;
+    register int i, j;
+
+    filename = ALLOC(char, strlen(fname) + 256);
+
+    /* Clear the return string */
+    i = 0;
+    filename[0] = '\0';
+
+    /* Tilde? */
+    if (fname[0] == '~') {
+	j = 0;
+	i = 1;
+	while ((fname[i] != '\0') && (fname[i] != '/')) {
+	    username[j++] = fname[i++];
+	}
+	username[j] = '\0';
+	dir = (char *)0;
+	if (username[0] == '\0') {
+	    /* ~/ resolves to home directory of current user */
+	    userRecord = getpwuid(getuid());
+	    if (userRecord) dir = userRecord->pw_dir;
+	} else {
+	    /* Special check for ~octtools */
+	    if (!strcmp(username,"octtools"))
+	        dir = getenv("OCTTOOLS");
+	    /* ~user/ resolves to home directory of 'user' */
+	    if (!dir) {
+	        userRecord = getpwnam(username);
+		if (userRecord) dir = userRecord->pw_dir;
+	    }
+	}
+	if (dir) (void) strcat(filename, dir);
+	else i = 0;	/* leave fname as-is */
+    } /* if tilde */
+
+    /* Concantenate remaining portion of file name */
+    (void) strcat(filename, fname + i);
+    return filename;
+#else
+    return util_strsav(fname);
+#endif
+}
Index: /vis_dev/glu-2.1/src/util/tmpfile.c
===================================================================
--- /vis_dev/glu-2.1/src/util/tmpfile.c	(revision 8)
+++ /vis_dev/glu-2.1/src/util/tmpfile.c	(revision 8)
@@ -0,0 +1,151 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: tmpfile.c,v 1.11 2005/04/30 22:38:11 fabio Exp $
+ *
+ */
+
+/*
+ *  util_tmpfile -- open an unnamed temporary file
+ *
+ *  Many compilers/systems do not have this, or have buggy versions.
+ *
+ */
+
+/* LINTLIBRARY */
+
+/* util_tempnam and check_directory are from
+   Jonathan I. Kamens          <jik@pit-manager.mit.edu> */
+
+/* modified slightly by Ellen Sentovich ellen@ic.berkeley.edu */
+
+#include <sys/types.h>
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+#if HAVE_SYS_FILE_H
+#  include <sys/file.h>
+#endif
+
+#include "util.h"
+
+static char check_directory(char *dir)
+{
+     struct stat statbuf;
+
+     if (! dir)
+         return 0;
+     else if (stat(dir, &statbuf) < 0)
+         return 0;
+     else if (S_ISDIR(statbuf.st_mode))
+         return 0;
+     else if (access(dir, W_OK | X_OK) < 0)
+         return 0;
+     else
+         return 1;
+}
+
+/* function for creating temporary filenames */
+char *util_tempnam(char *dir, char *pfx)
+{
+     extern char *getenv(const char *);
+     char *tmpdir = NULL, *env, *filename;
+     static char unique_letters[4] = "AAA";
+     char addslash = 0;
+
+     /*
+      * If a directory is passed in, verify that it exists and is a
+      * directory and is writeable by this process.  If no directory
+      * is passed in, or if the directory that is passed in does not
+      * exist, check the environment variable TMPDIR.  If it isn't
+      * set, check the predefined constant P_tmpdir.  If that isn't
+      * set, use "/tmp/".
+      */
+
+     if ((env = getenv ("TMPDIR")) && check_directory(env))
+         tmpdir = env;
+     else if (dir && check_directory(dir))
+         tmpdir = dir;
+#ifdef P_tmpdir
+     else if (check_directory(P_tmpdir))
+         tmpdir = P_tmpdir;
+#endif
+     else
+         tmpdir = "/tmp/";
+
+     /*
+      * OK, now that we've got a directory, figure out whether or not
+      * there's a slash at the end of it.
+      */
+     if (tmpdir[strlen(tmpdir) - 1] != '/')
+         addslash = 1;
+
+     /*
+      * Now figure out the set of unique letters.
+      */
+     unique_letters[0]++;
+     if (unique_letters[0] > 'Z') {
+         unique_letters[0] = 'A';
+         unique_letters[1]++;
+         if (unique_letters[1] > 'Z') {
+             unique_letters[1] = 'A';
+             unique_letters[2]++;
+             if (unique_letters[2] > 'Z') {
+                 unique_letters[2]++;
+             }
+         }
+     }
+
+     /*
+      * Allocate a string of sufficient length.
+      */
+     if (pfx) {
+         filename = (char *) malloc(strlen(tmpdir) + addslash + strlen(pfx) + 10
+);
+     } else {
+         filename = (char *) malloc(strlen(tmpdir) + addslash + 10);
+     }
+
+     /*
+      * And create the string.
+      */
+     (void) sprintf(filename, "%s%s%s%sa%05d", tmpdir, addslash ? "/" : "",
+                    pfx ? pfx : "", unique_letters, (int)getpid());
+
+     return filename;
+}
+
+
+#ifdef UNIX
+
+FILE *
+util_tmpfile(void)
+{
+    FILE *fp;
+    char *filename;
+
+    filename = util_tempnam(NIL(char), "VIS");
+    if ((fp = fopen(filename, "w+")) == NULL) {
+	FREE(filename);
+	return NULL;
+    }
+    (void) unlink(filename); 
+    FREE(filename);
+    return fp;
+}
+
+#else
+
+FILE *
+util_tmpfile(void)
+{
+    FILE *fp;
+
+    if ((fp = fopen("utiltmp", "w+")) == NULL) {
+	return NULL;
+    }
+    (void) unlink("utiltmp");
+    return fp;
+}
+
+#endif
Index: /vis_dev/glu-2.1/src/util/util.h
===================================================================
--- /vis_dev/glu-2.1/src/util/util.h	(revision 8)
+++ /vis_dev/glu-2.1/src/util/util.h	(revision 8)
@@ -0,0 +1,263 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ util.h ]
+
+  PackageName [ util ]
+
+  Synopsis    [ Very low-level utilities ]
+
+  Description [ Includes file access, pipes, forks, time, and temporary file
+  		access. ]
+
+  Author      [ Stephen Edwards <sedwards@eecs.berkeley.edu> and many others]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: util.h,v 1.16 2003/08/01 15:41:37 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _UTIL
+#define _UTIL
+
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+
+#if HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+
+#if HAVE_VARARGS_H
+#  include <varargs.h>
+#endif
+
+#if STDC_HEADERS
+#  include <stdlib.h>
+#  include <string.h>
+#else
+#  ifdef HAVE_STRCHR
+char * strchr(const char *, int);
+int strcmp(const char *, const char *);
+#  else
+#    define strchr index
+#  endif
+#  ifdef HAVE_GETENV
+char * getenv(const char *);
+#  endif
+#endif /* STDC_HEADERS */
+
+#if HAVE_ERRNO_H
+#  include <errno.h>
+#endif
+
+/*
+ * Ensure we have reasonable assert() and fail() functions
+ */
+
+#if HAVE_ASSERT_H
+#  include <assert.h>
+#else
+#  ifdef NDEBUG
+#    define assert(ex) ;
+#  else
+#    define assert(ex) {\
+    if (! (ex)) {\
+	(void) fprintf(stderr,\
+	    "Assertion failed: file %s, line %d\n\"%s\"\n",\
+	    __FILE__, __LINE__, "ex");\
+	(void) fflush(stdout);\
+	abort();\
+    }\
+}
+#  endif
+#endif
+
+#define fail(why) {\
+    (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+	__FILE__, __LINE__, why);\
+    (void) fflush(stdout);\
+    abort();\
+}
+
+/*
+ * Support for ANSI function prototypes in non-ANSI compilers
+ *
+ * Usage:
+ *   extern int foo ARGS((char *, double))
+ */
+
+#ifndef ARGS
+#  ifdef __STDC__
+#     define ARGS(args)	args
+#  else
+#     define ARGS(args) ()
+# endif
+#endif
+
+#ifndef NULLARGS
+#  ifdef __STDC__
+#    define NULLARGS	(void)
+#  else
+#    define NULLARGS	()
+#  endif
+#endif
+
+/*
+ * A little support for C++ compilers
+ */
+
+#ifdef __cplusplus
+#  define EXTERN	extern "C"
+#else
+#  define EXTERN	extern
+#endif
+
+/* 
+ * Support to define unused varibles
+ */
+#if defined (__GNUC__)
+#if (__GNUC__ >2 || __GNUC_MINOR__ >=7) && !defined(UNUSED)
+#define UNUSED __attribute__ ((unused))
+#else
+#define UNUSED
+#endif
+#else
+#define UNUSED
+#endif
+
+/*
+ * A neater way to define zero pointers
+ *
+ * Usage:
+ *  int * fred;
+ *  fred = NIL(int);
+ */
+
+#define NIL(type)		((type *) 0)
+
+/* #define USE_MM */
+
+#ifdef USE_MM
+/*
+ *  assumes the memory manager is libmm.a (a deprecated (?) Octtools library)
+ *	- allows malloc(0) or realloc(obj, 0)
+ *	- catches out of memory (and calls MMout_of_memory())
+ *	- catch free(0) and realloc(0, size) in the macros
+ */
+#  define ALLOC(type, num)	\
+    ((type *) malloc(sizeof(type) * (num)))
+#  define REALLOC(type, obj, num)	\
+    (obj) ? ((type *) realloc((void *) obj, sizeof(type) * (num))) : \
+	    ((type *) malloc(sizeof(type) * (num)))
+#  define FREE(obj)		\
+    ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
+#else
+/*
+ *  enforce strict semantics on the memory allocator
+ */
+#  define ALLOC(type, num)	\
+    ((type *) MMalloc(sizeof(type) * (unsigned long) (num)))
+#  define REALLOC(type, obj, num)	\
+    ((type *) MMrealloc((void *) (obj), sizeof(type) * (unsigned long) (num)))
+#  define FREE(obj)		\
+    ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
+#endif
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+#ifndef ABS
+#  define ABS(a)			((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef MAX
+#  define MAX(a,b)		((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#  define MIN(a,b)		((a) < (b) ? (a) : (b))
+#endif
+
+#define ptime()         util_cpu_time()
+#define print_time(t)   util_print_time(t)
+
+#ifndef HUGE_VAL
+#  ifndef HUGE
+#    define HUGE  8.9884656743115790e+307
+#  endif
+#  define HUGE_VAL HUGE
+#endif
+
+#ifndef MAXINT
+#  define MAXINT (1 << 30)
+#endif
+
+EXTERN void util_print_cpu_stats ARGS((FILE *));
+EXTERN long util_cpu_time ARGS((void));
+EXTERN long util_cpu_ctime ARGS((void));
+EXTERN void util_getopt_reset ARGS((void));
+EXTERN int util_getopt ARGS((int, char **, char *));
+EXTERN int util_check_file ARGS((char *, char *));
+EXTERN char *util_path_search ARGS((char *));
+EXTERN char *util_file_search ARGS((char *, char *, char *));
+EXTERN char *util_print_time ARGS((long));
+EXTERN int util_save_image ARGS((char *, char *));
+EXTERN char *util_strsav ARGS((char *));
+EXTERN char *util_inttostr ARGS((int));
+EXTERN char *util_strcat3 ARGS((char *, char *, char *));
+EXTERN char *util_strcat4 ARGS((char *, char *, char *, char *));
+EXTERN int util_do_nothing ARGS((void));
+EXTERN char *util_tilde_expand ARGS((char *));
+EXTERN char *util_tempnam ARGS((char *, char *));
+EXTERN FILE *util_tmpfile ARGS((void));
+EXTERN void util_srandom ARGS((long));
+EXTERN long util_random ARGS((void));
+EXTERN long getSoftDataLimit ARGS((void));
+EXTERN void MMout_of_memory ARGS((unsigned long));
+EXTERN void *MMalloc ARGS((unsigned long));
+EXTERN void *MMrealloc ARGS((void *, unsigned long));
+EXTERN void MMfree ARGS((void *));
+
+/*
+ * Global variables for util_getopt()
+ */
+
+extern int util_optind;
+extern char *util_optarg;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _UTIL */
Index: /vis_dev/glu-2.1/src/util/util.make
===================================================================
--- /vis_dev/glu-2.1/src/util/util.make	(revision 8)
+++ /vis_dev/glu-2.1/src/util/util.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += cpu_stats.c cpu_time.c datalimit.c getopt.c pathsearch.c prtime.c qsort.c random.c safe_mem.c strsav.c texpand.c tmpfile.c
+HEADERS += util.h
+MISC += util.doc 
+
+DEPENDENCYFILES = $(CSRC)
Index: /vis_dev/glu-2.1/src/var_set/var_set.c
===================================================================
--- /vis_dev/glu-2.1/src/var_set/var_set.c	(revision 8)
+++ /vis_dev/glu-2.1/src/var_set/var_set.c	(revision 8)
@@ -0,0 +1,218 @@
+/*
+ * Revision Control Information
+ *
+ * $Id: var_set.c,v 1.3 2002/08/25 05:30:13 fabio Exp $
+ *
+ */
+#include "util.h"
+#include "var_set.h"
+
+var_set_t *var_set_new(int size)
+{
+  var_set_t *result = ALLOC(var_set_t, 1);
+
+  result->n_elts = size;
+  result->n_words = size / VAR_SET_WORD_SIZE + ((size % VAR_SET_WORD_SIZE == 0) ? 0 : 1);
+  result->data = ALLOC(unsigned int, result->n_words);
+  (void) var_set_clear(result);
+  return result;
+}
+
+var_set_t *var_set_copy(var_set_t *set)
+{
+  int i;
+  var_set_t *result = ALLOC(var_set_t, 1);
+
+  *result = *set;
+  result->data = ALLOC(unsigned int, result->n_words);
+  for (i = 0; i < result->n_words; i++)
+    result->data[i] = set->data[i];
+  return result;
+}
+
+var_set_t *var_set_assign(var_set_t *result, var_set_t *set)
+{
+  int i;
+
+  assert(result->n_elts == set->n_elts);
+  for (i = 0; i < result->n_words; i++)
+    result->data[i] = set->data[i];
+  return result;
+}
+
+void var_set_free(var_set_t *set)
+{
+  FREE(set->data);
+  FREE(set);
+}
+
+static int size_array[256];
+
+static void init_size_array(void)
+{
+  int i;
+  unsigned j;
+  int count;
+
+  for (i = 0; i < 256; i++) {
+    count = 0;
+    for (j = 0; j < VAR_SET_WORD_SIZE; j++) {
+      count += VAR_SET_EXTRACT_BIT(i, j);
+    }
+    size_array[i] = count;
+  }
+}
+
+int var_set_n_elts(var_set_t *set)
+{
+  register int i, j;
+  register unsigned int value;
+  int n_bytes = VAR_SET_WORD_SIZE / VAR_SET_BYTE_SIZE;
+  int count = 0;
+
+  if (size_array[1] == 0) init_size_array();
+  for (i = 0; i < set->n_words; i++) {
+    value = set->data[i];
+    for (j = 0; j < n_bytes; j++) {
+      count += size_array[value & 0xff];
+      value >>= VAR_SET_BYTE_SIZE;
+    }
+  }
+  return count;
+}
+
+var_set_t *var_set_or(var_set_t *result, var_set_t *a, var_set_t *b)
+{
+  int i;
+  assert(result->n_elts == a->n_elts);
+  assert(result->n_elts == b->n_elts);
+  for (i = 0; i < result->n_words; i++)
+    result->data[i] = a->data[i] | b->data[i];
+  return result;
+}
+
+var_set_t *var_set_and(var_set_t *result, var_set_t *a, var_set_t *b)
+{
+  int i;
+  assert(result->n_elts == a->n_elts);
+  assert(result->n_elts == b->n_elts);
+  for (i = 0; i < result->n_words; i++)
+    result->data[i] = a->data[i] & b->data[i];
+  return result;
+}
+
+var_set_t *var_set_not(var_set_t *result, var_set_t *a)
+{
+  int i;
+  unsigned int mask;
+
+  assert(result->n_elts == a->n_elts);
+  for (i = 0; i < a->n_words; i++)
+    result->data[i] = ~a->data[i];
+  mask = (unsigned int) VAR_SET_ALL_ONES >> (a->n_words * VAR_SET_WORD_SIZE - a->n_elts);
+  result->data[a->n_words - 1] &= mask;
+  return result;
+}
+
+int var_set_get_elt(var_set_t *set, int index)
+{
+  assert(index >= 0 && index < set->n_elts);
+  return VAR_SET_EXTRACT_BIT(set->data[index / VAR_SET_WORD_SIZE], index % VAR_SET_WORD_SIZE);
+}
+
+void var_set_set_elt(var_set_t *set, int index)
+{
+  unsigned int *value;
+  assert(index >= 0 && index < set->n_elts);
+  value = &(set->data[index / VAR_SET_WORD_SIZE]);
+  *value = *value | (1 << (index % VAR_SET_WORD_SIZE));
+}
+
+void var_set_clear_elt(var_set_t *set, int index)
+{
+  unsigned int *value;
+  assert(index >= 0 && index < set->n_elts);
+  value = &(set->data[index / VAR_SET_WORD_SIZE]);
+  *value = *value & ~(1 << (index % VAR_SET_WORD_SIZE));
+}
+
+void var_set_clear(var_set_t *set)
+{
+  int i;
+
+  for (i = 0; i < set->n_words; i++)
+    set->data[i] = 0;
+}
+
+int var_set_intersect(var_set_t *a, var_set_t *b)
+{
+  int i;
+  assert(a->n_elts == b->n_elts);
+  for (i = 0; i < a->n_words; i++)
+    if (a->data[i] & b->data[i]) return 1;
+  return 0;
+}
+
+int var_set_is_empty(var_set_t *a)
+{
+  int i;
+  for (i = 0; i < a->n_words; i++)
+    if (a->data[i]) return 0;
+  return 1;
+}
+
+int var_set_is_full(var_set_t *a)
+{
+  int i;
+  unsigned value;
+  for (i = 0; i < a->n_words - 1; i++)
+    if (a->data[i] != VAR_SET_ALL_ONES) return 0;
+  value = VAR_SET_ALL_ONES >> (a->n_words * VAR_SET_WORD_SIZE - a->n_elts);
+  return (a->data[a->n_words - 1] == value);
+}
+
+void var_set_print(FILE *fp, var_set_t *set)
+{
+  int i;
+  for (i = 0; i < set->n_elts; i++) {
+    fprintf(fp, "%d ", var_set_get_elt(set, i));
+  }
+  fprintf(fp, "\n");
+}
+
+ /* returns 1 if equal, 0 otherwise */
+
+int var_set_equal(var_set_t *a, var_set_t *b)
+{
+  int i;
+
+  assert(a->n_elts == b->n_elts);
+  for (i = 0; i < a->n_words; i++)
+    if (a->data[i] != b->data[i]) return 0;
+  return 1;
+}
+
+ /* returns 0 if equal, 1 otherwise */
+
+int var_set_cmp(char *obj1, char *obj2)
+{
+  int i;
+  var_set_t *a = (var_set_t *) obj1;
+  var_set_t *b = (var_set_t *) obj2;
+
+  assert(a->n_elts == b->n_elts);
+  for (i = 0; i < a->n_words; i++)
+    if (a->data[i] != b->data[i]) return 1;
+  return 0;
+}
+
+ /* to be used when sets are used as keys in hash tables */
+unsigned int var_set_hash(var_set_t *set)
+{
+  int i;
+  unsigned int result = 0;
+
+  for (i = 0; i < set->n_words; i++)
+    result += (unsigned int) set->data[i];
+  return result;
+}
Index: /vis_dev/glu-2.1/src/var_set/var_set.h
===================================================================
--- /vis_dev/glu-2.1/src/var_set/var_set.h	(revision 8)
+++ /vis_dev/glu-2.1/src/var_set/var_set.h	(revision 8)
@@ -0,0 +1,76 @@
+#ifndef VAR_SET_H /* { */
+#define VAR_SET_H
+
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/var_set/var_set.h,v
+ * rajeev
+ * 1.3
+ * 1995/08/08 22:41:47
+ * var_set.h,v
+ * Revision 1.3  1995/08/08 22:41:47  rajeev
+ * Changes made by shazqadeer.420 as of 8/8/95
+ *
+ * Revision 1.1  1993/07/29  00:44:35  serdar
+ * Imported from /projects/classes/sis. Makefile changed for use in
+ *  /projects/hsis-util/hsis-util-1.0/common/src.
+ *
+ * Revision 1.3  1993/05/28  23:49:29  sis
+ * Aesthetic changes to prototypes.
+ *
+ * Revision 1.2  1993/05/11  19:49:14  sis
+ * Changes for ANSI C compatibility.
+ *
+ * Revision 1.1  1993/03/01  16:24:39  sis
+ * Initial revision
+ *
+ * Revision 1.1  1993/03/01  16:23:57  sis
+ * Initial revision
+ *
+ * Revision 1.3  1993/02/25  02:04:41  shiple
+ *  Added file pointer argument to declaration of var_set_print.
+ *
+ * Revision 1.2  1993/02/24  23:35:16  shiple
+ * Add VAR_SET_BYTE_SIZE macro. Fix newly introduced bug in
+ * definition of VAR_SET_WORD_SIZE.
+ *
+ * Revision 1.1  1993/02/23  22:58:28  shiple
+ * Initial revision
+ *
+ *
+ */
+
+#define VAR_SET_BYTE_SIZE 8
+#define VAR_SET_WORD_SIZE ((sizeof(unsigned int))*(VAR_SET_BYTE_SIZE))
+#define VAR_SET_ALL_ZEROS 0
+#define VAR_SET_ALL_ONES  ((unsigned int) ~0)
+#define VAR_SET_EXTRACT_BIT(word,pos) (((word) & (1 << (pos))) != 0)
+
+typedef struct var_set_struct {
+  int n_elts;
+  int n_words;
+  unsigned int *data;
+} var_set_t;
+
+EXTERN var_set_t *var_set_new ARGS((int));
+EXTERN var_set_t *var_set_copy ARGS((var_set_t *));
+EXTERN var_set_t *var_set_assign ARGS((var_set_t *, var_set_t *));
+EXTERN void       var_set_free ARGS((var_set_t *));
+EXTERN int        var_set_n_elts ARGS((var_set_t *));
+EXTERN var_set_t *var_set_or ARGS((var_set_t *, var_set_t *, var_set_t *));
+EXTERN var_set_t *var_set_and ARGS((var_set_t *, var_set_t *, var_set_t *));
+EXTERN var_set_t *var_set_not ARGS((var_set_t *, var_set_t *));
+EXTERN int        var_set_get_elt ARGS((var_set_t *, int));
+EXTERN void       var_set_set_elt ARGS((var_set_t *, int));
+EXTERN void       var_set_clear_elt ARGS((var_set_t *, int));
+EXTERN void       var_set_clear ARGS((var_set_t *));
+EXTERN int        var_set_intersect ARGS((var_set_t *, var_set_t *));
+EXTERN int        var_set_is_empty ARGS((var_set_t *));
+EXTERN int        var_set_is_full ARGS((var_set_t *));
+EXTERN void       var_set_print ARGS((FILE *, var_set_t *));
+EXTERN int        var_set_equal ARGS((var_set_t *, var_set_t *));
+EXTERN int        var_set_cmp ARGS((char *, char *));
+EXTERN unsigned int var_set_hash ARGS((var_set_t *));
+
+#endif /* } */
Index: /vis_dev/glu-2.1/src/var_set/var_set.make
===================================================================
--- /vis_dev/glu-2.1/src/var_set/var_set.make	(revision 8)
+++ /vis_dev/glu-2.1/src/var_set/var_set.make	(revision 8)
@@ -0,0 +1,5 @@
+CSRC += var_set.c
+HEADERS += var_set.h
+MISC += var_set.doc
+
+DEPENDENCYFILES = $(CSRC)
