summaryrefslogtreecommitdiffstats
path: root/src/misc
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2007-10-01 08:01:00 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2007-10-01 08:01:00 -0700
commit4812c90424dfc40d26725244723887a2d16ddfd9 (patch)
treeb32ace96e7e2d84d586e09ba605463b6f49c3271 /src/misc
parente54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 (diff)
downloadabc-4812c90424dfc40d26725244723887a2d16ddfd9.tar.gz
abc-4812c90424dfc40d26725244723887a2d16ddfd9.tar.bz2
abc-4812c90424dfc40d26725244723887a2d16ddfd9.zip
Version abc71001
Diffstat (limited to 'src/misc')
-rw-r--r--src/misc/espresso/cofactor.c382
-rw-r--r--src/misc/espresso/cols.c314
-rw-r--r--src/misc/espresso/compl.c680
-rw-r--r--src/misc/espresso/contain.c441
-rw-r--r--src/misc/espresso/cubehack.c138
-rw-r--r--src/misc/espresso/cubestr.c152
-rw-r--r--src/misc/espresso/cvrin.c810
-rw-r--r--src/misc/espresso/cvrm.c539
-rw-r--r--src/misc/espresso/cvrmisc.c142
-rw-r--r--src/misc/espresso/cvrout.c609
-rw-r--r--src/misc/espresso/dominate.c98
-rw-r--r--src/misc/espresso/equiv.c94
-rw-r--r--src/misc/espresso/espresso.c139
-rw-r--r--src/misc/espresso/espresso.h782
-rw-r--r--src/misc/espresso/essen.c179
-rw-r--r--src/misc/espresso/exact.c181
-rw-r--r--src/misc/espresso/expand.c693
-rw-r--r--src/misc/espresso/gasp.c228
-rw-r--r--src/misc/espresso/gimpel.c106
-rw-r--r--src/misc/espresso/globals.c76
-rw-r--r--src/misc/espresso/hack.c641
-rw-r--r--src/misc/espresso/indep.c134
-rw-r--r--src/misc/espresso/irred.c440
-rw-r--r--src/misc/espresso/main.c746
-rw-r--r--src/misc/espresso/main.h122
-rw-r--r--src/misc/espresso/map.c115
-rw-r--r--src/misc/espresso/matrix.c574
-rw-r--r--src/misc/espresso/mincov.c378
-rw-r--r--src/misc/espresso/mincov.h11
-rw-r--r--src/misc/espresso/mincov_int.h55
-rw-r--r--src/misc/espresso/module.make39
-rw-r--r--src/misc/espresso/opo.c624
-rw-r--r--src/misc/espresso/pair.c675
-rw-r--r--src/misc/espresso/part.c122
-rw-r--r--src/misc/espresso/primes.c170
-rw-r--r--src/misc/espresso/reduce.c258
-rw-r--r--src/misc/espresso/rows.c314
-rw-r--r--src/misc/espresso/set.c820
-rw-r--r--src/misc/espresso/setc.c483
-rw-r--r--src/misc/espresso/sharp.c247
-rw-r--r--src/misc/espresso/sminterf.c44
-rw-r--r--src/misc/espresso/solution.c114
-rw-r--r--src/misc/espresso/sparse.c146
-rw-r--r--src/misc/espresso/sparse.h135
-rw-r--r--src/misc/espresso/sparse_int.h121
-rw-r--r--src/misc/espresso/unate.c441
-rw-r--r--src/misc/espresso/util_old.h301
-rw-r--r--src/misc/espresso/verify.c193
-rw-r--r--src/misc/extra/extra.h626
-rw-r--r--src/misc/extra/extraBddAuto.c1558
-rw-r--r--src/misc/extra/extraBddCas.c1230
-rw-r--r--src/misc/extra/extraBddKmap.c783
-rw-r--r--src/misc/extra/extraBddMisc.c1614
-rw-r--r--src/misc/extra/extraBddSymm.c1469
-rw-r--r--src/misc/extra/extraBddUnate.c641
-rw-r--r--src/misc/extra/extraUtilBitMatrix.c415
-rw-r--r--src/misc/extra/extraUtilCanon.c701
-rw-r--r--src/misc/extra/extraUtilFile.c495
-rw-r--r--src/misc/extra/extraUtilMemory.c625
-rw-r--r--src/misc/extra/extraUtilMisc.c2235
-rw-r--r--src/misc/extra/extraUtilProgress.c176
-rw-r--r--src/misc/extra/extraUtilReader.c383
-rw-r--r--src/misc/extra/extraUtilTruth.c1148
-rw-r--r--src/misc/extra/extraUtilUtil.c330
-rw-r--r--src/misc/extra/module.make15
-rw-r--r--src/misc/hash/hash.h65
-rw-r--r--src/misc/hash/hashFlt.h330
-rw-r--r--src/misc/hash/hashInt.h293
-rw-r--r--src/misc/hash/hashPtr.h331
-rw-r--r--src/misc/hash/module.make1
-rw-r--r--src/misc/mvc/module.make16
-rw-r--r--src/misc/mvc/mvc.c46
-rw-r--r--src/misc/mvc/mvc.h732
-rw-r--r--src/misc/mvc/mvcApi.c233
-rw-r--r--src/misc/mvc/mvcCompare.c369
-rw-r--r--src/misc/mvc/mvcContain.c173
-rw-r--r--src/misc/mvc/mvcCover.c251
-rw-r--r--src/misc/mvc/mvcCube.c175
-rw-r--r--src/misc/mvc/mvcDivide.c436
-rw-r--r--src/misc/mvc/mvcDivisor.c90
-rw-r--r--src/misc/mvc/mvcList.c362
-rw-r--r--src/misc/mvc/mvcLits.c345
-rw-r--r--src/misc/mvc/mvcMan.c77
-rw-r--r--src/misc/mvc/mvcOpAlg.c163
-rw-r--r--src/misc/mvc/mvcOpBool.c151
-rw-r--r--src/misc/mvc/mvcPrint.c220
-rw-r--r--src/misc/mvc/mvcSort.c141
-rw-r--r--src/misc/mvc/mvcUtils.c868
-rw-r--r--src/misc/nm/module.make2
-rw-r--r--src/misc/nm/nm.h92
-rw-r--r--src/misc/nm/nmApi.c272
-rw-r--r--src/misc/nm/nmInt.h91
-rw-r--r--src/misc/nm/nmTable.c340
-rw-r--r--src/misc/st/module.make2
-rw-r--r--src/misc/st/st.c625
-rw-r--r--src/misc/st/st.h96
-rw-r--r--src/misc/st/stmm.c688
-rw-r--r--src/misc/st/stmm.h127
-rw-r--r--src/misc/util/leaks.h30
-rw-r--r--src/misc/util/module.make1
-rw-r--r--src/misc/util/stdlib_hack.h4
-rw-r--r--src/misc/util/util_hack.h95
-rw-r--r--src/misc/vec/module.make1
-rw-r--r--src/misc/vec/vec.h121
-rw-r--r--src/misc/vec/vecAtt.h391
-rw-r--r--src/misc/vec/vecFlt.h630
-rw-r--r--src/misc/vec/vecInt.h834
-rw-r--r--src/misc/vec/vecPtr.h762
-rw-r--r--src/misc/vec/vecStr.h583
-rw-r--r--src/misc/vec/vecVec.h356
110 files changed, 41701 insertions, 0 deletions
diff --git a/src/misc/espresso/cofactor.c b/src/misc/espresso/cofactor.c
new file mode 100644
index 00000000..b851a639
--- /dev/null
+++ b/src/misc/espresso/cofactor.c
@@ -0,0 +1,382 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ The cofactor of a cover against a cube "c" is a cover formed by the
+ cofactor of each cube in the cover against c. The cofactor of two
+ cubes is null if they are distance 1 or more apart. If they are
+ distance zero apart, the cofactor is the restriction of the cube
+ to the minterms of c.
+
+ The cube list contains the following information:
+
+ T[0] = pointer to a cube identifying the variables that have
+ been cofactored against
+ T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case)
+ T[2]
+ .
+ . = pointers to cubes
+ .
+ T[n-2]
+ T[n-1] = NULL pointer (sentinel)
+
+
+ Cofactoring involves repeated application of "cdist0" to check if a
+ cube of the cover intersects the cofactored cube. This can be
+ slow, especially for the recursive descent of the espresso
+ routines. Therefore, a special cofactor routine "scofactor" is
+ provided which assumes the cofactor is only in a single variable.
+*/
+
+
+/* cofactor -- compute the cofactor of a cover with respect to a cube */
+pcube *cofactor(T, c)
+IN pcube *T;
+IN register pcube c;
+{
+ pcube temp = cube.temp[0], *Tc_save, *Tc, *T1;
+ register pcube p;
+ int listlen;
+
+ listlen = CUBELISTSIZE(T) + 5;
+
+ /* Allocate a new list of cube pointers (max size is previous size) */
+ Tc_save = Tc = ALLOC(pcube, listlen);
+
+ /* pass on which variables have been cofactored against */
+ *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c));
+ Tc++;
+
+ /* Loop for each cube in the list, determine suitability, and save */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (p != c) {
+
+#ifdef NO_INLINE
+ if (! cdist0(p, c)) goto false;
+#else
+ {register int w,last;register unsigned int x;if((last=cube.inword)!=-1)
+ {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<last;w++)
+ {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,last;
+ register pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){
+ mask=cube.var_mask[var];last=cube.last_word[var];for(w=cube.first_word[var
+ ];w<=last;w++)if(p[w]&c[w]&mask[w])goto nextvar;goto false;nextvar:;}}
+#endif
+
+ *Tc++ = p;
+ false: ;
+ }
+ }
+
+ *Tc++ = (pcube) NULL; /* sentinel */
+ Tc_save[1] = (pcube) Tc; /* save pointer to last */
+ return Tc_save;
+}
+
+/*
+ scofactor -- compute the cofactor of a cover with respect to a cube,
+ where the cube is "active" in only a single variable.
+
+ This routine has been optimized for speed.
+*/
+
+pcube *scofactor(T, c, var)
+IN pcube *T, c;
+IN int var;
+{
+ pcube *Tc, *Tc_save;
+ register pcube p, mask = cube.temp[1], *T1;
+ register int first = cube.first_word[var], last = cube.last_word[var];
+ int listlen;
+
+ listlen = CUBELISTSIZE(T) + 5;
+
+ /* Allocate a new list of cube pointers (max size is previous size) */
+ Tc_save = Tc = ALLOC(pcube, listlen);
+
+ /* pass on which variables have been cofactored against */
+ *Tc++ = set_or(new_cube(), T[0], set_diff(mask, cube.fullset, c));
+ Tc++;
+
+ /* Setup for the quick distance check */
+ (void) set_and(mask, cube.var_mask[var], c);
+
+ /* Loop for each cube in the list, determine suitability, and save */
+ for(T1 = T+2; (p = *T1++) != NULL; )
+ if (p != c) {
+ register int i = first;
+ do
+ if (p[i] & mask[i]) {
+ *Tc++ = p;
+ break;
+ }
+ while (++i <= last);
+ }
+
+ *Tc++ = (pcube) NULL; /* sentinel */
+ Tc_save[1] = (pcube) Tc; /* save pointer to last */
+ return Tc_save;
+}
+
+void massive_count(T)
+IN pcube *T;
+{
+ int *count = cdata.part_zeros;
+ pcube *T1;
+
+ /* Clear the column counts (count of # zeros in each column) */
+ { register int i;
+ for(i = cube.size - 1; i >= 0; i--)
+ count[i] = 0;
+ }
+
+ /* Count the number of zeros in each column */
+ { register int i, *cnt;
+ register unsigned int val;
+ register pcube p, cof = T[0], full = cube.fullset;
+ for(T1 = T+2; (p = *T1++) != NULL; )
+ for(i = LOOP(p); i > 0; i--)
+ if (val = full[i] & ~ (p[i] | cof[i])) {
+ cnt = count + ((i-1) << LOGBPI);
+#if BPI == 32
+ if (val & 0xFF000000) {
+ if (val & 0x80000000) cnt[31]++;
+ if (val & 0x40000000) cnt[30]++;
+ if (val & 0x20000000) cnt[29]++;
+ if (val & 0x10000000) cnt[28]++;
+ if (val & 0x08000000) cnt[27]++;
+ if (val & 0x04000000) cnt[26]++;
+ if (val & 0x02000000) cnt[25]++;
+ if (val & 0x01000000) cnt[24]++;
+ }
+ if (val & 0x00FF0000) {
+ if (val & 0x00800000) cnt[23]++;
+ if (val & 0x00400000) cnt[22]++;
+ if (val & 0x00200000) cnt[21]++;
+ if (val & 0x00100000) cnt[20]++;
+ if (val & 0x00080000) cnt[19]++;
+ if (val & 0x00040000) cnt[18]++;
+ if (val & 0x00020000) cnt[17]++;
+ if (val & 0x00010000) cnt[16]++;
+ }
+#endif
+ if (val & 0xFF00) {
+ if (val & 0x8000) cnt[15]++;
+ if (val & 0x4000) cnt[14]++;
+ if (val & 0x2000) cnt[13]++;
+ if (val & 0x1000) cnt[12]++;
+ if (val & 0x0800) cnt[11]++;
+ if (val & 0x0400) cnt[10]++;
+ if (val & 0x0200) cnt[ 9]++;
+ if (val & 0x0100) cnt[ 8]++;
+ }
+ if (val & 0x00FF) {
+ if (val & 0x0080) cnt[ 7]++;
+ if (val & 0x0040) cnt[ 6]++;
+ if (val & 0x0020) cnt[ 5]++;
+ if (val & 0x0010) cnt[ 4]++;
+ if (val & 0x0008) cnt[ 3]++;
+ if (val & 0x0004) cnt[ 2]++;
+ if (val & 0x0002) cnt[ 1]++;
+ if (val & 0x0001) cnt[ 0]++;
+ }
+ }
+ }
+
+ /*
+ * Perform counts for each variable:
+ * cdata.var_zeros[var] = number of zeros in the variable
+ * cdata.parts_active[var] = number of active parts for each variable
+ * cdata.vars_active = number of variables which are active
+ * cdata.vars_unate = number of variables which are active and unate
+ *
+ * best -- the variable which is best for splitting based on:
+ * mostactive -- most # active parts in any variable
+ * mostzero -- most # zeros in any variable
+ * mostbalanced -- minimum over the maximum # zeros / part / variable
+ */
+
+ { register int var, i, lastbit, active, maxactive;
+ int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000;
+ cdata.vars_unate = cdata.vars_active = 0;
+
+ for(var = 0; var < cube.num_vars; var++) {
+ if (var < cube.num_binary_vars) { /* special hack for binary vars */
+ i = count[var*2];
+ lastbit = count[var*2 + 1];
+ active = (i > 0) + (lastbit > 0);
+ cdata.var_zeros[var] = i + lastbit;
+ maxactive = MAX(i, lastbit);
+ } else {
+ maxactive = active = cdata.var_zeros[var] = 0;
+ lastbit = cube.last_part[var];
+ for(i = cube.first_part[var]; i <= lastbit; i++) {
+ cdata.var_zeros[var] += count[i];
+ active += (count[i] > 0);
+ if (active > maxactive) maxactive = active;
+ }
+ }
+
+ /* first priority is to maximize the number of active parts */
+ /* for binary case, this will usually select the output first */
+ if (active > mostactive)
+ best = var, mostactive = active, mostzero = cdata.var_zeros[best],
+ mostbalanced = maxactive;
+ else if (active == mostactive)
+ /* secondary condition is to maximize the number zeros */
+ /* for binary variables, this is the same as minimum # of 2's */
+ if (cdata.var_zeros[var] > mostzero)
+ best = var, mostzero = cdata.var_zeros[best],
+ mostbalanced = maxactive;
+ else if (cdata.var_zeros[var] == mostzero)
+ /* third condition is to pick a balanced variable */
+ /* for binary vars, this means roughly equal # 0's and 1's */
+ if (maxactive < mostbalanced)
+ best = var, mostbalanced = maxactive;
+
+ cdata.parts_active[var] = active;
+ cdata.is_unate[var] = (active == 1);
+ cdata.vars_active += (active > 0);
+ cdata.vars_unate += (active == 1);
+ }
+ cdata.best = best;
+ }
+}
+
+int binate_split_select(T, cleft, cright, debug_flag)
+IN pcube *T;
+IN register pcube cleft, cright;
+IN int debug_flag;
+{
+ int best = cdata.best;
+ register int i, lastbit = cube.last_part[best], halfbit = 0;
+ register pcube cof=T[0];
+
+ /* Create the cubes to cofactor against */
+ (void) set_diff(cleft, cube.fullset, cube.var_mask[best]);
+ (void) set_diff(cright, cube.fullset, cube.var_mask[best]);
+ for(i = cube.first_part[best]; i <= lastbit; i++)
+ if (! is_in_set(cof,i))
+ halfbit++;
+ for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++)
+ if (! is_in_set(cof,i))
+ halfbit--, set_insert(cleft, i);
+ for(; i <= lastbit; i++)
+ if (! is_in_set(cof,i))
+ set_insert(cright, i);
+
+ if (debug & debug_flag) {
+ (void) printf("BINATE_SPLIT_SELECT: split against %d\n", best);
+ if (verbose_debug)
+ (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright));
+ }
+ return best;
+}
+
+
+pcube *cube1list(A)
+pcover A;
+{
+ register pcube last, p, *plist, *list;
+
+ list = plist = ALLOC(pcube, A->count + 3);
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL; /* sentinel */
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcube *cube2list(A, B)
+pcover A, B;
+{
+ register pcube last, p, *plist, *list;
+
+ list = plist = ALLOC(pcube, A->count + B->count + 3);
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(B, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL;
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcube *cube3list(A, B, C)
+pcover A, B, C;
+{
+ register pcube last, p, *plist, *list;
+
+ plist = ALLOC(pcube, A->count + B->count + C->count + 3);
+ list = plist;
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(B, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(C, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL;
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcover cubeunlist(A1)
+pcube *A1;
+{
+ register int i;
+ register pcube p, pdest, cof = A1[0];
+ register pcover A;
+
+ A = new_cover(CUBELISTSIZE(A1));
+ for(i = 2; (p = A1[i]) != NULL; i++) {
+ pdest = GETSET(A, i-2);
+ INLINEset_or(pdest, p, cof);
+ }
+ A->count = CUBELISTSIZE(A1);
+ return A;
+}
+
+simplify_cubelist(T)
+pcube *T;
+{
+ register pcube *Tdest;
+ register int i, ncubes;
+
+ (void) set_copy(cube.temp[0], T[0]); /* retrieve cofactor */
+
+ ncubes = CUBELISTSIZE(T);
+ qsort((char *) (T+2), ncubes, sizeof(pset), (int (*)()) d1_order);
+
+ Tdest = T+2;
+ /* *Tdest++ = T[2]; */
+ for(i = 3; i < ncubes; i++) {
+ if (d1_order(&T[i-1], &T[i]) != 0) {
+ *Tdest++ = T[i];
+ }
+ }
+
+ *Tdest++ = NULL; /* sentinel */
+ Tdest[1] = (pcube) Tdest; /* save pointer to last */
+}
diff --git a/src/misc/espresso/cols.c b/src/misc/espresso/cols.c
new file mode 100644
index 00000000..ec3797e6
--- /dev/null
+++ b/src/misc/espresso/cols.c
@@ -0,0 +1,314 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+
+/*
+ * allocate a new col vector
+ */
+sm_col *
+sm_col_alloc()
+{
+ 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(pcol)
+register 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(pcol)
+register 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(pcol, row)
+register sm_col *pcol;
+register 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(pcol, row)
+register sm_col *pcol;
+register 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(pcol, row)
+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(p1, p2)
+sm_col *p1, *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(p1, p2)
+sm_col *p1, *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(p1, p2)
+sm_col *p1, *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(p1, p2)
+sm_col *p1, *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(pcol, modulus)
+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(pcol, p)
+register sm_col *pcol;
+register 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(fp, pcol)
+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);
+ }
+}
diff --git a/src/misc/espresso/compl.c b/src/misc/espresso/compl.c
new file mode 100644
index 00000000..8f1c6606
--- /dev/null
+++ b/src/misc/espresso/compl.c
@@ -0,0 +1,680 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * module: compl.c
+ * purpose: compute the complement of a multiple-valued function
+ *
+ * The "unate recursive paradigm" is used. After a set of special
+ * cases are examined, the function is split on the "most active
+ * variable". These two halves are complemented recursively, and then
+ * the results are merged.
+ *
+ * Changes (from Version 2.1 to Version 2.2)
+ * 1. Minor bug in compl_lifting -- cubes in the left half were
+ * not marked as active, so that when merging a leaf from the left
+ * hand side, the active flags were essentially random. This led
+ * to minor impredictability problem, but never affected the
+ * accuracy of the results.
+ */
+
+#include "espresso.h"
+
+#define USE_COMPL_LIFT 0
+#define USE_COMPL_LIFT_ONSET 1
+#define USE_COMPL_LIFT_ONSET_COMPLEX 2
+#define NO_LIFTING 3
+
+static bool compl_special_cases();
+static pcover compl_merge();
+static void compl_d1merge();
+static pcover compl_cube();
+static void compl_lift();
+static void compl_lift_onset();
+static void compl_lift_onset_complex();
+static bool simp_comp_special_cases();
+static bool simplify_special_cases();
+
+
+/* complement -- compute the complement of T */
+pcover complement(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tbar, Tl, Tr;
+ int lifting;
+ static int compl_level = 0;
+
+ if (debug & COMPL)
+ debug_print(T, "COMPLEMENT", compl_level++);
+
+ if (compl_special_cases(T, &Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ Tl = complement(scofactor(T, cl, best));
+ Tr = complement(scofactor(T, cr, best));
+
+ if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) {
+ lifting = USE_COMPL_LIFT_ONSET;
+ } else {
+ lifting = USE_COMPL_LIFT;
+ }
+ Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL)
+ debug1_print(Tbar, "exit COMPLEMENT", --compl_level);
+ return Tbar;
+}
+
+static bool compl_special_cases(T, Tbar)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tbar; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcover A, ceil_compl;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tbar = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tbar = compl_cube(set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies complement is null) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tbar = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ ceil_compl = compl_cube(ceil);
+ (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil));
+ set_free(ceil);
+ *Tbar = sf_append(complement(T), ceil_compl);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tbar = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = map_cover_to_unate(T);
+ free_cubelist(T);
+ A = unate_compl(A);
+ *Tbar = map_unate_to_cover(A);
+ sf_free(A);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+/*
+ * compl_merge -- merge the two cofactors around the splitting
+ * variable
+ *
+ * The merge operation involves intersecting each cube of the left
+ * cofactor with cl, and intersecting each cube of the right cofactor
+ * with cr. The union of these two covers is the merged result.
+ *
+ * In order to reduce the number of cubes, a distance-1 merge is
+ * performed (note that two cubes can only combine distance-1 in the
+ * splitting variable). Also, a simple expand is performed in the
+ * splitting variable (simple implies the covering check for the
+ * expansion is not full containment, but single-cube containment).
+ */
+
+static pcover compl_merge(T1, L, R, cl, cr, var, lifting)
+pcube *T1; /* Original ON-set */
+pcover L, R; /* Complement from each recursion branch */
+register pcube cl, cr; /* cubes used for cofactoring */
+int var; /* splitting variable */
+int lifting; /* whether to perform lifting or not */
+{
+ register pcube p, last, pt;
+ pcover T, Tbar;
+ pcube *L1, *R1;
+
+ if (debug & COMPL) {
+ (void) printf("compl_merge: left %d, right %d\n", L->count, R->count);
+ (void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr));
+ cprint(L);
+ (void) printf("Right is\n");
+ cprint(R);
+ }
+
+ /* Intersect each cube with the cofactored cube */
+ foreach_set(L, last, p) {
+ INLINEset_and(p, p, cl);
+ SET(p, ACTIVE);
+ }
+ foreach_set(R, last, p) {
+ INLINEset_and(p, p, cr);
+ SET(p, ACTIVE);
+ }
+
+ /* Sort the arrays for a distance-1 merge */
+ (void) set_copy(cube.temp[0], cube.var_mask[var]);
+ qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order);
+ qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order);
+
+ /* Perform distance-1 merge */
+ compl_d1merge(L1, R1);
+
+ /* Perform lifting */
+ switch(lifting) {
+ case USE_COMPL_LIFT_ONSET:
+ T = cubeunlist(T1);
+ compl_lift_onset(L1, T, cr, var);
+ compl_lift_onset(R1, T, cl, var);
+ free_cover(T);
+ break;
+ case USE_COMPL_LIFT_ONSET_COMPLEX:
+ T = cubeunlist(T1);
+ compl_lift_onset_complex(L1, T, var);
+ compl_lift_onset_complex(R1, T, var);
+ free_cover(T);
+ break;
+ case USE_COMPL_LIFT:
+ compl_lift(L1, R1, cr, var);
+ compl_lift(R1, L1, cl, var);
+ break;
+ case NO_LIFTING:
+ break;
+ default:
+ ;
+ }
+ FREE(L1);
+ FREE(R1);
+
+ /* Re-create the merged cover */
+ Tbar = new_cover(L->count + R->count);
+ pt = Tbar->data;
+ foreach_set(L, last, p) {
+ INLINEset_copy(pt, p);
+ Tbar->count++;
+ pt += Tbar->wsize;
+ }
+ foreach_active_set(R, last, p) {
+ INLINEset_copy(pt, p);
+ Tbar->count++;
+ pt += Tbar->wsize;
+ }
+
+ if (debug & COMPL) {
+ (void) printf("Result %d\n", Tbar->count);
+ if (verbose_debug)
+ cprint(Tbar);
+ }
+
+ free_cover(L);
+ free_cover(R);
+ return Tbar;
+}
+
+/*
+ * compl_lift_simple -- expand in the splitting variable using single
+ * cube containment against the other recursion branch to check
+ * validity of the expansion, and expanding all (or none) of the
+ * splitting variable.
+ */
+static void compl_lift(A1, B1, bcube, var)
+pcube *A1, *B1, bcube;
+int var;
+{
+ register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5];
+ pcube mask = cube.var_mask[var];
+
+ (void) set_and(liftor, bcube, mask);
+
+ /* for each cube in the first array ... */
+ for(; (a = *A1++) != NULL; ) {
+ if (TESTP(a, ACTIVE)) {
+
+ /* create a lift of this cube in the merging coord */
+ (void) set_merge(lift, bcube, a, mask);
+
+ /* for each cube in the second array */
+ for(B2 = B1; (b = *B2++) != NULL; ) {
+ INLINEsetp_implies(lift, b, /* when_false => */ continue);
+ /* when_true => fall through to next statement */
+
+ /* cube of A1 was contained by some cube of B1, so raise */
+ INLINEset_or(a, a, liftor);
+ break;
+ }
+ }
+ }
+}
+
+
+
+/*
+ * compl_lift_onset -- expand in the splitting variable using a
+ * distance-1 check against the original on-set; expand all (or
+ * none) of the splitting variable. Each cube of A1 is expanded
+ * against the original on-set T.
+ */
+static void compl_lift_onset(A1, T, bcube, var)
+pcube *A1;
+pcover T;
+pcube bcube;
+int var;
+{
+ register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var];
+
+ /* for each active cube from one branch of the complement */
+ for(; (a = *A1++) != NULL; ) {
+ if (TESTP(a, ACTIVE)) {
+
+ /* create a lift of this cube in the merging coord */
+ INLINEset_and(lift, bcube, mask); /* isolate parts to raise */
+ INLINEset_or(lift, a, lift); /* raise these parts in a */
+
+ /* for each cube in the ON-set, check for intersection */
+ foreach_set(T, last, p) {
+ if (cdist0(p, lift)) {
+ goto nolift;
+ }
+ }
+ INLINEset_copy(a, lift); /* save the raising */
+ SET(a, ACTIVE);
+nolift : ;
+ }
+ }
+}
+
+/*
+ * compl_lift_complex -- expand in the splitting variable, but expand all
+ * parts which can possibly expand.
+ * T is the original ON-set
+ * A1 is either the left or right cofactor
+ */
+static void compl_lift_onset_complex(A1, T, var)
+pcube *A1; /* array of pointers to new result */
+pcover T; /* original ON-set */
+int var; /* which variable we split on */
+{
+ register int dist;
+ register pcube last, p, a, xlower;
+
+ /* for each cube in the complement */
+ xlower = new_cube();
+ for(; (a = *A1++) != NULL; ) {
+
+ if (TESTP(a, ACTIVE)) {
+
+ /* Find which parts of the splitting variable are forced low */
+ INLINEset_clear(xlower, cube.size);
+ foreach_set(T, last, p) {
+ if ((dist = cdist01(p, a)) < 2) {
+ if (dist == 0) {
+ fatal("compl: ON-set and OFF-set are not orthogonal");
+ } else {
+ (void) force_lower(xlower, p, a);
+ }
+ }
+ }
+
+ (void) set_diff(xlower, cube.var_mask[var], xlower);
+ (void) set_or(a, a, xlower);
+ free_cube(xlower);
+ }
+ }
+}
+
+
+
+/*
+ * compl_d1merge -- distance-1 merge in the splitting variable
+ */
+static void compl_d1merge(L1, R1)
+register pcube *L1, *R1;
+{
+ register pcube pl, pr;
+
+ /* Find equal cubes between the two cofactors */
+ for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); )
+ switch (d1_order(L1, R1)) {
+ case 1:
+ pr = *(++R1); break; /* advance right pointer */
+ case -1:
+ pl = *(++L1); break; /* advance left pointer */
+ case 0:
+ RESET(pr, ACTIVE);
+ INLINEset_or(pl, pl, pr);
+ pr = *(++R1);
+ default:
+ ;
+ }
+}
+
+
+
+/* compl_cube -- return the complement of a single cube (De Morgan's law) */
+static pcover compl_cube(p)
+register pcube p;
+{
+ register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset;
+ int var;
+ pcover R;
+
+ /* Allocate worst-case size cover (to avoid checking overflow) */
+ R = new_cover(cube.num_vars);
+
+ /* Compute bit-wise complement of the cube */
+ INLINEset_diff(diff, full, p);
+
+ for(var = 0; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ /* If the bit-wise complement is not empty in var ... */
+ if (! setp_disjoint(diff, mask)) {
+ pdest = GETSET(R, R->count++);
+ INLINEset_merge(pdest, diff, full, mask);
+ }
+ }
+ return R;
+}
+
+/* simp_comp -- quick simplification of T */
+void simp_comp(T, Tnew, Tbar)
+pcube *T; /* T will be disposed of */
+pcover *Tnew;
+pcover *Tbar;
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tl, Tr, Tlbar, Trbar;
+ int lifting;
+ static int simplify_level = 0;
+
+ if (debug & COMPL)
+ debug_print(T, "SIMPCOMP", simplify_level++);
+
+ if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ simp_comp(scofactor(T, cl, best), &Tl, &Tlbar);
+ simp_comp(scofactor(T, cr, best), &Tr, &Trbar);
+
+ lifting = USE_COMPL_LIFT;
+ *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ lifting = USE_COMPL_LIFT;
+ *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting);
+
+ /* All of this work for nothing ? Let's hope not ... */
+ if ((*Tnew)->count > CUBELISTSIZE(T)) {
+ sf_free(*Tnew);
+ *Tnew = cubeunlist(T);
+ }
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL) {
+ debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level);
+ debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level);
+ simplify_level--;
+ }
+}
+
+static bool simp_comp_special_cases(T, Tnew, Tbar)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+pcover *Tbar; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover (function is empty) */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(1);
+ *Tbar = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ (void) set_or(cof, cof, T[2]);
+ *Tnew = sf_addset(new_cover(1), cof);
+ *Tbar = compl_cube(cof);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ *Tbar = new_cover(1);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ set_free(p);
+ simp_comp(T, Tnew, Tbar);
+
+ /* Adjust the ON-set */
+ A = *Tnew;
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+
+ /* Compute the new complement */
+ *Tbar = sf_append(*Tbar, compl_cube(ceil));
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ *Tbar = new_cover(1);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ /* Make the cover minimum by single-cube containment */
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+
+ /* Now form a minimum representation of the complement */
+ A = map_cover_to_unate(T);
+ A = unate_compl(A);
+ *Tbar = map_unate_to_cover(A);
+ sf_free(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+/* simplify -- quick simplification of T */
+pcover simplify(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tbar, Tl, Tr;
+ int lifting;
+ static int simplify_level = 0;
+
+ if (debug & COMPL) {
+ debug_print(T, "SIMPLIFY", simplify_level++);
+ }
+
+ if (simplify_special_cases(T, &Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ Tl = simplify(scofactor(T, cl, best));
+ Tr = simplify(scofactor(T, cr, best));
+
+ lifting = USE_COMPL_LIFT;
+ Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ /* All of this work for nothing ? Let's hope not ... */
+ if (Tbar->count > CUBELISTSIZE(T)) {
+ sf_free(Tbar);
+ Tbar = cubeunlist(T);
+ }
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL) {
+ debug1_print(Tbar, "exit SIMPLIFY", --simplify_level);
+ }
+ return Tbar;
+}
+
+static bool simplify_special_cases(T, Tnew)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ free_cube(p);
+
+ A = simplify(T);
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+ *Tnew = A;
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
diff --git a/src/misc/espresso/contain.c b/src/misc/espresso/contain.c
new file mode 100644
index 00000000..180dceb6
--- /dev/null
+++ b/src/misc/espresso/contain.c
@@ -0,0 +1,441 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ contain.c -- set containment routines
+
+ These are complex routines for performing containment over a
+ family of sets, but they have the advantage of being much faster
+ than a straightforward n*n routine.
+
+ First the cubes are sorted by size, and as a secondary key they are
+ sorted so that if two cubes are equal they end up adjacent. We can
+ than quickly remove equal cubes from further consideration by
+ comparing each cube to its neighbor. Finally, because the cubes
+ are sorted by size, we need only check cubes which are larger (or
+ smaller) than a given cube for containment.
+*/
+
+#include "espresso.h"
+
+
+/*
+ sf_contain -- perform containment on a set family (delete sets which
+ are contained by some larger set in the family). No assumptions are
+ made about A, and the result will be returned in decreasing order of
+ set size.
+*/
+pset_family sf_contain(A)
+INOUT pset_family A; /* disposes of A */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort into descending order */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ cnt = rm_contain(A1); /* remove contained sets */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_rev_contain -- perform containment on a set family (delete sets which
+ contain some smaller set in the family). No assumptions are made about
+ A, and the result will be returned in increasing order of set size
+*/
+pset_family sf_rev_contain(A)
+INOUT pset_family A; /* disposes of A */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, ascend); /* sort into ascending order */
+ cnt = rm_equal(A1, ascend); /* remove duplicates */
+ cnt = rm_rev_contain(A1); /* remove containing sets */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_ind_contain -- perform containment on a set family (delete sets which
+ are contained by some larger set in the family). No assumptions are
+ made about A, and the result will be returned in decreasing order of
+ set size. Also maintains a set of row_indices to track which rows
+ disappear and how the rows end up permuted.
+*/
+pset_family sf_ind_contain(A, row_indices)
+INOUT pset_family A; /* disposes of A */
+INOUT int *row_indices; /* updated with the new values */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort into descending order */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ cnt = rm_contain(A1); /* remove contained sets */
+ R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data);
+ sf_free(A);
+ return R;
+}
+
+
+/* sf_dupl -- delete duplicate sets in a set family */
+pset_family sf_dupl(A)
+INOUT pset_family A; /* disposes of A */
+{
+ register int cnt;
+ register pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort the set family */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_union -- form the contained union of two set families (delete
+ sets which are contained by some larger set in the family). A and
+ B are assumed already sorted in decreasing order of set size (and
+ the SIZE field is assumed to contain the set size), and the result
+ will be returned sorted likewise.
+*/
+pset_family sf_union(A, B)
+INOUT pset_family A, B; /* disposes of A and B */
+{
+ int cnt;
+ pset_family R;
+ pset *A1 = sf_list(A), *B1 = sf_list(B), *E1;
+
+ E1 = ALLOC(pset, MAX(A->count, B->count) + 1);
+ cnt = rm2_equal(A1, B1, E1, descend);
+ cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1);
+ R = sf_merge(A1, B1, E1, cnt, A->sf_size);
+ sf_free(A); sf_free(B);
+ return R;
+}
+
+
+/*
+ dist_merge -- consider all sets to be "or"-ed with "mask" and then
+ delete duplicates from the set family.
+*/
+pset_family dist_merge(A, mask)
+INOUT pset_family A; /* disposes of A */
+IN pset mask; /* defines variables to mask out */
+{
+ pset *A1;
+ int cnt;
+ pset_family R;
+
+ (void) set_copy(cube.temp[0], mask);
+ A1 = sf_sort(A, d1_order);
+ cnt = d1_rm_equal(A1, d1_order);
+ R = sf_unlist(A1, cnt, A->sf_size);
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ d1merge -- perform an efficient distance-1 merge of cubes of A
+*/
+pset_family d1merge(A, var)
+INOUT pset_family A; /* disposes of A */
+IN int var;
+{
+ return dist_merge(A, cube.var_mask[var]);
+}
+
+
+
+/* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */
+int d1_rm_equal(A1, compare)
+register pset *A1; /* array of set pointers */
+int (*compare)(); /* comparison function */
+{
+ register int i, j, dest;
+
+ dest = 0;
+ if (A1[0] != (pcube) NULL) {
+ for(i = 0, j = 1; A1[j] != (pcube) NULL; j++)
+ if ( (*compare)(&A1[i], &A1[j]) == 0) {
+ /* if sets are equal (under the mask) merge them */
+ (void) set_or(A1[i], A1[i], A1[j]);
+ } else {
+ /* sets are unequal, so save the set i */
+ A1[dest++] = A1[i];
+ i = j;
+ }
+ A1[dest++] = A1[i];
+ }
+ A1[dest] = (pcube) NULL;
+ return dest;
+}
+
+
+/* rm_equal -- scan a sorted array of set pointers for duplicate sets */
+int rm_equal(A1, compare)
+INOUT pset *A1; /* updated in place */
+IN int (*compare)();
+{
+ register pset *p, *pdest = A1;
+
+ if (*A1 != NULL) { /* If more than one set */
+ for(p = A1+1; *p != NULL; p++)
+ if ((*compare)(p, p-1) != 0)
+ *pdest++ = *(p-1);
+ *pdest++ = *(p-1);
+ *pdest = NULL;
+ }
+ return pdest - A1;
+}
+
+
+/* rm_contain -- perform containment over a sorted array of set pointers */
+int rm_contain(A1)
+INOUT pset *A1; /* updated in place */
+{
+ register pset *pa, *pb, *pcheck, a, b;
+ pset *pdest = A1;
+ int last_size = -1;
+
+ /* Loop for all cubes of A1 */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* Update the check pointer if the size has changed */
+ if (SIZE(a) != last_size)
+ last_size = SIZE(a), pcheck = pdest;
+ for(pb = A1; pb != pcheck; ) {
+ b = *pb++;
+ INLINEsetp_implies(a, b, /* when_false => */ continue);
+ goto lnext1;
+ }
+ /* set a was not contained by some larger set, so save it */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL;
+ return pdest - A1;
+}
+
+
+/* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */
+int rm_rev_contain(A1)
+INOUT pset *A1; /* updated in place */
+{
+ register pset *pa, *pb, *pcheck, a, b;
+ pset *pdest = A1;
+ int last_size = -1;
+
+ /* Loop for all cubes of A1 */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* Update the check pointer if the size has changed */
+ if (SIZE(a) != last_size)
+ last_size = SIZE(a), pcheck = pdest;
+ for(pb = A1; pb != pcheck; ) {
+ b = *pb++;
+ INLINEsetp_implies(b, a, /* when_false => */ continue);
+ goto lnext1;
+ }
+ /* the set a did not contain some smaller set, so save it */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL;
+ return pdest - A1;
+}
+
+
+/* rm2_equal -- check two sorted arrays of set pointers for equal cubes */
+int rm2_equal(A1, B1, E1, compare)
+INOUT register pset *A1, *B1; /* updated in place */
+OUT pset *E1;
+IN int (*compare)();
+{
+ register pset *pda = A1, *pdb = B1, *pde = E1;
+
+ /* Walk through the arrays advancing pointer to larger cube */
+ for(; *A1 != NULL && *B1 != NULL; )
+ switch((*compare)(A1, B1)) {
+ case -1: /* "a" comes before "b" */
+ *pda++ = *A1++; break;
+ case 0: /* equal cubes */
+ *pde++ = *A1++; B1++; break;
+ case 1: /* "a" is to follow "b" */
+ *pdb++ = *B1++; break;
+ }
+
+ /* Finish moving down the pointers of A and B */
+ while (*A1 != NULL)
+ *pda++ = *A1++;
+ while (*B1 != NULL)
+ *pdb++ = *B1++;
+ *pda = *pdb = *pde = NULL;
+
+ return pde - E1;
+}
+
+
+/* rm2_contain -- perform containment between two arrays of set pointers */
+int rm2_contain(A1, B1)
+INOUT pset *A1; /* updated in place */
+IN pset *B1; /* unchanged */
+{
+ register pset *pa, *pb, a, b, *pdest = A1;
+
+ /* for each set in the first array ... */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* for each set in the second array which is larger ... */
+ for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) {
+ INLINEsetp_implies(a, b, /* when_false => */ continue);
+ /* set was contained in some set of B, so don't save pointer */
+ goto lnext1;
+ }
+ /* set wasn't contained in any set of B, so save the pointer */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL; /* sentinel */
+ return pdest - A1; /* # elements in A1 */
+}
+
+
+
+/* sf_sort -- sort the sets of A */
+pset *sf_sort(A, compare)
+IN pset_family A;
+IN int (*compare)();
+{
+ register pset p, last, *pdest, *A1;
+
+ /* Create a single array pointing to each cube of A */
+ pdest = A1 = ALLOC(pset, A->count + 1);
+ foreach_set(A, last, p) {
+ PUTSIZE(p, set_ord(p)); /* compute the set size */
+ *pdest++ = p; /* save the pointer */
+ }
+ *pdest = NULL; /* Sentinel -- never seen by sort */
+
+ /* Sort cubes by size */
+ qsort((char *) A1, A->count, sizeof(pset), compare);
+ return A1;
+}
+
+
+/* sf_list -- make a list of pointers to the sets in a set family */
+pset *sf_list(A)
+IN register pset_family A;
+{
+ register pset p, last, *pdest, *A1;
+
+ /* Create a single array pointing to each cube of A */
+ pdest = A1 = ALLOC(pset, A->count + 1);
+ foreach_set(A, last, p)
+ *pdest++ = p; /* save the pointer */
+ *pdest = NULL; /* Sentinel */
+ return A1;
+}
+
+
+/* sf_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_unlist(A1, totcnt, size)
+IN pset *A1;
+IN int totcnt, size;
+{
+ register pset pr, p, *pa;
+ pset_family R = sf_new(totcnt, size);
+
+ R->count = totcnt;
+ for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize)
+ INLINEset_copy(pr, p);
+ FREE(A1);
+ return R;
+}
+
+
+/* sf_ind_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst)
+IN pset *A1;
+IN int totcnt, size;
+INOUT int *row_indices;
+IN register pset pfirst;
+{
+ register pset pr, p, *pa;
+ register int i, *new_row_indices;
+ pset_family R = sf_new(totcnt, size);
+
+ R->count = totcnt;
+ new_row_indices = ALLOC(int, totcnt);
+ for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) {
+ INLINEset_copy(pr, p);
+ new_row_indices[i] = row_indices[(p - pfirst)/R->wsize];
+ }
+ for(i = 0; i < totcnt; i++)
+ row_indices[i] = new_row_indices[i];
+ FREE(new_row_indices);
+ FREE(A1);
+ return R;
+}
+
+
+/* sf_merge -- merge three sorted lists of set pointers */
+pset_family sf_merge(A1, B1, E1, totcnt, size)
+INOUT pset *A1, *B1, *E1; /* will be disposed of */
+IN int totcnt, size;
+{
+ register pset pr, ps, *pmin, *pmid, *pmax;
+ pset_family R;
+ pset *temp[3], *swap;
+ int i, j, n;
+
+ /* Allocate the result set_family */
+ R = sf_new(totcnt, size);
+ R->count = totcnt;
+ pr = R->data;
+
+ /* Quick bubble sort to order the top member of the three arrays */
+ n = 3; temp[0] = A1; temp[1] = B1; temp[2] = E1;
+ for(i = 0; i < n-1; i++)
+ for(j = i+1; j < n; j++)
+ if (desc1(*temp[i], *temp[j]) > 0) {
+ swap = temp[j];
+ temp[j] = temp[i];
+ temp[i] = swap;
+ }
+ pmin = temp[0]; pmid = temp[1]; pmax = temp[2];
+
+ /* Save the minimum element, then update pmin, pmid, pmax */
+ while (*pmin != (pset) NULL) {
+ ps = *pmin++;
+ INLINEset_copy(pr, ps);
+ pr += R->wsize;
+ if (desc1(*pmin, *pmax) > 0) {
+ swap = pmax; pmax = pmin; pmin = pmid; pmid = swap;
+ } else if (desc1(*pmin, *pmid) > 0) {
+ swap = pmin; pmin = pmid; pmid = swap;
+ }
+ }
+
+ FREE(A1);
+ FREE(B1);
+ FREE(E1);
+ return R;
+}
diff --git a/src/misc/espresso/cubehack.c b/src/misc/espresso/cubehack.c
new file mode 100644
index 00000000..8e1724fc
--- /dev/null
+++ b/src/misc/espresso/cubehack.c
@@ -0,0 +1,138 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.1/common/src/sis/node/RCS/cubehack.c,v $
+ * $Author: sis $
+ * $Revision: 1.2 $
+ * $Date: 1992/05/06 18:57:41 $
+ *
+ */
+/*
+#include "sis.h"
+#include "node_int.h"
+
+#ifdef lint
+struct cube_struct cube;
+bool summary;
+bool trace;
+bool remove_essential;
+bool force_irredundant;
+bool unwrap_onset;
+bool single_expand;
+bool pos;
+bool recompute_onset;
+bool use_super_gasp;
+bool use_random_order;
+#endif
+*/
+#include "espresso.h"
+
+
+void
+cautious_define_cube_size(n)
+int n;
+{
+ if (cube.fullset != 0 && cube.num_binary_vars == n)
+ return;
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ cube.num_binary_vars = cube.num_vars = n;
+ cube.part_size = ALLOC(int, n);
+ cube_setup();
+}
+
+
+void
+define_cube_size(n)
+int n;
+{
+ register int q, i;
+ static int called_before = 0;
+
+ /* check if the cube is already just the right size */
+ if (cube.fullset != 0 && cube.num_binary_vars == n && cube.num_vars == n)
+ return;
+
+ /* We can't handle more than 100 inputs */
+ if (n > 100) {
+ cautious_define_cube_size(n);
+ called_before = 0;
+ return;
+ }
+
+ if (cube.fullset == 0 || ! called_before) {
+ cautious_define_cube_size(100);
+ called_before = 1;
+ }
+
+ cube.num_vars = n;
+ cube.num_binary_vars = n;
+ cube.num_mv_vars = 0;
+ cube.output = -1;
+ cube.size = n * 2;
+
+ /* first_part, last_part, first_word, last_word, part_size OKAY */
+ /* cube.sparse is OKAY */
+
+ /* need to completely re-make cube.fullset and cube.binary_mask */
+ (void) set_fill(cube.fullset, n*2);
+ (void) set_fill(cube.binary_mask, n*2);
+
+ /* need to resize each set in cube.var_mask and cube.temp */
+ q = cube.fullset[0];
+ for(i = 0; i < cube.num_vars; i++)
+ cube.var_mask[i][0] = q;
+ for(i = 0; i < CUBE_TEMP; i++)
+ cube.temp[i][0] = q;
+
+ /* need to resize cube.emptyset and cube.mv_mask */
+ cube.emptyset[0] = q;
+ cube.mv_mask[0] = q;
+
+ /* need to reset the inword and inmask */
+ if (cube.num_binary_vars != 0) {
+ cube.inword = cube.last_word[cube.num_binary_vars - 1];
+ cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+ } else {
+ cube.inword = -1;
+ cube.inmask = 0;
+ }
+
+ /* cdata (entire structure) is OKAY */
+}
+
+
+void
+undefine_cube_size()
+{
+ if (cube.num_binary_vars > 100) {
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ } else {
+ cube.num_vars = cube.num_binary_vars = 100;
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ }
+}
+
+
+void
+set_espresso_flags()
+{
+ summary = FALSE;
+ trace = FALSE;
+ remove_essential = TRUE;
+ force_irredundant = TRUE;
+ unwrap_onset = TRUE;
+ single_expand = FALSE;
+ pos = FALSE;
+ recompute_onset = FALSE;
+ use_super_gasp = FALSE;
+ use_random_order = FALSE;
+}
diff --git a/src/misc/espresso/cubestr.c b/src/misc/espresso/cubestr.c
new file mode 100644
index 00000000..77389e73
--- /dev/null
+++ b/src/misc/espresso/cubestr.c
@@ -0,0 +1,152 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ Module: cubestr.c -- routines for managing the global cube structure
+*/
+
+#include "espresso.h"
+
+/*
+ cube_setup -- assume that the fields "num_vars", "num_binary_vars", and
+ part_size[num_binary_vars .. num_vars-1] are setup, and initialize the
+ rest of cube and cdata.
+
+ If a part_size is < 0, then the field size is abs(part_size) and the
+ field read from the input is symbolic.
+*/
+void cube_setup()
+{
+ register int i, var;
+ register pcube p;
+
+ if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars)
+ fatal("cube size is silly, error in .i/.o or .mv");
+
+ cube.num_mv_vars = cube.num_vars - cube.num_binary_vars;
+ cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1;
+
+ cube.size = 0;
+ cube.first_part = ALLOC(int, cube.num_vars);
+ cube.last_part = ALLOC(int, cube.num_vars);
+ cube.first_word = ALLOC(int, cube.num_vars);
+ cube.last_word = ALLOC(int, cube.num_vars);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (var < cube.num_binary_vars)
+ cube.part_size[var] = 2;
+ cube.first_part[var] = cube.size;
+ cube.first_word[var] = WHICH_WORD(cube.size);
+ cube.size += ABS(cube.part_size[var]);
+ cube.last_part[var] = cube.size - 1;
+ cube.last_word[var] = WHICH_WORD(cube.size - 1);
+ }
+
+ cube.var_mask = ALLOC(pset, cube.num_vars);
+ cube.sparse = ALLOC(int, cube.num_vars);
+ cube.binary_mask = new_cube();
+ cube.mv_mask = new_cube();
+ for(var = 0; var < cube.num_vars; var++) {
+ p = cube.var_mask[var] = new_cube();
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ set_insert(p, i);
+ if (var < cube.num_binary_vars) {
+ INLINEset_or(cube.binary_mask, cube.binary_mask, p);
+ cube.sparse[var] = 0;
+ } else {
+ INLINEset_or(cube.mv_mask, cube.mv_mask, p);
+ cube.sparse[var] = 1;
+ }
+ }
+ if (cube.num_binary_vars == 0)
+ cube.inword = -1;
+ else {
+ cube.inword = cube.last_word[cube.num_binary_vars - 1];
+ cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+ }
+
+ cube.temp = ALLOC(pset, CUBE_TEMP);
+ for(i = 0; i < CUBE_TEMP; i++)
+ cube.temp[i] = new_cube();
+ cube.fullset = set_fill(new_cube(), cube.size);
+ cube.emptyset = new_cube();
+
+ cdata.part_zeros = ALLOC(int, cube.size);
+ cdata.var_zeros = ALLOC(int, cube.num_vars);
+ cdata.parts_active = ALLOC(int, cube.num_vars);
+ cdata.is_unate = ALLOC(int, cube.num_vars);
+}
+
+/*
+ setdown_cube -- free memory allocated for the cube/cdata structs
+ (free's all but the part_size array)
+
+ (I wanted to call this cube_setdown, but that violates the 8-character
+ external routine limit on the IBM !)
+*/
+void setdown_cube()
+{
+ register int i, var;
+
+ FREE(cube.first_part);
+ FREE(cube.last_part);
+ FREE(cube.first_word);
+ FREE(cube.last_word);
+ FREE(cube.sparse);
+
+ free_cube(cube.binary_mask);
+ free_cube(cube.mv_mask);
+ free_cube(cube.fullset);
+ free_cube(cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++)
+ free_cube(cube.var_mask[var]);
+ FREE(cube.var_mask);
+
+ for(i = 0; i < CUBE_TEMP; i++)
+ free_cube(cube.temp[i]);
+ FREE(cube.temp);
+
+ FREE(cdata.part_zeros);
+ FREE(cdata.var_zeros);
+ FREE(cdata.parts_active);
+ FREE(cdata.is_unate);
+
+ cube.first_part = cube.last_part = (int *) NULL;
+ cube.first_word = cube.last_word = (int *) NULL;
+ cube.sparse = (int *) NULL;
+ cube.binary_mask = cube.mv_mask = (pcube) NULL;
+ cube.fullset = cube.emptyset = (pcube) NULL;
+ cube.var_mask = cube.temp = (pcube *) NULL;
+
+ cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+ cdata.is_unate = (bool *) NULL;
+}
+
+
+void save_cube_struct()
+{
+ temp_cube_save = cube; /* structure copy ! */
+ temp_cdata_save = cdata; /* "" */
+
+ cube.first_part = cube.last_part = (int *) NULL;
+ cube.first_word = cube.last_word = (int *) NULL;
+ cube.part_size = (int *) NULL;
+ cube.binary_mask = cube.mv_mask = (pcube) NULL;
+ cube.fullset = cube.emptyset = (pcube) NULL;
+ cube.var_mask = cube.temp = (pcube *) NULL;
+
+ cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+ cdata.is_unate = (bool *) NULL;
+}
+
+
+void restore_cube_struct()
+{
+ cube = temp_cube_save; /* structure copy ! */
+ cdata = temp_cdata_save; /* "" */
+}
diff --git a/src/misc/espresso/cvrin.c b/src/misc/espresso/cvrin.c
new file mode 100644
index 00000000..7790b38b
--- /dev/null
+++ b/src/misc/espresso/cvrin.c
@@ -0,0 +1,810 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrin.c
+ purpose: cube and cover input routines
+*/
+
+#include "espresso.h"
+
+static bool line_length_error;
+static int lineno;
+
+void skip_line(fpin, fpout, echo)
+register FILE *fpin, *fpout;
+register bool echo;
+{
+ register int ch;
+ while ((ch=getc(fpin)) != EOF && ch != '\n')
+ if (echo)
+ putc(ch, fpout);
+ if (echo)
+ putc('\n', fpout);
+ lineno++;
+}
+
+char *get_word(fp, word)
+register FILE *fp;
+register char *word;
+{
+ register int ch, i = 0;
+ while ((ch = getc(fp)) != EOF && isspace(ch))
+ ;
+ word[i++] = ch;
+ while ((ch = getc(fp)) != EOF && ! isspace(ch))
+ word[i++] = ch;
+ word[i++] = '\0';
+ return word;
+}
+
+/*
+ * Yes, I know this routine is a mess
+ */
+void read_cube(fp, PLA)
+register FILE *fp;
+pPLA PLA;
+{
+ register int var, i;
+ pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2];
+ bool savef = FALSE, saved = FALSE, saver = FALSE;
+ char token[256]; /* for kiss read hack */
+ int varx, first, last, offset; /* for kiss read hack */
+
+ set_clear(cf, cube.size);
+
+ /* Loop and read binary variables */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ switch(getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ var--;
+ break;
+ case ' ': case '|': case '\t':
+ var--;
+ break;
+ case '2': case '-':
+ set_insert(cf, var*2+1);
+ case '0':
+ set_insert(cf, var*2);
+ break;
+ case '1':
+ set_insert(cf, var*2+1);
+ break;
+ case '?':
+ break;
+ default:
+ goto bad_char;
+ }
+
+
+ /* Loop for the all but one of the multiple-valued variables */
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++)
+
+ /* Read a symbolic multiple-valued variable */
+ if (cube.part_size[var] < 0) {
+ (void) fscanf(fp, "%s", token);
+ if (equal(token, "-") || equal(token, "ANY")) {
+ if (kiss && var == cube.num_vars - 2) {
+ /* leave it empty */
+ } else {
+ /* make it full */
+ set_or(cf, cf, cube.var_mask[var]);
+ }
+ } else if (equal(token, "~")) {
+ ;
+ /* leave it empty ... (?) */
+ } else {
+ if (kiss && var == cube.num_vars - 2)
+ varx = var - 1, offset = ABS(cube.part_size[var-1]);
+ else
+ varx = var, offset = 0;
+ /* Find the symbolic label in the label table */
+ first = cube.first_part[varx];
+ last = cube.last_part[varx];
+ for(i = first; i <= last; i++)
+ if (PLA->label[i] == (char *) NULL) {
+ PLA->label[i] = util_strsav(token); /* add new label */
+ set_insert(cf, i+offset);
+ break;
+ } else if (equal(PLA->label[i], token)) {
+ set_insert(cf, i+offset); /* use column i */
+ break;
+ }
+ if (i > last) {
+ (void) fprintf(stderr,
+"declared size of variable %d (counting from variable 0) is too small\n", var);
+ exit(-1);
+ }
+ }
+
+ } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ switch (getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ i--;
+ break;
+ case ' ': case '|': case '\t':
+ i--;
+ break;
+ case '1':
+ set_insert(cf, i);
+ case '0':
+ break;
+ default:
+ goto bad_char;
+ }
+
+ /* Loop for last multiple-valued variable */
+ if (kiss) {
+ saver = savef = TRUE;
+ (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]);
+ } else
+ set_copy(cr, cf);
+ set_copy(cd, cf);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ switch (getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ i--;
+ break;
+ case ' ': case '|': case '\t':
+ i--;
+ break;
+ case '4': case '1':
+ if (PLA->pla_type & F_type)
+ set_insert(cf, i), savef = TRUE;
+ break;
+ case '3': case '0':
+ if (PLA->pla_type & R_type)
+ set_insert(cr, i), saver = TRUE;
+ break;
+ case '2': case '-':
+ if (PLA->pla_type & D_type)
+ set_insert(cd, i), saved = TRUE;
+ case '~':
+ break;
+ default:
+ goto bad_char;
+ }
+ if (savef) PLA->F = sf_addset(PLA->F, cf);
+ if (saved) PLA->D = sf_addset(PLA->D, cd);
+ if (saver) PLA->R = sf_addset(PLA->R, cr);
+ return;
+
+bad_char:
+ (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno);
+ skip_line(fp, stdout, TRUE);
+ return;
+}
+void parse_pla(fp, PLA)
+IN FILE *fp;
+INOUT pPLA PLA;
+{
+ int i, var, ch, np, last;
+ char word[256];
+
+ lineno = 1;
+ line_length_error = FALSE;
+
+loop:
+ switch(ch = getc(fp)) {
+ case EOF:
+ return;
+
+ case '\n':
+ lineno++;
+
+ case ' ': case '\t': case '\f': case '\r':
+ break;
+
+ case '#':
+ (void) ungetc(ch, fp);
+ skip_line(fp, stdout, echo_comments);
+ break;
+
+ case '.':
+ /* .i gives the cube input size (binary-functions only) */
+ if (equal(get_word(fp, word), "i")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .i ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (fscanf(fp, "%d", &cube.num_binary_vars) != 1)
+ fatal("error reading .i");
+ cube.num_vars = cube.num_binary_vars + 1;
+ cube.part_size = ALLOC(int, cube.num_vars);
+ }
+
+ /* .o gives the cube output size (binary-functions only) */
+ } else if (equal(word, "o")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .o ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (cube.part_size == NULL)
+ fatal(".o cannot appear before .i");
+ if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1)
+ fatal("error reading .o");
+ cube_setup();
+ PLA_labels(PLA);
+ }
+
+ /* .mv gives the cube size for a multiple-valued function */
+ } else if (equal(word, "mv")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .mv ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (cube.part_size != NULL)
+ fatal("cannot mix .i and .mv");
+ if (fscanf(fp,"%d %d",
+ &cube.num_vars,&cube.num_binary_vars) != 2)
+ fatal("error reading .mv");
+ if (cube.num_binary_vars < 0)
+fatal("num_binary_vars (second field of .mv) cannot be negative");
+ if (cube.num_vars < cube.num_binary_vars)
+ fatal(
+"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)");
+ cube.part_size = ALLOC(int, cube.num_vars);
+ for(var=cube.num_binary_vars; var < cube.num_vars; var++)
+ if (fscanf(fp, "%d", &(cube.part_size[var])) != 1)
+ fatal("error reading .mv");
+ cube_setup();
+ PLA_labels(PLA);
+ }
+
+ /* .p gives the number of product terms -- we ignore it */
+ } else if (equal(word, "p"))
+ (void) fscanf(fp, "%d", &np);
+ /* .e and .end specify the end of the file */
+ else if (equal(word, "e") || equal(word,"end")) {
+ if (cube.fullset == NULL) {
+ /* fatal("unknown PLA size, need .i/.o or .mv");*/
+ } else if (PLA->F == NULL) {
+ PLA->F = new_cover(10);
+ PLA->D = new_cover(10);
+ PLA->R = new_cover(10);
+ }
+ return;
+ }
+ /* .kiss turns on the kiss-hack option */
+ else if (equal(word, "kiss"))
+ kiss = TRUE;
+
+ /* .type specifies a logical type for the PLA */
+ else if (equal(word, "type")) {
+ (void) get_word(fp, word);
+ for(i = 0; pla_types[i].key != 0; i++)
+ if (equal(pla_types[i].key + 1, word)) {
+ PLA->pla_type = pla_types[i].value;
+ break;
+ }
+ if (pla_types[i].key == 0)
+ fatal("unknown type in .type command");
+
+ /* parse the labels */
+ } else if (equal(word, "ilb")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .ilb or .ob");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ (void) get_word(fp, word);
+ i = cube.first_part[var];
+ PLA->label[i+1] = util_strsav(word);
+ PLA->label[i] = ALLOC(char, strlen(word) + 6);
+ (void) sprintf(PLA->label[i], "%s.bar", word);
+ }
+ } else if (equal(word, "ob")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .ilb or .ob");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ var = cube.num_vars - 1;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ (void) get_word(fp, word);
+ PLA->label[i] = util_strsav(word);
+ }
+ /* .label assigns labels to multiple-valued variables */
+ } else if (equal(word, "label")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .label");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ if (fscanf(fp, "var=%d", &var) != 1)
+ fatal("Error reading labels");
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ (void) get_word(fp, word);
+ PLA->label[i] = util_strsav(word);
+ }
+
+ } else if (equal(word, "symbolic")) {
+ symbolic_t *newlist, *p1;
+ if (read_symbolic(fp, PLA, word, &newlist)) {
+ if (PLA->symbolic == NIL(symbolic_t)) {
+ PLA->symbolic = newlist;
+ } else {
+ for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t);
+ p1=p1->next){
+ }
+ p1->next = newlist;
+ }
+ } else {
+ fatal("error reading .symbolic");
+ }
+
+ } else if (equal(word, "symbolic-output")) {
+ symbolic_t *newlist, *p1;
+ if (read_symbolic(fp, PLA, word, &newlist)) {
+ if (PLA->symbolic_output == NIL(symbolic_t)) {
+ PLA->symbolic_output = newlist;
+ } else {
+ for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t);
+ p1=p1->next){
+ }
+ p1->next = newlist;
+ }
+ } else {
+ fatal("error reading .symbolic-output");
+ }
+
+ /* .phase allows a choice of output phases */
+ } else if (equal(word, "phase")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .phase");
+ if (PLA->phase != NULL) {
+ (void) fprintf(stderr, "extra .phase ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ do ch = getc(fp); while (ch == ' ' || ch == '\t');
+ (void) ungetc(ch, fp);
+ PLA->phase = set_save(cube.fullset);
+ last = cube.last_part[cube.num_vars - 1];
+ for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++)
+ if ((ch = getc(fp)) == '0')
+ set_remove(PLA->phase, i);
+ else if (ch != '1')
+ fatal("only 0 or 1 allowed in phase description");
+ }
+
+ /* .pair allows for bit-pairing input variables */
+ } else if (equal(word, "pair")) {
+ int j;
+ if (PLA->pair != NULL) {
+ (void) fprintf(stderr, "extra .pair ignored\n");
+ } else {
+ ppair pair;
+ PLA->pair = pair = ALLOC(pair_t, 1);
+ if (fscanf(fp, "%d", &(pair->cnt)) != 1)
+ fatal("syntax error in .pair");
+ pair->var1 = ALLOC(int, pair->cnt);
+ pair->var2 = ALLOC(int, pair->cnt);
+ for(i = 0; i < pair->cnt; i++) {
+ (void) get_word(fp, word);
+ if (word[0] == '(') (void) strcpy(word, word+1);
+ if (label_index(PLA, word, &var, &j)) {
+ pair->var1[i] = var+1;
+ } else {
+ fatal("syntax error in .pair");
+ }
+
+ (void) get_word(fp, word);
+ if (word[strlen(word)-1] == ')') {
+ word[strlen(word)-1]='\0';
+ }
+ if (label_index(PLA, word, &var, &j)) {
+ pair->var2[i] = var+1;
+ } else {
+ fatal("syntax error in .pair");
+ }
+ }
+ }
+
+ } else {
+ if (echo_unknown_commands)
+ printf("%c%s ", ch, word);
+ skip_line(fp, stdout, echo_unknown_commands);
+ }
+ break;
+ default:
+ (void) ungetc(ch, fp);
+ if (cube.fullset == NULL) {
+/* fatal("unknown PLA size, need .i/.o or .mv");*/
+ if (echo_comments)
+ putchar('#');
+ skip_line(fp, stdout, echo_comments);
+ break;
+ }
+ if (PLA->F == NULL) {
+ PLA->F = new_cover(10);
+ PLA->D = new_cover(10);
+ PLA->R = new_cover(10);
+ }
+ read_cube(fp, PLA);
+ }
+ goto loop;
+}
+/*
+ read_pla -- read a PLA from a file
+
+ Input stops when ".e" is encountered in the input file, or upon reaching
+ end of file.
+
+ Returns the PLA in the variable PLA after massaging the "symbolic"
+ representation into a positional cube notation of the ON-set, OFF-set,
+ and the DC-set.
+
+ needs_dcset and needs_offset control the computation of the OFF-set
+ and DC-set (i.e., if either needs to be computed, then it will be
+ computed via complement only if the corresponding option is TRUE.)
+ pla_type specifies the interpretation to be used when reading the
+ PLA.
+
+ The phase of the output functions is adjusted according to the
+ global option "pos" or according to an imbedded .phase option in
+ the input file. Note that either phase option implies that the
+ OFF-set be computed regardless of whether the caller needs it
+ explicitly or not.
+
+ Bit pairing of the binary variables is performed according to an
+ imbedded .pair option in the input file.
+
+ The global cube structure also reflects the sizes of the PLA which
+ was just read. If these fields have already been set, then any
+ subsequent PLA must conform to these sizes.
+
+ The global flags trace and summary control the output produced
+ during the read.
+
+ Returns a status code as a result:
+ EOF (-1) : End of file reached before any data was read
+ > 0 : Operation successful
+*/
+
+int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return)
+IN FILE *fp;
+IN bool needs_dcset, needs_offset;
+IN int pla_type;
+OUT pPLA *PLA_return;
+{
+ pPLA PLA;
+ int i, second, third;
+ long time;
+ cost_t cost;
+
+ /* Allocate and initialize the PLA structure */
+ PLA = *PLA_return = new_PLA();
+ PLA->pla_type = pla_type;
+
+ /* Read the pla */
+ time = ptime();
+ parse_pla(fp, PLA);
+
+ /* Check for nothing on the file -- implies reached EOF */
+ if (PLA->F == NULL) {
+ return EOF;
+ }
+
+ /* This hack merges the next-state field with the outputs */
+ for(i = 0; i < cube.num_vars; i++) {
+ cube.part_size[i] = ABS(cube.part_size[i]);
+ }
+ if (kiss) {
+ third = cube.num_vars - 3;
+ second = cube.num_vars - 2;
+ if (cube.part_size[third] != cube.part_size[second]) {
+ (void) fprintf(stderr," with .kiss option, third to last and second\n");
+ (void) fprintf(stderr, "to last variables must be the same size.\n");
+ return EOF;
+ }
+ for(i = 0; i < cube.part_size[second]; i++) {
+ PLA->label[i + cube.first_part[second]] =
+ util_strsav(PLA->label[i + cube.first_part[third]]);
+ }
+ cube.part_size[second] += cube.part_size[cube.num_vars-1];
+ cube.num_vars--;
+ setdown_cube();
+ cube_setup();
+ }
+
+ if (trace) {
+ totals(time, READ_TIME, PLA->F, &cost);
+ }
+
+ /* Decide how to break PLA into ON-set, OFF-set and DC-set */
+ time = ptime();
+ if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) {
+ needs_offset = TRUE;
+ }
+ if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) {
+ free_cover(PLA->R);
+ PLA->R = complement(cube2list(PLA->F, PLA->D));
+ } else if (needs_dcset && PLA->pla_type == FR_type) {
+ pcover X;
+ free_cover(PLA->D);
+ /* hack, why not? */
+ X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1);
+ PLA->D = complement(cube1list(X));
+ free_cover(X);
+ } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) {
+ free_cover(PLA->F);
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ }
+
+ if (trace) {
+ totals(time, COMPL_TIME, PLA->R, &cost);
+ }
+
+ /* Check for phase rearrangement of the functions */
+ if (pos) {
+ pcover onset = PLA->F;
+ PLA->F = PLA->R;
+ PLA->R = onset;
+ PLA->phase = new_cube();
+ set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]);
+ } else if (PLA->phase != NULL) {
+ (void) set_phase(PLA);
+ }
+
+ /* Setup minimization for two-bit decoders */
+ if (PLA->pair != (ppair) NULL) {
+ set_pair(PLA);
+ }
+
+ if (PLA->symbolic != NIL(symbolic_t)) {
+ EXEC(map_symbolic(PLA), "MAP-INPUT ", PLA->F);
+ }
+ if (PLA->symbolic_output != NIL(symbolic_t)) {
+ EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F);
+ if (needs_offset) {
+ free_cover(PLA->R);
+EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost);
+ }
+ }
+
+ return 1;
+}
+
+void PLA_summary(PLA)
+pPLA PLA;
+{
+ int var, i;
+ symbolic_list_t *p2;
+ symbolic_t *p1;
+
+ printf("# PLA is %s", PLA->filename);
+ if (cube.num_binary_vars == cube.num_vars - 1)
+ printf(" with %d inputs and %d outputs\n",
+ cube.num_binary_vars, cube.part_size[cube.num_vars - 1]);
+ else {
+ printf(" with %d variables (%d binary, mv sizes",
+ cube.num_vars, cube.num_binary_vars);
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ printf(" %d", cube.part_size[var]);
+ printf(")\n");
+ }
+ printf("# ON-set cost is %s\n", print_cost(PLA->F));
+ printf("# OFF-set cost is %s\n", print_cost(PLA->R));
+ printf("# DC-set cost is %s\n", print_cost(PLA->D));
+ if (PLA->phase != NULL)
+ printf("# phase is %s\n", pc1(PLA->phase));
+ if (PLA->pair != NULL) {
+ printf("# two-bit decoders:");
+ for(i = 0; i < PLA->pair->cnt; i++)
+ printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]);
+ printf("\n");
+ }
+ if (PLA->symbolic != NIL(symbolic_t)) {
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ printf("# symbolic: ");
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ printf(" %d", p2->variable);
+ }
+ printf("\n");
+ }
+ }
+ if (PLA->symbolic_output != NIL(symbolic_t)) {
+ for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) {
+ printf("# output symbolic: ");
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ printf(" %d", p2->pos);
+ }
+ printf("\n");
+ }
+ }
+ (void) fflush(stdout);
+}
+
+
+pPLA new_PLA()
+{
+ pPLA PLA;
+
+ PLA = ALLOC(PLA_t, 1);
+ PLA->F = PLA->D = PLA->R = (pcover) NULL;
+ PLA->phase = (pcube) NULL;
+ PLA->pair = (ppair) NULL;
+ PLA->label = (char **) NULL;
+ PLA->filename = (char *) NULL;
+ PLA->pla_type = 0;
+ PLA->symbolic = NIL(symbolic_t);
+ PLA->symbolic_output = NIL(symbolic_t);
+ return PLA;
+}
+
+
+PLA_labels(PLA)
+pPLA PLA;
+{
+ int i;
+
+ PLA->label = ALLOC(char *, cube.size);
+ for(i = 0; i < cube.size; i++)
+ PLA->label[i] = (char *) NULL;
+}
+
+
+void free_PLA(PLA)
+pPLA PLA;
+{
+ symbolic_list_t *p2, *p2next;
+ symbolic_t *p1, *p1next;
+ int i;
+
+ if (PLA->F != (pcover) NULL)
+ free_cover(PLA->F);
+ if (PLA->R != (pcover) NULL)
+ free_cover(PLA->R);
+ if (PLA->D != (pcover) NULL)
+ free_cover(PLA->D);
+ if (PLA->phase != (pcube) NULL)
+ free_cube(PLA->phase);
+ if (PLA->pair != (ppair) NULL) {
+ FREE(PLA->pair->var1);
+ FREE(PLA->pair->var2);
+ FREE(PLA->pair);
+ }
+ if (PLA->label != NULL) {
+ for(i = 0; i < cube.size; i++)
+ if (PLA->label[i] != NULL)
+ FREE(PLA->label[i]);
+ FREE(PLA->label);
+ }
+ if (PLA->filename != NULL) {
+ FREE(PLA->filename);
+ }
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) {
+ for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ p2next = p2->next;
+ FREE(p2);
+ }
+ p1next = p1->next;
+ FREE(p1);
+ }
+ PLA->symbolic = NIL(symbolic_t);
+ for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) {
+ for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ p2next = p2->next;
+ FREE(p2);
+ }
+ p1next = p1->next;
+ FREE(p1);
+ }
+ PLA->symbolic_output = NIL(symbolic_t);
+ FREE(PLA);
+}
+
+
+int read_symbolic(fp, PLA, word, retval)
+FILE *fp;
+pPLA PLA;
+char *word; /* scratch string for words */
+symbolic_t **retval;
+{
+ symbolic_list_t *listp, *prev_listp;
+ symbolic_label_t *labelp, *prev_labelp;
+ symbolic_t *newlist;
+ int i, var;
+
+ newlist = ALLOC(symbolic_t, 1);
+ newlist->next = NIL(symbolic_t);
+ newlist->symbolic_list = NIL(symbolic_list_t);
+ newlist->symbolic_list_length = 0;
+ newlist->symbolic_label = NIL(symbolic_label_t);
+ newlist->symbolic_label_length = 0;
+ prev_listp = NIL(symbolic_list_t);
+ prev_labelp = NIL(symbolic_label_t);
+
+ for(;;) {
+ (void) get_word(fp, word);
+ if (equal(word, ";"))
+ break;
+ if (label_index(PLA, word, &var, &i)) {
+ listp = ALLOC(symbolic_list_t, 1);
+ listp->variable = var;
+ listp->pos = i;
+ listp->next = NIL(symbolic_list_t);
+ if (prev_listp == NIL(symbolic_list_t)) {
+ newlist->symbolic_list = listp;
+ } else {
+ prev_listp->next = listp;
+ }
+ prev_listp = listp;
+ newlist->symbolic_list_length++;
+ } else {
+ return FALSE;
+ }
+ }
+
+ for(;;) {
+ (void) get_word(fp, word);
+ if (equal(word, ";"))
+ break;
+ labelp = ALLOC(symbolic_label_t, 1);
+ labelp->label = util_strsav(word);
+ labelp->next = NIL(symbolic_label_t);
+ if (prev_labelp == NIL(symbolic_label_t)) {
+ newlist->symbolic_label = labelp;
+ } else {
+ prev_labelp->next = labelp;
+ }
+ prev_labelp = labelp;
+ newlist->symbolic_label_length++;
+ }
+
+ *retval = newlist;
+ return TRUE;
+}
+
+
+int label_index(PLA, word, varp, ip)
+pPLA PLA;
+char *word;
+int *varp;
+int *ip;
+{
+ int var, i;
+
+ if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) {
+ if (sscanf(word, "%d", varp) == 1) {
+ *ip = *varp;
+ return TRUE;
+ }
+ } else {
+ for(var = 0; var < cube.num_vars; var++) {
+ for(i = 0; i < cube.part_size[var]; i++) {
+ if (equal(PLA->label[cube.first_part[var]+i], word)) {
+ *varp = var;
+ *ip = i;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
diff --git a/src/misc/espresso/cvrm.c b/src/misc/espresso/cvrm.c
new file mode 100644
index 00000000..7d42d6e3
--- /dev/null
+++ b/src/misc/espresso/cvrm.c
@@ -0,0 +1,539 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrm.c
+ Purpose: miscellaneous cover manipulation
+ a) verify two covers are equal, check consistency of a cover
+ b) unravel a multiple-valued cover into minterms
+ c) sort covers
+*/
+
+#include "espresso.h"
+
+
+static void cb_unravel(c, start, end, startbase, B1)
+IN register pcube c;
+IN int start, end;
+IN pcube startbase;
+INOUT pcover B1;
+{
+ pcube base = cube.temp[0], p, last;
+ int expansion, place, skip, var, size, offset;
+ register int i, j, k, n;
+
+ /* Determine how many cubes it will blow up into, and create a mask
+ for those parts that have only a single coordinate
+ */
+ expansion = 1;
+ (void) set_copy(base, startbase);
+ for(var = start; var <= end; var++) {
+ if ((size = set_dist(c, cube.var_mask[var])) < 2) {
+ (void) set_or(base, base, cube.var_mask[var]);
+ } else {
+ expansion *= size;
+ }
+ }
+ (void) set_and(base, c, base);
+
+ /* Add the unravelled sets starting at the last element of B1 */
+ offset = B1->count;
+ B1->count += expansion;
+ foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) {
+ INLINEset_copy(p, base);
+ }
+
+ place = expansion;
+ for(var = start; var <= end; var++) {
+ if ((size = set_dist(c, cube.var_mask[var])) > 1) {
+ skip = place;
+ place = place / size;
+ n = 0;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (is_in_set(c, i)) {
+ for(j = n; j < expansion; j += skip) {
+ for(k = 0; k < place; k++) {
+ p = GETSET(B1, j+k+offset);
+ (void) set_insert(p, i);
+ }
+ }
+ n += place;
+ }
+ }
+ }
+ }
+}
+
+
+pcover unravel_range(B, start, end)
+IN pcover B;
+IN int start, end;
+{
+ pcover B1;
+ int var, total_size, expansion, size;
+ register pcube p, last, startbase = cube.temp[1];
+
+ /* Create the starting base for those variables not being unravelled */
+ (void) set_copy(startbase, cube.emptyset);
+ for(var = 0; var < start; var++)
+ (void) set_or(startbase, startbase, cube.var_mask[var]);
+ for(var = end+1; var < cube.num_vars; var++)
+ (void) set_or(startbase, startbase, cube.var_mask[var]);
+
+ /* Determine how many cubes it will blow up into */
+ total_size = 0;
+ foreach_set(B, last, p) {
+ expansion = 1;
+ for(var = start; var <= end; var++)
+ if ((size = set_dist(p, cube.var_mask[var])) >= 2)
+ if ((expansion *= size) > 1000000)
+ fatal("unreasonable expansion in unravel");
+ total_size += expansion;
+ }
+
+ /* We can now allocate a cover of exactly the correct size */
+ B1 = new_cover(total_size);
+ foreach_set(B, last, p) {
+ cb_unravel(p, start, end, startbase, B1);
+ }
+ free_cover(B);
+ return B1;
+}
+
+
+pcover unravel(B, start)
+IN pcover B;
+IN int start;
+{
+ return unravel_range(B, start, cube.num_vars-1);
+}
+
+/* lex_sort -- sort cubes in a standard lexical fashion */
+pcover lex_sort(T)
+pcover T;
+{
+ pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size);
+ free_cover(T);
+ return T1;
+}
+
+
+/* size_sort -- sort cubes by their size */
+pcover size_sort(T)
+pcover T;
+{
+ pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size);
+ free_cover(T);
+ return T1;
+}
+
+
+/* mini_sort -- sort cubes according to the heuristics of mini */
+pcover mini_sort(F, compare)
+pcover F;
+int (*compare)();
+{
+ register int *count, cnt, n = cube.size, i;
+ register pcube p, last;
+ pcover F_sorted;
+ pcube *F1;
+
+ /* Perform a column sum over the set family */
+ count = sf_count(F);
+
+ /* weight is "inner product of the cube and the column sums" */
+ foreach_set(F, last, p) {
+ cnt = 0;
+ for(i = 0; i < n; i++)
+ if (is_in_set(p, i))
+ cnt += count[i];
+ PUTSIZE(p, cnt);
+ }
+ FREE(count);
+
+ /* use qsort to sort the array */
+ qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare);
+ F_sorted = sf_unlist(F1, F->count, F->sf_size);
+ free_cover(F);
+
+ return F_sorted;
+}
+
+
+/* sort_reduce -- Espresso strategy for ordering the cubes before reduction */
+pcover sort_reduce(T)
+IN pcover T;
+{
+ register pcube p, last, largest = NULL;
+ register int bestsize = -1, size, n = cube.num_vars;
+ pcover T_sorted;
+ pcube *T1;
+
+ if (T->count == 0)
+ return T;
+
+ /* find largest cube */
+ foreach_set(T, last, p)
+ if ((size = set_ord(p)) > bestsize)
+ largest = p, bestsize = size;
+
+ foreach_set(T, last, p)
+ PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127));
+
+ qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), (int (*)()) descend);
+ T_sorted = sf_unlist(T1, T->count, T->sf_size);
+ free_cover(T);
+
+ return T_sorted;
+}
+
+pcover random_order(F)
+register pcover F;
+{
+ pset temp;
+ register int i, k;
+#ifdef RANDOM
+ long random();
+#endif
+
+ temp = set_new(F->sf_size);
+ for(i = F->count - 1; i > 0; i--) {
+ /* Choose a random number between 0 and i */
+#ifdef RANDOM
+ k = random() % i;
+#else
+ /* this is not meant to be really used; just provides an easy
+ "out" if random() and srandom() aren't around
+ */
+ k = (i*23 + 997) % i;
+#endif
+ /* swap sets i and k */
+ (void) set_copy(temp, GETSET(F, k));
+ (void) set_copy(GETSET(F, k), GETSET(F, i));
+ (void) set_copy(GETSET(F, i), temp);
+ }
+ set_free(temp);
+ return F;
+}
+
+/*
+ * cubelist_partition -- take a cubelist T and see if it has any components;
+ * if so, return cubelist's of the two partitions A and B; the return value
+ * is the size of the partition; if not, A and B
+ * are undefined and the return value is 0
+ */
+int cubelist_partition(T, A, B, comp_debug)
+pcube *T; /* a list of cubes */
+pcube **A, **B; /* cubelist of partition and remainder */
+unsigned int comp_debug;
+{
+ register pcube *T1, p, seed, cof;
+ pcube *A1, *B1;
+ bool change;
+ int count, numcube;
+
+ numcube = CUBELISTSIZE(T);
+
+ /* Mark all cubes -- covered cubes belong to the partition */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ RESET(p, COVERED);
+ }
+
+ /*
+ * Extract a partition from the cubelist T; start with the first cube as a
+ * seed, and then pull in all cubes which share a variable with the seed;
+ * iterate until no new cubes are brought into the partition.
+ */
+ seed = set_save(T[2]);
+ cof = T[0];
+ SET(T[2], COVERED);
+ count = 1;
+
+ do {
+ change = FALSE;
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) {
+ INLINEset_and(seed, seed, p);
+ SET(p, COVERED);
+ change = TRUE;
+ count++;
+ }
+
+ }
+ } while (change);
+
+ set_free(seed);
+
+ if (comp_debug) {
+ (void) printf("COMPONENT_REDUCTION: split into %d %d\n",
+ count, numcube - count);
+ }
+
+ if (count != numcube) {
+ /* Allocate and setup the cubelist's for the two partitions */
+ *A = A1 = ALLOC(pcube, numcube+3);
+ *B = B1 = ALLOC(pcube, numcube+3);
+ (*A)[0] = set_save(T[0]);
+ (*B)[0] = set_save(T[0]);
+ A1 = *A + 2;
+ B1 = *B + 2;
+
+ /* Loop over the cubes in T and distribute to A and B */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (TESTP(p, COVERED)) {
+ *A1++ = p;
+ } else {
+ *B1++ = p;
+ }
+ }
+
+ /* Stuff needed at the end of the cubelist's */
+ *A1++ = NULL;
+ (*A)[1] = (pcube) A1;
+ *B1++ = NULL;
+ (*B)[1] = (pcube) B1;
+ }
+
+ return numcube - count;
+}
+
+/*
+ * quick cofactor against a single output function
+ */
+pcover cof_output(T, i)
+pcover T;
+register int i;
+{
+ pcover T1;
+ register pcube p, last, pdest, mask;
+
+ mask = cube.var_mask[cube.output];
+ T1 = new_cover(T->count);
+ foreach_set(T, last, p) {
+ if (is_in_set(p, i)) {
+ pdest = GETSET(T1, T1->count++);
+ INLINEset_or(pdest, p, mask);
+ RESET(pdest, PRIME);
+ }
+ }
+ return T1;
+}
+
+
+/*
+ * quick intersection against a single output function
+ */
+pcover uncof_output(T, i)
+pcover T;
+int i;
+{
+ register pcube p, last, mask;
+
+ if (T == NULL) {
+ return T;
+ }
+
+ mask = cube.var_mask[cube.output];
+ foreach_set(T, last, p) {
+ INLINEset_diff(p, p, mask);
+ set_insert(p, i);
+ }
+ return T;
+}
+
+
+/*
+ * A generic routine to perform an operation for each output function
+ *
+ * func() is called with a PLA for each output function (with the output
+ * part effectively removed).
+ * func1() is called after reforming the equivalent output function
+ *
+ * Each function returns TRUE if process is to continue
+ */
+foreach_output_function(PLA, func, func1)
+pPLA PLA;
+int (*func)();
+int (*func1)();
+{
+ pPLA PLA1;
+ int i;
+
+ /* Loop for each output function */
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+ /* cofactor on the output part */
+ PLA1 = new_PLA();
+ PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]);
+ PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]);
+ PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]);
+
+ /* Call a routine to do something with the cover */
+ if ((*func)(PLA1, i) == 0) {
+ free_PLA(PLA1);
+ return;
+ }
+
+ /* intersect with the particular output part again */
+ PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]);
+ PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]);
+ PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]);
+
+ /* Call a routine to do something with the final result */
+ if ((*func1)(PLA1, i) == 0) {
+ free_PLA(PLA1);
+ return;
+ }
+
+ /* Cleanup for next go-around */
+ free_PLA(PLA1);
+
+
+ }
+}
+
+static pcover Fmin;
+static pcube phase;
+
+/*
+ * minimize each output function individually
+ */
+void so_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ Fmin = new_cover(PLA->F->count);
+ if (strategy == 0) {
+ foreach_output_function(PLA, so_do_espresso, so_save);
+ } else {
+ foreach_output_function(PLA, so_do_exact, so_save);
+ }
+ sf_free(PLA->F);
+ PLA->F = Fmin;
+}
+
+
+/*
+ * minimize each output function, choose function or complement based on the
+ * one with the fewer number of terms
+ */
+void so_both_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ phase = set_save(cube.fullset);
+ Fmin = new_cover(PLA->F->count);
+ if (strategy == 0) {
+ foreach_output_function(PLA, so_both_do_espresso, so_both_save);
+ } else {
+ foreach_output_function(PLA, so_both_do_exact, so_both_save);
+ }
+ sf_free(PLA->F);
+ PLA->F = Fmin;
+ PLA->phase = phase;
+}
+
+
+int so_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ skip_make_sparse = 1;
+ (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+ return 1;
+}
+
+
+int so_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ skip_make_sparse = 1;
+ (void) sprintf(word, "EXACT-POS(%d)", i);
+ EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+ return 1;
+}
+
+
+/*ARGSUSED*/
+int so_save(PLA, i)
+pPLA PLA;
+int i;
+{
+ Fmin = sf_append(Fmin, PLA->F); /* disposes of PLA->F */
+ PLA->F = NULL;
+ return 1;
+}
+
+
+int so_both_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+
+ /* minimize the single-output function (off-set) */
+ (void) sprintf(word, "ESPRESSO-NEG(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R);
+
+ return 1;
+}
+
+
+int so_both_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ (void) sprintf(word, "EXACT-POS(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+
+ /* minimize the single-output function (off-set) */
+ (void) sprintf(word, "EXACT-NEG(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R);
+
+ return 1;
+}
+
+
+int so_both_save(PLA, i)
+pPLA PLA;
+int i;
+{
+ if (PLA->F->count > PLA->R->count) {
+ sf_free(PLA->F);
+ PLA->F = PLA->R;
+ PLA->R = NULL;
+ i += cube.first_part[cube.output];
+ set_remove(phase, i);
+ } else {
+ sf_free(PLA->R);
+ PLA->R = NULL;
+ }
+ Fmin = sf_append(Fmin, PLA->F);
+ PLA->F = NULL;
+ return 1;
+}
diff --git a/src/misc/espresso/cvrmisc.c b/src/misc/espresso/cvrmisc.c
new file mode 100644
index 00000000..0f3de195
--- /dev/null
+++ b/src/misc/espresso/cvrmisc.c
@@ -0,0 +1,142 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+/* cost -- compute the cost of a cover */
+void cover_cost(F, cost)
+IN pcover F;
+INOUT pcost cost;
+{
+ register pcube p, last;
+ pcube *T;
+ int var;
+
+ /* use the routine used by cofactor to decide splitting variables */
+ massive_count(T = cube1list(F));
+ free_cubelist(T);
+
+ cost->cubes = F->count;
+ cost->total = cost->in = cost->out = cost->mv = cost->primes = 0;
+
+ /* Count transistors (zeros) for each binary variable (inputs) */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ cost->in += cdata.var_zeros[var];
+
+ /* Count transistors for each mv variable based on sparse/dense */
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++)
+ if (cube.sparse[var])
+ cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var];
+ else
+ cost->mv += cdata.var_zeros[var];
+
+ /* Count the transistors (ones) for the output variable */
+ if (cube.num_binary_vars != cube.num_vars) {
+ var = cube.num_vars - 1;
+ cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var];
+ }
+
+ /* Count the number of nonprime cubes */
+ foreach_set(F, last, p)
+ cost->primes += TESTP(p, PRIME) != 0;
+
+ /* Count the total number of literals */
+ cost->total = cost->in + cost->out + cost->mv;
+}
+
+
+/* fmt_cost -- return a string which reports the "cost" of a cover */
+char *fmt_cost(cost)
+IN pcost cost;
+{
+ static char s[200];
+
+ if (cube.num_binary_vars == cube.num_vars - 1)
+ (void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d",
+ cost->cubes, cost->cubes - cost->primes, cost->in,
+ cost->out, cost->total);
+ else
+ (void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d",
+ cost->cubes, cost->cubes - cost->primes, cost->in,
+ cost->mv, cost->out);
+ return s;
+}
+
+
+char *print_cost(F)
+IN pcover F;
+{
+ cost_t cost;
+ cover_cost(F, &cost);
+ return fmt_cost(&cost);
+}
+
+
+/* copy_cost -- copy a cost function from s to d */
+void copy_cost(s, d)
+pcost s, d;
+{
+ d->cubes = s->cubes;
+ d->in = s->in;
+ d->out = s->out;
+ d->mv = s->mv;
+ d->total = s->total;
+ d->primes = s->primes;
+}
+
+
+/* size_stamp -- print single line giving the size of a cover */
+void size_stamp(T, name)
+IN pcover T;
+IN char *name;
+{
+ (void) printf("# %s\tCost is %s\n", name, print_cost(T));
+ (void) fflush(stdout);
+}
+
+
+/* print_trace -- print a line reporting size and time after a function */
+void print_trace(T, name, time)
+pcover T;
+char *name;
+long time;
+{
+ (void) printf("# %s\tTime was %s, cost is %s\n",
+ name, print_time(time), print_cost(T));
+ (void) fflush(stdout);
+}
+
+
+/* totals -- add time spent in the function into the totals */
+void totals(time, i, T, cost)
+long time;
+int i;
+pcover T;
+pcost cost;
+{
+ time = ptime() - time;
+ total_time[i] += time;
+ total_calls[i]++;
+ cover_cost(T, cost);
+ if (trace) {
+ (void) printf("# %s\tTime was %s, cost is %s\n",
+ total_name[i], print_time(time), fmt_cost(cost));
+ (void) fflush(stdout);
+ }
+}
+
+
+/* fatal -- report fatal error message and take a dive */
+void fatal(s)
+char *s;
+{
+ (void) fprintf(stderr, "espresso: %s\n", s);
+ exit(1);
+}
diff --git a/src/misc/espresso/cvrout.c b/src/misc/espresso/cvrout.c
new file mode 100644
index 00000000..4bd1c53b
--- /dev/null
+++ b/src/misc/espresso/cvrout.c
@@ -0,0 +1,609 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrout.c
+ purpose: cube and cover output routines
+*/
+
+#include "espresso.h"
+
+void fprint_pla(fp, PLA, output_type)
+INOUT FILE *fp;
+IN pPLA PLA;
+IN int output_type;
+{
+ int num;
+ register pcube last, p;
+
+ if ((output_type & CONSTRAINTS_type) != 0) {
+ output_symbolic_constraints(fp, PLA, 0);
+ output_type &= ~ CONSTRAINTS_type;
+ if (output_type == 0) {
+ return;
+ }
+ }
+
+ if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) {
+ output_symbolic_constraints(fp, PLA, 1);
+ output_type &= ~ SYMBOLIC_CONSTRAINTS_type;
+ if (output_type == 0) {
+ return;
+ }
+ }
+
+ if (output_type == PLEASURE_type) {
+ pls_output(PLA);
+ } else if (output_type == EQNTOTT_type) {
+ eqn_output(PLA);
+ } else if (output_type == KISS_type) {
+ kiss_output(fp, PLA);
+ } else {
+ fpr_header(fp, PLA, output_type);
+
+ num = 0;
+ if (output_type & F_type) num += (PLA->F)->count;
+ if (output_type & D_type) num += (PLA->D)->count;
+ if (output_type & R_type) num += (PLA->R)->count;
+ (void) fprintf(fp, ".p %d\n", num);
+
+ /* quick patch 01/17/85 to support TPLA ! */
+ if (output_type == F_type) {
+ foreach_set(PLA->F, last, p) {
+ print_cube(fp, p, "01");
+ }
+ (void) fprintf(fp, ".e\n");
+ } else {
+ if (output_type & F_type) {
+ foreach_set(PLA->F, last, p) {
+ print_cube(fp, p, "~1");
+ }
+ }
+ if (output_type & D_type) {
+ foreach_set(PLA->D, last, p) {
+ print_cube(fp, p, "~2");
+ }
+ }
+ if (output_type & R_type) {
+ foreach_set(PLA->R, last, p) {
+ print_cube(fp, p, "~0");
+ }
+ }
+ (void) fprintf(fp, ".end\n");
+ }
+ }
+}
+
+void fpr_header(fp, PLA, output_type)
+FILE *fp;
+pPLA PLA;
+int output_type;
+{
+ register int i, var;
+ int first, last;
+
+ /* .type keyword gives logical type */
+ if (output_type != F_type) {
+ (void) fprintf(fp, ".type ");
+ if (output_type & F_type) putc('f', fp);
+ if (output_type & D_type) putc('d', fp);
+ if (output_type & R_type) putc('r', fp);
+ putc('\n', fp);
+ }
+
+ /* Check for binary or multiple-valued labels */
+ if (cube.num_mv_vars <= 1) {
+ (void) fprintf(fp, ".i %d\n", cube.num_binary_vars);
+ if (cube.output != -1)
+ (void) fprintf(fp, ".o %d\n", cube.part_size[cube.output]);
+ } else {
+ (void) fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars);
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ (void) fprintf(fp, " %d", cube.part_size[var]);
+ (void) fprintf(fp, "\n");
+ }
+
+ /* binary valued labels */
+ if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char)
+ && cube.num_binary_vars > 0) {
+ (void) fprintf(fp, ".ilb");
+ for(var = 0; var < cube.num_binary_vars; var++)
+ /* see (NIL) OUTLABELS comment below */
+ if(INLABEL(var) == NIL(char)){
+ (void) fprintf(fp, " (null)");
+ }
+ else{
+ (void) fprintf(fp, " %s", INLABEL(var));
+ }
+ putc('\n', fp);
+ }
+
+ /* output-part (last multiple-valued variable) labels */
+ if (PLA->label != NIL(char *) &&
+ PLA->label[cube.first_part[cube.output]] != NIL(char)
+ && cube.output != -1) {
+ (void) fprintf(fp, ".ob");
+ for(i = 0; i < cube.part_size[cube.output]; i++)
+ /* (NIL) OUTLABELS caused espresso to segfault under solaris */
+ if(OUTLABEL(i) == NIL(char)){
+ (void) fprintf(fp, " (null)");
+ }
+ else{
+ (void) fprintf(fp, " %s", OUTLABEL(i));
+ }
+ putc('\n', fp);
+ }
+
+ /* multiple-valued labels */
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ first = cube.first_part[var];
+ last = cube.last_part[var];
+ if (PLA->label != NULL && PLA->label[first] != NULL) {
+ (void) fprintf(fp, ".label var=%d", var);
+ for(i = first; i <= last; i++) {
+ (void) fprintf(fp, " %s", PLA->label[i]);
+ }
+ putc('\n', fp);
+ }
+ }
+
+ if (PLA->phase != (pcube) NULL) {
+ first = cube.first_part[cube.output];
+ last = cube.last_part[cube.output];
+ (void) fprintf(fp, "#.phase ");
+ for(i = first; i <= last; i++)
+ putc(is_in_set(PLA->phase,i) ? '1' : '0', fp);
+ (void) fprintf(fp, "\n");
+ }
+}
+
+void pls_output(PLA)
+IN pPLA PLA;
+{
+ register pcube last, p;
+
+ (void) printf(".option unmerged\n");
+ makeup_labels(PLA);
+ pls_label(PLA, stdout);
+ pls_group(PLA, stdout);
+ (void) printf(".p %d\n", PLA->F->count);
+ foreach_set(PLA->F, last, p) {
+ print_expanded_cube(stdout, p, PLA->phase);
+ }
+ (void) printf(".end\n");
+}
+
+
+void pls_group(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+ int var, i, col, len;
+
+ (void) fprintf(fp, "\n.group");
+ col = 6;
+ for(var = 0; var < cube.num_vars-1; var++) {
+ (void) fprintf(fp, " ("), col += 2;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ len = strlen(PLA->label[i]);
+ if (col + len > 75)
+ (void) fprintf(fp, " \\\n"), col = 0;
+ else if (i != 0)
+ putc(' ', fp), col += 1;
+ (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+ }
+ (void) fprintf(fp, ")"), col += 1;
+ }
+ (void) fprintf(fp, "\n");
+}
+
+
+void pls_label(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+ int var, i, col, len;
+
+ (void) fprintf(fp, ".label");
+ col = 6;
+ for(var = 0; var < cube.num_vars; var++)
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ len = strlen(PLA->label[i]);
+ if (col + len > 75)
+ (void) fprintf(fp, " \\\n"), col = 0;
+ else
+ putc(' ', fp), col += 1;
+ (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+ }
+}
+
+
+
+/*
+ eqntott output mode -- output algebraic equations
+*/
+void eqn_output(PLA)
+pPLA PLA;
+{
+ register pcube p, last;
+ register int i, var, col, len;
+ int x;
+ bool firstand, firstor;
+
+ if (cube.output == -1)
+ fatal("Cannot have no-output function for EQNTOTT output mode");
+ if (cube.num_mv_vars != 1)
+ fatal("Must have binary-valued function for EQNTOTT output mode");
+ makeup_labels(PLA);
+
+ /* Write a single equation for each output */
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ (void) printf("%s = ", OUTLABEL(i));
+ col = strlen(OUTLABEL(i)) + 3;
+ firstor = TRUE;
+
+ /* Write product terms for each cube in this output */
+ foreach_set(PLA->F, last, p)
+ if (is_in_set(p, i + cube.first_part[cube.output])) {
+ if (firstor)
+ (void) printf("("), col += 1;
+ else
+ (void) printf(" | ("), col += 4;
+ firstor = FALSE;
+ firstand = TRUE;
+
+ /* print out a product term */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ if ((x=GETINPUT(p, var)) != DASH) {
+ len = strlen(INLABEL(var));
+ if (col+len > 72)
+ (void) printf("\n "), col = 4;
+ if (! firstand)
+ (void) printf("&"), col += 1;
+ firstand = FALSE;
+ if (x == ZERO)
+ (void) printf("!"), col += 1;
+ (void) printf("%s", INLABEL(var)), col += len;
+ }
+ (void) printf(")"), col += 1;
+ }
+ (void) printf(";\n\n");
+ }
+}
+
+
+char *fmt_cube(c, out_map, s)
+register pcube c;
+register char *out_map, *s;
+{
+ register int i, var, last, len = 0;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ s[len++] = "?01-" [GETINPUT(c, var)];
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ s[len++] = ' ';
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ s[len++] = "01" [is_in_set(c, i) != 0];
+ }
+ }
+ if (cube.output != -1) {
+ last = cube.last_part[cube.output];
+ s[len++] = ' ';
+ for(i = cube.first_part[cube.output]; i <= last; i++) {
+ s[len++] = out_map [is_in_set(c, i) != 0];
+ }
+ }
+ s[len] = '\0';
+ return s;
+}
+
+
+void print_cube(fp, c, out_map)
+register FILE *fp;
+register pcube c;
+register char *out_map;
+{
+ register int i, var, ch;
+ int last;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ ch = "?01-" [GETINPUT(c, var)];
+ putc(ch, fp);
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "01" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ if (cube.output != -1) {
+ last = cube.last_part[cube.output];
+ putc(' ', fp);
+ for(i = cube.first_part[cube.output]; i <= last; i++) {
+ ch = out_map [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ putc('\n', fp);
+}
+
+
+void print_expanded_cube(fp, c, phase)
+register FILE *fp;
+register pcube c;
+pcube phase;
+{
+ register int i, var, ch;
+ char *out_map;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "~1" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "1~" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ if (cube.output != -1) {
+ var = cube.num_vars - 1;
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (phase == (pcube) NULL || is_in_set(phase, i)) {
+ out_map = "~1";
+ } else {
+ out_map = "~0";
+ }
+ ch = out_map[is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ putc('\n', fp);
+}
+
+
+char *pc1(c) pcube c;
+{static char s1[256];return fmt_cube(c, "01", s1);}
+char *pc2(c) pcube c;
+{static char s2[256];return fmt_cube(c, "01", s2);}
+
+
+void debug_print(T, name, level)
+pcube *T;
+char *name;
+int level;
+{
+ register pcube *T1, p, temp;
+ register int cnt;
+
+ cnt = CUBELISTSIZE(T);
+ temp = new_cube();
+ if (verbose_debug && level == 0)
+ (void) printf("\n");
+ (void) printf("%s[%d]: ord(T)=%d\n", name, level, cnt);
+ if (verbose_debug) {
+ (void) printf("cofactor=%s\n", pc1(T[0]));
+ for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++)
+ (void) printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0])));
+ }
+ free_cube(temp);
+}
+
+
+void debug1_print(T, name, num)
+pcover T;
+char *name;
+int num;
+{
+ register int cnt = 1;
+ register pcube p, last;
+
+ if (verbose_debug && num == 0)
+ (void) printf("\n");
+ (void) printf("%s[%d]: ord(T)=%d\n", name, num, T->count);
+ if (verbose_debug)
+ foreach_set(T, last, p)
+ (void) printf("%4d. %s\n", cnt++, pc1(p));
+}
+
+
+void cprint(T)
+pcover T;
+{
+ register pcube p, last;
+
+ foreach_set(T, last, p)
+ (void) printf("%s\n", pc1(p));
+}
+
+
+int makeup_labels(PLA)
+pPLA PLA;
+{
+ int var, i, ind;
+
+ if (PLA->label == (char **) NULL)
+ PLA_labels(PLA);
+
+ for(var = 0; var < cube.num_vars; var++)
+ for(i = 0; i < cube.part_size[var]; i++) {
+ ind = cube.first_part[var] + i;
+ if (PLA->label[ind] == (char *) NULL) {
+ PLA->label[ind] = ALLOC(char, 15);
+ if (var < cube.num_binary_vars)
+ if ((i % 2) == 0)
+ (void) sprintf(PLA->label[ind], "v%d.bar", var);
+ else
+ (void) sprintf(PLA->label[ind], "v%d", var);
+ else
+ (void) sprintf(PLA->label[ind], "v%d.%d", var, i);
+ }
+ }
+}
+
+
+kiss_output(fp, PLA)
+FILE *fp;
+pPLA PLA;
+{
+ register pset last, p;
+
+ foreach_set(PLA->F, last, p) {
+ kiss_print_cube(fp, PLA, p, "~1");
+ }
+ foreach_set(PLA->D, last, p) {
+ kiss_print_cube(fp, PLA, p, "~2");
+ }
+}
+
+
+kiss_print_cube(fp, PLA, p, out_string)
+FILE *fp;
+pPLA PLA;
+pcube p;
+char *out_string;
+{
+ register int i, var;
+ int part, x;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ x = "?01-" [GETINPUT(p, var)];
+ putc(x, fp);
+ }
+
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ putc(' ', fp);
+ if (setp_implies(cube.var_mask[var], p)) {
+ putc('-', fp);
+ } else {
+ part = -1;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (is_in_set(p, i)) {
+ if (part != -1) {
+ fatal("more than 1 part in a symbolic variable\n");
+ }
+ part = i;
+ }
+ }
+ if (part == -1) {
+ putc('~', fp); /* no parts, hope its an output ... */
+ } else {
+ (void) fputs(PLA->label[part], fp);
+ }
+ }
+ }
+
+ if ((var = cube.output) != -1) {
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ x = out_string [is_in_set(p, i) != 0];
+ putc(x, fp);
+ }
+ }
+
+ putc('\n', fp);
+}
+
+output_symbolic_constraints(fp, PLA, output_symbolic)
+FILE *fp;
+pPLA PLA;
+int output_symbolic;
+{
+ pset_family A;
+ register int i, j;
+ int size, var, npermute, *permute, *weight, noweight;
+
+ if ((cube.num_vars - cube.num_binary_vars) <= 1) {
+ return;
+ }
+ makeup_labels(PLA);
+
+ for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) {
+
+ /* pull out the columns for variable "var" */
+ npermute = cube.part_size[var];
+ permute = ALLOC(int, npermute);
+ for(i=0; i < npermute; i++) {
+ permute[i] = cube.first_part[var] + i;
+ }
+ A = sf_permute(sf_save(PLA->F), permute, npermute);
+ FREE(permute);
+
+
+ /* Delete the singletons and the full sets */
+ noweight = 0;
+ for(i = 0; i < A->count; i++) {
+ size = set_ord(GETSET(A,i));
+ if (size == 1 || size == A->sf_size) {
+ sf_delset(A, i--);
+ noweight++;
+ }
+ }
+
+
+ /* Count how many times each is duplicated */
+ weight = ALLOC(int, A->count);
+ for(i = 0; i < A->count; i++) {
+ RESET(GETSET(A, i), COVERED);
+ }
+ for(i = 0; i < A->count; i++) {
+ weight[i] = 0;
+ if (! TESTP(GETSET(A,i), COVERED)) {
+ weight[i] = 1;
+ for(j = i+1; j < A->count; j++) {
+ if (setp_equal(GETSET(A,i), GETSET(A,j))) {
+ weight[i]++;
+ SET(GETSET(A,j), COVERED);
+ }
+ }
+ }
+ }
+
+
+ /* Print out the contraints */
+ if (! output_symbolic) {
+ (void) fprintf(fp,
+ "# Symbolic constraints for variable %d (Numeric form)\n", var);
+ (void) fprintf(fp, "# unconstrained weight = %d\n", noweight);
+ (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]);
+ for(i = 0; i < A->count; i++) {
+ if (weight[i] > 0) {
+ (void) fprintf(fp, "weight=%d: ", weight[i]);
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(GETSET(A,i), j)) {
+ (void) fprintf(fp, " %d", j);
+ }
+ }
+ (void) fprintf(fp, "\n");
+ }
+ }
+ } else {
+ (void) fprintf(fp,
+ "# Symbolic constraints for variable %d (Symbolic form)\n", var);
+ for(i = 0; i < A->count; i++) {
+ if (weight[i] > 0) {
+ (void) fprintf(fp, "# w=%d: (", weight[i]);
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(GETSET(A,i), j)) {
+ (void) fprintf(fp, " %s",
+ PLA->label[cube.first_part[var]+j]);
+ }
+ }
+ (void) fprintf(fp, " )\n");
+ }
+ }
+ FREE(weight);
+ }
+ }
+}
diff --git a/src/misc/espresso/dominate.c b/src/misc/espresso/dominate.c
new file mode 100644
index 00000000..a930d453
--- /dev/null
+++ b/src/misc/espresso/dominate.c
@@ -0,0 +1,98 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+int
+sm_row_dominance(A)
+sm_matrix *A;
+{
+ register sm_row *prow, *prow1;
+ register sm_col *pcol, *least_col;
+ register sm_element *p, *pnext;
+ int rowcnt;
+
+ rowcnt = A->nrows;
+
+ /* Check each row against all other rows */
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+ /* Among all columns with a 1 in this row, choose smallest */
+ least_col = sm_get_col(A, prow->first_col->col_num);
+ for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ if (pcol->length < least_col->length) {
+ least_col = pcol;
+ }
+ }
+
+ /* Only check for containment against rows in this column */
+ for(p = least_col->first_row; p != 0; p = pnext) {
+ pnext = p->next_row;
+
+ prow1 = sm_get_row(A, p->row_num);
+ if ((prow1->length > prow->length) ||
+ (prow1->length == prow->length &&
+ prow1->row_num > prow->row_num)) {
+ if (sm_row_contains(prow, prow1)) {
+ sm_delrow(A, prow1->row_num);
+ }
+ }
+ }
+ }
+
+ return rowcnt - A->nrows;
+}
+
+int
+sm_col_dominance(A, weight)
+sm_matrix *A;
+int *weight;
+{
+ register sm_row *prow;
+ register sm_col *pcol, *pcol1;
+ register sm_element *p;
+ sm_row *least_row;
+ sm_col *next_col;
+ int colcnt;
+
+ colcnt = A->ncols;
+
+ /* Check each column against all other columns */
+ for(pcol = A->first_col; pcol != 0; pcol = next_col) {
+ next_col = pcol->next_col;
+
+ /* Check all rows to find the one with fewest elements */
+ least_row = sm_get_row(A, pcol->first_row->row_num);
+ for(p = pcol->first_row->next_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ if (prow->length < least_row->length) {
+ least_row = prow;
+ }
+ }
+
+ /* Only check for containment against columns in this row */
+ for(p = least_row->first_col; p != 0; p = p->next_col) {
+ pcol1 = sm_get_col(A, p->col_num);
+ if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num])
+ continue;
+ if ((pcol1->length > pcol->length) ||
+ (pcol1->length == pcol->length &&
+ pcol1->col_num > pcol->col_num)) {
+ if (sm_col_contains(pcol, pcol1)) {
+ sm_delcol(A, pcol->col_num);
+ break;
+ }
+ }
+ }
+ }
+
+ return colcnt - A->ncols;
+}
diff --git a/src/misc/espresso/equiv.c b/src/misc/espresso/equiv.c
new file mode 100644
index 00000000..ba898a70
--- /dev/null
+++ b/src/misc/espresso/equiv.c
@@ -0,0 +1,94 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+find_equiv_outputs(PLA)
+pPLA PLA;
+{
+ int i, j, ipart, jpart, some_equiv;
+ pcover *R, *F;
+
+ some_equiv = FALSE;
+
+ makeup_labels(PLA);
+
+ F = ALLOC(pcover, cube.part_size[cube.output]);
+ R = ALLOC(pcover, cube.part_size[cube.output]);
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ ipart = cube.first_part[cube.output] + i;
+ R[i] = cof_output(PLA->R, ipart);
+ F[i] = complement(cube1list(R[i]));
+ }
+
+ for(i = 0; i < cube.part_size[cube.output]-1; i++) {
+ for(j = i+1; j < cube.part_size[cube.output]; j++) {
+ ipart = cube.first_part[cube.output] + i;
+ jpart = cube.first_part[cube.output] + j;
+
+ if (check_equiv(F[i], F[j])) {
+ (void) printf("# Outputs %d and %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(F[i], R[j])) {
+ (void) printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(R[i], F[j])) {
+ (void) printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(R[i], R[j])) {
+ (void) printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ }
+ }
+ }
+
+ if (! some_equiv) {
+ (void) printf("# No outputs are equivalent\n");
+ }
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ free_cover(F[i]);
+ free_cover(R[i]);
+ }
+ FREE(F);
+ FREE(R);
+}
+
+
+
+int check_equiv(f1, f2)
+pcover f1, f2;
+{
+ register pcube *f1list, *f2list;
+ register pcube p, last;
+
+ f1list = cube1list(f1);
+ foreach_set(f2, last, p) {
+ if (! cube_is_covered(f1list, p)) {
+ return FALSE;
+ }
+ }
+ free_cubelist(f1list);
+
+ f2list = cube1list(f2);
+ foreach_set(f1, last, p) {
+ if (! cube_is_covered(f2list, p)) {
+ return FALSE;
+ }
+ }
+ free_cubelist(f2list);
+
+ return TRUE;
+}
diff --git a/src/misc/espresso/espresso.c b/src/misc/espresso/espresso.c
new file mode 100644
index 00000000..8f05d43f
--- /dev/null
+++ b/src/misc/espresso/espresso.c
@@ -0,0 +1,139 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * Module: espresso.c
+ * Purpose: The main espresso algorithm
+ *
+ * Returns a minimized version of the ON-set of a function
+ *
+ * The following global variables affect the operation of Espresso:
+ *
+ * MISCELLANEOUS:
+ * trace
+ * print trace information as the minimization progresses
+ *
+ * remove_essential
+ * remove essential primes
+ *
+ * single_expand
+ * if true, stop after first expand/irredundant
+ *
+ * LAST_GASP or SUPER_GASP strategy:
+ * use_super_gasp
+ * uses the super_gasp strategy rather than last_gasp
+ *
+ * SETUP strategy:
+ * recompute_onset
+ * recompute onset using the complement before starting
+ *
+ * unwrap_onset
+ * unwrap the function output part before first expand
+ *
+ * MAKE_SPARSE strategy:
+ * force_irredundant
+ * iterates make_sparse to force a minimal solution (used
+ * indirectly by make_sparse)
+ *
+ * skip_make_sparse
+ * skip the make_sparse step (used by opo only)
+ */
+
+#include "espresso.h"
+
+pcover espresso(F, D1, R)
+pcover F, D1, R;
+{
+ pcover E, D, Fsave;
+ pset last, p;
+ cost_t cost, best_cost;
+
+begin:
+ Fsave = sf_save(F); /* save original function */
+ D = sf_save(D1); /* make a scratch copy of D */
+
+ /* Setup has always been a problem */
+ if (recompute_onset) {
+ EXEC(E = simplify(cube1list(F)), "SIMPLIFY ", E);
+ free_cover(F);
+ F = E;
+ }
+ cover_cost(F, &cost);
+ if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1)
+ && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1])
+ && (cost.out < 5000))
+ EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP ", F);
+
+ /* Initial expand and irredundant */
+ foreach_set(F, last, p) {
+ RESET(p, PRIME);
+ }
+ EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+ EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+
+ if (! single_expand) {
+ if (remove_essential) {
+ EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost);
+ } else {
+ E = new_cover(0);
+ }
+
+ cover_cost(F, &cost);
+ do {
+
+ /* Repeat inner loop until solution becomes "stable" */
+ do {
+ copy_cost(&cost, &best_cost);
+ EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost);
+ EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+ EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+ } while (cost.cubes < best_cost.cubes);
+
+ /* Perturb solution to see if we can continue to iterate */
+ copy_cost(&cost, &best_cost);
+ if (use_super_gasp) {
+ F = super_gasp(F, D, R, &cost);
+ if (cost.cubes >= best_cost.cubes)
+ break;
+ } else {
+ F = last_gasp(F, D, R, &cost);
+ }
+
+ } while (cost.cubes < best_cost.cubes ||
+ (cost.cubes == best_cost.cubes && cost.total < best_cost.total));
+
+ /* Append the essential cubes to F */
+ F = sf_append(F, E); /* disposes of E */
+ if (trace) size_stamp(F, "ADJUST ");
+ }
+
+ /* Free the D which we used */
+ free_cover(D);
+
+ /* Attempt to make the PLA matrix sparse */
+ if (! skip_make_sparse) {
+ F = make_sparse(F, D1, R);
+ }
+
+ /*
+ * Check to make sure function is actually smaller !!
+ * This can only happen because of the initial unravel. If we fail,
+ * then run the whole thing again without the unravel.
+ */
+ if (Fsave->count < F->count) {
+ free_cover(F);
+ F = Fsave;
+ unwrap_onset = FALSE;
+ goto begin;
+ } else {
+ free_cover(Fsave);
+ }
+
+ return F;
+}
diff --git a/src/misc/espresso/espresso.h b/src/misc/espresso/espresso.h
new file mode 100644
index 00000000..1c7a8646
--- /dev/null
+++ b/src/misc/espresso/espresso.h
@@ -0,0 +1,782 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * espresso.h -- header file for Espresso-mv
+ */
+
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+#define ptime() util_cpu_time()
+#define print_time(t) util_print_time(t)
+
+#ifdef IBM_WATC
+#define void int
+#include "short.h"
+#endif
+
+#ifdef IBMPC /* set default options for IBM/PC */
+#define NO_INLINE
+#define BPI 16
+#endif
+
+/*-----THIS USED TO BE set.h----- */
+
+/*
+ * set.h -- definitions for packed arrays of bits
+ *
+ * This header file describes the data structures which comprise a
+ * facility for efficiently implementing packed arrays of bits
+ * (otherwise known as sets, cf. Pascal).
+ *
+ * A set is a vector of bits and is implemented here as an array of
+ * unsigned integers. The low order bits of set[0] give the index of
+ * the last word of set data. The higher order bits of set[0] are
+ * used to store data associated with the set. The set data is
+ * contained in elements set[1] ... set[LOOP(set)] as a packed bit
+ * array.
+ *
+ * A family of sets is a two-dimensional matrix of bits and is
+ * implemented with the data type "set_family".
+ *
+ * BPI == 32 and BPI == 16 have been tested and work.
+ */
+
+
+/* Define host machine characteristics of "unsigned int" */
+#ifndef BPI
+#define BPI 32 /* # bits per integer */
+#endif
+
+#if BPI == 32
+#define LOGBPI 5 /* log(BPI)/log(2) */
+#else
+#define LOGBPI 4 /* log(BPI)/log(2) */
+#endif
+
+/* Define the set type */
+typedef unsigned int *pset;
+
+/* Define the set family type -- an array of sets */
+typedef struct set_family {
+ int wsize; /* Size of each set in 'ints' */
+ int sf_size; /* User declared set size */
+ int capacity; /* Number of sets allocated */
+ int count; /* The number of sets in the family */
+ int active_count; /* Number of "active" sets */
+ pset data; /* Pointer to the set data */
+ struct set_family *next; /* For garbage collection */
+} set_family_t, *pset_family;
+
+/* Macros to set and test single elements */
+#define WHICH_WORD(element) (((element) >> LOGBPI) + 1)
+#define WHICH_BIT(element) ((element) & (BPI-1))
+
+/* # of ints needed to allocate a set with "size" elements */
+#if BPI == 32
+#define SET_SIZE(size) ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1))
+#else
+#define SET_SIZE(size) ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2))
+#endif
+
+/*
+ * Three fields are maintained in the first word of the set
+ * LOOP is the index of the last word used for set data
+ * LOOPCOPY is the index of the last word in the set
+ * SIZE is available for general use (e.g., recording # elements in set)
+ * NELEM retrieves the number of elements in the set
+ */
+#define LOOP(set) (set[0] & 0x03ff)
+#define PUTLOOP(set, i) (set[0] &= ~0x03ff, set[0] |= (i))
+#if BPI == 32
+#define LOOPCOPY(set) LOOP(set)
+#define SIZE(set) (set[0] >> 16)
+#define PUTSIZE(set, size) (set[0] &= 0xffff, set[0] |= ((size) << 16))
+#else
+#define LOOPCOPY(set) (LOOP(set) + 1)
+#define SIZE(set) (set[LOOP(set)+1])
+#define PUTSIZE(set, size) ((set[LOOP(set)+1]) = (size))
+#endif
+
+#define NELEM(set) (BPI * LOOP(set))
+#define LOOPINIT(size) ((size <= BPI) ? 1 : WHICH_WORD((size)-1))
+
+/*
+ * FLAGS store general information about the set
+ */
+#define SET(set, flag) (set[0] |= (flag))
+#define RESET(set, flag) (set[0] &= ~ (flag))
+#define TESTP(set, flag) (set[0] & (flag))
+
+/* Flag definitions are ... */
+#define PRIME 0x8000 /* cube is prime */
+#define NONESSEN 0x4000 /* cube cannot be essential prime */
+#define ACTIVE 0x2000 /* cube is still active */
+#define REDUND 0x1000 /* cube is redundant(at this point) */
+#define COVERED 0x0800 /* cube has been covered */
+#define RELESSEN 0x0400 /* cube is relatively essential */
+
+/* Most efficient way to look at all members of a set family */
+#define foreach_set(R, last, p)\
+ for(p=R->data,last=p+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_remaining_set(R, last, pfirst, p)\
+ for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_active_set(R, last, p)\
+ foreach_set(R,last,p) if (TESTP(p, ACTIVE))
+
+/* Another way that also keeps the index of the current set member in i */
+#define foreachi_set(R, i, p)\
+ for(p=R->data,i=0;i<R->count;p+=R->wsize,i++)
+#define foreachi_active_set(R, i, p)\
+ foreachi_set(R,i,p) if (TESTP(p, ACTIVE))
+
+/* Looping over all elements in a set:
+ * foreach_set_element(pset p, int i, unsigned val, int base) {
+ * .
+ * .
+ * .
+ * }
+ */
+#define foreach_set_element(p, i, val, base) \
+ for(i = LOOP(p); i > 0; ) \
+ for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) \
+ if (val & 1)
+
+/* Return a pointer to a given member of a set family */
+#define GETSET(family, index) ((family)->data + (family)->wsize * (index))
+
+/* Allocate and deallocate sets */
+#define set_new(size) set_clear(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_full(size) set_fill(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_save(r) set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r)
+#define set_free(r) FREE(r)
+
+/* Check for set membership, remove set element and insert set element */
+#define is_in_set(set, e) (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e)))
+#define set_remove(set, e) (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e)))
+#define set_insert(set, e) (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e))
+
+/* Inline code substitution for those places that REALLY need it on a VAX */
+#ifdef NO_INLINE
+#define INLINEset_copy(r, a) (void) set_copy(r,a)
+#define INLINEset_clear(r, size) (void) set_clear(r, size)
+#define INLINEset_fill(r, size) (void) set_fill(r, size)
+#define INLINEset_and(r, a, b) (void) set_and(r, a, b)
+#define INLINEset_or(r, a, b) (void) set_or(r, a, b)
+#define INLINEset_diff(r, a, b) (void) set_diff(r, a, b)
+#define INLINEset_ndiff(r, a, b, f) (void) set_ndiff(r, a, b, f)
+#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f)
+#define INLINEset_merge(r, a, b, mask) (void) set_merge(r, a, b, mask)
+#define INLINEsetp_implies(a, b, when_false) \
+ if (! setp_implies(a,b)) when_false
+#define INLINEsetp_disjoint(a, b, when_false) \
+ if (! setp_disjoint(a,b)) when_false
+#define INLINEsetp_equal(a, b, when_false) \
+ if (! setp_equal(a,b)) when_false
+
+#else
+
+#define INLINEset_copy(r, a)\
+ {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);}
+#define INLINEset_clear(r, size)\
+ {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);}
+#define INLINEset_fill(r, size)\
+ {register int i_=LOOPINIT(size); *r=i_; \
+ r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;}
+#define INLINEset_and(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] & b[i_]; while (--i_>0);}
+#define INLINEset_or(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] | b[i_]; while (--i_>0);}
+#define INLINEset_diff(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);}
+#define INLINEset_ndiff(r, a, b, fullset)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);}
+#ifdef IBM_WATC
+#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f)
+#else
+#define INLINEset_xor(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] ^ b[i_]; while (--i_>0);}
+#define INLINEset_xnor(r, a, b, fullset)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);}
+#endif
+#define INLINEset_merge(r, a, b, mask)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);}
+#define INLINEsetp_implies(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+#define INLINEsetp_disjoint(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+#define INLINEsetp_equal(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+
+#endif
+
+#if BPI == 32
+#define count_ones(v)\
+ (bit_count[v & 255] + bit_count[(v >> 8) & 255]\
+ + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255])
+#else
+#define count_ones(v) (bit_count[v & 255] + bit_count[(v >> 8) & 255])
+#endif
+
+/* Table for efficient bit counting */
+extern int bit_count[256];
+/*----- END OF set.h ----- */
+
+
+/* Define a boolean type */
+#define bool int
+#define FALSE 0
+#define TRUE 1
+#define MAYBE 2
+#define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE"))
+
+/* Map many cube/cover types/routines into equivalent set types/routines */
+#define pcube pset
+#define new_cube() set_new(cube.size)
+#define free_cube(r) set_free(r)
+#define pcover pset_family
+#define new_cover(i) sf_new(i, cube.size)
+#define free_cover(r) sf_free(r)
+#define free_cubelist(T) FREE(T[0]); FREE(T);
+
+
+/* cost_t describes the cost of a cover */
+typedef struct cost_struct {
+ int cubes; /* number of cubes in the cover */
+ int in; /* transistor count, binary-valued variables */
+ int out; /* transistor count, output part */
+ int mv; /* transistor count, multiple-valued vars */
+ int total; /* total number of transistors */
+ int primes; /* number of prime cubes */
+} cost_t, *pcost;
+
+
+/* pair_t describes bit-paired variables */
+typedef struct pair_struct {
+ int cnt;
+ int *var1;
+ int *var2;
+} pair_t, *ppair;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_list_struct {
+ int variable;
+ int pos;
+ struct symbolic_list_struct *next;
+} symbolic_list_t;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_label_struct {
+ char *label;
+ struct symbolic_label_struct *next;
+} symbolic_label_t;
+
+
+/* symbolic_t describes a linked list of ".symbolic" lines */
+typedef struct symbolic_struct {
+ symbolic_list_t *symbolic_list; /* linked list of items */
+ int symbolic_list_length; /* length of symbolic_list list */
+ symbolic_label_t *symbolic_label; /* linked list of new names */
+ int symbolic_label_length; /* length of symbolic_label list */
+ struct symbolic_struct *next;
+} symbolic_t;
+
+
+/* PLA_t stores the logical representation of a PLA */
+typedef struct {
+ pcover F, D, R; /* on-set, off-set and dc-set */
+ char *filename; /* filename */
+ int pla_type; /* logical PLA format */
+ pcube phase; /* phase to split into on-set and off-set */
+ ppair pair; /* how to pair variables */
+ char **label; /* labels for the columns */
+ symbolic_t *symbolic; /* allow binary->symbolic mapping */
+ symbolic_t *symbolic_output;/* allow symbolic output mapping */
+} PLA_t, *pPLA;
+
+#define equal(a,b) (strcmp(a,b) == 0)
+
+/* This is a hack which I wish I hadn't done, but too painful to change */
+#define CUBELISTSIZE(T) (((pcube *) T[1] - T) - 3)
+
+/* For documentation purposes */
+#define IN
+#define OUT
+#define INOUT
+
+/* The pla_type field describes the input and output format of the PLA */
+#define F_type 1
+#define D_type 2
+#define R_type 4
+#define PLEASURE_type 8 /* output format */
+#define EQNTOTT_type 16 /* output format algebraic eqns */
+#define KISS_type 128 /* output format kiss */
+#define CONSTRAINTS_type 256 /* output the constraints (numeric) */
+#define SYMBOLIC_CONSTRAINTS_type 512 /* output the constraints (symbolic) */
+#define FD_type (F_type | D_type)
+#define FR_type (F_type | R_type)
+#define DR_type (D_type | R_type)
+#define FDR_type (F_type | D_type | R_type)
+
+/* Definitions for the debug variable */
+#define COMPL 0x0001
+#define ESSEN 0x0002
+#define EXPAND 0x0004
+#define EXPAND1 0x0008
+#define GASP 0x0010
+#define IRRED 0x0020
+#define REDUCE 0x0040
+#define REDUCE1 0x0080
+#define SPARSE 0x0100
+#define TAUT 0x0200
+#define EXACT 0x0400
+#define MINCOV 0x0800
+#define MINCOV1 0x1000
+#define SHARP 0x2000
+#define IRRED1 0x4000
+
+#define VERSION\
+ "UC Berkeley, Espresso Version #2.3, Release date 01/31/88"
+
+/* Define constants used for recording program statistics */
+#define TIME_COUNT 16
+#define READ_TIME 0
+#define COMPL_TIME 1
+#define ONSET_TIME 2
+#define ESSEN_TIME 3
+#define EXPAND_TIME 4
+#define IRRED_TIME 5
+#define REDUCE_TIME 6
+#define GEXPAND_TIME 7
+#define GIRRED_TIME 8
+#define GREDUCE_TIME 9
+#define PRIMES_TIME 10
+#define MINCOV_TIME 11
+#define MV_REDUCE_TIME 12
+#define RAISE_IN_TIME 13
+#define VERIFY_TIME 14
+#define WRITE_TIME 15
+
+
+/* For those who like to think about PLAs, macros to get at inputs/outputs */
+#define NUMINPUTS cube.num_binary_vars
+#define NUMOUTPUTS cube.part_size[cube.num_vars - 1]
+
+#define POSITIVE_PHASE(pos)\
+ (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0)
+
+#define INLABEL(var) PLA->label[cube.first_part[var] + 1]
+#define OUTLABEL(pos) PLA->label[cube.first_part[cube.output] + pos]
+
+#define GETINPUT(c, pos)\
+ ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3)
+#define GETOUTPUT(c, pos)\
+ (is_in_set(c, cube.first_part[cube.output] + pos) != 0)
+
+#define PUTINPUT(c, pos, value)\
+ c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\
+ | (value << WHICH_BIT(2*pos))
+#define PUTOUTPUT(c, pos, value)\
+ c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & ~(1 << WHICH_BIT(pos)))\
+ | (value << WHICH_BIT(pos))
+
+#define TWO 3
+#define DASH 3
+#define ONE 2
+#define ZERO 1
+
+
+#define EXEC(fct, name, S)\
+ {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);}
+#define EXEC_S(fct, name, S)\
+ {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);}
+#define EXECUTE(fct,i,S,cost)\
+ {long t=ptime();fct;totals(t,i,S,&(cost));}
+
+/*
+ * Global Variable Declarations
+ */
+
+extern unsigned int debug; /* debug parameter */
+extern bool verbose_debug; /* -v: whether to print a lot */
+extern char *total_name[TIME_COUNT]; /* basic function names */
+extern long total_time[TIME_COUNT]; /* time spent in basic fcts */
+extern int total_calls[TIME_COUNT]; /* # calls to each fct */
+
+extern bool echo_comments; /* turned off by -eat option */
+extern bool echo_unknown_commands; /* always true ?? */
+extern bool force_irredundant; /* -nirr command line option */
+extern bool skip_make_sparse;
+extern bool kiss; /* -kiss command line option */
+extern bool pos; /* -pos command line option */
+extern bool print_solution; /* -x command line option */
+extern bool recompute_onset; /* -onset command line option */
+extern bool remove_essential; /* -ness command line option */
+extern bool single_expand; /* -fast command line option */
+extern bool summary; /* -s command line option */
+extern bool trace; /* -t command line option */
+extern bool unwrap_onset; /* -nunwrap command line option */
+extern bool use_random_order; /* -random command line option */
+extern bool use_super_gasp; /* -strong command line option */
+extern char *filename; /* filename PLA was read from */
+extern bool debug_exact_minimization; /* dumps info for -do exact */
+
+
+/*
+ * pla_types are the input and output types for reading/writing a PLA
+ */
+struct pla_types_struct {
+ char *key;
+ int value;
+};
+
+
+/*
+ * The cube structure is a global structure which contains information
+ * on how a set maps into a cube -- i.e., number of parts per variable,
+ * number of variables, etc. Also, many fields are pre-computed to
+ * speed up various primitive operations.
+ */
+#define CUBE_TEMP 10
+
+struct cube_struct {
+ int size; /* set size of a cube */
+ int num_vars; /* number of variables in a cube */
+ int num_binary_vars; /* number of binary variables */
+ int *first_part; /* first element of each variable */
+ int *last_part; /* first element of each variable */
+ int *part_size; /* number of elements in each variable */
+ int *first_word; /* first word for each variable */
+ int *last_word; /* last word for each variable */
+ pset binary_mask; /* Mask to extract binary variables */
+ pset mv_mask; /* mask to get mv parts */
+ pset *var_mask; /* mask to extract a variable */
+ pset *temp; /* an array of temporary sets */
+ pset fullset; /* a full cube */
+ pset emptyset; /* an empty cube */
+ unsigned int inmask; /* mask to get odd word of binary part */
+ int inword; /* which word number for above */
+ int *sparse; /* should this variable be sparse? */
+ int num_mv_vars; /* number of multiple-valued variables */
+ int output; /* which variable is "output" (-1 if none) */
+};
+
+struct cdata_struct {
+ int *part_zeros; /* count of zeros for each element */
+ int *var_zeros; /* count of zeros for each variable */
+ int *parts_active; /* number of "active" parts for each var */
+ bool *is_unate; /* indicates given var is unate */
+ int vars_active; /* number of "active" variables */
+ int vars_unate; /* number of unate variables */
+ int best; /* best "binate" variable */
+};
+
+
+extern struct pla_types_struct pla_types[];
+extern struct cube_struct cube, temp_cube_save;
+extern struct cdata_struct cdata, temp_cdata_save;
+
+#ifdef lint
+#define DISJOINT 0x5555
+#else
+#if BPI == 32
+#define DISJOINT 0x55555555
+#else
+#define DISJOINT 0x5555
+#endif
+#endif
+
+/* function declarations */
+
+/* cofactor.c */ extern int binate_split_select();
+/* cofactor.c */ extern pcover cubeunlist();
+/* cofactor.c */ extern pcube *cofactor();
+/* cofactor.c */ extern pcube *cube1list();
+/* cofactor.c */ extern pcube *cube2list();
+/* cofactor.c */ extern pcube *cube3list();
+/* cofactor.c */ extern pcube *scofactor();
+/* cofactor.c */ extern void massive_count();
+/* compl.c */ extern pcover complement();
+/* compl.c */ extern pcover simplify();
+/* compl.c */ extern void simp_comp();
+/* contain.c */ extern int d1_rm_equal();
+/* contain.c */ extern int rm2_contain();
+/* contain.c */ extern int rm2_equal();
+/* contain.c */ extern int rm_contain();
+/* contain.c */ extern int rm_equal();
+/* contain.c */ extern int rm_rev_contain();
+/* contain.c */ extern pset *sf_list();
+/* contain.c */ extern pset *sf_sort();
+/* contain.c */ extern pset_family d1merge();
+/* contain.c */ extern pset_family dist_merge();
+/* contain.c */ extern pset_family sf_contain();
+/* contain.c */ extern pset_family sf_dupl();
+/* contain.c */ extern pset_family sf_ind_contain();
+/* contain.c */ extern pset_family sf_ind_unlist();
+/* contain.c */ extern pset_family sf_merge();
+/* contain.c */ extern pset_family sf_rev_contain();
+/* contain.c */ extern pset_family sf_union();
+/* contain.c */ extern pset_family sf_unlist();
+/* cubestr.c */ extern void cube_setup();
+/* cubestr.c */ extern void restore_cube_struct();
+/* cubestr.c */ extern void save_cube_struct();
+/* cubestr.c */ extern void setdown_cube();
+/* cvrin.c */ extern PLA_labels();
+/* cvrin.c */ extern char *get_word();
+/* cvrin.c */ extern int label_index();
+/* cvrin.c */ extern int read_pla();
+/* cvrin.c */ extern int read_symbolic();
+/* cvrin.c */ extern pPLA new_PLA();
+/* cvrin.c */ extern void PLA_summary();
+/* cvrin.c */ extern void free_PLA();
+/* cvrin.c */ extern void parse_pla();
+/* cvrin.c */ extern void read_cube();
+/* cvrin.c */ extern void skip_line();
+/* cvrm.c */ extern foreach_output_function();
+/* cvrm.c */ extern int cubelist_partition();
+/* cvrm.c */ extern int so_both_do_espresso();
+/* cvrm.c */ extern int so_both_do_exact();
+/* cvrm.c */ extern int so_both_save();
+/* cvrm.c */ extern int so_do_espresso();
+/* cvrm.c */ extern int so_do_exact();
+/* cvrm.c */ extern int so_save();
+/* cvrm.c */ extern pcover cof_output();
+/* cvrm.c */ extern pcover lex_sort();
+/* cvrm.c */ extern pcover mini_sort();
+/* cvrm.c */ extern pcover random_order();
+/* cvrm.c */ extern pcover size_sort();
+/* cvrm.c */ extern pcover sort_reduce();
+/* cvrm.c */ extern pcover uncof_output();
+/* cvrm.c */ extern pcover unravel();
+/* cvrm.c */ extern pcover unravel_range();
+/* cvrm.c */ extern void so_both_espresso();
+/* cvrm.c */ extern void so_espresso();
+/* cvrmisc.c */ extern char *fmt_cost();
+/* cvrmisc.c */ extern char *print_cost();
+/* cvrmisc.c */ extern char *strsav();
+/* cvrmisc.c */ extern void copy_cost();
+/* cvrmisc.c */ extern void cover_cost();
+/* cvrmisc.c */ extern void fatal();
+/* cvrmisc.c */ extern void print_trace();
+/* cvrmisc.c */ extern void size_stamp();
+/* cvrmisc.c */ extern void totals();
+/* cvrout.c */ extern char *fmt_cube();
+/* cvrout.c */ extern char *fmt_expanded_cube();
+/* cvrout.c */ extern char *pc1();
+/* cvrout.c */ extern char *pc2();
+/* cvrout.c */ extern char *pc3();
+/* cvrout.c */ extern int makeup_labels();
+/* cvrout.c */ extern kiss_output();
+/* cvrout.c */ extern kiss_print_cube();
+/* cvrout.c */ extern output_symbolic_constraints();
+/* cvrout.c */ extern void cprint();
+/* cvrout.c */ extern void debug1_print();
+/* cvrout.c */ extern void debug_print();
+/* cvrout.c */ extern void eqn_output();
+/* cvrout.c */ extern void fpr_header();
+/* cvrout.c */ extern void fprint_pla();
+/* cvrout.c */ extern void pls_group();
+/* cvrout.c */ extern void pls_label();
+/* cvrout.c */ extern void pls_output();
+/* cvrout.c */ extern void print_cube();
+/* cvrout.c */ extern void print_expanded_cube();
+/* cvrout.c */ extern void sf_debug_print();
+/* equiv.c */ extern find_equiv_outputs();
+/* equiv.c */ extern int check_equiv();
+/* espresso.c */ extern pcover espresso();
+/* essen.c */ extern bool essen_cube();
+/* essen.c */ extern pcover cb_consensus();
+/* essen.c */ extern pcover cb_consensus_dist0();
+/* essen.c */ extern pcover essential();
+/* exact.c */ extern pcover minimize_exact();
+/* exact.c */ extern pcover minimize_exact_literals();
+/* expand.c */ extern bool feasibly_covered();
+/* expand.c */ extern int most_frequent();
+/* expand.c */ extern pcover all_primes();
+/* expand.c */ extern pcover expand();
+/* expand.c */ extern pcover find_all_primes();
+/* expand.c */ extern void elim_lowering();
+/* expand.c */ extern void essen_parts();
+/* expand.c */ extern void essen_raising();
+/* expand.c */ extern void expand1();
+/* expand.c */ extern void mincov();
+/* expand.c */ extern void select_feasible();
+/* expand.c */ extern void setup_BB_CC();
+/* gasp.c */ extern pcover expand_gasp();
+/* gasp.c */ extern pcover irred_gasp();
+/* gasp.c */ extern pcover last_gasp();
+/* gasp.c */ extern pcover super_gasp();
+/* gasp.c */ extern void expand1_gasp();
+/* getopt.c */ extern int util_getopt();
+/* hack.c */ extern find_dc_inputs();
+/* hack.c */ extern find_inputs();
+/* hack.c */ extern form_bitvector();
+/* hack.c */ extern map_dcset();
+/* hack.c */ extern map_output_symbolic();
+/* hack.c */ extern map_symbolic();
+/* hack.c */ extern pcover map_symbolic_cover();
+/* hack.c */ extern symbolic_hack_labels();
+/* irred.c */ extern bool cube_is_covered();
+/* irred.c */ extern bool taut_special_cases();
+/* irred.c */ extern bool tautology();
+/* irred.c */ extern pcover irredundant();
+/* irred.c */ extern void mark_irredundant();
+/* irred.c */ extern void irred_split_cover();
+/* irred.c */ extern sm_matrix *irred_derive_table();
+/* map.c */ extern pset minterms();
+/* map.c */ extern void explode();
+/* map.c */ extern void map();
+/* opo.c */ extern output_phase_setup();
+/* opo.c */ extern pPLA set_phase();
+/* opo.c */ extern pcover opo();
+/* opo.c */ extern pcube find_phase();
+/* opo.c */ extern pset_family find_covers();
+/* opo.c */ extern pset_family form_cover_table();
+/* opo.c */ extern pset_family opo_leaf();
+/* opo.c */ extern pset_family opo_recur();
+/* opo.c */ extern void opoall();
+/* opo.c */ extern void phase_assignment();
+/* opo.c */ extern void repeated_phase_assignment();
+/* pair.c */ extern generate_all_pairs();
+/* pair.c */ extern int **find_pairing_cost();
+/* pair.c */ extern int find_best_cost();
+/* pair.c */ extern int greedy_best_cost();
+/* pair.c */ extern int minimize_pair();
+/* pair.c */ extern int pair_free();
+/* pair.c */ extern pair_all();
+/* pair.c */ extern pcover delvar();
+/* pair.c */ extern pcover pairvar();
+/* pair.c */ extern ppair pair_best_cost();
+/* pair.c */ extern ppair pair_new();
+/* pair.c */ extern ppair pair_save();
+/* pair.c */ extern print_pair();
+/* pair.c */ extern void find_optimal_pairing();
+/* pair.c */ extern void set_pair();
+/* pair.c */ extern void set_pair1();
+/* primes.c */ extern pcover primes_consensus();
+/* reduce.c */ extern bool sccc_special_cases();
+/* reduce.c */ extern pcover reduce();
+/* reduce.c */ extern pcube reduce_cube();
+/* reduce.c */ extern pcube sccc();
+/* reduce.c */ extern pcube sccc_cube();
+/* reduce.c */ extern pcube sccc_merge();
+/* set.c */ extern bool set_andp();
+/* set.c */ extern bool set_orp();
+/* set.c */ extern bool setp_disjoint();
+/* set.c */ extern bool setp_empty();
+/* set.c */ extern bool setp_equal();
+/* set.c */ extern bool setp_full();
+/* set.c */ extern bool setp_implies();
+/* set.c */ extern char *pbv1();
+/* set.c */ extern char *ps1();
+/* set.c */ extern int *sf_count();
+/* set.c */ extern int *sf_count_restricted();
+/* set.c */ extern int bit_index();
+/* set.c */ extern int set_dist();
+/* set.c */ extern int set_ord();
+/* set.c */ extern void set_adjcnt();
+/* set.c */ extern pset set_and();
+/* set.c */ extern pset set_clear();
+/* set.c */ extern pset set_copy();
+/* set.c */ extern pset set_diff();
+/* set.c */ extern pset set_fill();
+/* set.c */ extern pset set_merge();
+/* set.c */ extern pset set_or();
+/* set.c */ extern pset set_xor();
+/* set.c */ extern pset sf_and();
+/* set.c */ extern pset sf_or();
+/* set.c */ extern pset_family sf_active();
+/* set.c */ extern pset_family sf_addcol();
+/* set.c */ extern pset_family sf_addset();
+/* set.c */ extern pset_family sf_append();
+/* set.c */ extern pset_family sf_bm_read();
+/* set.c */ extern pset_family sf_compress();
+/* set.c */ extern pset_family sf_copy();
+/* set.c */ extern pset_family sf_copy_col();
+/* set.c */ extern pset_family sf_delc();
+/* set.c */ extern pset_family sf_delcol();
+/* set.c */ extern pset_family sf_inactive();
+/* set.c */ extern pset_family sf_join();
+/* set.c */ extern pset_family sf_new();
+/* set.c */ extern pset_family sf_permute();
+/* set.c */ extern pset_family sf_read();
+/* set.c */ extern pset_family sf_save();
+/* set.c */ extern pset_family sf_transpose();
+/* set.c */ extern void set_write();
+/* set.c */ extern void sf_bm_print();
+/* set.c */ extern void sf_cleanup();
+/* set.c */ extern void sf_delset();
+/* set.c */ extern void sf_free();
+/* set.c */ extern void sf_print();
+/* set.c */ extern void sf_write();
+/* setc.c */ extern bool ccommon();
+/* setc.c */ extern bool cdist0();
+/* setc.c */ extern bool full_row();
+/* setc.c */ extern int ascend();
+/* setc.c */ extern int cactive();
+/* setc.c */ extern int cdist();
+/* setc.c */ extern int cdist01();
+/* setc.c */ extern int cvolume();
+/* setc.c */ extern int d1_order();
+/* setc.c */ extern int d1_order_size();
+/* setc.c */ extern int desc1();
+/* setc.c */ extern int descend();
+/* setc.c */ extern int lex_order();
+/* setc.c */ extern int lex_order1();
+/* setc.c */ extern pset force_lower();
+/* setc.c */ extern void consensus();
+/* sharp.c */ extern pcover cb1_dsharp();
+/* sharp.c */ extern pcover cb_dsharp();
+/* sharp.c */ extern pcover cb_recur_dsharp();
+/* sharp.c */ extern pcover cb_recur_sharp();
+/* sharp.c */ extern pcover cb_sharp();
+/* sharp.c */ extern pcover cv_dsharp();
+/* sharp.c */ extern pcover cv_intersect();
+/* sharp.c */ extern pcover cv_sharp();
+/* sharp.c */ extern pcover dsharp();
+/* sharp.c */ extern pcover make_disjoint();
+/* sharp.c */ extern pcover sharp();
+/* sminterf.c */pset do_sm_minimum_cover();
+/* sparse.c */ extern pcover make_sparse();
+/* sparse.c */ extern pcover mv_reduce();
+#if !defined(__osf__) && !defined(__STDC__) && !defined(__hpux)
+/* ucbqsort.c */ extern qsort();
+#endif
+/* ucbqsort.c */ extern qst();
+/* unate.c */ extern pcover find_all_minimal_covers_petrick();
+/* unate.c */ extern pcover map_cover_to_unate();
+/* unate.c */ extern pcover map_unate_to_cover();
+/* unate.c */ extern pset_family exact_minimum_cover();
+/* unate.c */ extern pset_family gen_primes();
+/* unate.c */ extern pset_family unate_compl();
+/* unate.c */ extern pset_family unate_complement();
+/* unate.c */ extern pset_family unate_intersect();
+/* verify.c */ extern PLA_permute();
+/* verify.c */ extern bool PLA_verify();
+/* verify.c */ extern bool check_consistency();
+/* verify.c */ extern bool verify();
diff --git a/src/misc/espresso/essen.c b/src/misc/espresso/essen.c
new file mode 100644
index 00000000..6a46295d
--- /dev/null
+++ b/src/misc/espresso/essen.c
@@ -0,0 +1,179 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: essen.c
+ purpose: Find essential primes in a multiple-valued function
+*/
+
+#include "espresso.h"
+
+/*
+ essential -- return a cover consisting of the cubes of F which are
+ essential prime implicants (with respect to F u D); Further, remove
+ these cubes from the ON-set F, and add them to the OFF-set D.
+
+ Sometimes EXPAND can determine that a cube is not an essential prime.
+ If so, it will set the "NONESSEN" flag in the cube.
+
+ We count on IRREDUNDANT to have set the flag RELESSEN to indicate
+ that a prime was relatively essential (i.e., covers some minterm
+ not contained in any other prime in the current cover), or to have
+ reset the flag to indicate that a prime was relatively redundant
+ (i.e., all minterms covered by other primes in the current cover).
+ Of course, after executing irredundant, all of the primes in the
+ cover are relatively essential, but we can mark the primes which
+ were redundant at the start of irredundant and avoid an extra check
+ on these primes for essentiality.
+*/
+
+pcover essential(Fp, Dp)
+IN pcover *Fp, *Dp;
+{
+ register pcube last, p;
+ pcover E, F = *Fp, D = *Dp;
+
+ /* set all cubes in F active */
+ (void) sf_active(F);
+
+ /* Might as well start out with some cubes in E */
+ E = new_cover(10);
+
+ foreach_set(F, last, p) {
+ /* don't test a prime which EXPAND says is nonessential */
+ if (! TESTP(p, NONESSEN)) {
+ /* only test a prime which was relatively essential */
+ if (TESTP(p, RELESSEN)) {
+ /* Check essentiality */
+ if (essen_cube(F, D, p)) {
+ if (debug & ESSEN)
+ printf("ESSENTIAL: %s\n", pc1(p));
+ E = sf_addset(E, p);
+ RESET(p, ACTIVE);
+ F->active_count--;
+ }
+ }
+ }
+ }
+
+ *Fp = sf_inactive(F); /* delete the inactive cubes from F */
+ *Dp = sf_join(D, E); /* add the essentials to D */
+ sf_free(D);
+ return E;
+}
+
+/*
+ essen_cube -- check if a single cube is essential or not
+
+ The prime c is essential iff
+
+ consensus((F u D) # c, c) u D
+
+ does not contain c.
+*/
+bool essen_cube(F, D, c)
+IN pcover F, D;
+IN pcube c;
+{
+ pcover H, FD;
+ pcube *H1;
+ bool essen;
+
+ /* Append F and D together, and take the sharp-consensus with c */
+ FD = sf_join(F, D);
+ H = cb_consensus(FD, c);
+ free_cover(FD);
+
+ /* Add the don't care set, and see if this covers c */
+ H1 = cube2list(H, D);
+ essen = ! cube_is_covered(H1, c);
+ free_cubelist(H1);
+
+ free_cover(H);
+ return essen;
+}
+
+
+/*
+ * cb_consensus -- compute consensus(T # c, c)
+ */
+pcover cb_consensus(T, c)
+register pcover T;
+register pcube c;
+{
+ register pcube temp, last, p;
+ register pcover R;
+
+ R = new_cover(T->count*2);
+ temp = new_cube();
+ foreach_set(T, last, p) {
+ if (p != c) {
+ switch (cdist01(p, c)) {
+ case 0:
+ /* distance-0 needs special care */
+ R = cb_consensus_dist0(R, p, c);
+ break;
+
+ case 1:
+ /* distance-1 is easy because no sharping required */
+ consensus(temp, p, c);
+ R = sf_addset(R, temp);
+ break;
+ }
+ }
+ }
+ set_free(temp);
+ return R;
+}
+
+
+/*
+ * form the sharp-consensus for p and c when they intersect
+ * What we are forming is consensus(p # c, c).
+ */
+pcover cb_consensus_dist0(R, p, c)
+pcover R;
+register pcube p, c;
+{
+ int var;
+ bool got_one;
+ register pcube temp, mask;
+ register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1];
+
+ /* If c contains p, then this gives us no information for essential test */
+ if (setp_implies(p, c)) {
+ return R;
+ }
+
+ /* For the multiple-valued variables */
+ temp = new_cube();
+ got_one = FALSE;
+ INLINEset_diff(p_diff_c, p, c);
+ INLINEset_and(p_and_c, p, c);
+
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ /* Check if c(var) is contained in p(var) -- if so, no news */
+ mask = cube.var_mask[var];
+ if (! setp_disjoint(p_diff_c, mask)) {
+ INLINEset_merge(temp, c, p_and_c, mask);
+ R = sf_addset(R, temp);
+ got_one = TRUE;
+ }
+ }
+
+ /* if no cube so far, add one for the intersection */
+ if (! got_one && cube.num_binary_vars > 0) {
+ /* Add a single cube for the intersection of p and c */
+ INLINEset_and(temp, p, c);
+ R = sf_addset(R, temp);
+ }
+
+ set_free(temp);
+ return R;
+}
diff --git a/src/misc/espresso/exact.c b/src/misc/espresso/exact.c
new file mode 100644
index 00000000..b1943636
--- /dev/null
+++ b/src/misc/espresso/exact.c
@@ -0,0 +1,181 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+static void dump_irredundant();
+static pcover do_minimize();
+
+
+/*
+ * minimize_exact -- main entry point for exact minimization
+ *
+ * Global flags which affect this routine are:
+ *
+ * debug
+ * skip_make_sparse
+ */
+
+pcover
+minimize_exact(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+ return do_minimize(F, D, R, exact_cover, /*weighted*/ 0);
+}
+
+
+pcover
+minimize_exact_literals(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+ return do_minimize(F, D, R, exact_cover, /*weighted*/ 1);
+}
+
+
+
+static pcover
+do_minimize(F, D, R, exact_cover, weighted)
+pcover F, D, R;
+int exact_cover;
+int weighted;
+{
+ pcover newF, E, Rt, Rp;
+ pset p, last;
+ int heur, level, *weights, i;
+ sm_matrix *table;
+ sm_row *cover;
+ sm_element *pe;
+ int debug_save = debug;
+
+ if (debug & EXACT) {
+ debug |= (IRRED | MINCOV);
+ }
+#if defined(sun) || defined(bsd4_2) /* hack ... */
+ if (debug & MINCOV) {
+ setlinebuf(stdout);
+ }
+#endif
+ level = (debug & MINCOV) ? 4 : 0;
+ heur = ! exact_cover;
+
+ /* Generate all prime implicants */
+ EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES ", F);
+
+ /* Setup the prime implicant table */
+ EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E);
+ EXEC(table = irred_derive_table(D, E, Rp), "PI-TABLE ", Rp);
+
+ /* Solve either a weighted or nonweighted covering problem */
+ if (weighted) {
+ /* correct only for all 2-valued variables */
+ weights = ALLOC(int, F->count);
+ foreach_set(Rp, last, p) {
+ weights[SIZE(p)] = cube.size - set_ord(p);
+ /* We have added the 0's in the output part instead of the 1's.
+ This loop corrects the literal count. */
+ for (i = cube.first_part[cube.output];
+ i <= cube.last_part[cube.output]; i++) {
+ is_in_set(p, i) ? weights[SIZE(p)]++ : weights[SIZE(p)]--;
+ }
+ }
+ } else {
+ weights = NIL(int);
+ }
+ EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV ", F);
+ if (weights != 0) {
+ FREE(weights);
+ }
+
+ if (debug & EXACT) {
+ dump_irredundant(E, Rt, Rp, table);
+ }
+
+ /* Form the result cover */
+ newF = new_cover(100);
+ foreach_set(E, last, p) {
+ newF = sf_addset(newF, p);
+ }
+ sm_foreach_row_element(cover, pe) {
+ newF = sf_addset(newF, GETSET(F, pe->col_num));
+ }
+
+ free_cover(E);
+ free_cover(Rt);
+ free_cover(Rp);
+ sm_free(table);
+ sm_row_free(cover);
+ free_cover(F);
+
+ /* Attempt to make the results more sparse */
+ debug &= ~ (IRRED | SHARP | MINCOV);
+ if (! skip_make_sparse && R != 0) {
+ newF = make_sparse(newF, D, R);
+ }
+
+ debug = debug_save;
+ return newF;
+}
+
+static void
+dump_irredundant(E, Rt, Rp, table)
+pcover E, Rt, Rp;
+sm_matrix *table;
+{
+ FILE *fp_pi_table, *fp_primes;
+ pPLA PLA;
+ pset last, p;
+ char *file;
+
+ if (filename == 0 || strcmp(filename, "(stdin)") == 0) {
+ fp_pi_table = fp_primes = stdout;
+ } else {
+ file = ALLOC(char, strlen(filename)+20);
+ (void) sprintf(file, "%s.primes", filename);
+ if ((fp_primes = fopen(file, "w")) == NULL) {
+ (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+ fp_primes = stdout;
+ }
+ (void) sprintf(file, "%s.pi", filename);
+ if ((fp_pi_table = fopen(file, "w")) == NULL) {
+ (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+ fp_pi_table = stdout;
+ }
+ FREE(file);
+ }
+
+ PLA = new_PLA();
+ PLA_labels(PLA);
+
+ fpr_header(fp_primes, PLA, F_type);
+ free_PLA(PLA);
+
+ (void) fprintf(fp_primes, "# Essential primes are\n");
+ foreach_set(E, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ (void) fprintf(fp_primes, "# Totally redundant primes are\n");
+ foreach_set(Rt, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ (void) fprintf(fp_primes, "# Partially redundant primes are\n");
+ foreach_set(Rp, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ if (fp_primes != stdout) {
+ (void) fclose(fp_primes);
+ }
+
+ sm_write(fp_pi_table, table);
+ if (fp_pi_table != stdout) {
+ (void) fclose(fp_pi_table);
+ }
+}
diff --git a/src/misc/espresso/expand.c b/src/misc/espresso/expand.c
new file mode 100644
index 00000000..2765d71c
--- /dev/null
+++ b/src/misc/espresso/expand.c
@@ -0,0 +1,693 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: expand.c
+ purpose: Perform the Espresso-II Expansion Step
+
+ The idea is to take each nonprime cube of the on-set and expand it
+ into a prime implicant such that we can cover as many other cubes
+ of the on-set. If no cube of the on-set can be covered, then we
+ expand each cube into a large prime implicant by transforming the
+ problem into a minimum covering problem which is solved by the
+ heuristics of minimum_cover.
+
+ These routines revolve around having a representation of the
+ OFF-set. (In contrast to the Espresso-II manuscript, we do NOT
+ require an "unwrapped" version of the OFF-set).
+
+ Some conventions on variable names:
+
+ SUPER_CUBE is the supercube of all cubes which can be covered
+ by an expansion of the cube being expanded
+
+ OVEREXPANDED_CUBE is the cube which would result from expanding
+ all parts which can expand individually of the cube being expanded
+
+ RAISE is the current expansion of the current cube
+
+ FREESET is the set of parts which haven't been raised or lowered yet.
+
+ INIT_LOWER is a set of parts to be removed from the free parts before
+ starting the expansion
+*/
+
+#include "espresso.h"
+
+/*
+ expand -- expand each nonprime cube of F into a prime implicant
+
+ If nonsparse is true, only the non-sparse variables will be expanded;
+ this is done by forcing all of the sparse variables out of the free set.
+*/
+
+pcover expand(F, R, nonsparse)
+INOUT pcover F;
+IN pcover R;
+IN bool nonsparse; /* expand non-sparse variables only */
+{
+ register pcube last, p;
+ pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE;
+ int var, num_covered;
+ bool change;
+
+ /* Order the cubes according to "chewing-away from the edges" of mini */
+ if (use_random_order)
+ F = random_order(F);
+ else
+ F = mini_sort(F, ascend);
+
+ /* Allocate memory for variables needed by expand1() */
+ RAISE = new_cube();
+ FREESET = new_cube();
+ INIT_LOWER = new_cube();
+ SUPER_CUBE = new_cube();
+ OVEREXPANDED_CUBE = new_cube();
+
+ /* Setup the initial lowering set (differs only for nonsparse) */
+ if (nonsparse)
+ for(var = 0; var < cube.num_vars; var++)
+ if (cube.sparse[var])
+ (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]);
+
+ /* Mark all cubes as not covered, and maybe essential */
+ foreach_set(F, last, p) {
+ RESET(p, COVERED);
+ RESET(p, NONESSEN);
+ }
+
+ /* Try to expand each nonprime and noncovered cube */
+ foreach_set(F, last, p) {
+ /* do not expand if PRIME or if covered by previous expansion */
+ if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) {
+
+ /* expand the cube p, result is RAISE */
+ expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ INIT_LOWER, &num_covered, p);
+ if (debug & EXPAND)
+ printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered);
+ (void) set_copy(p, RAISE);
+ SET(p, PRIME);
+ RESET(p, COVERED); /* not really necessary */
+
+ /* See if we generated an inessential prime */
+ if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) {
+ SET(p, NONESSEN);
+ }
+ }
+ }
+
+ /* Delete any cubes of F which became covered during the expansion */
+ F->active_count = 0;
+ change = FALSE;
+ foreach_set(F, last, p) {
+ if (TESTP(p, COVERED)) {
+ RESET(p, ACTIVE);
+ change = TRUE;
+ } else {
+ SET(p, ACTIVE);
+ F->active_count++;
+ }
+ }
+ if (change)
+ F = sf_inactive(F);
+
+ free_cube(RAISE);
+ free_cube(FREESET);
+ free_cube(INIT_LOWER);
+ free_cube(SUPER_CUBE);
+ free_cube(OVEREXPANDED_CUBE);
+ return F;
+}
+
+/*
+ expand1 -- Expand a single cube against the OFF-set
+*/
+void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ INIT_LOWER, num_covered, c)
+pcover BB; /* Blocking matrix (OFF-set) */
+pcover CC; /* Covering matrix (ON-set) */
+pcube RAISE; /* The current parts which have been raised */
+pcube FREESET; /* The current parts which are free */
+pcube OVEREXPANDED_CUBE; /* Overexpanded cube of c */
+pcube SUPER_CUBE; /* Supercube of all cubes of CC we cover */
+pcube INIT_LOWER; /* Parts to initially remove from FREESET */
+int *num_covered; /* Number of cubes of CC which are covered */
+pcube c; /* The cube to be expanded */
+{
+ int bestindex;
+
+ if (debug & EXPAND1)
+ printf("\nEXPAND1: \t%s\n", pc1(c));
+
+ /* initialize BB and CC */
+ SET(c, PRIME); /* don't try to cover ourself */
+ setup_BB_CC(BB, CC);
+
+ /* initialize count of # cubes covered, and the supercube of them */
+ *num_covered = 0;
+ (void) set_copy(SUPER_CUBE, c);
+
+ /* Initialize the lowering, raising and unassigned sets */
+ (void) set_copy(RAISE, c);
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+
+ /* If some parts are forced into lowering set, remove them */
+ if (! setp_empty(INIT_LOWER)) {
+ (void) set_diff(FREESET, FREESET, INIT_LOWER);
+ elim_lowering(BB, CC, RAISE, FREESET);
+ }
+
+ /* Determine what can be raised, and return the over-expanded cube */
+ essen_parts(BB, CC, RAISE, FREESET);
+ (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET);
+
+ /* While there are still cubes which can be covered, cover them ! */
+ if (CC->active_count > 0) {
+ select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered);
+ }
+
+ /* While there are still cubes covered by the overexpanded cube ... */
+ while (CC->active_count > 0) {
+ bestindex = most_frequent(CC, FREESET);
+ set_insert(RAISE, bestindex);
+ set_remove(FREESET, bestindex);
+ essen_parts(BB, CC, RAISE, FREESET);
+ }
+
+ /* Finally, when all else fails, choose the largest possible prime */
+ /* We will loop only if we decide unravelling OFF-set is too expensive */
+ while (BB->active_count > 0) {
+ mincov(BB, RAISE, FREESET);
+ }
+
+ /* Raise any remaining free coordinates */
+ (void) set_or(RAISE, RAISE, FREESET);
+}
+
+/*
+ essen_parts -- determine which parts are forced into the lowering
+ set to insure that the cube be orthognal to the OFF-set.
+
+ If any cube of the OFF-set is distance 1 from the raising cube,
+ then we must lower all parts of the conflicting variable. (If the
+ cube is distance 0, we detect this error here.)
+
+ If there are essentially lowered parts, we can remove from consideration
+ any cubes of the OFF-set which are more than distance 1 from the
+ overexpanded cube of RAISE.
+*/
+
+void essen_parts(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+ register pcube p, r = RAISE;
+ pcube lastp, xlower = cube.temp[0];
+ int dist;
+
+ (void) set_copy(xlower, cube.emptyset);
+
+ foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+ if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+ if (dist == 0) {
+ fatal("ON-set and OFF-set are not orthogonal");
+ } else {
+ (void) force_lower(xlower, p, r);
+ BB->active_count--;
+ RESET(p, ACTIVE);
+ }
+exit_if: ;
+ }
+
+ if (! setp_empty(xlower)) {
+ (void) set_diff(FREESET, FREESET, xlower);/* remove from free set */
+ elim_lowering(BB, CC, RAISE, FREESET);
+ }
+
+ if (debug & EXPAND1)
+ printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+}
+
+/*
+ essen_raising -- determine which parts may always be added to
+ the raising set without restricting further expansions
+
+ General rule: if some part is not blocked by any cube of BB, then
+ this part can always be raised.
+*/
+
+void essen_raising(BB, RAISE, FREESET)
+register pcover BB;
+pcube RAISE, FREESET;
+{
+ register pcube last, p, xraise = cube.temp[0];
+
+ /* Form union of all cubes of BB, and then take complement wrt FREESET */
+ (void) set_copy(xraise, cube.emptyset);
+ foreach_active_set(BB, last, p)
+ INLINEset_or(xraise, xraise, p);
+ (void) set_diff(xraise, FREESET, xraise);
+
+ (void) set_or(RAISE, RAISE, xraise); /* add to raising set */
+ (void) set_diff(FREESET, FREESET, xraise); /* remove from free set */
+
+ if (debug & EXPAND1)
+ printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n",
+ pc1(RAISE), pc2(FREESET));
+}
+
+/*
+ elim_lowering -- after removing parts from FREESET, we can reduce the
+ size of both BB and CC.
+
+ We mark as inactive any cube of BB which does not intersect the
+ overexpanded cube (i.e., RAISE + FREESET). Likewise, we remove
+ from CC any cube which is not covered by the overexpanded cube.
+*/
+
+void elim_lowering(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+ register pcube p, r = set_or(cube.temp[0], RAISE, FREESET);
+ pcube last;
+
+ /*
+ * Remove sets of BB which are orthogonal to future expansions
+ */
+ foreach_active_set(BB, last, p) {
+#ifdef NO_INLINE
+ if (! cdist0(p, r))
+#else
+ {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[
+lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<lastw;w++){x=p[w]
+&r[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register
+pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.
+var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++)
+if(p[w]&r[w]&mask[w])goto nextvar;goto false;nextvar:;}}continue;false:
+#endif
+ BB->active_count--, RESET(p, ACTIVE);
+ }
+
+
+ /*
+ * Remove sets of CC which cannot be covered by future expansions
+ */
+ if (CC != (pcover) NULL) {
+ foreach_active_set(CC, last, p) {
+#ifdef NO_INLINE
+ if (! setp_implies(p, r))
+#else
+ INLINEsetp_implies(p, r, /* when false => */ goto false1);
+ /* when true => go to end of loop */ continue;
+ false1:
+#endif
+ CC->active_count--, RESET(p, ACTIVE);
+ }
+ }
+}
+
+/*
+ most_frequent -- When all else fails, select a reasonable part to raise
+ The active cubes of CC are the cubes which are covered by the
+ overexpanded cube of the original cube (however, we know that none
+ of them can actually be covered by a feasible expansion of the
+ original cube). We resort to the MINI strategy of selecting to
+ raise the part which will cover the same part in the most cubes of CC.
+*/
+int most_frequent(CC, FREESET)
+pcover CC;
+pcube FREESET;
+{
+ register int i, best_part, best_count, *count;
+ register pset p, last;
+
+ /* Count occurences of each variable */
+ count = ALLOC(int, cube.size);
+ for(i = 0; i < cube.size; i++)
+ count[i] = 0;
+ if (CC != (pcover) NULL)
+ foreach_active_set(CC, last, p)
+ set_adjcnt(p, count, 1);
+
+ /* Now find which free part occurs most often */
+ best_count = best_part = -1;
+ for(i = 0; i < cube.size; i++)
+ if (is_in_set(FREESET,i) && count[i] > best_count) {
+ best_part = i;
+ best_count = count[i];
+ }
+ FREE(count);
+
+ if (debug & EXPAND1)
+ printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET));
+ return best_part;
+}
+
+/*
+ setup_BB_CC -- set up the blocking and covering set families;
+
+ Note that the blocking family is merely the set of cubes of R, and
+ that CC is the set of cubes of F which might possibly be covered
+ (i.e., nonprime cubes, and cubes not already covered)
+*/
+
+void setup_BB_CC(BB, CC)
+register pcover BB, CC;
+{
+ register pcube p, last;
+
+ /* Create the block and cover set families */
+ BB->active_count = BB->count;
+ foreach_set(BB, last, p)
+ SET(p, ACTIVE);
+
+ if (CC != (pcover) NULL) {
+ CC->active_count = CC->count;
+ foreach_set(CC, last, p)
+ if (TESTP(p, COVERED) || TESTP(p, PRIME))
+ CC->active_count--, RESET(p, ACTIVE);
+ else
+ SET(p, ACTIVE);
+ }
+}
+
+/*
+ select_feasible -- Determine if there are cubes which can be covered,
+ and if so, raise those parts necessary to cover as many as possible.
+
+ We really don't check to maximize the number that can be covered;
+ instead, we check, for each fcc, how many other fcc remain fcc
+ after expanding to cover the fcc. (Essentially one-level lookahead).
+*/
+
+void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered)
+pcover BB, CC;
+pcube RAISE, FREESET, SUPER_CUBE;
+int *num_covered;
+{
+ register pcube p, last, bestfeas, *feas;
+ register int i, j;
+ pcube *feas_new_lower;
+ int bestcount, bestsize, count, size, numfeas, lastfeas;
+ pcover new_lower;
+
+ /* Start out with all cubes covered by the over-expanded cube as
+ * the "possibly" feasibly-covered cubes (pfcc)
+ */
+ feas = ALLOC(pcube, CC->active_count);
+ numfeas = 0;
+ foreach_active_set(CC, last, p)
+ feas[numfeas++] = p;
+
+ /* Setup extra cubes to record parts forced low after a covering */
+ feas_new_lower = ALLOC(pcube, CC->active_count);
+ new_lower = new_cover(numfeas);
+ for(i = 0; i < numfeas; i++)
+ feas_new_lower[i] = GETSET(new_lower, i);
+
+
+loop:
+ /* Find the essentially raised parts -- this might cover some cubes
+ for us, without having to find out if they are fcc or not
+ */
+ essen_raising(BB, RAISE, FREESET);
+
+ /* Now check all "possibly" feasibly covered cubes to check feasibility */
+ lastfeas = numfeas;
+ numfeas = 0;
+ for(i = 0; i < lastfeas; i++) {
+ p = feas[i];
+
+ /* Check active because essen_parts might have removed it */
+ if (TESTP(p, ACTIVE)) {
+
+ /* See if the cube is already covered by RAISE --
+ * this can happen because of essen_raising() or because of
+ * the previous "loop"
+ */
+ if (setp_implies(p, RAISE)) {
+ (*num_covered) += 1;
+ (void) set_or(SUPER_CUBE, SUPER_CUBE, p);
+ CC->active_count--;
+ RESET(p, ACTIVE);
+ SET(p, COVERED);
+ /* otherwise, test if it is feasibly covered */
+ } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) {
+ feas[numfeas] = p; /* save the fcc */
+ numfeas++;
+ }
+ }
+ }
+ if (debug & EXPAND1)
+ printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n",
+ lastfeas, numfeas);
+
+ /* Exit here if there are no feasibly covered cubes */
+ if (numfeas == 0) {
+ FREE(feas);
+ FREE(feas_new_lower);
+ free_cover(new_lower);
+ return;
+ }
+
+ /* Now find which is the best feasibly covered cube */
+ bestcount = 0;
+ bestsize = 9999;
+ for(i = 0; i < numfeas; i++) {
+ size = set_dist(feas[i], FREESET); /* # of newly raised parts */
+ count = 0; /* # of other cubes which remain fcc after raising */
+
+#define NEW
+#ifdef NEW
+ for(j = 0; j < numfeas; j++)
+ if (setp_disjoint(feas_new_lower[i], feas[j]))
+ count++;
+#else
+ for(j = 0; j < numfeas; j++)
+ if (setp_implies(feas[j], feas[i]))
+ count++;
+#endif
+ if (count > bestcount) {
+ bestcount = count;
+ bestfeas = feas[i];
+ bestsize = size;
+ } else if (count == bestcount && size < bestsize) {
+ bestfeas = feas[i];
+ bestsize = size;
+ }
+ }
+
+ /* Add the necessary parts to the raising set */
+ (void) set_or(RAISE, RAISE, bestfeas);
+ (void) set_diff(FREESET, FREESET, RAISE);
+ if (debug & EXPAND1)
+ printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+ essen_parts(BB, CC, RAISE, FREESET);
+ goto loop;
+/* NOTREACHED */
+}
+
+/*
+ feasibly_covered -- determine if the cube c is feasibly covered
+ (i.e., if it is possible to raise all of the necessary variables
+ while still insuring orthogonality with R). Also, if c is feasibly
+ covered, then compute the new set of parts which are forced into
+ the lowering set.
+*/
+
+bool feasibly_covered(BB, c, RAISE, new_lower)
+pcover BB;
+pcube c, RAISE, new_lower;
+{
+ register pcube p, r = set_or(cube.temp[0], RAISE, c);
+ int dist;
+ pcube lastp;
+
+ set_copy(new_lower, cube.emptyset);
+ foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+ if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+ if (dist == 0)
+ return FALSE;
+ else
+ (void) force_lower(new_lower, p, r);
+ exit_if: ;
+ }
+ return TRUE;
+}
+
+/*
+ mincov -- transform the problem of expanding a cube to a maximally-
+ large prime implicant into the problem of selecting a minimum
+ cardinality cover over a family of sets.
+
+ When we get to this point, we must unravel the remaining off-set.
+ This may be painful.
+*/
+
+void mincov(BB, RAISE, FREESET)
+pcover BB;
+pcube RAISE, FREESET;
+{
+ int expansion, nset, var, dist;
+ pset_family B;
+ register pcube xraise=cube.temp[0], xlower, p, last, plower;
+
+#ifdef RANDOM_MINCOV
+#if defined(_POSIX_SOURCE) || defined(__SVR4)
+ dist = rand() % set_ord(FREESET);
+#else
+ dist = random() % set_ord(FREESET);
+#endif
+ for(var = 0; var < cube.size && dist >= 0; var++) {
+ if (is_in_set(FREESET, var)) {
+ dist--;
+ }
+ }
+
+ set_insert(RAISE, var);
+ set_remove(FREESET, var);
+ (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+#else
+
+ /* Create B which are those cubes which we must avoid intersecting */
+ B = new_cover(BB->active_count);
+ foreach_active_set(BB, last, p) {
+ plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ (void) force_lower(plower, p, RAISE);
+ }
+
+ /* Determine how many sets it will blow up into after the unravel */
+ nset = 0;
+ foreach_set(B, last, p) {
+ expansion = 1;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ if ((dist=set_dist(p, cube.var_mask[var])) > 1) {
+ expansion *= dist;
+ if (expansion > 500) goto heuristic_mincov;
+ }
+ }
+ nset += expansion;
+ if (nset > 500) goto heuristic_mincov;
+ }
+
+ B = unravel(B, cube.num_binary_vars);
+ xlower = do_sm_minimum_cover(B);
+
+ /* Add any remaining free parts to the raising set */
+ (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower));
+ (void) set_copy(FREESET, cube.emptyset); /* free set is empty */
+ BB->active_count = 0; /* BB satisfied */
+ if (debug & EXPAND1) {
+ printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+ }
+ sf_free(B);
+ set_free(xlower);
+ return;
+
+heuristic_mincov:
+ sf_free(B);
+ /* most_frequent will pick first free part */
+ set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET));
+ (void) set_diff(FREESET, FREESET, RAISE);
+ essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+ return;
+#endif
+}
+
+/*
+ find_all_primes -- find all of the primes which cover the
+ currently reduced BB
+*/
+pcover find_all_primes(BB, RAISE, FREESET)
+pcover BB;
+register pcube RAISE, FREESET;
+{
+ register pset last, p, plower;
+ pset_family B, B1;
+
+ if (BB->active_count == 0) {
+ B1 = new_cover(1);
+ p = GETSET(B1, B1->count++);
+ (void) set_copy(p, RAISE);
+ SET(p, PRIME);
+ } else {
+ B = new_cover(BB->active_count);
+ foreach_active_set(BB, last, p) {
+ plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ (void) force_lower(plower, p, RAISE);
+ }
+ B = sf_rev_contain(unravel(B, cube.num_binary_vars));
+ B1 = exact_minimum_cover(B);
+ foreach_set(B1, last, p) {
+ INLINEset_diff(p, FREESET, p);
+ INLINEset_or(p, p, RAISE);
+ SET(p, PRIME);
+ }
+ free_cover(B);
+ }
+ return B1;
+}
+
+/*
+ all_primes -- foreach cube in F, generate all of the primes
+ which cover the cube.
+*/
+
+pcover all_primes(F, R)
+pcover F, R;
+{
+ register pcube last, p, RAISE, FREESET;
+ pcover Fall_primes, B1;
+
+ FREESET = new_cube();
+ RAISE = new_cube();
+ Fall_primes = new_cover(F->count);
+
+ foreach_set(F, last, p) {
+ if (TESTP(p, PRIME)) {
+ Fall_primes = sf_addset(Fall_primes, p);
+ } else {
+ /* Setup for call to essential parts */
+ (void) set_copy(RAISE, p);
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+ setup_BB_CC(R, /* CC */ (pcover) NULL);
+ essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET);
+
+ /* Find all of the primes, and add them to the prime set */
+ B1 = find_all_primes(R, RAISE, FREESET);
+ Fall_primes = sf_append(Fall_primes, B1);
+ }
+ }
+
+ set_free(RAISE);
+ set_free(FREESET);
+ return Fall_primes;
+}
diff --git a/src/misc/espresso/gasp.c b/src/misc/espresso/gasp.c
new file mode 100644
index 00000000..aa3254d3
--- /dev/null
+++ b/src/misc/espresso/gasp.c
@@ -0,0 +1,228 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: gasp.c
+
+ The "last_gasp" heuristic computes the reduction of each cube in
+ the cover (without replacement) and then performs an expansion of
+ these cubes. The cubes which expand to cover some other cube are
+ added to the original cover and irredundant finds a minimal subset.
+
+ If one of the reduced cubes expands to cover some other reduced
+ cube, then the new prime thus generated is a candidate for reducing
+ the size of the cover.
+
+ super_gasp is a variation on this strategy which extracts a minimal
+ subset from the set of all prime implicants which cover all
+ maximally reduced cubes.
+*/
+
+#include "espresso.h"
+
+
+/*
+ * reduce_gasp -- compute the maximal reduction of each cube of F
+ *
+ * If a cube does not reduce, it remains prime; otherwise, it is marked
+ * as nonprime. If the cube is redundant (should NEVER happen here) we
+ * just crap out ...
+ *
+ * A cover with all of the cubes of F is returned. Those that did
+ * reduce are marked "NONPRIME"; those that reduced are marked "PRIME".
+ * The cubes are in the same order as in F.
+ */
+static pcover reduce_gasp(F, D)
+pcover F, D;
+{
+ pcube p, last, cunder, *FD;
+ pcover G;
+
+ G = new_cover(F->count);
+ FD = cube2list(F, D);
+
+ /* Reduce cubes of F without replacement */
+ foreach_set(F, last, p) {
+ cunder = reduce_cube(FD, p);
+ if (setp_empty(cunder)) {
+ fatal("empty reduction in reduce_gasp, shouldn't happen");
+ } else if (setp_equal(cunder, p)) {
+ SET(cunder, PRIME); /* just to make sure */
+ G = sf_addset(G, p); /* it did not reduce ... */
+ } else {
+ RESET(cunder, PRIME); /* it reduced ... */
+ G = sf_addset(G, cunder);
+ }
+ if (debug & GASP) {
+ printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder));
+ }
+ free_cube(cunder);
+ }
+
+ free_cubelist(FD);
+ return G;
+}
+
+/*
+ * expand_gasp -- expand each nonprime cube of F into a prime implicant
+ *
+ * The gasp strategy differs in that only those cubes which expand to
+ * cover some other cube are saved; also, all cubes are expanded
+ * regardless of whether they become covered or not.
+ */
+
+pcover expand_gasp(F, D, R, Foriginal)
+INOUT pcover F;
+IN pcover D;
+IN pcover R;
+IN pcover Foriginal;
+{
+ int c1index;
+ pcover G;
+
+ /* Try to expand each nonprime and noncovered cube */
+ G = new_cover(10);
+ for(c1index = 0; c1index < F->count; c1index++) {
+ expand1_gasp(F, D, R, Foriginal, c1index, &G);
+ }
+ G = sf_dupl(G);
+ G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */
+ return G;
+}
+
+
+
+/*
+ * expand1 -- Expand a single cube against the OFF-set, using the gasp strategy
+ */
+void expand1_gasp(F, D, R, Foriginal, c1index, G)
+pcover F; /* reduced cubes of ON-set */
+pcover D; /* DC-set */
+pcover R; /* OFF-set */
+pcover Foriginal; /* ON-set before reduction (same order as F) */
+int c1index; /* which index of F (or Freduced) to be checked */
+pcover *G;
+{
+ register int c2index;
+ register pcube p, last, c2under;
+ pcube RAISE, FREESET, temp, *FD, c2essential;
+ pcover F1;
+
+ if (debug & EXPAND1) {
+ printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index)));
+ }
+
+ RAISE = new_cube();
+ FREESET = new_cube();
+ temp = new_cube();
+
+ /* Initialize the OFF-set */
+ R->active_count = R->count;
+ foreach_set(R, last, p) {
+ SET(p, ACTIVE);
+ }
+ /* Initialize the reduced ON-set, all nonprime cubes become active */
+ F->active_count = F->count;
+ foreachi_set(F, c2index, c2under) {
+ if (c1index == c2index || TESTP(c2under, PRIME)) {
+ F->active_count--;
+ RESET(c2under, ACTIVE);
+ } else {
+ SET(c2under, ACTIVE);
+ }
+ }
+
+ /* Initialize the raising and unassigned sets */
+ (void) set_copy(RAISE, GETSET(F, c1index));
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+
+ /* Determine parts which must be lowered */
+ essen_parts(R, F, RAISE, FREESET);
+
+ /* Determine parts which can always be raised */
+ essen_raising(R, RAISE, FREESET);
+
+ /* See which, if any, of the reduced cubes we can cover */
+ foreachi_set(F, c2index, c2under) {
+ if (TESTP(c2under, ACTIVE)) {
+ /* See if this cube can be covered by an expansion */
+ if (setp_implies(c2under, RAISE) ||
+ feasibly_covered(R, c2under, RAISE, temp)) {
+
+ /* See if c1under can expanded to cover c2 reduced against
+ * (F - c1) u c1under; if so, c2 can definitely be removed !
+ */
+
+ /* Copy F and replace c1 with c1under */
+ F1 = sf_save(Foriginal);
+ (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index));
+
+ /* Reduce c2 against ((F - c1) u c1under) */
+ FD = cube2list(F1, D);
+ c2essential = reduce_cube(FD, GETSET(F1, c2index));
+ free_cubelist(FD);
+ sf_free(F1);
+
+ /* See if c2essential is covered by an expansion of c1under */
+ if (feasibly_covered(R, c2essential, RAISE, temp)) {
+ (void) set_or(temp, RAISE, c2essential);
+ RESET(temp, PRIME); /* cube not prime */
+ *G = sf_addset(*G, temp);
+ }
+ set_free(c2essential);
+ }
+ }
+ }
+
+ free_cube(RAISE);
+ free_cube(FREESET);
+ free_cube(temp);
+}
+
+/* irred_gasp -- Add new primes to F and find an irredundant subset */
+pcover irred_gasp(F, D, G)
+pcover F, D, G; /* G is disposed of */
+{
+ if (G->count != 0)
+ F = irredundant(sf_append(F, G), D);
+ else
+ free_cover(G);
+ return F;
+}
+
+
+/* last_gasp */
+pcover last_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+ pcover G, G1;
+
+ EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+ EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost);
+ free_cover(G);
+ EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost);
+ return F;
+}
+
+
+/* super_gasp */
+pcover super_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+ pcover G, G1;
+
+ EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+ EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost);
+ free_cover(G);
+ EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G);
+ EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost);
+ return F;
+}
diff --git a/src/misc/espresso/gimpel.c b/src/misc/espresso/gimpel.c
new file mode 100644
index 00000000..648bb64a
--- /dev/null
+++ b/src/misc/espresso/gimpel.c
@@ -0,0 +1,106 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+/*
+ * check for:
+ *
+ * c1 c2 rest
+ * -- -- ---
+ * 1 1 0 0 0 0 <-- primary row
+ * 1 0 S1 <-- secondary row
+ * 0 1 T1
+ * 0 1 T2
+ * 0 1 Tn
+ * 0 0 R
+ */
+
+int
+gimpel_reduce(A, select, weight, lb, bound, depth, stats, best)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+solution_t **best;
+{
+ register sm_row *prow, *save_sec;
+ register sm_col *c1, *c2;
+ register sm_element *p, *p1;
+ int c1_col_num, c2_col_num, primary_row_num, secondary_row_num;
+ int reduce_it;
+
+ reduce_it = 0;
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->length == 2) {
+ c1 = sm_get_col(A, prow->first_col->col_num);
+ c2 = sm_get_col(A, prow->last_col->col_num);
+ if (c1->length == 2) {
+ reduce_it = 1;
+ } else if (c2->length == 2) {
+ c1 = sm_get_col(A, prow->last_col->col_num);
+ c2 = sm_get_col(A, prow->first_col->col_num);
+ reduce_it = 1;
+ }
+ if (reduce_it) {
+ primary_row_num = prow->row_num;
+ secondary_row_num = c1->first_row->row_num;
+ if (secondary_row_num == primary_row_num) {
+ secondary_row_num = c1->last_row->row_num;
+ }
+ break;
+ }
+ }
+ }
+
+ if (reduce_it) {
+ c1_col_num = c1->col_num;
+ c2_col_num = c2->col_num;
+ save_sec = sm_row_dup(sm_get_row(A, secondary_row_num));
+ sm_row_remove(save_sec, c1_col_num);
+
+ for(p = c2->first_row; p != 0; p = p->next_row) {
+ if (p->row_num != primary_row_num) {
+ /* merge rows S1 and T */
+ for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) {
+ (void) sm_insert(A, p->row_num, p1->col_num);
+ }
+ }
+ }
+
+ sm_delcol(A, c1_col_num);
+ sm_delcol(A, c2_col_num);
+ sm_delrow(A, primary_row_num);
+ sm_delrow(A, secondary_row_num);
+
+ stats->gimpel_count++;
+ stats->gimpel++;
+ *best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats);
+ stats->gimpel--;
+
+ if (*best != NIL(solution_t)) {
+ /* is secondary row covered ? */
+ if (sm_row_intersects(save_sec, (*best)->row)) {
+ /* yes, actually select c2 */
+ solution_add(*best, weight, c2_col_num);
+ } else {
+ solution_add(*best, weight, c1_col_num);
+ }
+ }
+
+ sm_row_free(save_sec);
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/src/misc/espresso/globals.c b/src/misc/espresso/globals.c
new file mode 100644
index 00000000..d04771e9
--- /dev/null
+++ b/src/misc/espresso/globals.c
@@ -0,0 +1,76 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ * Global Variable Declarations
+ */
+
+unsigned int debug; /* debug parameter */
+bool verbose_debug; /* -v: whether to print a lot */
+char *total_name[TIME_COUNT]; /* basic function names */
+long total_time[TIME_COUNT]; /* time spent in basic fcts */
+int total_calls[TIME_COUNT]; /* # calls to each fct */
+
+bool echo_comments; /* turned off by -eat option */
+bool echo_unknown_commands; /* always true ?? */
+bool force_irredundant; /* -nirr command line option */
+bool skip_make_sparse;
+bool kiss; /* -kiss command line option */
+bool pos; /* -pos command line option */
+bool print_solution; /* -x command line option */
+bool recompute_onset; /* -onset command line option */
+bool remove_essential; /* -ness command line option */
+bool single_expand; /* -fast command line option */
+bool summary; /* -s command line option */
+bool trace; /* -t command line option */
+bool unwrap_onset; /* -nunwrap command line option */
+bool use_random_order; /* -random command line option */
+bool use_super_gasp; /* -strong command line option */
+char *filename; /* filename PLA was read from */
+
+struct pla_types_struct pla_types[] = {
+ "-f", F_type,
+ "-r", R_type,
+ "-d", D_type,
+ "-fd", FD_type,
+ "-fr", FR_type,
+ "-dr", DR_type,
+ "-fdr", FDR_type,
+ "-fc", F_type | CONSTRAINTS_type,
+ "-rc", R_type | CONSTRAINTS_type,
+ "-dc", D_type | CONSTRAINTS_type,
+ "-fdc", FD_type | CONSTRAINTS_type,
+ "-frc", FR_type | CONSTRAINTS_type,
+ "-drc", DR_type | CONSTRAINTS_type,
+ "-fdrc", FDR_type | CONSTRAINTS_type,
+ "-pleasure", PLEASURE_type,
+ "-eqn", EQNTOTT_type,
+ "-eqntott", EQNTOTT_type,
+ "-kiss", KISS_type,
+ "-cons", CONSTRAINTS_type,
+ "-scons", SYMBOLIC_CONSTRAINTS_type,
+ 0, 0
+};
+
+
+struct cube_struct cube, temp_cube_save;
+struct cdata_struct cdata, temp_cdata_save;
+
+int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
diff --git a/src/misc/espresso/hack.c b/src/misc/espresso/hack.c
new file mode 100644
index 00000000..927f5341
--- /dev/null
+++ b/src/misc/espresso/hack.c
@@ -0,0 +1,641 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+map_dcset(PLA)
+pPLA PLA;
+{
+ int var, i;
+ pcover Tplus, Tminus, Tplusbar, Tminusbar;
+ pcover newf, term1, term2, dcset, dcsetbar;
+ pcube cplus, cminus, last, p;
+
+ if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char))
+ return;
+
+ /* try to find a binary variable named "DONT_CARE" */
+ var = -1;
+ for(i = 0; i < cube.num_binary_vars * 2; i++) {
+ if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 ||
+ strncmp(PLA->label[i], "DONTCARE", 8) == 0 ||
+ strncmp(PLA->label[i], "dont_care", 9) == 0 ||
+ strncmp(PLA->label[i], "dontcare", 8) == 0) {
+ var = i/2;
+ break;
+ }
+ }
+ if (var == -1) {
+ return;
+ }
+
+ /* form the cofactor cubes for the don't-care variable */
+ cplus = set_save(cube.fullset);
+ cminus = set_save(cube.fullset);
+ set_remove(cplus, var*2);
+ set_remove(cminus, var*2 + 1);
+
+ /* form the don't-care set */
+ EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar),
+ "simpcomp+", Tplus);
+ EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar),
+ "simpcomp-", Tminus);
+ EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1 ", term1);
+ EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2 ", term2);
+ EXEC(dcset = sf_union(term1, term2), "union ", dcset);
+ EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D);
+ EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate ", PLA->F);
+ free_cover(PLA->F);
+ PLA->F = newf;
+ free_cover(Tplus);
+ free_cover(Tminus);
+ free_cover(Tplusbar);
+ free_cover(Tminusbar);
+ free_cover(dcsetbar);
+
+ /* remove any cubes dependent on the DONT_CARE variable */
+ (void) sf_active(PLA->F);
+ foreach_set(PLA->F, last, p) {
+ if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) {
+ RESET(p, ACTIVE);
+ }
+ }
+ PLA->F = sf_inactive(PLA->F);
+
+ /* resize the cube and delete the don't-care variable */
+ setdown_cube();
+ for(i = 2*var+2; i < cube.size; i++) {
+ PLA->label[i-2] = PLA->label[i];
+ }
+ for(i = var+1; i < cube.num_vars; i++) {
+ cube.part_size[i-1] = cube.part_size[i];
+ }
+ cube.num_binary_vars--;
+ cube.num_vars--;
+ cube_setup();
+ PLA->F = sf_delc(PLA->F, 2*var, 2*var+1);
+ PLA->D = sf_delc(PLA->D, 2*var, 2*var+1);
+}
+
+map_output_symbolic(PLA)
+pPLA PLA;
+{
+ pset_family newF, newD;
+ pset compress;
+ symbolic_t *p1;
+ symbolic_list_t *p2;
+ int i, bit, tot_size, base, old_size;
+
+ /* Remove the DC-set from the ON-set (is this necessary ??) */
+ if (PLA->D->count > 0) {
+ sf_free(PLA->F);
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ }
+
+ /* tot_size = width added for all symbolic variables */
+ tot_size = 0;
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) {
+ fatal("symbolic-output index out of range");
+/* } else if (p2->variable != cube.output) {
+ fatal("symbolic-output label must be an output");*/
+ }
+ }
+ tot_size += 1 << p1->symbolic_list_length;
+ }
+
+ /* adjust the indices to skip over new outputs */
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ p2->pos += tot_size;
+ }
+ }
+
+ /* resize the cube structure -- add enough for the one-hot outputs */
+ old_size = cube.size;
+ cube.part_size[cube.output] += tot_size;
+ setdown_cube();
+ cube_setup();
+
+ /* insert space in the output part for the one-hot output */
+ base = cube.first_part[cube.output];
+ PLA->F = sf_addcol(PLA->F, base, tot_size);
+ PLA->D = sf_addcol(PLA->D, base, tot_size);
+ PLA->R = sf_addcol(PLA->R, base, tot_size);
+
+ /* do the real work */
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ newF = new_cover(100);
+ newD = new_cover(100);
+ find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0,
+ &newF, &newD);
+/*
+ * Not sure what this means
+ find_dc_inputs(PLA, p1->symbolic_list,
+ base, 1 << p1->symbolic_list_length, &newF, &newD);
+ */
+ free_cover(PLA->F);
+ PLA->F = newF;
+/*
+ * retain OLD DC-set -- but we've lost the don't-care arc information
+ * (it defaults to branch to the zero state)
+ free_cover(PLA->D);
+ PLA->D = newD;
+ */
+ free_cover(newD);
+ base += 1 << p1->symbolic_list_length;
+ }
+
+ /* delete the old outputs, and resize the cube */
+ compress = set_full(newF->sf_size);
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ bit = cube.first_part[cube.output] + p2->pos;
+ set_remove(compress, bit);
+ }
+ }
+ cube.part_size[cube.output] -= newF->sf_size - set_ord(compress);
+ setdown_cube();
+ cube_setup();
+ PLA->F = sf_compress(PLA->F, compress);
+ PLA->D = sf_compress(PLA->D, compress);
+ if (cube.size != PLA->F->sf_size) fatal("error");
+
+ /* Quick minimization */
+ PLA->F = sf_contain(PLA->F);
+ PLA->D = sf_contain(PLA->D);
+ for(i = 0; i < cube.num_vars; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ PLA->D = d1merge(PLA->D, i);
+ }
+ PLA->F = sf_contain(PLA->F);
+ PLA->D = sf_contain(PLA->D);
+
+ free_cover(PLA->R);
+ PLA->R = new_cover(0);
+
+ symbolic_hack_labels(PLA, PLA->symbolic_output,
+ compress, cube.size, old_size, tot_size);
+ set_free(compress);
+}
+
+
+find_inputs(A, PLA, list, base, value, newF, newD)
+pcover A;
+pPLA PLA;
+symbolic_list_t *list;
+int base, value;
+pcover *newF, *newD;
+{
+ pcover S, S1;
+ register pset last, p;
+
+ /*
+ * A represents th 'input' values for which the outputs assume
+ * the integer value 'value
+ */
+ if (list == NIL(symbolic_list_t)) {
+ /*
+ * Simulate these inputs against the on-set; then, insert into the
+ * new on-set a 1 in the proper position
+ */
+ S = cv_intersect(A, PLA->F);
+ foreach_set(S, last, p) {
+ set_insert(p, base + value);
+ }
+ *newF = sf_append(*newF, S);
+
+ /*
+ * 'simulate' these inputs against the don't-care set
+ S = cv_intersect(A, PLA->D);
+ *newD = sf_append(*newD, S);
+ */
+
+ } else {
+ /* intersect and recur with the OFF-set */
+ S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos);
+ if (A != NIL(set_family_t)) {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ S = S1;
+ }
+ find_inputs(S, PLA, list->next, base, value*2, newF, newD);
+ free_cover(S);
+
+ /* intersect and recur with the ON-set */
+ S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos);
+ if (A != NIL(set_family_t)) {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ S = S1;
+ }
+ find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD);
+ free_cover(S);
+ }
+}
+
+
+#if 0
+find_dc_inputs(PLA, list, base, maxval, newF, newD)
+pPLA PLA;
+symbolic_list_t *list;
+int base, maxval;
+pcover *newF, *newD;
+{
+ pcover A, S, S1;
+ symbolic_list_t *p2;
+ register pset p, last;
+ register int i;
+
+ /* painfully find the points for which the symbolic output is dc */
+ A = NIL(set_family_t);
+ for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos);
+ if (A == NIL(set_family_t)) {
+ A = S;
+ } else {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ free_cover(A);
+ A = S1;
+ }
+ }
+
+ S = cv_intersect(A, PLA->F);
+ *newF = sf_append(*newF, S);
+
+ S = cv_intersect(A, PLA->D);
+ foreach_set(S, last, p) {
+ for(i = base; i < base + maxval; i++) {
+ set_insert(p, i);
+ }
+ }
+ *newD = sf_append(*newD, S);
+ free_cover(A);
+}
+#endif
+
+map_symbolic(PLA)
+pPLA PLA;
+{
+ symbolic_t *p1;
+ symbolic_list_t *p2;
+ int var, base, num_vars, num_binary_vars, *new_part_size;
+ int new_size, size_added, num_deleted_vars, num_added_vars, newvar;
+ pset compress;
+
+ /* Verify legal values are in the symbolic lists */
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ if (p2->variable < 0 || p2->variable >= cube.num_binary_vars) {
+ fatal(".symbolic requires binary variables");
+ }
+ }
+ }
+
+ /*
+ * size_added = width added for all symbolic variables
+ * num_deleted_vars = # binary variables to be deleted
+ * num_added_vars = # new mv variables
+ * compress = a cube which will be used to compress the set families
+ */
+ size_added = 0;
+ num_added_vars = 0;
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ size_added += 1 << p1->symbolic_list_length;
+ num_added_vars++;
+ }
+ compress = set_full(PLA->F->sf_size + size_added);
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ set_remove(compress, p2->variable*2);
+ set_remove(compress, p2->variable*2+1);
+ }
+ }
+ num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2;
+
+ /* compute the new cube constants */
+ num_vars = cube.num_vars - num_deleted_vars + num_added_vars;
+ num_binary_vars = cube.num_binary_vars - num_deleted_vars;
+ new_size = cube.size - num_deleted_vars*2 + size_added;
+ new_part_size = ALLOC(int, num_vars);
+ new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1];
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ new_part_size[var-num_deleted_vars] = cube.part_size[var];
+ }
+
+ /* re-size the covers, opening room for the new mv variables */
+ base = cube.first_part[cube.output];
+ PLA->F = sf_addcol(PLA->F, base, size_added);
+ PLA->D = sf_addcol(PLA->D, base, size_added);
+ PLA->R = sf_addcol(PLA->R, base, size_added);
+
+ /* compute the values for the new mv variables */
+ newvar = (cube.num_vars - 1) - num_deleted_vars;
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base);
+ PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base);
+ PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base);
+ base += 1 << p1->symbolic_list_length;
+ new_part_size[newvar++] = 1 << p1->symbolic_list_length;
+ }
+
+ /* delete the binary variables which disappear */
+ PLA->F = sf_compress(PLA->F, compress);
+ PLA->D = sf_compress(PLA->D, compress);
+ PLA->R = sf_compress(PLA->R, compress);
+
+ symbolic_hack_labels(PLA, PLA->symbolic, compress,
+ new_size, cube.size, size_added);
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_vars = num_vars;
+ cube.num_binary_vars = num_binary_vars;
+ cube.part_size = new_part_size;
+ cube_setup();
+ set_free(compress);
+}
+
+
+pcover map_symbolic_cover(T, list, base)
+pcover T;
+symbolic_list_t *list;
+int base;
+{
+ pset last, p;
+ foreach_set(T, last, p) {
+ form_bitvector(p, base, 0, list);
+ }
+ return T;
+}
+
+
+form_bitvector(p, base, value, list)
+pset p; /* old cube, looking at binary variables */
+int base; /* where in mv cube the new variable starts */
+int value; /* current value for this recursion */
+symbolic_list_t *list; /* current place in the symbolic list */
+{
+ if (list == NIL(symbolic_list_t)) {
+ set_insert(p, base + value);
+ } else {
+ switch(GETINPUT(p, list->variable)) {
+ case ZERO:
+ form_bitvector(p, base, value*2, list->next);
+ break;
+ case ONE:
+ form_bitvector(p, base, value*2+1, list->next);
+ break;
+ case TWO:
+ form_bitvector(p, base, value*2, list->next);
+ form_bitvector(p, base, value*2+1, list->next);
+ break;
+ default:
+ fatal("bad cube in form_bitvector");
+ }
+ }
+}
+
+
+symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added)
+pPLA PLA;
+symbolic_t *list;
+pset compress;
+int new_size, old_size, size_added;
+{
+ int i, base;
+ char **oldlabel;
+ symbolic_t *p1;
+ symbolic_label_t *p3;
+
+ /* hack with the labels */
+ if ((oldlabel = PLA->label) == NIL(char *))
+ return;
+ PLA->label = ALLOC(char *, new_size);
+ for(i = 0; i < new_size; i++) {
+ PLA->label[i] = NIL(char);
+ }
+
+ /* copy the binary variable labels and unchanged mv variable labels */
+ base = 0;
+ for(i = 0; i < cube.first_part[cube.output]; i++) {
+ if (is_in_set(compress, i)) {
+ PLA->label[base++] = oldlabel[i];
+ } else {
+ if (oldlabel[i] != NIL(char)) {
+ FREE(oldlabel[i]);
+ }
+ }
+ }
+
+ /* add the user-defined labels for the symbolic outputs */
+ for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) {
+ p3 = p1->symbolic_label;
+ for(i = 0; i < (1 << p1->symbolic_list_length); i++) {
+ if (p3 == NIL(symbolic_label_t)) {
+ PLA->label[base+i] = ALLOC(char, 10);
+ (void) sprintf(PLA->label[base+i], "X%d", i);
+ } else {
+ PLA->label[base+i] = p3->label;
+ p3 = p3->next;
+ }
+ }
+ base += 1 << p1->symbolic_list_length;
+ }
+
+ /* copy the labels for the binary outputs which remain */
+ for(i = cube.first_part[cube.output]; i < old_size; i++) {
+ if (is_in_set(compress, i + size_added)) {
+ PLA->label[base++] = oldlabel[i];
+ } else {
+ if (oldlabel[i] != NIL(char)) {
+ FREE(oldlabel[i]);
+ }
+ }
+ }
+ FREE(oldlabel);
+}
+
+static pcover fsm_simplify(F)
+pcover F;
+{
+ pcover D, R;
+ D = new_cover(0);
+ R = complement(cube1list(F));
+ F = espresso(F, D, R);
+ free_cover(D);
+ free_cover(R);
+ return F;
+}
+
+
+disassemble_fsm(PLA, verbose_mode)
+pPLA PLA;
+int verbose_mode;
+{
+ int nin, nstates, nout;
+ int before, after, present_state, next_state, i, j;
+ pcube next_state_mask, present_state_mask, state_mask, p, p1, last;
+ pcover go_nowhere, F, tF;
+
+ /* We make the DISGUSTING assumption that the first 'n' outputs have
+ * been created by .symbolic-output, and represent a one-hot encoding
+ * of the next state. 'n' is the size of the second-to-last multiple-
+ * valued variable (i.e., before the outputs
+ */
+
+ if (cube.num_vars - cube.num_binary_vars != 2) {
+ (void) fprintf(stderr,
+ "use .symbolic and .symbolic-output to specify\n");
+ (void) fprintf(stderr,
+ "the present state and next state field information\n");
+ fatal("disassemble_pla: need two multiple-valued variables\n");
+ }
+
+ nin = cube.num_binary_vars;
+ nstates = cube.part_size[cube.num_binary_vars];
+ nout = cube.part_size[cube.num_vars - 1];
+ if (nout < nstates) {
+ (void) fprintf(stderr,
+ "use .symbolic and .symbolic-output to specify\n");
+ (void) fprintf(stderr,
+ "the present state and next state field information\n");
+ fatal("disassemble_pla: # outputs < # states\n");
+ }
+
+
+ present_state = cube.first_part[cube.num_binary_vars];
+ present_state_mask = new_cube();
+ for(i = 0; i < nstates; i++) {
+ set_insert(present_state_mask, i + present_state);
+ }
+
+ next_state = cube.first_part[cube.num_binary_vars+1];
+ next_state_mask = new_cube();
+ for(i = 0; i < nstates; i++) {
+ set_insert(next_state_mask, i + next_state);
+ }
+
+ state_mask = set_or(new_cube(), next_state_mask, present_state_mask);
+
+ F = new_cover(10);
+
+
+ /*
+ * check for arcs which go from ANY state to state #i
+ */
+ for(i = 0; i < nstates; i++) {
+ tF = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ if (setp_implies(present_state_mask, p)) { /* from any state ! */
+ if (is_in_set(p, next_state + i)) {
+ tF = sf_addset(tF, p);
+ }
+ }
+ }
+ before = tF->count;
+ if (before > 0) {
+ tF = fsm_simplify(tF);
+ /* don't allow the next state to disappear ... */
+ foreach_set(tF, last, p) {
+ set_insert(p, next_state + i);
+ }
+ after = tF->count;
+ F = sf_append(F, tF);
+ if (verbose_mode) {
+ printf("# state EVERY to %d, before=%d after=%d\n",
+ i, before, after);
+ }
+ }
+ }
+
+
+ /*
+ * some 'arcs' may NOT have a next state -- handle these
+ * we must unravel the present state part
+ */
+ go_nowhere = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ if (setp_disjoint(p, next_state_mask)) { /* no next state !! */
+ go_nowhere = sf_addset(go_nowhere, p);
+ }
+ }
+ before = go_nowhere->count;
+ go_nowhere = unravel_range(go_nowhere,
+ cube.num_binary_vars, cube.num_binary_vars);
+ after = go_nowhere->count;
+ F = sf_append(F, go_nowhere);
+ if (verbose_mode) {
+ printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after);
+ }
+
+
+ /*
+ * minimize cover for all arcs from state #i to state #j
+ */
+ for(i = 0; i < nstates; i++) {
+ for(j = 0; j < nstates; j++) {
+ tF = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ /* not EVERY state */
+ if (! setp_implies(present_state_mask, p)) {
+ if (is_in_set(p, present_state + i)) {
+ if (is_in_set(p, next_state + j)) {
+ p1 = set_save(p);
+ set_diff(p1, p1, state_mask);
+ set_insert(p1, present_state + i);
+ set_insert(p1, next_state + j);
+ tF = sf_addset(tF, p1);
+ set_free(p1);
+ }
+ }
+ }
+ }
+ before = tF->count;
+ if (before > 0) {
+ tF = fsm_simplify(tF);
+ /* don't allow the next state to disappear ... */
+ foreach_set(tF, last, p) {
+ set_insert(p, next_state + j);
+ }
+ after = tF->count;
+ F = sf_append(F, tF);
+ if (verbose_mode) {
+ printf("# state %d to %d, before=%d after=%d\n",
+ i, j, before, after);
+ }
+ }
+ }
+ }
+
+
+ free_cube(state_mask);
+ free_cube(present_state_mask);
+ free_cube(next_state_mask);
+
+ free_cover(PLA->F);
+ PLA->F = F;
+ free_cover(PLA->D);
+ PLA->D = new_cover(0);
+
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = nin;
+ cube.num_vars = nin + 3;
+ cube.part_size = ALLOC(int, cube.num_vars);
+ cube.part_size[cube.num_binary_vars] = nstates;
+ cube.part_size[cube.num_binary_vars+1] = nstates;
+ cube.part_size[cube.num_binary_vars+2] = nout - nstates;
+ cube_setup();
+
+ foreach_set(PLA->F, last, p) {
+ kiss_print_cube(stdout, PLA, p, "~1");
+ }
+}
diff --git a/src/misc/espresso/indep.c b/src/misc/espresso/indep.c
new file mode 100644
index 00000000..10b363a0
--- /dev/null
+++ b/src/misc/espresso/indep.c
@@ -0,0 +1,134 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+static sm_matrix *build_intersection_matrix();
+
+
+#if 0
+/*
+ * verify that all rows in 'indep' are actually independent !
+ */
+static int
+verify_indep_set(A, indep)
+sm_matrix *A;
+sm_row *indep;
+{
+ register sm_row *prow, *prow1;
+ register sm_element *p, *p1;
+
+ for(p = indep->first_col; p != 0; p = p->next_col) {
+ prow = sm_get_row(A, p->col_num);
+ for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) {
+ prow1 = sm_get_row(A, p1->col_num);
+ if (sm_row_intersects(prow, prow1)) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+solution_t *
+sm_maximal_independent_set(A, weight)
+sm_matrix *A;
+int *weight;
+{
+ register sm_row *best_row, *prow;
+ register sm_element *p;
+ int least_weight;
+ sm_row *save;
+ sm_matrix *B;
+ solution_t *indep;
+
+ indep = solution_alloc();
+ B = build_intersection_matrix(A);
+
+ while (B->nrows > 0) {
+ /* Find the row which is disjoint from a maximum number of rows */
+ best_row = B->first_row;
+ for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) {
+ if (prow->length < best_row->length) {
+ best_row = prow;
+ }
+ }
+
+ /* Find which element in this row has least weight */
+ if (weight == NIL(int)) {
+ least_weight = 1;
+ } else {
+ prow = sm_get_row(A, best_row->row_num);
+ least_weight = weight[prow->first_col->col_num];
+ for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ if (weight[p->col_num] < least_weight) {
+ least_weight = weight[p->col_num];
+ }
+ }
+ }
+ indep->cost += least_weight;
+ (void) sm_row_insert(indep->row, best_row->row_num);
+
+ /* Discard the rows which intersect this row */
+ save = sm_row_dup(best_row);
+ for(p = save->first_col; p != 0; p = p->next_col) {
+ sm_delrow(B, p->col_num);
+ sm_delcol(B, p->col_num);
+ }
+ sm_row_free(save);
+ }
+
+ sm_free(B);
+
+/*
+ if (! verify_indep_set(A, indep->row)) {
+ fail("sm_maximal_independent_set: row set is not independent");
+ }
+*/
+ return indep;
+}
+
+static sm_matrix *
+build_intersection_matrix(A)
+sm_matrix *A;
+{
+ register sm_row *prow, *prow1;
+ register sm_element *p, *p1;
+ register sm_col *pcol;
+ sm_matrix *B;
+
+ /* Build row-intersection matrix */
+ B = sm_alloc();
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+ /* Clear flags on all rows we can reach from row 'prow' */
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ prow1 = sm_get_row(A, p1->row_num);
+ prow1->flag = 0;
+ }
+ }
+
+ /* Now record which rows can be reached */
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ prow1 = sm_get_row(A, p1->row_num);
+ if (! prow1->flag) {
+ prow1->flag = 1;
+ (void) sm_insert(B, prow->row_num, prow1->row_num);
+ }
+ }
+ }
+ }
+
+ return B;
+}
diff --git a/src/misc/espresso/irred.c b/src/misc/espresso/irred.c
new file mode 100644
index 00000000..384e698f
--- /dev/null
+++ b/src/misc/espresso/irred.c
@@ -0,0 +1,440 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static void fcube_is_covered();
+static void ftautology();
+static bool ftaut_special_cases();
+
+
+static int Rp_current;
+
+/*
+ * irredundant -- Return a minimal subset of F
+ */
+
+pcover
+irredundant(F, D)
+pcover F, D;
+{
+ mark_irredundant(F, D);
+ return sf_inactive(F);
+}
+
+
+/*
+ * mark_irredundant -- find redundant cubes, and mark them "INACTIVE"
+ */
+
+void
+mark_irredundant(F, D)
+pcover F, D;
+{
+ pcover E, Rt, Rp;
+ pset p, p1, last;
+ sm_matrix *table;
+ sm_row *cover;
+ sm_element *pe;
+
+ /* extract a minimum cover */
+ irred_split_cover(F, D, &E, &Rt, &Rp);
+ table = irred_derive_table(D, E, Rp);
+ cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0);
+
+ /* mark the cubes for the result */
+ foreach_set(F, last, p) {
+ RESET(p, ACTIVE);
+ RESET(p, RELESSEN);
+ }
+ foreach_set(E, last, p) {
+ p1 = GETSET(F, SIZE(p));
+ assert(setp_equal(p1, p));
+ SET(p1, ACTIVE);
+ SET(p1, RELESSEN); /* for essen(), mark as rel. ess. */
+ }
+ sm_foreach_row_element(cover, pe) {
+ p1 = GETSET(F, pe->col_num);
+ SET(p1, ACTIVE);
+ }
+
+ if (debug & IRRED) {
+ printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n",
+ F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count,
+ cover->length, E->count + cover->length, 0);
+ }
+
+ free_cover(E);
+ free_cover(Rt);
+ free_cover(Rp);
+ sm_free(table);
+ sm_row_free(cover);
+}
+
+/*
+ * irred_split_cover -- find E, Rt, and Rp from the cover F, D
+ *
+ * E -- relatively essential cubes
+ * Rt -- totally redundant cubes
+ * Rp -- partially redundant cubes
+ */
+
+void
+irred_split_cover(F, D, E, Rt, Rp)
+pcover F, D;
+pcover *E, *Rt, *Rp;
+{
+ register pcube p, last;
+ register int index;
+ pcover R;
+ pcube *FD, *ED;
+
+ /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */
+ index = 0;
+ foreach_set(F, last, p) {
+ PUTSIZE(p, index);
+ index++;
+ }
+
+ *E = new_cover(10);
+ *Rt = new_cover(10);
+ *Rp = new_cover(10);
+ R = new_cover(10);
+
+ /* Split F into E and R */
+ FD = cube2list(F, D);
+ foreach_set(F, last, p) {
+ if (cube_is_covered(FD, p)) {
+ R = sf_addset(R, p);
+ } else {
+ *E = sf_addset(*E, p);
+ }
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n",
+ R->count, (*E)->count, F->count - (R->count + (*E)->count),
+ print_time(ptime()));
+ }
+ }
+ free_cubelist(FD);
+
+ /* Split R into Rt and Rp */
+ ED = cube2list(*E, D);
+ foreach_set(R, last, p) {
+ if (cube_is_covered(ED, p)) {
+ *Rt = sf_addset(*Rt, p);
+ } else {
+ *Rp = sf_addset(*Rp, p);
+ }
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n",
+ (*Rp)->count, (*Rt)->count,
+ R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime()));
+ }
+ }
+ free_cubelist(ED);
+
+ free_cover(R);
+}
+
+/*
+ * irred_derive_table -- given the covers D, E and the set of
+ * partially redundant primes Rp, build a covering table showing
+ * possible selections of primes to cover Rp.
+ */
+
+sm_matrix *
+irred_derive_table(D, E, Rp)
+pcover D, E, Rp;
+{
+ register pcube last, p, *list;
+ sm_matrix *table;
+ int size_last_dominance, i;
+
+ /* Mark each cube in DE as not part of the redundant set */
+ foreach_set(D, last, p) {
+ RESET(p, REDUND);
+ }
+ foreach_set(E, last, p) {
+ RESET(p, REDUND);
+ }
+
+ /* Mark each cube in Rp as partially redundant */
+ foreach_set(Rp, last, p) {
+ SET(p, REDUND); /* belongs to redundant set */
+ }
+
+ /* For each cube in Rp, find ways to cover its minterms */
+ list = cube3list(D, E, Rp);
+ table = sm_alloc();
+ size_last_dominance = 0;
+ i = 0;
+ foreach_set(Rp, last, p) {
+ Rp_current = SIZE(p);
+ fcube_is_covered(list, p, table);
+ RESET(p, REDUND); /* can now consider this cube redundant */
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n",
+ i, Rp->count, Rp->count - i,
+ table->nrows, table->ncols, print_time(ptime()));
+ }
+ /* try to keep memory limits down by reducing table as we go along */
+ if (table->nrows - size_last_dominance > 1000) {
+ (void) sm_row_dominance(table);
+ size_last_dominance = table->nrows;
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: delete redundant rows, now %dx%d\n",
+ table->nrows, table->ncols);
+ }
+ }
+ i++;
+ }
+ free_cubelist(list);
+
+ return table;
+}
+
+/* cube_is_covered -- determine if a cubelist "covers" a single cube */
+bool
+cube_is_covered(T, c)
+pcube *T, c;
+{
+ return tautology(cofactor(T,c));
+}
+
+
+
+/* tautology -- answer the tautology question for T */
+bool
+tautology(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best, result;
+ static int taut_level = 0;
+
+ if (debug & TAUT) {
+ debug_print(T, "TAUTOLOGY", taut_level++);
+ }
+
+ if ((result = taut_special_cases(T)) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, TAUT);
+ result = tautology(scofactor(T, cl, best)) &&
+ tautology(scofactor(T, cr, best));
+ free_cubelist(T);
+ free_cube(cl);
+ free_cube(cr);
+ }
+
+ if (debug & TAUT) {
+ printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result));
+ }
+ return result;
+}
+
+/*
+ * taut_special_cases -- check special cases for tautology
+ */
+
+bool
+taut_special_cases(T)
+pcube *T; /* will be disposed if answer is determined */
+{
+ register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1];
+ pcube *A, *B;
+ int var;
+
+ /* Check for a row of all 1's which implies tautology */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, T[0])) {
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which implies no tautology */
+start:
+ INLINEset_copy(ceil, T[0]);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ free_cubelist(T);
+ return FALSE;
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If function is unate (and no row of all 1's), then no tautology */
+ if (cdata.vars_unate == cdata.vars_active) {
+ free_cubelist(T);
+ return FALSE;
+
+ /* If active in a single variable (and no column of 0's) then tautology */
+ } else if (cdata.vars_active == 1) {
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate variables, and reduce cover if there are any */
+ } else if (cdata.vars_unate != 0) {
+ /* Form a cube "ceil" with full variables in the unate variables */
+ (void) set_copy(ceil, cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ }
+ }
+
+ /* Save only those cubes that are "full" in all unate variables */
+ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ *Tsave++ = p;
+ }
+ }
+ *Tsave++ = NULL;
+ T[1] = (pcube) Tsave;
+
+ if (debug & TAUT) {
+ printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ cdata.vars_unate, CUBELISTSIZE(T));
+ }
+ goto start;
+
+ /* Check for component reduction */
+ } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) {
+ if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) {
+ return MAYBE;
+ } else {
+ free_cubelist(T);
+ if (tautology(A)) {
+ free_cubelist(B);
+ return TRUE;
+ } else {
+ return tautology(B);
+ }
+ }
+ }
+
+ /* We tried as hard as we could, but must recurse from here on */
+ return MAYBE;
+}
+
+/* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */
+static void
+fcube_is_covered(T, c, table)
+pcube *T, c;
+sm_matrix *table;
+{
+ ftautology(cofactor(T,c), table);
+}
+
+
+/* ftautology -- find ways to make a tautology */
+static void
+ftautology(T, table)
+pcube *T; /* T will be disposed of */
+sm_matrix *table;
+{
+ register pcube cl, cr;
+ register int best;
+ static int ftaut_level = 0;
+
+ if (debug & TAUT) {
+ debug_print(T, "FIND_TAUTOLOGY", ftaut_level++);
+ }
+
+ if (ftaut_special_cases(T, table) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, TAUT);
+
+ ftautology(scofactor(T, cl, best), table);
+ ftautology(scofactor(T, cr, best), table);
+
+ free_cubelist(T);
+ free_cube(cl);
+ free_cube(cr);
+ }
+
+ if (debug & TAUT) {
+ (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n",
+ --ftaut_level, table->nrows, table->ncols);
+ }
+}
+
+static bool
+ftaut_special_cases(T, table)
+pcube *T; /* will be disposed if answer is determined */
+sm_matrix *table;
+{
+ register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1];
+ int var, rownum;
+
+ /* Check for a row of all 1's in the essential cubes */
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if (! TESTP(p, REDUND)) {
+ if (full_row(p, T[0])) {
+ /* subspace is covered by essentials -- no new rows for table */
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+start:
+ massive_count(T);
+
+ /* If function is unate, find the rows of all 1's */
+ if (cdata.vars_unate == cdata.vars_active) {
+ /* find which nonessentials cover this subspace */
+ rownum = table->last_row ? table->last_row->row_num+1 : 0;
+ (void) sm_insert(table, rownum, Rp_current);
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if (TESTP(p, REDUND)) {
+ /* See if a redundant cube covers this leaf */
+ if (full_row(p, T[0])) {
+ (void) sm_insert(table, rownum, (int) SIZE(p));
+ }
+ }
+ }
+ free_cubelist(T);
+ return TRUE;
+
+ /* Perform unate reduction if there are any unate variables */
+ } else if (cdata.vars_unate != 0) {
+ /* Form a cube "ceil" with full variables in the unate variables */
+ (void) set_copy(ceil, cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ }
+ }
+
+ /* Save only those cubes that are "full" in all unate variables */
+ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ *Tsave++ = p;
+ }
+ }
+ *Tsave++ = 0;
+ T[1] = (pcube) Tsave;
+
+ if (debug & TAUT) {
+ printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ cdata.vars_unate, CUBELISTSIZE(T));
+ }
+ goto start;
+ }
+
+ /* Not much we can do about it */
+ return MAYBE;
+}
diff --git a/src/misc/espresso/main.c b/src/misc/espresso/main.c
new file mode 100644
index 00000000..0a511c0e
--- /dev/null
+++ b/src/misc/espresso/main.c
@@ -0,0 +1,746 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * Main driver for espresso
+ *
+ * Old style -do xxx, -out xxx, etc. are still supported.
+ */
+
+#include "espresso.h"
+#include "main.h" /* table definitions for options */
+
+static FILE *last_fp;
+static int input_type = FD_type;
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int i, j, first, last, strategy, out_type, option;
+ pPLA PLA, PLA1;
+ pcover F, Fold, Dold;
+ pset last1, p;
+ cost_t cost;
+ bool error, exact_cover;
+ long start;
+ extern char *util_optarg;
+ extern int util_optind;
+
+ start = ptime();
+
+ error = FALSE;
+ init_runtime();
+#ifdef RANDOM
+ srandom(314973);
+#endif
+
+ option = 0; /* default -D: ESPRESSO */
+ out_type = F_type; /* default -o: default is ON-set only */
+ debug = 0; /* default -d: no debugging info */
+ verbose_debug = FALSE; /* default -v: not verbose */
+ print_solution = TRUE; /* default -x: print the solution (!) */
+ summary = FALSE; /* default -s: no summary */
+ trace = FALSE; /* default -t: no trace information */
+ strategy = 0; /* default -S: strategy number */
+ first = -1; /* default -R: select range */
+ last = -1;
+ remove_essential = TRUE; /* default -e: */
+ force_irredundant = TRUE;
+ unwrap_onset = TRUE;
+ single_expand = FALSE;
+ pos = FALSE;
+ recompute_onset = FALSE;
+ use_super_gasp = FALSE;
+ use_random_order = FALSE;
+ kiss = FALSE;
+ echo_comments = TRUE;
+ echo_unknown_commands = TRUE;
+ exact_cover = FALSE; /* for -qm option, the default */
+
+ backward_compatibility_hack(&argc, argv, &option, &out_type);
+
+
+ /* parse command line options*/
+ while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) {
+ switch(i) {
+ case 'D': /* -Dcommand invokes a subcommand */
+ for(j = 0; option_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, option_table[j].name) == 0) {
+ option = j;
+ break;
+ }
+ }
+ if (option_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'o': /* -ooutput selects and output option */
+ for(j = 0; pla_types[j].key != 0; j++) {
+ if (strcmp(util_optarg, pla_types[j].key+1) == 0) {
+ out_type = pla_types[j].value;
+ break;
+ }
+ }
+ if (pla_types[j].key == 0) {
+ (void) fprintf(stderr, "%s: bad output type \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'e': /* -eespresso selects an option for espresso */
+ for(j = 0; esp_opt_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, esp_opt_table[j].name) == 0) {
+ *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ break;
+ }
+ }
+ if (esp_opt_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'd': /* -d turns on (softly) all debug switches */
+ debug = debug_table[0].value;
+ trace = TRUE;
+ summary = TRUE;
+ break;
+
+ case 'v': /* -vdebug invokes a debug option */
+ verbose_debug = TRUE;
+ for(j = 0; debug_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, debug_table[j].name) == 0) {
+ debug |= debug_table[j].value;
+ break;
+ }
+ }
+ if (debug_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad debug type \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 't':
+ trace = TRUE;
+ break;
+
+ case 's':
+ summary = TRUE;
+ break;
+
+ case 'x': /* -x suppress printing of results */
+ print_solution = FALSE;
+ break;
+
+ case 'S': /* -S sets a strategy for several cmds */
+ strategy = atoi(util_optarg);
+ break;
+
+ case 'r': /* -r selects range (outputs or vars) */
+ if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) {
+ (void) fprintf(stderr, "%s: bad output range \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ /* provide version information and summaries */
+ if (summary || trace) {
+ /* echo command line and arguments */
+ printf("#");
+ for(i = 0; i < argc; i++) {
+ printf(" %s", argv[i]);
+ }
+ printf("\n");
+ printf("# %s\n", VERSION);
+ }
+
+ /* the remaining arguments are argv[util_optind ... argc-1] */
+ PLA = PLA1 = NIL(PLA_t);
+ switch(option_table[option].num_plas) {
+ case 2:
+ if (util_optind+2 < argc) fatal("trailing arguments on command line");
+ getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+ getPLA(util_optind++, argc, argv, option, &PLA1, out_type);
+ break;
+ case 1:
+ if (util_optind+1 < argc) fatal("trailing arguments on command line");
+ getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+ break;
+ }
+ if (util_optind < argc) fatal("trailing arguments on command line");
+
+ if (summary || trace) {
+ if (PLA != NIL(PLA_t)) PLA_summary(PLA);
+ if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1);
+ }
+
+/*
+ * Now a case-statement to decide what to do
+ */
+
+ switch(option_table[option].key) {
+
+
+/******************** Espresso operations ********************/
+
+ case KEY_ESPRESSO:
+ Fold = sf_save(PLA->F);
+ PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ print_solution = FALSE;
+ PLA->F = Fold;
+ (void) check_consistency(PLA);
+ } else {
+ free_cover(Fold);
+ }
+ break;
+
+ case KEY_MANY_ESPRESSO: {
+ int pla_type;
+ do {
+ EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
+ if (print_solution) {
+ fprint_pla(stdout, PLA, out_type);
+ (void) fflush(stdout);
+ }
+ pla_type = PLA->pla_type;
+ free_PLA(PLA);
+ setdown_cube();
+ FREE(cube.part_size);
+ } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF);
+ exit(0);
+ }
+
+ case KEY_simplify:
+ EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F);
+ break;
+
+ case KEY_so: /* minimize all functions as single-output */
+ if (strategy < 0 || strategy > 1) {
+ strategy = 0;
+ }
+ so_espresso(PLA, strategy);
+ break;
+
+ case KEY_so_both: /* minimize all functions as single-output */
+ if (strategy < 0 || strategy > 1) {
+ strategy = 0;
+ }
+ so_both_espresso(PLA, strategy);
+ break;
+
+ case KEY_expand: /* execute expand */
+ EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost);
+ break;
+
+ case KEY_irred: /* extract minimal irredundant subset */
+ EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost);
+ break;
+
+ case KEY_reduce: /* perform reduction */
+ EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost);
+ break;
+
+ case KEY_essen: /* check for essential primes */
+ foreach_set(PLA->F, last1, p) {
+ SET(p, RELESSEN);
+ RESET(p, NONESSEN);
+ }
+ EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost);
+ free_cover(F);
+ break;
+
+ case KEY_super_gasp:
+ PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ break;
+
+ case KEY_gasp:
+ PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ break;
+
+ case KEY_make_sparse: /* make_sparse step of Espresso */
+ PLA->F = make_sparse(PLA->F, PLA->D, PLA->R);
+ break;
+
+ case KEY_exact:
+ exact_cover = TRUE;
+
+ case KEY_qm:
+ Fold = sf_save(PLA->F);
+ PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover);
+ EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ print_solution = FALSE;
+ PLA->F = Fold;
+ (void) check_consistency(PLA);
+ }
+ free_cover(Fold);
+ break;
+
+ case KEY_primes: /* generate all prime implicants */
+ EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)),
+ "PRIMES ", PLA->F);
+ break;
+
+ case KEY_map: /* print out a Karnaugh map of function */
+ map(PLA->F);
+ print_solution = FALSE;
+ break;
+
+
+
+/******************** Output phase and bit pairing ********************/
+
+ case KEY_opo: /* sasao output phase assignment */
+ phase_assignment(PLA, strategy);
+ break;
+
+ case KEY_opoall: /* try all phase assignments (!) */
+ if (first < 0 || first >= cube.part_size[cube.output]) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.part_size[cube.output]) {
+ last = cube.part_size[cube.output] - 1;
+ }
+ opoall(PLA, first, last, strategy);
+ break;
+
+ case KEY_pair: /* find an optimal pairing */
+ find_optimal_pairing(PLA, strategy);
+ break;
+
+ case KEY_pairall: /* try all pairings !! */
+ pair_all(PLA, strategy);
+ break;
+
+
+
+/******************** Simple cover operations ********************/
+
+ case KEY_echo: /* echo the PLA */
+ break;
+
+ case KEY_taut: /* tautology check */
+ printf("ON-set is%sa tautology\n",
+ tautology(cube1list(PLA->F)) ? " " : " not ");
+ print_solution = FALSE;
+ break;
+
+ case KEY_contain: /* single cube containment */
+ PLA->F = sf_contain(PLA->F);
+ break;
+
+ case KEY_intersect: /* cover intersection */
+ PLA->F = cv_intersect(PLA->F, PLA1->F);
+ break;
+
+ case KEY_union: /* cover union */
+ PLA->F = sf_union(PLA->F, PLA1->F);
+ break;
+
+ case KEY_disjoint: /* make cover disjoint */
+ PLA->F = make_disjoint(PLA->F);
+ break;
+
+ case KEY_dsharp: /* cover disjoint-sharp */
+ PLA->F = cv_dsharp(PLA->F, PLA1->F);
+ break;
+
+ case KEY_sharp: /* cover sharp */
+ PLA->F = cv_sharp(PLA->F, PLA1->F);
+ break;
+
+ case KEY_lexsort: /* lexical sort order */
+ PLA->F = lex_sort(PLA->F);
+ break;
+
+ case KEY_stats: /* print info on size */
+ if (! summary) PLA_summary(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_minterms: /* explode into minterms */
+ if (first < 0 || first >= cube.num_vars) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.num_vars) {
+ last = cube.num_vars - 1;
+ }
+ PLA->F = sf_dupl(unravel_range(PLA->F, first, last));
+ break;
+
+ case KEY_d1merge: /* distance-1 merge */
+ if (first < 0 || first >= cube.num_vars) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.num_vars) {
+ last = cube.num_vars - 1;
+ }
+ for(i = first; i <= last; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ }
+ break;
+
+ case KEY_d1merge_in: /* distance-1 merge inputs only */
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ }
+ break;
+
+ case KEY_PLA_verify: /* check two PLAs for equivalence */
+ EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ printf("PLA comparison failed; the PLA's are not equivalent\n");
+ exit(1);
+ } else {
+ printf("PLA's compared equal\n");
+ exit(0);
+ }
+ break; /* silly */
+
+ case KEY_verify: /* check two covers for equivalence */
+ Fold = PLA->F; Dold = PLA->D; F = PLA1->F;
+ EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ printf("PLA comparison failed; the PLA's are not equivalent\n");
+ exit(1);
+ } else {
+ printf("PLA's compared equal\n");
+ exit(0);
+ }
+ break; /* silly */
+
+ case KEY_check: /* check consistency */
+ (void) check_consistency(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_mapdc: /* compute don't care set */
+ map_dcset(PLA);
+ out_type = FD_type;
+ break;
+
+ case KEY_equiv:
+ find_equiv_outputs(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_separate: /* remove PLA->D from PLA->F */
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ break;
+
+ case KEY_xor: {
+ pcover T1 = cv_intersect(PLA->F, PLA1->R);
+ pcover T2 = cv_intersect(PLA1->F, PLA->R);
+ free_cover(PLA->F);
+ PLA->F = sf_contain(sf_join(T1, T2));
+ free_cover(T1);
+ free_cover(T2);
+ break;
+ }
+
+ case KEY_fsm: {
+ disassemble_fsm(PLA, summary);
+ print_solution = FALSE;
+ break;
+ }
+
+ case KEY_test: {
+ pcover T, E;
+ T = sf_join(PLA->D, PLA->R);
+ E = new_cover(10);
+ sf_free(PLA->F);
+ EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost);
+ EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost);
+ EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost);
+ sf_free(T);
+ T = sf_join(PLA->F, PLA->R);
+ EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost);
+ EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost);
+ sf_free(T);
+ sf_free(E);
+ break;
+ }
+
+
+ }
+
+ /* Print a runtime summary if trace mode enabled */
+ if (trace) {
+ runtime();
+ }
+
+ /* Print total runtime */
+ if (summary || trace) {
+ print_trace(PLA->F, option_table[option].name, ptime()-start);
+ }
+
+ /* Output the solution */
+ if (print_solution) {
+ EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost);
+ }
+
+ /* Crash and burn if there was a verify error */
+ if (error) {
+ fatal("cover verification failed");
+ }
+
+ /* cleanup all used memory */
+ free_PLA(PLA);
+ FREE(cube.part_size);
+ setdown_cube(); /* free the cube/cdata structure data */
+ sf_cleanup(); /* free unused set structures */
+ sm_cleanup(); /* sparse matrix cleanup */
+
+ exit(0);
+}
+
+
+getPLA(opt, argc, argv, option, PLA, out_type)
+int opt;
+int argc;
+char *argv[];
+int option;
+pPLA *PLA;
+int out_type;
+{
+ FILE *fp;
+ int needs_dcset, needs_offset;
+ char *fname;
+
+ if (opt >= argc) {
+ fp = stdin;
+ fname = "(stdin)";
+ } else {
+ fname = argv[opt];
+ if (strcmp(fname, "-") == 0) {
+ fp = stdin;
+ } else if ((fp = fopen(argv[opt], "r")) == NULL) {
+ (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname);
+ exit(1);
+ }
+ }
+ if (option_table[option].key == KEY_echo) {
+ needs_dcset = (out_type & D_type) != 0;
+ needs_offset = (out_type & R_type) != 0;
+ } else {
+ needs_dcset = option_table[option].needs_dcset;
+ needs_offset = option_table[option].needs_offset;
+ }
+
+ if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) {
+ (void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname);
+ exit(1);
+ }
+ (*PLA)->filename = util_strsav(fname);
+ filename = (*PLA)->filename;
+/* (void) fclose(fp);*/
+/* hackto support -Dmany */
+ last_fp = fp;
+}
+
+
+runtime()
+{
+ int i;
+ long total = 1, temp;
+
+ for(i = 0; i < TIME_COUNT; i++) {
+ total += total_time[i];
+ }
+ for(i = 0; i < TIME_COUNT; i++) {
+ if (total_calls[i] != 0) {
+ temp = 100 * total_time[i];
+ printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
+ total_name[i], total_calls[i], print_time(total_time[i]),
+ temp/total, (10 * (temp%total)) / total);
+ }
+ }
+}
+
+
+init_runtime()
+{
+ total_name[READ_TIME] = "READ ";
+ total_name[WRITE_TIME] = "WRITE ";
+ total_name[COMPL_TIME] = "COMPL ";
+ total_name[REDUCE_TIME] = "REDUCE ";
+ total_name[EXPAND_TIME] = "EXPAND ";
+ total_name[ESSEN_TIME] = "ESSEN ";
+ total_name[IRRED_TIME] = "IRRED ";
+ total_name[GREDUCE_TIME] = "REDUCE_GASP";
+ total_name[GEXPAND_TIME] = "EXPAND_GASP";
+ total_name[GIRRED_TIME] = "IRRED_GASP ";
+ total_name[MV_REDUCE_TIME] ="MV_REDUCE ";
+ total_name[RAISE_IN_TIME] = "RAISE_IN ";
+ total_name[VERIFY_TIME] = "VERIFY ";
+ total_name[PRIMES_TIME] = "PRIMES ";
+ total_name[MINCOV_TIME] = "MINCOV ";
+}
+
+
+subcommands()
+{
+ int i, col;
+ printf(" ");
+ col = 16;
+ for(i = 0; option_table[i].name != 0; i++) {
+ if ((col + strlen(option_table[i].name) + 1) > 76) {
+ printf(",\n ");
+ col = 16;
+ } else if (i != 0) {
+ printf(", ");
+ }
+ printf("%s", option_table[i].name);
+ col += strlen(option_table[i].name) + 2;
+ }
+ printf("\n");
+}
+
+
+usage()
+{
+ printf("%s\n\n", VERSION);
+ printf("SYNOPSIS: espresso [options] [file]\n\n");
+ printf(" -d Enable debugging\n");
+ printf(" -e[opt] Select espresso option:\n");
+ printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n");
+ printf(" eat, eatdots, kiss, random\n");
+ printf(" -o[type] Select output format:\n");
+ printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n");
+ printf(" -rn-m Select range for subcommands:\n");
+ printf(" d1merge: first and last variables (0 ... m-1)\n");
+ printf(" minterms: first and last variables (0 ... m-1)\n");
+ printf(" opoall: first and last outputs (0 ... m-1)\n");
+ printf(" -s Provide short execution summary\n");
+ printf(" -t Provide longer execution trace\n");
+ printf(" -x Suppress printing of solution\n");
+ printf(" -v[type] Verbose debugging detail (-v '' for all)\n");
+ printf(" -D[cmd] Execute subcommand 'cmd':\n");
+ subcommands();
+ printf(" -Sn Select strategy for subcommands:\n");
+ printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n");
+ printf(" opoall: 0=minimize, 1=exact\n");
+ printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n");
+ printf(" pairall: 0=minimize, 1=exact, 2=opo\n");
+ printf(" so_espresso: 0=minimize, 1=exact\n");
+ printf(" so_both: 0=minimize, 1=exact\n");
+}
+
+/*
+ * Hack for backward compatibility (ACK! )
+ */
+
+backward_compatibility_hack(argc, argv, option, out_type)
+int *argc;
+char **argv;
+int *option;
+int *out_type;
+{
+ int i, j;
+
+ /* Scan the argument list for something to do (default is ESPRESSO) */
+ *option = 0;
+ for(i = 1; i < (*argc)-1; i++) {
+ if (strcmp(argv[i], "-do") == 0) {
+ for(j = 0; option_table[j].name != 0; j++)
+ if (strcmp(argv[i+1], option_table[j].name) == 0) {
+ *option = j;
+ delete_arg(argc, argv, i+1);
+ delete_arg(argc, argv, i);
+ break;
+ }
+ if (option_table[j].name == 0) {
+ (void) fprintf(stderr,
+ "espresso: bad keyword \"%s\" following -do\n",argv[i+1]);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ for(i = 1; i < (*argc)-1; i++) {
+ if (strcmp(argv[i], "-out") == 0) {
+ for(j = 0; pla_types[j].key != 0; j++)
+ if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) {
+ *out_type = pla_types[j].value;
+ delete_arg(argc, argv, i+1);
+ delete_arg(argc, argv, i);
+ break;
+ }
+ if (pla_types[j].key == 0) {
+ (void) fprintf(stderr,
+ "espresso: bad keyword \"%s\" following -out\n",argv[i+1]);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ for(i = 1; i < (*argc); i++) {
+ if (argv[i][0] == '-') {
+ for(j = 0; esp_opt_table[j].name != 0; j++) {
+ if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) {
+ delete_arg(argc, argv, i);
+ *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ break;
+ }
+ }
+ }
+ }
+
+ if (check_arg(argc, argv, "-fdr")) input_type = FDR_type;
+ if (check_arg(argc, argv, "-fr")) input_type = FR_type;
+ if (check_arg(argc, argv, "-f")) input_type = F_type;
+}
+
+
+/* delete_arg -- delete an argument from the argument list */
+delete_arg(argc, argv, num)
+int *argc, num;
+register char *argv[];
+{
+ register int i;
+ (*argc)--;
+ for(i = num; i < *argc; i++) {
+ argv[i] = argv[i+1];
+ }
+}
+
+
+/* check_arg -- scan argv for an argument, and return TRUE if found */
+bool check_arg(argc, argv, s)
+int *argc;
+register char *argv[], *s;
+{
+ register int i;
+ for(i = 1; i < *argc; i++) {
+ if (strcmp(argv[i], s) == 0) {
+ delete_arg(argc, argv, i);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/src/misc/espresso/main.h b/src/misc/espresso/main.h
new file mode 100644
index 00000000..00657f39
--- /dev/null
+++ b/src/misc/espresso/main.h
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+enum keys {
+ KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge,
+ KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand,
+ KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse,
+ KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall,
+ KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp,
+ KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut,
+ KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO,
+ KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm,
+ KEY_unknown
+};
+
+/* Lookup table for program options */
+struct {
+ char *name;
+ enum keys key;
+ int num_plas;
+ bool needs_offset;
+ bool needs_dcset;
+} option_table [] = {
+ /* ways to minimize functions */
+ "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE, /* must be first */
+ "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE,
+ "exact", KEY_exact, 1, TRUE, TRUE,
+ "qm", KEY_qm, 1, TRUE, TRUE,
+ "single_output", KEY_so, 1, TRUE, TRUE,
+ "so", KEY_so, 1, TRUE, TRUE,
+ "so_both", KEY_so_both, 1, TRUE, TRUE,
+ "simplify", KEY_simplify, 1, FALSE, FALSE,
+ "echo", KEY_echo, 1, FALSE, FALSE,
+
+ /* output phase assignment and assignment of inputs to two-bit decoders */
+ "opo", KEY_opo, 1, TRUE, TRUE,
+ "opoall", KEY_opoall, 1, TRUE, TRUE,
+ "pair", KEY_pair, 1, TRUE, TRUE,
+ "pairall", KEY_pairall, 1, TRUE, TRUE,
+
+ /* Ways to check covers */
+ "check", KEY_check, 1, TRUE, TRUE,
+ "stats", KEY_stats, 1, FALSE, FALSE,
+ "verify", KEY_verify, 2, FALSE, TRUE,
+ "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE,
+
+ /* hacks */
+ "equiv", KEY_equiv, 1, TRUE, TRUE,
+ "map", KEY_map, 1, FALSE, FALSE,
+ "mapdc", KEY_mapdc, 1, FALSE, FALSE,
+ "fsm", KEY_fsm, 1, FALSE, TRUE,
+
+ /* the basic boolean operations on covers */
+ "contain", KEY_contain, 1, FALSE, FALSE,
+ "d1merge", KEY_d1merge, 1, FALSE, FALSE,
+ "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE,
+ "disjoint", KEY_disjoint, 1, TRUE, FALSE,
+ "dsharp", KEY_dsharp, 2, FALSE, FALSE,
+ "intersect", KEY_intersect, 2, FALSE, FALSE,
+ "minterms", KEY_minterms, 1, FALSE, FALSE,
+ "primes", KEY_primes, 1, FALSE, TRUE,
+ "separate", KEY_separate, 1, TRUE, TRUE,
+ "sharp", KEY_sharp, 2, FALSE, FALSE,
+ "union", KEY_union, 2, FALSE, FALSE,
+ "xor", KEY_xor, 2, TRUE, TRUE,
+
+ /* debugging only -- call each step of the espresso algorithm */
+ "essen", KEY_essen, 1, FALSE, TRUE,
+ "expand", KEY_expand, 1, TRUE, FALSE,
+ "gasp", KEY_gasp, 1, TRUE, TRUE,
+ "irred", KEY_irred, 1, FALSE, TRUE,
+ "make_sparse", KEY_make_sparse, 1, TRUE, TRUE,
+ "reduce", KEY_reduce, 1, FALSE, TRUE,
+ "taut", KEY_taut, 1, FALSE, FALSE,
+ "super_gasp", KEY_super_gasp, 1, TRUE, TRUE,
+ "lexsort", KEY_lexsort, 1, FALSE, FALSE,
+ "test", KEY_test, 1, TRUE, TRUE,
+ 0, KEY_unknown, 0, FALSE, FALSE /* must be last */
+};
+
+
+struct {
+ char *name;
+ int value;
+} debug_table[] = {
+ "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV,
+ "compl", COMPL, "essen", ESSEN,
+ "expand", EXPAND, "expand1", EXPAND1|EXPAND,
+ "irred", IRRED, "irred1", IRRED1|IRRED,
+ "reduce", REDUCE, "reduce1", REDUCE1|REDUCE,
+ "mincov", MINCOV, "mincov1", MINCOV1|MINCOV,
+ "sparse", SPARSE, "sharp", SHARP,
+ "taut", TAUT, "gasp", GASP,
+ "exact", EXACT,
+ 0,
+};
+
+
+struct {
+ char *name;
+ int *variable;
+ int value;
+} esp_opt_table[] = {
+ "eat", &echo_comments, FALSE,
+ "eatdots", &echo_unknown_commands, FALSE,
+ "fast", &single_expand, TRUE,
+ "kiss", &kiss, TRUE,
+ "ness", &remove_essential, FALSE,
+ "nirr", &force_irredundant, FALSE,
+ "nunwrap", &unwrap_onset, FALSE,
+ "onset", &recompute_onset, TRUE,
+ "pos", &pos, TRUE,
+ "random", &use_random_order, TRUE,
+ "strong", &use_super_gasp, TRUE,
+ 0,
+};
diff --git a/src/misc/espresso/map.c b/src/misc/espresso/map.c
new file mode 100644
index 00000000..5ccf264c
--- /dev/null
+++ b/src/misc/espresso/map.c
@@ -0,0 +1,115 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static pcube Gcube;
+static pset Gminterm;
+
+pset minterms(T)
+pcover T;
+{
+ int size, var;
+ register pcube last;
+
+ size = 1;
+ for(var = 0; var < cube.num_vars; var++)
+ size *= cube.part_size[var];
+ Gminterm = set_new(size);
+
+ foreach_set(T, last, Gcube)
+ explode(cube.num_vars-1, 0);
+
+ return Gminterm;
+}
+
+
+void explode(var, z)
+int var, z;
+{
+ int i, last = cube.last_part[var];
+ for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++)
+ if (is_in_set(Gcube, i))
+ if (var == 0)
+ set_insert(Gminterm, z);
+ else
+ explode(var-1, z);
+}
+
+
+static int mapindex[16][16] = {
+ 0, 1, 3, 2, 16, 17, 19, 18, 80, 81, 83, 82, 64, 65, 67, 66,
+ 4, 5, 7, 6, 20, 21, 23, 22, 84, 85, 87, 86, 68, 69, 71, 70,
+ 12, 13, 15, 14, 28, 29, 31, 30, 92, 93, 95, 94, 76, 77, 79, 78,
+ 8, 9, 11, 10, 24, 25, 27, 26, 88, 89, 91, 90, 72, 73, 75, 74,
+
+ 32, 33, 35, 34, 48, 49, 51, 50, 112,113,115,114, 96, 97, 99, 98,
+ 36, 37, 39, 38, 52, 53, 55, 54, 116,117,119,118, 100,101,103,102,
+ 44, 45, 47, 46, 60, 61, 63, 62, 124,125,127,126, 108,109,111,110,
+ 40, 41, 43, 42, 56, 57, 59, 58, 120,121,123,122, 104,105,107,106,
+
+
+ 160,161,163,162, 176,177,179,178, 240,241,243,242, 224,225,227,226,
+ 164,165,167,166, 180,181,183,182, 244,245,247,246, 228,229,231,230,
+ 172,173,175,174, 188,189,191,190, 252,253,255,254, 236,237,239,238,
+ 168,169,171,170, 184,185,187,186, 248,249,251,250, 232,233,235,234,
+
+ 128,129,131,130, 144,145,147,146, 208,209,211,210, 192,193,195,194,
+ 132,133,135,134, 148,149,151,150, 212,213,215,214, 196,197,199,198,
+ 140,141,143,142, 156,157,159,158, 220,221,223,222, 204,205,207,206,
+ 136,137,139,138, 152,153,155,154, 216,217,219,218, 200,201,203,202
+};
+
+#define POWER2(n) (1 << n)
+void map(T)
+pcover T;
+{
+ int j, k, l, other_input_offset, output_offset, outnum, ind;
+ int largest_input_ind, numout;
+ char c;
+ pset m;
+ bool some_output;
+
+ m = minterms(T);
+ largest_input_ind = POWER2(cube.num_binary_vars);
+ numout = cube.part_size[cube.num_vars-1];
+
+ for(outnum = 0; outnum < numout; outnum++) {
+ output_offset = outnum * largest_input_ind;
+ printf("\n\nOutput space # %d\n", outnum);
+ for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) {
+ other_input_offset = l * 256;
+ for(k = 0; k < 16; k++) {
+ some_output = FALSE;
+ for(j = 0; j < 16; j++) {
+ ind = mapindex[k][j] + other_input_offset;
+ if (ind < largest_input_ind) {
+ c = is_in_set(m, ind+output_offset) ? '1' : '.';
+ putchar(c);
+ some_output = TRUE;
+ }
+ if ((j+1)%4 == 0)
+ putchar(' ');
+ if ((j+1)%8 == 0)
+ printf(" ");
+ }
+ if (some_output)
+ putchar('\n');
+ if ((k+1)%4 == 0) {
+ if (k != 15 && mapindex[k+1][0] >= largest_input_ind)
+ break;
+ putchar('\n');
+ }
+ if ((k+1)%8 == 0)
+ putchar('\n');
+ }
+ }
+ }
+ set_free(m);
+}
diff --git a/src/misc/espresso/matrix.c b/src/misc/espresso/matrix.c
new file mode 100644
index 00000000..747fe54f
--- /dev/null
+++ b/src/misc/espresso/matrix.c
@@ -0,0 +1,574 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.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_alloc()
+{
+ 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(row, col)
+int row, col;
+{
+ register sm_matrix *A;
+
+ A = sm_alloc();
+ sm_resize(A, row, col);
+ return A;
+}
+
+
+void
+sm_free(A)
+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(A)
+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(A, row, col)
+register sm_matrix *A;
+int row, 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(A, row, col)
+register sm_matrix *A;
+register int row, 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(A, rownum, colnum)
+sm_matrix *A;
+int rownum, 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(A, rownum, colnum)
+sm_matrix *A;
+int rownum, colnum;
+{
+ sm_remove_element(A, sm_find(A, rownum, colnum));
+}
+
+
+
+void
+sm_remove_element(A, p)
+register sm_matrix *A;
+register 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(A, i)
+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(A, i)
+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(dest, dest_row, prow)
+register 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(dest, dest_col, pcol)
+register 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(A)
+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(A)
+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(A)
+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(fp, A)
+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(fp, A)
+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(fp, A)
+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(fp, A)
+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(A, s, max)
+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()
+{
+#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
+}
diff --git a/src/misc/espresso/mincov.c b/src/misc/espresso/mincov.c
new file mode 100644
index 00000000..ee18a3f1
--- /dev/null
+++ b/src/misc/espresso/mincov.c
@@ -0,0 +1,378 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+/*
+ * mincov.c
+ */
+
+#define USE_GIMPEL
+#define USE_INDEP_SET
+
+static int select_column();
+static void select_essential();
+static int verify_cover();
+
+#define fail(why) {\
+ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+ __FILE__, __LINE__, why);\
+ (void) fflush(stdout);\
+ abort();\
+}
+
+sm_row *
+sm_minimum_cover(A, weight, heuristic, debug_level)
+sm_matrix *A;
+int *weight;
+int heuristic; /* set to 1 for a heuristic covering */
+int debug_level; /* how deep in the recursion to provide info */
+{
+ stats_t stats;
+ solution_t *best, *select;
+ sm_row *prow, *sol;
+ sm_col *pcol;
+ sm_matrix *dup_A;
+ int nelem, bound;
+ double sparsity;
+
+ /* Avoid sillyness */
+ if (A->nrows <= 0) {
+ return sm_row_alloc(); /* easy to cover */
+ }
+
+ /* Initialize debugging structure */
+ stats.start_time = util_cpu_time();
+ stats.debug = debug_level > 0;
+ stats.max_print_depth = debug_level;
+ stats.max_depth = -1;
+ stats.nodes = 0;
+ stats.component = stats.comp_count = 0;
+ stats.gimpel = stats.gimpel_count = 0;
+ stats.no_branching = heuristic != 0;
+ stats.lower_bound = -1;
+
+ /* Check the matrix sparsity */
+ nelem = 0;
+ sm_foreach_row(A, prow) {
+ nelem += prow->length;
+ }
+ sparsity = (double) nelem / (double) (A->nrows * A->ncols);
+
+ /* Determine an upper bound on the solution */
+ bound = 1;
+ sm_foreach_col(A, pcol) {
+ bound += WEIGHT(weight, pcol->col_num);
+ }
+
+ /* Perform the covering */
+ select = solution_alloc();
+ dup_A = sm_dup(A);
+ best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats);
+ sm_free(dup_A);
+ solution_free(select);
+
+ if (stats.debug) {
+ if (stats.no_branching) {
+ (void) printf("**** heuristic covering ...\n");
+ (void) printf("lower bound = %d\n", stats.lower_bound);
+ }
+ (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n",
+ A->nrows, A->ncols, nelem, sparsity * 100.0);
+ (void) printf("cover size = %d elements\n", best->row->length);
+ (void) printf("cover cost = %d\n", best->cost);
+ (void) printf("time = %s\n",
+ util_print_time(util_cpu_time() - stats.start_time));
+ (void) printf("components = %d\n", stats.comp_count);
+ (void) printf("gimpel = %d\n", stats.gimpel_count);
+ (void) printf("nodes = %d\n", stats.nodes);
+ (void) printf("max_depth = %d\n", stats.max_depth);
+ }
+
+ sol = sm_row_dup(best->row);
+ if (! verify_cover(A, sol)) {
+ fail("mincov: internal error -- cover verification failed\n");
+ }
+ solution_free(best);
+ return sol;
+}
+
+/*
+ * Find the best cover for 'A' (given that 'select' already selected);
+ *
+ * - abort search if a solution cannot be found which beats 'bound'
+ *
+ * - if any solution meets 'lower_bound', then it is the optimum solution
+ * and can be returned without further work.
+ */
+
+solution_t *
+sm_mincov(A, select, weight, lb, bound, depth, stats)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+{
+ sm_matrix *A1, *A2, *L, *R;
+ sm_element *p;
+ solution_t *select1, *select2, *best, *best1, *best2, *indep;
+ int pick, lb_new, debug;
+
+ /* Start out with some debugging information */
+ stats->nodes++;
+ if (depth > stats->max_depth) stats->max_depth = depth;
+ debug = stats->debug && (depth <= stats->max_print_depth);
+
+ /* Apply row dominance, column dominance, and select essentials */
+ select_essential(A, select, weight, bound);
+ if (select->cost >= bound) {
+ return NIL(solution_t);
+ }
+
+ /* See if gimpel's reduction technique applies ... */
+#ifdef USE_GIMPEL
+ if ( weight == NIL(int)) { /* hack until we fix it */
+ if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) {
+ return best;
+ }
+ }
+#endif
+
+#ifdef USE_INDEP_SET
+ /* Determine bound from here to final solution using independent-set */
+ indep = sm_maximal_independent_set(A, weight);
+
+ /* make sure the lower bound is monotonically increasing */
+ lb_new = MAX(select->cost + indep->cost, lb);
+ pick = select_column(A, weight, indep);
+ solution_free(indep);
+#else
+ lb_new = select->cost + (A->nrows > 0);
+ pick = select_column(A, weight, NIL(solution_t));
+#endif
+
+ if (depth == 0) {
+ stats->lower_bound = lb_new + stats->gimpel;
+ }
+
+ if (debug) {
+ (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " ");
+ (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ",
+ A->nrows, A->ncols, select->cost + stats->gimpel,
+ bound + stats->gimpel, lb_new + stats->gimpel,
+ util_print_time(util_cpu_time()-stats->start_time));
+ }
+
+ /* Check for bounding based on no better solution possible */
+ if (lb_new >= bound) {
+ if (debug) (void) printf("bounded\n");
+ best = NIL(solution_t);
+
+
+ /* Check for new best solution */
+ } else if (A->nrows == 0) {
+ best = solution_dup(select);
+ if (debug) (void) printf("BEST\n");
+ if (stats->debug && stats->component == 0) {
+ (void) printf("new 'best' solution %d at level %d (time is %s)\n",
+ best->cost + stats->gimpel, depth,
+ util_print_time(util_cpu_time() - stats->start_time));
+ }
+
+
+ /* Check for a partition of the problem */
+ } else if (sm_block_partition(A, &L, &R)) {
+ /* Make L the smaller problem */
+ if (L->ncols > R->ncols) {
+ A1 = L;
+ L = R;
+ R = A1;
+ }
+ if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows);
+ stats->comp_count++;
+
+ /* Solve problem for L */
+ select1 = solution_alloc();
+ stats->component++;
+ best1 = sm_mincov(L, select1, weight, 0,
+ bound-select->cost, depth+1, stats);
+ stats->component--;
+ solution_free(select1);
+ sm_free(L);
+
+ /* Add best solution to the selected set */
+ if (best1 == NIL(solution_t)) {
+ best = NIL(solution_t);
+ } else {
+ for(p = best1->row->first_col; p != 0; p = p->next_col) {
+ solution_add(select, weight, p->col_num);
+ }
+ solution_free(best1);
+
+ /* recur for the remaining block */
+ best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats);
+ }
+ sm_free(R);
+
+ /* We've tried as hard as possible, but now we must split and recur */
+ } else {
+ if (debug) (void) printf("pick=%d\n", pick);
+
+ /* Assume we choose this column to be in the covering set */
+ A1 = sm_dup(A);
+ select1 = solution_dup(select);
+ solution_accept(select1, A1, weight, pick);
+ best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats);
+ solution_free(select1);
+ sm_free(A1);
+
+ /* Update the upper bound if we found a better solution */
+ if (best1 != NIL(solution_t) && bound > best1->cost) {
+ bound = best1->cost;
+ }
+
+ /* See if this is a heuristic covering (no branching) */
+ if (stats->no_branching) {
+ return best1;
+ }
+
+ /* Check for reaching lower bound -- if so, don't actually branch */
+ if (best1 != NIL(solution_t) && best1->cost == lb_new) {
+ return best1;
+ }
+
+ /* Now assume we cannot have that column */
+ A2 = sm_dup(A);
+ select2 = solution_dup(select);
+ solution_reject(select2, A2, weight, pick);
+ best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats);
+ solution_free(select2);
+ sm_free(A2);
+
+ best = solution_choose_best(best1, best2);
+ }
+
+ return best;
+}
+
+static int
+select_column(A, weight, indep)
+sm_matrix *A;
+int *weight;
+solution_t *indep;
+{
+ register sm_col *pcol;
+ register sm_row *prow, *indep_cols;
+ register sm_element *p, *p1;
+ double w, best;
+ int best_col;
+
+ indep_cols = sm_row_alloc();
+ if (indep != NIL(solution_t)) {
+ /* Find which columns are in the independent sets */
+ for(p = indep->row->first_col; p != 0; p = p->next_col) {
+ prow = sm_get_row(A, p->col_num);
+ for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) {
+ (void) sm_row_insert(indep_cols, p1->col_num);
+ }
+ }
+ } else {
+ /* select out of all columns */
+ sm_foreach_col(A, pcol) {
+ (void) sm_row_insert(indep_cols, pcol->col_num);
+ }
+ }
+
+ /* Find the best column */
+ best_col = -1;
+ best = -1;
+
+ /* Consider only columns which are in some independent row */
+ sm_foreach_row_element(indep_cols, p1) {
+ pcol = sm_get_col(A, p1->col_num);
+
+ /* Compute the total 'value' of all things covered by the column */
+ w = 0.0;
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ w += 1.0 / ((double) prow->length - 1.0);
+ }
+
+ /* divide this by the relative cost of choosing this column */
+ w = w / (double) WEIGHT(weight, pcol->col_num);
+
+ /* maximize this ratio */
+ if (w > best) {
+ best_col = pcol->col_num;
+ best = w;
+ }
+ }
+
+ sm_row_free(indep_cols);
+ return best_col;
+}
+
+static void
+select_essential(A, select, weight, bound)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int bound; /* must beat this solution */
+{
+ register sm_element *p;
+ register sm_row *prow, *essen;
+ int delcols, delrows, essen_count;
+
+ do {
+ /* Check for dominated columns */
+ delcols = sm_col_dominance(A, weight);
+
+ /* Find the rows with only 1 element (the essentials) */
+ essen = sm_row_alloc();
+ sm_foreach_row(A, prow) {
+ if (prow->length == 1) {
+ (void) sm_row_insert(essen, prow->first_col->col_num);
+ }
+ }
+
+ /* Select all of the elements */
+ sm_foreach_row_element(essen, p) {
+ solution_accept(select, A, weight, p->col_num);
+ /* Make sure solution still looks good */
+ if (select->cost >= bound) {
+ sm_row_free(essen);
+ return;
+ }
+ }
+ essen_count = essen->length;
+ sm_row_free(essen);
+
+ /* Check for dominated rows */
+ delrows = sm_row_dominance(A);
+
+ } while (delcols > 0 || delrows > 0 || essen_count > 0);
+}
+
+static int
+verify_cover(A, cover)
+sm_matrix *A;
+sm_row *cover;
+{
+ sm_row *prow;
+
+ sm_foreach_row(A, prow) {
+ if (! sm_row_intersects(prow, cover)) {
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/src/misc/espresso/mincov.h b/src/misc/espresso/mincov.h
new file mode 100644
index 00000000..95310774
--- /dev/null
+++ b/src/misc/espresso/mincov.h
@@ -0,0 +1,11 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/* exported */
+extern sm_row *sm_minimum_cover();
diff --git a/src/misc/espresso/mincov_int.h b/src/misc/espresso/mincov_int.h
new file mode 100644
index 00000000..e81850f2
--- /dev/null
+++ b/src/misc/espresso/mincov_int.h
@@ -0,0 +1,55 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+
+typedef struct stats_struct stats_t;
+struct stats_struct {
+ int debug; /* 1 if debugging is enabled */
+ int max_print_depth; /* dump stats for levels up to this level */
+ int max_depth; /* deepest the recursion has gone */
+ int nodes; /* total nodes visited */
+ int component; /* currently solving a component */
+ int comp_count; /* number of components detected */
+ int gimpel_count; /* number of times Gimpel reduction applied */
+ int gimpel; /* currently inside Gimpel reduction */
+ long start_time; /* cpu time when the covering started */
+ int no_branching;
+ int lower_bound;
+};
+
+
+
+typedef struct solution_struct solution_t;
+struct solution_struct {
+ sm_row *row;
+ int cost;
+};
+
+
+extern solution_t *solution_alloc();
+extern void solution_free();
+extern solution_t *solution_dup();
+extern void solution_accept();
+extern void solution_reject();
+extern void solution_add();
+extern solution_t *solution_choose_best();
+
+extern solution_t *sm_maximal_independent_set();
+extern solution_t *sm_mincov();
+extern int gimpel_reduce();
+
+
+#define WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col])
diff --git a/src/misc/espresso/module.make b/src/misc/espresso/module.make
new file mode 100644
index 00000000..53ce982a
--- /dev/null
+++ b/src/misc/espresso/module.make
@@ -0,0 +1,39 @@
+SRC += src/misc/espresso/cofactor.c \
+ src/misc/espresso/cols.c \
+ src/misc/espresso/compl.c \
+ src/misc/espresso/contain.c \
+ src/misc/espresso/cubehack.c \
+ src/misc/espresso/cubestr.c \
+ src/misc/espresso/cvrin.c \
+ src/misc/espresso/cvrm.c \
+ src/misc/espresso/cvrmisc.c \
+ src/misc/espresso/cvrout.c \
+ src/misc/espresso/dominate.c \
+ src/misc/espresso/equiv.c \
+ src/misc/espresso/espresso.c \
+ src/misc/espresso/essen.c \
+ src/misc/espresso/exact.c \
+ src/misc/espresso/expand.c \
+ src/misc/espresso/gasp.c \
+ src/misc/espresso/gimpel.c \
+ src/misc/espresso/globals.c \
+ src/misc/espresso/hack.c \
+ src/misc/espresso/indep.c \
+ src/misc/espresso/irred.c \
+ src/misc/espresso/map.c \
+ src/misc/espresso/matrix.c \
+ src/misc/espresso/mincov.c \
+ src/misc/espresso/opo.c \
+ src/misc/espresso/pair.c \
+ src/misc/espresso/part.c \
+ src/misc/espresso/primes.c \
+ src/misc/espresso/reduce.c \
+ src/misc/espresso/rows.c \
+ src/misc/espresso/set.c \
+ src/misc/espresso/setc.c \
+ src/misc/espresso/sharp.c \
+ src/misc/espresso/sminterf.c \
+ src/misc/espresso/solution.c \
+ src/misc/espresso/sparse.c \
+ src/misc/espresso/unate.c \
+ src/misc/espresso/verify.c
diff --git a/src/misc/espresso/opo.c b/src/misc/espresso/opo.c
new file mode 100644
index 00000000..8daa0771
--- /dev/null
+++ b/src/misc/espresso/opo.c
@@ -0,0 +1,624 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ * Phase assignment technique (T. Sasao):
+ *
+ * 1. create a function with 2*m outputs which implements the
+ * original function and its complement for each output
+ *
+ * 2. minimize this function
+ *
+ * 3. choose the minimum number of prime implicants from the
+ * result of step 2 which are needed to realize either a function
+ * or its complement for each output
+ *
+ * Step 3 is performed in a rather crude way -- by simply multiplying
+ * out a large expression of the form:
+ *
+ * I = (ab + cdef)(acd + bgh) ...
+ *
+ * which is a product of m expressions where each expression has two
+ * product terms -- one representing which primes are needed for the
+ * function, and one representing which primes are needed for the
+ * complement. The largest product term resulting shows which primes
+ * to keep to implement one function or the other for each output.
+ * For problems with many outputs, this may grind to a
+ * halt.
+ *
+ * Untried: form complement of I and use unate_complement ...
+ *
+ * I have unsuccessfully tried several modifications to the basic
+ * algorithm. The first is quite simple: use Sasao's technique, but
+ * only commit to a single output at a time (rather than all
+ * outputs). The goal would be that the later minimizations can "take
+ * into account" the partial assignment at each step. This is
+ * expensive (m+1 minimizations rather than 2), and the results are
+ * discouraging.
+ *
+ * The second modification is rather complicated. The result from the
+ * minimization in step 2 is guaranteed to be minimal. Hence, for
+ * each output, the set of primes with a 1 in that output are both
+ * necessary and sufficient to implement the function. Espresso
+ * achieves the minimality using the routine MAKE_SPARSE. The
+ * modification is to prevent MAKE_SPARSE from running. Hence, there
+ * are potentially many subsets of the set of primes with a 1 in a
+ * column which can be used to implement that output. We use
+ * IRREDUNDANT to enumerate all possible subsets and then proceed as
+ * before.
+ */
+
+static int opo_no_make_sparse;
+static int opo_repeated;
+static int opo_exact;
+static void minimize();
+
+void phase_assignment(PLA, opo_strategy)
+pPLA PLA;
+int opo_strategy;
+{
+ opo_no_make_sparse = opo_strategy % 2;
+ skip_make_sparse = opo_no_make_sparse;
+ opo_repeated = (opo_strategy / 2) % 2;
+ opo_exact = (opo_strategy / 4) % 2;
+
+ /* Determine a phase assignment */
+ if (PLA->phase != NULL) {
+ FREE(PLA->phase);
+ }
+
+ if (opo_repeated) {
+ PLA->phase = set_save(cube.fullset);
+ repeated_phase_assignment(PLA);
+ } else {
+ PLA->phase = find_phase(PLA, 0, (pcube) NULL);
+ }
+
+ /* Now minimize with this assignment */
+ skip_make_sparse = FALSE;
+ (void) set_phase(PLA);
+ minimize(PLA);
+}
+
+/*
+ * repeated_phase_assignment -- an alternate strategy which commits
+ * to a single phase assignment a step at a time. Performs m + 1
+ * minimizations !
+ */
+void repeated_phase_assignment(PLA)
+pPLA PLA;
+{
+ int i;
+ pcube phase;
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+ /* Find best assignment for all undecided outputs */
+ phase = find_phase(PLA, i, PLA->phase);
+
+ /* Commit for only a single output ... */
+ if (! is_in_set(phase, cube.first_part[cube.output] + i)) {
+ set_remove(PLA->phase, cube.first_part[cube.output] + i);
+ }
+
+ if (trace || summary) {
+ printf("\nOPO loop for output #%d\n", i);
+ printf("PLA->phase is %s\n", pc1(PLA->phase));
+ printf("phase is %s\n", pc1(phase));
+ }
+ set_free(phase);
+ }
+}
+
+
+/*
+ * find_phase -- find a phase assignment for the PLA for all outputs starting
+ * with output number first_output.
+ */
+pcube find_phase(PLA, first_output, phase1)
+pPLA PLA;
+int first_output;
+pcube phase1;
+{
+ pcube phase;
+ pPLA PLA1;
+
+ phase = set_save(cube.fullset);
+
+ /* setup the double-phase characteristic function, resize the cube */
+ PLA1 = new_PLA();
+ PLA1->F = sf_save(PLA->F);
+ PLA1->R = sf_save(PLA->R);
+ PLA1->D = sf_save(PLA->D);
+ if (phase1 != NULL) {
+ PLA1->phase = set_save(phase1);
+ (void) set_phase(PLA1);
+ }
+ EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F);
+
+ /* minimize the double-phase function */
+ minimize(PLA1);
+
+ /* set the proper phases according to what gives a minimum solution */
+ EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output),
+ "OPO ", PLA1->F);
+ free_PLA(PLA1);
+
+ /* set the cube structure to reflect the old size */
+ setdown_cube();
+ cube.part_size[cube.output] -=
+ (cube.part_size[cube.output] - first_output) / 2;
+ cube_setup();
+
+ return phase;
+}
+
+/*
+ * opo -- multiply the expression out to determine a minimum subset of
+ * primes.
+ */
+
+/*ARGSUSED*/
+pcover opo(phase, T, D, R, first_output)
+pcube phase;
+pcover T, D, R;
+int first_output;
+{
+ int offset, output, i, last_output, ind;
+ pset pdest, select, p, p1, last, last1, not_covered, tmp;
+ pset_family temp, T1, T2;
+
+ /* must select all primes for outputs [0 .. first_output-1] */
+ select = set_full(T->count);
+ for(output = 0; output < first_output; output++) {
+ ind = cube.first_part[cube.output] + output;
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, ind)) {
+ set_remove(select, i);
+ }
+ }
+ }
+
+ /* Recursively perform the intersections */
+ offset = (cube.part_size[cube.output] - first_output) / 2;
+ last_output = first_output + offset - 1;
+ temp = opo_recur(T, D, select, offset, first_output, last_output);
+
+ /* largest set is on top -- select primes which are inferred from it */
+ pdest = temp->data;
+ T1 = new_cover(T->count);
+ foreachi_set(T, i, p) {
+ if (! is_in_set(pdest, i)) {
+ T1 = sf_addset(T1, p);
+ }
+ }
+
+ set_free(select);
+ sf_free(temp);
+
+ /* finding phases is difficult -- see which functions are not covered */
+ T2 = complement(cube1list(T1));
+ not_covered = new_cube();
+ tmp = new_cube();
+ foreach_set(T, last, p) {
+ foreach_set(T2, last1, p1) {
+ if (cdist0(p, p1)) {
+ (void) set_or(not_covered, not_covered, set_and(tmp, p, p1));
+ }
+ }
+ }
+ free_cover(T);
+ free_cover(T2);
+ set_free(tmp);
+
+ /* Now reflect the phase choice in a single cube */
+ for(output = first_output; output <= last_output; output++) {
+ ind = cube.first_part[cube.output] + output;
+ if (is_in_set(not_covered, ind)) {
+ if (is_in_set(not_covered, ind + offset)) {
+ fatal("error in output phase assignment");
+ } else {
+ set_remove(phase, ind);
+ }
+ }
+ }
+ set_free(not_covered);
+ return T1;
+}
+
+pset_family opo_recur(T, D, select, offset, first, last)
+pcover T, D;
+pcube select;
+int offset, first, last;
+{
+ static int level = 0;
+ int middle;
+ pset_family sl, sr, temp;
+
+ level++;
+ if (first == last) {
+#if 0
+ if (opo_no_make_sparse) {
+ temp = form_cover_table(T, D, select, first, first + offset);
+ } else {
+ temp = opo_leaf(T, select, first, first + offset);
+ }
+#else
+ temp = opo_leaf(T, select, first, first + offset);
+#endif
+ } else {
+ middle = (first + last) / 2;
+ sl = opo_recur(T, D, select, offset, first, middle);
+ sr = opo_recur(T, D, select, offset, middle+1, last);
+ temp = unate_intersect(sl, sr, level == 1);
+ if (trace) {
+ printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1,
+ temp->count, sl->count, sr->count, print_time(ptime()));
+ (void) fflush(stdout);
+ }
+ free_cover(sl);
+ free_cover(sr);
+ }
+ level--;
+ return temp;
+}
+
+
+pset_family opo_leaf(T, select, out1, out2)
+register pcover T;
+pset select;
+int out1, out2;
+{
+ register pset_family temp;
+ register pset p, pdest;
+ register int i;
+
+ out1 += cube.first_part[cube.output];
+ out2 += cube.first_part[cube.output];
+
+ /* Allocate space for the result */
+ temp = sf_new(2, T->count);
+
+ /* Find which primes are needed for the ON-set of this fct */
+ pdest = GETSET(temp, temp->count++);
+ (void) set_copy(pdest, select);
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, out1)) {
+ set_remove(pdest, i);
+ }
+ }
+
+ /* Find which primes are needed for the OFF-set of this fct */
+ pdest = GETSET(temp, temp->count++);
+ (void) set_copy(pdest, select);
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, out2)) {
+ set_remove(pdest, i);
+ }
+ }
+
+ return temp;
+}
+
+#if 0
+pset_family form_cover_table(F, D, select, f, fbar)
+pcover F, D;
+pset select;
+int f, fbar; /* indices of f and fbar in the output part */
+{
+ register int i;
+ register pcube p;
+ pset_family f_table, fbar_table;
+
+ /* setup required for fcube_is_covered */
+ Rp_size = F->count;
+ Rp_start = set_new(Rp_size);
+ foreachi_set(F, i, p) {
+ PUTSIZE(p, i);
+ }
+ foreachi_set(D, i, p) {
+ RESET(p, REDUND);
+ }
+
+ f_table = find_covers(F, D, select, f);
+ fbar_table = find_covers(F, D, select, fbar);
+ f_table = sf_append(f_table, fbar_table);
+
+ set_free(Rp_start);
+ return f_table;
+}
+
+
+pset_family find_covers(F, D, select, n)
+pcover F, D;
+register pset select;
+int n;
+{
+ register pset p, last, new;
+ pcover F1;
+ pcube *Flist;
+ pset_family f_table, table;
+ int i;
+
+ n += cube.first_part[cube.output];
+
+ /* save cubes in this output, and remove the output variable */
+ F1 = new_cover(F->count);
+ foreach_set(F, last, p)
+ if (is_in_set(p, n)) {
+ new = GETSET(F1, F1->count++);
+ set_or(new, p, cube.var_mask[cube.output]);
+ PUTSIZE(new, SIZE(p));
+ SET(new, REDUND);
+ }
+
+ /* Find ways (sop form) to fail to cover output indexed by n */
+ Flist = cube2list(F1, D);
+ table = sf_new(10, Rp_size);
+ foreach_set(F1, last, p) {
+ set_fill(Rp_start, Rp_size);
+ set_remove(Rp_start, SIZE(p));
+ table = sf_append(table, fcube_is_covered(Flist, p));
+ RESET(p, REDUND);
+ }
+ set_fill(Rp_start, Rp_size);
+ foreach_set(table, last, p) {
+ set_diff(p, Rp_start, p);
+ }
+
+ /* complement this to get possible ways to cover the function */
+ for(i = 0; i < Rp_size; i++) {
+ if (! is_in_set(select, i)) {
+ p = set_new(Rp_size);
+ set_insert(p, i);
+ table = sf_addset(table, p);
+ set_free(p);
+ }
+ }
+ f_table = unate_compl(table);
+
+ /* what a pain, but we need bitwise complement of this */
+ set_fill(Rp_start, Rp_size);
+ foreach_set(f_table, last, p) {
+ set_diff(p, Rp_start, p);
+ }
+
+ free_cubelist(Flist);
+ sf_free(F1);
+ return f_table;
+}
+#endif
+
+/*
+ * Take a PLA (ON-set, OFF-set and DC-set) and create the
+ * "double-phase characteristic function" which is merely a new
+ * function which has twice as many outputs and realizes both the
+ * function and the complement.
+ *
+ * The cube structure is assumed to represent the PLA upon entering.
+ * It will be modified to represent the double-phase function upon
+ * exit.
+ *
+ * Only the outputs numbered starting with "first_output" are
+ * duplicated in the output part
+ */
+
+output_phase_setup(PLA, first_output)
+INOUT pPLA PLA;
+int first_output;
+{
+ pcover F, R, D;
+ pcube mask, mask1, last;
+ int first_part, offset;
+ bool save;
+ register pcube p, pr, pf;
+ register int i, last_part;
+
+ if (cube.output == -1)
+ fatal("output_phase_setup: must have an output");
+
+ F = PLA->F;
+ D = PLA->D;
+ R = PLA->R;
+ first_part = cube.first_part[cube.output] + first_output;
+ last_part = cube.last_part[cube.output];
+ offset = cube.part_size[cube.output] - first_output;
+
+ /* Change the output size, setup the cube structure */
+ setdown_cube();
+ cube.part_size[cube.output] += offset;
+ cube_setup();
+
+ /* Create a mask to select that part of the cube which isn't changing */
+ mask = set_save(cube.fullset);
+ for(i = first_part; i < cube.size; i++)
+ set_remove(mask, i);
+ mask1 = set_save(mask);
+ for(i = cube.first_part[cube.output]; i < first_part; i++) {
+ set_remove(mask1, i);
+ }
+
+ PLA->F = new_cover(F->count + R->count);
+ PLA->R = new_cover(F->count + R->count);
+ PLA->D = new_cover(D->count);
+
+ foreach_set(F, last, p) {
+ pf = GETSET(PLA->F, (PLA->F)->count++);
+ pr = GETSET(PLA->R, (PLA->R)->count++);
+ INLINEset_and(pf, mask, p);
+ INLINEset_and(pr, mask1, p);
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ set_insert(pf, i);
+ save = FALSE;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ save = TRUE, set_insert(pr, i+offset);
+ if (! save) PLA->R->count--;
+ }
+
+ foreach_set(R, last, p) {
+ pf = GETSET(PLA->F, (PLA->F)->count++);
+ pr = GETSET(PLA->R, (PLA->R)->count++);
+ INLINEset_and(pf, mask1, p);
+ INLINEset_and(pr, mask, p);
+ save = FALSE;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ save = TRUE, set_insert(pf, i+offset);
+ if (! save) PLA->F->count--;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ set_insert(pr, i);
+ }
+
+ foreach_set(D, last, p) {
+ pf = GETSET(PLA->D, (PLA->D)->count++);
+ INLINEset_and(pf, mask, p);
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i)) {
+ set_insert(pf, i);
+ set_insert(pf, i+offset);
+ }
+ }
+
+ free_cover(F);
+ free_cover(D);
+ free_cover(R);
+ set_free(mask);
+ set_free(mask1);
+}
+
+/*
+ * set_phase -- given a "cube" which describes which phases of the output
+ * are to be implemented, compute the appropriate on-set and off-set
+ */
+pPLA set_phase(PLA)
+INOUT pPLA PLA;
+{
+ pcover F1, R1;
+ register pcube last, p, outmask;
+ register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1];
+
+ outmask = cube.var_mask[cube.num_vars - 1];
+ set_diff(phase1, outmask, phase);
+ set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1);
+ F1 = new_cover((PLA->F)->count + (PLA->R)->count);
+ R1 = new_cover((PLA->F)->count + (PLA->R)->count);
+
+ foreach_set(PLA->F, last, p) {
+ if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ set_copy(GETSET(F1, F1->count++), temp);
+ if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ set_copy(GETSET(R1, R1->count++), temp);
+ }
+ foreach_set(PLA->R, last, p) {
+ if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ set_copy(GETSET(R1, R1->count++), temp);
+ if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ set_copy(GETSET(F1, F1->count++), temp);
+ }
+ free_cover(PLA->F);
+ free_cover(PLA->R);
+ PLA->F = F1;
+ PLA->R = R1;
+ return PLA;
+}
+
+#define POW2(x) (1 << (x))
+
+void opoall(PLA, first_output, last_output, opo_strategy)
+pPLA PLA;
+int first_output, last_output;
+int opo_strategy;
+{
+ pcover F, D, R, best_F, best_D, best_R;
+ int i, j, ind, num;
+ pcube bestphase;
+
+ opo_exact = opo_strategy;
+
+ if (PLA->phase != NULL) {
+ set_free(PLA->phase);
+ }
+
+ bestphase = set_save(cube.fullset);
+ best_F = sf_save(PLA->F);
+ best_D = sf_save(PLA->D);
+ best_R = sf_save(PLA->R);
+
+ for(i = 0; i < POW2(last_output - first_output + 1); i++) {
+
+ /* save the initial PLA covers */
+ F = sf_save(PLA->F);
+ D = sf_save(PLA->D);
+ R = sf_save(PLA->R);
+
+ /* compute the phase cube for this iteration */
+ PLA->phase = set_save(cube.fullset);
+ num = i;
+ for(j = last_output; j >= first_output; j--) {
+ if (num % 2 == 0) {
+ ind = cube.first_part[cube.output] + j;
+ set_remove(PLA->phase, ind);
+ }
+ num /= 2;
+ }
+
+ /* set the phase and minimize */
+ (void) set_phase(PLA);
+ printf("# phase is %s\n", pc1(PLA->phase));
+ summary = TRUE;
+ minimize(PLA);
+
+ /* see if this is the best so far */
+ if (PLA->F->count < best_F->count) {
+ /* save new best solution */
+ set_copy(bestphase, PLA->phase);
+ sf_free(best_F);
+ sf_free(best_D);
+ sf_free(best_R);
+ best_F = PLA->F;
+ best_D = PLA->D;
+ best_R = PLA->R;
+ } else {
+ /* throw away the solution */
+ free_cover(PLA->F);
+ free_cover(PLA->D);
+ free_cover(PLA->R);
+ }
+ set_free(PLA->phase);
+
+ /* restore the initial PLA covers */
+ PLA->F = F;
+ PLA->D = D;
+ PLA->R = R;
+ }
+
+ /* one more minimization to restore the best answer */
+ PLA->phase = bestphase;
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = best_F;
+ PLA->D = best_D;
+ PLA->R = best_R;
+}
+
+static void minimize(PLA)
+pPLA PLA;
+{
+ if (opo_exact) {
+ EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F);
+ } else {
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F);
+ }
+}
diff --git a/src/misc/espresso/pair.c b/src/misc/espresso/pair.c
new file mode 100644
index 00000000..a8077176
--- /dev/null
+++ b/src/misc/espresso/pair.c
@@ -0,0 +1,675 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+void set_pair(PLA)
+pPLA PLA;
+{
+ set_pair1(PLA, TRUE);
+}
+
+void set_pair1(PLA, adjust_labels)
+pPLA PLA;
+bool adjust_labels;
+{
+ int i, var, *paired, newvar;
+ int old_num_vars, old_num_binary_vars, old_size, old_mv_start;
+ int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start;
+ ppair pair = PLA->pair;
+ char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar;
+
+ if (adjust_labels)
+ makeup_labels(PLA);
+
+ /* Check the pair structure for valid entries and see which binary
+ variables are left unpaired
+ */
+ paired = ALLOC(bool, cube.num_binary_vars);
+ for(var = 0; var < cube.num_binary_vars; var++)
+ paired[var] = FALSE;
+ for(i = 0; i < pair->cnt; i++)
+ if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) &&
+ (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) {
+ paired[pair->var1[i]-1] = TRUE;
+ paired[pair->var2[i]-1] = TRUE;
+ } else
+ fatal("can only pair binary-valued variables");
+
+ PLA->F = delvar(pairvar(PLA->F, pair), paired);
+ PLA->R = delvar(pairvar(PLA->R, pair), paired);
+ PLA->D = delvar(pairvar(PLA->D, pair), paired);
+
+ /* Now painfully adjust the cube size */
+ old_size = cube.size;
+ old_num_vars = cube.num_vars;
+ old_num_binary_vars = cube.num_binary_vars;
+ old_mv_start = cube.first_part[cube.num_binary_vars];
+ /* Create the new cube.part_size vector and setup the cube structure */
+ new_num_binary_vars = 0;
+ for(var = 0; var < old_num_binary_vars; var++)
+ new_num_binary_vars += (paired[var] == FALSE);
+ new_num_vars = new_num_binary_vars + pair->cnt;
+ new_num_vars += old_num_vars - old_num_binary_vars;
+ new_part_size = ALLOC(int, new_num_vars);
+ for(var = 0; var < pair->cnt; var++)
+ new_part_size[new_num_binary_vars + var] = 4;
+ for(var = 0; var < old_num_vars - old_num_binary_vars; var++)
+ new_part_size[new_num_binary_vars + pair->cnt + var] =
+ cube.part_size[old_num_binary_vars + var];
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_vars = new_num_vars;
+ cube.num_binary_vars = new_num_binary_vars;
+ cube.part_size = new_part_size;
+ cube_setup();
+
+ /* hack with the labels to get them correct */
+ if (adjust_labels) {
+ oldlabel = PLA->label;
+ PLA->label = ALLOC(char *, cube.size);
+ for(var = 0; var < pair->cnt; var++) {
+ newvar = cube.num_binary_vars*2 + var*4;
+ var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1];
+ var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1];
+ var1bar = oldlabel[ (pair->var1[var]-1) * 2];
+ var2bar = oldlabel[ (pair->var2[var]-1) * 2];
+ (void) sprintf(scratch, "%s+%s", var1bar, var2bar);
+ PLA->label[newvar] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1bar, var2);
+ PLA->label[newvar+1] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1, var2bar);
+ PLA->label[newvar+2] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1, var2);
+ PLA->label[newvar+3] = util_strsav(scratch);
+ }
+ /* Copy the old labels for the unpaired binary vars */
+ i = 0;
+ for(var = 0; var < old_num_binary_vars; var++) {
+ if (paired[var] == FALSE) {
+ PLA->label[2*i] = oldlabel[2*var];
+ PLA->label[2*i+1] = oldlabel[2*var+1];
+ oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL;
+ i++;
+ }
+ }
+ /* Copy the old labels for the remaining unpaired vars */
+ new_mv_start = cube.num_binary_vars*2 + pair->cnt*4;
+ for(i = old_mv_start; i < old_size; i++) {
+ PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i];
+ oldlabel[i] = (char *) NULL;
+ }
+ /* free remaining entries in oldlabel */
+ for(i = 0; i < old_size; i++)
+ if (oldlabel[i] != (char *) NULL)
+ FREE(oldlabel[i]);
+ FREE(oldlabel);
+ }
+
+ /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/
+ for(var = 0; var < pair->cnt; var++)
+ cube.sparse[cube.num_binary_vars + var] = 0;
+ FREE(paired);
+}
+
+pcover pairvar(A, pair)
+pcover A;
+ppair pair;
+{
+ register pcube last, p;
+ register int val, p1, p2, b1, b0;
+ int insert_col, pairnum;
+
+ insert_col = cube.first_part[cube.num_vars - 1];
+
+ /* stretch the cover matrix to make room for the paired variables */
+ A = sf_delcol(A, insert_col, -4*pair->cnt);
+
+ /* compute the paired values */
+ foreach_set(A, last, p) {
+ for(pairnum = 0; pairnum < pair->cnt; pairnum++) {
+ p1 = cube.first_part[pair->var1[pairnum] - 1];
+ p2 = cube.first_part[pair->var2[pairnum] - 1];
+ b1 = is_in_set(p, p2+1);
+ b0 = is_in_set(p, p2);
+ val = insert_col + pairnum * 4;
+ if (/* a0 */ is_in_set(p, p1)) {
+ if (b0)
+ set_insert(p, val + 3);
+ if (b1)
+ set_insert(p, val + 2);
+ }
+ if (/* a1 */ is_in_set(p, p1+1)) {
+ if (b0)
+ set_insert(p, val + 1);
+ if (b1)
+ set_insert(p, val);
+ }
+ }
+ }
+ return A;
+}
+
+
+/* delvar -- delete variables from A, minimize the number of column shifts */
+pcover delvar(A, paired)
+pcover A;
+bool paired[];
+{
+ bool run;
+ int first_run, run_length, var, offset = 0;
+
+ run = FALSE; run_length = 0;
+ for(var = 0; var < cube.num_binary_vars; var++)
+ if (paired[var])
+ if (run)
+ run_length += cube.part_size[var];
+ else {
+ run = TRUE;
+ first_run = cube.first_part[var];
+ run_length = cube.part_size[var];
+ }
+ else
+ if (run) {
+ A = sf_delcol(A, first_run-offset, run_length);
+ run = FALSE;
+ offset += run_length;
+ }
+ if (run)
+ A = sf_delcol(A, first_run-offset, run_length);
+ return A;
+}
+
+/*
+ find_optimal_pairing -- find which binary variables should be paired
+ to maximally reduce the number of terms
+
+ This is essentially the technique outlined by T. Sasao in the
+ Trans. on Comp., Oct 1984. We estimate the cost of pairing each
+ pair individually using 1 of 4 strategies: (1) algebraic division
+ of F by the pair (exactly T. Sasao technique); (2) strong division
+ of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from
+ espresso); (3) full minimization using espresso; (4) exact
+ minimization. These are in order of both increasing accuracy and
+ increasing difficulty (!)
+
+ Once the n squared pairs have been evaluated, T. Sasao proposes a
+ graph covering of nodes by disjoint edges. For now, I solve this
+ problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n
+ variables when n is even). Note that solving this problem exactly
+ is the same as evaluating the cost function for all possible
+ pairings.
+
+ n pairs
+
+ 1, 2 1
+ 3, 4 3
+ 5, 6 15
+ 7, 8 105
+ 9,10 945
+ 11,12 10,395
+ 13,14 135,135
+ 15,16 2,027,025
+ 17,18 34,459,425
+ 19,20 654,729,075
+*/
+void find_optimal_pairing(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ int i, j, **cost_array;
+
+ cost_array = find_pairing_cost(PLA, strategy);
+
+ if (summary) {
+ printf(" ");
+ for(i = 0; i < cube.num_binary_vars; i++)
+ printf("%3d ", i+1);
+ printf("\n");
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ printf("%3d ", i+1);
+ for(j = 0; j < cube.num_binary_vars; j++)
+ printf("%3d ", cost_array[i][j]);
+ printf("\n");
+ }
+ }
+
+ if (cube.num_binary_vars <= 14) {
+ PLA->pair = pair_best_cost(cost_array);
+ } else {
+ (void) greedy_best_cost(cost_array, &(PLA->pair));
+ }
+ printf("# ");
+ print_pair(PLA->pair);
+
+ for(i = 0; i < cube.num_binary_vars; i++)
+ FREE(cost_array[i]);
+ FREE(cost_array);
+
+ set_pair(PLA);
+ EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
+}
+
+int **find_pairing_cost(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ int var1, var2, **cost_array;
+ int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost;
+ pcover T, Fsave, Dsave, Rsave;
+ pset mask;
+/* char *s;*/
+
+ /* data is returned in the cost array */
+ cost_array = ALLOC(int *, cube.num_binary_vars);
+ for(i = 0; i < cube.num_binary_vars; i++)
+ cost_array[i] = ALLOC(int, cube.num_binary_vars);
+ for(i = 0; i < cube.num_binary_vars; i++)
+ for(j = 0; j < cube.num_binary_vars; j++)
+ cost_array[i][j] = 0;
+
+ /* Setup the pair structure for pairing variables together */
+ PLA->pair = pair_new(1);
+ PLA->pair->cnt = 1;
+
+ for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) {
+ for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) {
+ /* if anything but simple strategy, perform setup */
+ if (strategy > 0) {
+ /* save the original covers */
+ Fsave = sf_save(PLA->F);
+ Dsave = sf_save(PLA->D);
+ Rsave = sf_save(PLA->R);
+
+ /* save the original cube structure */
+ xnum_binary_vars = cube.num_binary_vars;
+ xnum_vars = cube.num_vars;
+ xpart_size = ALLOC(int, cube.num_vars);
+ for(i = 0; i < cube.num_vars; i++)
+ xpart_size[i] = cube.part_size[i];
+
+ /* pair two variables together */
+ PLA->pair->var1[0] = var1 + 1;
+ PLA->pair->var2[0] = var2 + 1;
+ set_pair1(PLA, /* adjust_labels */ FALSE);
+ }
+
+
+ /* decide how to best estimate worth of this pairing */
+ switch(strategy) {
+ case 3:
+ /*s = "exact minimization";*/
+ PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 2:
+ /*s = "full minimization";*/
+ PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 1:
+ /*s = "strong division";*/
+ PLA->F = reduce(PLA->F, PLA->D);
+ PLA->F = expand(PLA->F, PLA->R, FALSE);
+ PLA->F = irredundant(PLA->F, PLA->D);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 0:
+ /*s = "weak division";*/
+ mask = new_cube();
+ set_or(mask, cube.var_mask[var1], cube.var_mask[var2]);
+ T = dist_merge(sf_save(PLA->F), mask);
+ cost = PLA->F->count - T->count;
+ sf_free(T);
+ set_free(mask);
+ }
+
+ cost_array[var1][var2] = cost;
+
+ if (strategy > 0) {
+ /* restore the original cube structure -- free the new ones */
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = xnum_binary_vars;
+ cube.num_vars = xnum_vars;
+ cube.part_size = xpart_size;
+ cube_setup();
+
+ /* restore the original cover(s) -- free the new ones */
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = Fsave;
+ PLA->D = Dsave;
+ PLA->R = Rsave;
+ }
+ }
+ }
+
+ pair_free(PLA->pair);
+ PLA->pair = NULL;
+ return cost_array;
+}
+
+static int best_cost;
+static int **cost_array;
+static ppair best_pair;
+static pset best_phase;
+static pPLA global_PLA;
+static pcover best_F, best_D, best_R;
+static int pair_minim_strategy;
+
+
+print_pair(pair)
+ppair pair;
+{
+ int i;
+
+ printf("pair is");
+ for(i = 0; i < pair->cnt; i++)
+ printf (" (%d %d)", pair->var1[i], pair->var2[i]);
+ printf("\n");
+}
+
+
+int greedy_best_cost(cost_array_local, pair_p)
+int **cost_array_local;
+ppair *pair_p;
+{
+ int i, j, besti, bestj, maxcost, total_cost;
+ pset cand;
+ ppair pair;
+
+ pair = pair_new(cube.num_binary_vars);
+ cand = set_full(cube.num_binary_vars);
+ total_cost = 0;
+
+ while (set_ord(cand) >= 2) {
+ maxcost = -1;
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ if (is_in_set(cand, i)) {
+ for(j = i+1; j < cube.num_binary_vars; j++) {
+ if (is_in_set(cand, j)) {
+ if (cost_array_local[i][j] > maxcost) {
+ maxcost = cost_array_local[i][j];
+ besti = i;
+ bestj = j;
+ }
+ }
+ }
+ }
+ }
+ pair->var1[pair->cnt] = besti+1;
+ pair->var2[pair->cnt] = bestj+1;
+ pair->cnt++;
+ set_remove(cand, besti);
+ set_remove(cand, bestj);
+ total_cost += maxcost;
+ }
+ set_free(cand);
+ *pair_p = pair;
+ return total_cost;
+}
+
+
+ppair pair_best_cost(cost_array_local)
+int **cost_array_local;
+{
+ ppair pair;
+ pset candidate;
+
+ best_cost = -1;
+ best_pair = NULL;
+ cost_array = cost_array_local;
+
+ pair = pair_new(cube.num_binary_vars);
+ candidate = set_full(cube.num_binary_vars);
+ generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost);
+ pair_free(pair);
+ set_free(candidate);
+ return best_pair;
+}
+
+
+int find_best_cost(pair)
+register ppair pair;
+{
+ register int i, cost;
+
+ cost = 0;
+ for(i = 0; i < pair->cnt; i++)
+ cost += cost_array[pair->var1[i]-1][pair->var2[i]-1];
+ if (cost > best_cost) {
+ best_cost = cost;
+ best_pair = pair_save(pair, pair->cnt);
+ }
+ if ((debug & MINCOV) && trace) {
+ printf("cost is %d ", cost);
+ print_pair(pair);
+ }
+}
+
+/*
+ pair_all: brute-force approach to try all possible pairings
+
+ pair_strategy is:
+ 2) for espresso
+ 3) for minimize_exact
+ 4) for phase assignment
+*/
+
+pair_all(PLA, pair_strategy)
+pPLA PLA;
+int pair_strategy;
+{
+ ppair pair;
+ pset candidate;
+
+ global_PLA = PLA;
+ pair_minim_strategy = pair_strategy;
+ best_cost = PLA->F->count + 1;
+ best_pair = NULL;
+ best_phase = NULL;
+ best_F = best_D = best_R = NULL;
+ pair = pair_new(cube.num_binary_vars);
+ candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars);
+
+ generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair);
+
+ pair_free(pair);
+ set_free(candidate);
+
+ PLA->pair = best_pair;
+ PLA->phase = best_phase;
+/* not really necessary
+ if (phase != NULL)
+ (void) set_phase(PLA->phase);
+*/
+ set_pair(PLA);
+ printf("# ");
+ print_pair(PLA->pair);
+
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = best_F;
+ PLA->D = best_D;
+ PLA->R = best_R;
+}
+
+
+/*
+ * minimize_pair -- called as each pair is generated
+ */
+int minimize_pair(pair)
+ppair pair;
+{
+ pcover Fsave, Dsave, Rsave;
+ int i, xnum_binary_vars, xnum_vars, *xpart_size;
+
+ /* save the original covers */
+ Fsave = sf_save(global_PLA->F);
+ Dsave = sf_save(global_PLA->D);
+ Rsave = sf_save(global_PLA->R);
+
+ /* save the original cube structure */
+ xnum_binary_vars = cube.num_binary_vars;
+ xnum_vars = cube.num_vars;
+ xpart_size = ALLOC(int, cube.num_vars);
+ for(i = 0; i < cube.num_vars; i++)
+ xpart_size[i] = cube.part_size[i];
+
+ /* setup the paired variables */
+ global_PLA->pair = pair;
+ set_pair1(global_PLA, /* adjust_labels */ FALSE);
+
+ /* call the minimizer */
+ if (summary)
+ print_pair(pair);
+ switch(pair_minim_strategy) {
+ case 2:
+ EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F);
+ if (summary)
+ printf("# phase is %s\n", pc1(global_PLA->phase));
+ break;
+ case 1:
+ EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D,
+ global_PLA->R, 1), "EXACT ", global_PLA->F);
+ break;
+ case 0:
+ EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D,
+ global_PLA->R), "ESPRESSO ", global_PLA->F);
+ break;
+ default:
+ break;
+ }
+
+ /* see if we have a new best solution */
+ if (global_PLA->F->count < best_cost) {
+ best_cost = global_PLA->F->count;
+ best_pair = pair_save(pair, pair->cnt);
+ best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL;
+ if (best_F != NULL) sf_free(best_F);
+ if (best_D != NULL) sf_free(best_D);
+ if (best_R != NULL) sf_free(best_R);
+ best_F = sf_save(global_PLA->F);
+ best_D = sf_save(global_PLA->D);
+ best_R = sf_save(global_PLA->R);
+ }
+
+ /* restore the original cube structure -- free the new ones */
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = xnum_binary_vars;
+ cube.num_vars = xnum_vars;
+ cube.part_size = xpart_size;
+ cube_setup();
+
+ /* restore the original cover(s) -- free the new ones */
+ sf_free(global_PLA->F);
+ sf_free(global_PLA->D);
+ sf_free(global_PLA->R);
+ global_PLA->F = Fsave;
+ global_PLA->D = Dsave;
+ global_PLA->R = Rsave;
+ global_PLA->pair = NULL;
+ global_PLA->phase = NULL;
+}
+
+generate_all_pairs(pair, n, candidate, action)
+ppair pair;
+int n;
+pset candidate;
+int (*action)();
+{
+ int i, j;
+ pset recur_candidate;
+ ppair recur_pair;
+
+ if (set_ord(candidate) < 2) {
+ (*action)(pair);
+ return;
+ }
+
+ recur_pair = pair_save(pair, n);
+ recur_candidate = set_save(candidate);
+
+ /* Find first variable still in the candidate set */
+ for(i = 0; i < n; i++)
+ if (is_in_set(candidate, i))
+ break;
+
+ /* Try all pairs of i with other variables */
+ for(j = i+1; j < n; j++)
+ if (is_in_set(candidate, j)) {
+ /* pair (i j) -- remove from candidate set for future pairings */
+ set_remove(recur_candidate, i);
+ set_remove(recur_candidate, j);
+
+ /* add to the pair array */
+ recur_pair->var1[recur_pair->cnt] = i+1;
+ recur_pair->var2[recur_pair->cnt] = j+1;
+ recur_pair->cnt++;
+
+ /* recur looking for the end ... */
+ generate_all_pairs(recur_pair, n, recur_candidate, action);
+
+ /* now break this pair, and restore candidate set */
+ recur_pair->cnt--;
+ set_insert(recur_candidate, i);
+ set_insert(recur_candidate, j);
+ }
+
+ /* if odd, generate all pairs which do NOT include i */
+ if ((set_ord(candidate) % 2) == 1) {
+ set_remove(recur_candidate, i);
+ generate_all_pairs(recur_pair, n, recur_candidate, action);
+ }
+
+ pair_free(recur_pair);
+ set_free(recur_candidate);
+}
+
+ppair pair_new(n)
+register int n;
+{
+ register ppair pair1;
+
+ pair1 = ALLOC(pair_t, 1);
+ pair1->cnt = 0;
+ pair1->var1 = ALLOC(int, n);
+ pair1->var2 = ALLOC(int, n);
+ return pair1;
+}
+
+
+ppair pair_save(pair, n)
+register ppair pair;
+register int n;
+{
+ register int k;
+ register ppair pair1;
+
+ pair1 = pair_new(n);
+ pair1->cnt = pair->cnt;
+ for(k = 0; k < pair->cnt; k++) {
+ pair1->var1[k] = pair->var1[k];
+ pair1->var2[k] = pair->var2[k];
+ }
+ return pair1;
+}
+
+
+int pair_free(pair)
+register ppair pair;
+{
+ FREE(pair->var1);
+ FREE(pair->var2);
+ FREE(pair);
+}
diff --git a/src/misc/espresso/part.c b/src/misc/espresso/part.c
new file mode 100644
index 00000000..42843aeb
--- /dev/null
+++ b/src/misc/espresso/part.c
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+static int visit_col();
+
+static void
+copy_row(A, prow)
+register sm_matrix *A;
+register sm_row *prow;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_insert(A, p->row_num, p->col_num);
+ }
+}
+
+
+static int
+visit_row(A, prow, rows_visited, cols_visited)
+sm_matrix *A;
+sm_row *prow;
+int *rows_visited;
+int *cols_visited;
+{
+ sm_element *p;
+ sm_col *pcol;
+
+ if (! prow->flag) {
+ prow->flag = 1;
+ (*rows_visited)++;
+ if (*rows_visited == A->nrows) {
+ return 1;
+ }
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ if (! pcol->flag) {
+ if (visit_col(A, pcol, rows_visited, cols_visited)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int
+visit_col(A, pcol, rows_visited, cols_visited)
+sm_matrix *A;
+sm_col *pcol;
+int *rows_visited;
+int *cols_visited;
+{
+ sm_element *p;
+ sm_row *prow;
+
+ if (! pcol->flag) {
+ pcol->flag = 1;
+ (*cols_visited)++;
+ if (*cols_visited == A->ncols) {
+ return 1;
+ }
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ if (! prow->flag) {
+ if (visit_row(A, prow, rows_visited, cols_visited)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+sm_block_partition(A, L, R)
+sm_matrix *A;
+sm_matrix **L, **R;
+{
+ int cols_visited, rows_visited;
+ register sm_row *prow;
+ register sm_col *pcol;
+
+ /* Avoid the trivial case */
+ if (A->nrows == 0) {
+ return 0;
+ }
+
+ /* Reset the visited flags for each row and column */
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ prow->flag = 0;
+ }
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ pcol->flag = 0;
+ }
+
+ cols_visited = rows_visited = 0;
+ if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) {
+ /* we found all of the rows */
+ return 0;
+ } else {
+ *L = sm_alloc();
+ *R = sm_alloc();
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->flag) {
+ copy_row(*L, prow);
+ } else {
+ copy_row(*R, prow);
+ }
+ }
+ return 1;
+ }
+}
diff --git a/src/misc/espresso/primes.c b/src/misc/espresso/primes.c
new file mode 100644
index 00000000..3e40da27
--- /dev/null
+++ b/src/misc/espresso/primes.c
@@ -0,0 +1,170 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static bool primes_consensus_special_cases();
+static pcover primes_consensus_merge();
+static pcover and_with_cofactor();
+
+
+/* primes_consensus -- generate primes using consensus */
+pcover primes_consensus(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tnew, Tl, Tr;
+
+ if (primes_consensus_special_cases(T, &Tnew) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ Tl = primes_consensus(scofactor(T, cl, best));
+ Tr = primes_consensus(scofactor(T, cr, best));
+ Tnew = primes_consensus_merge(Tl, Tr, cl, cr);
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ return Tnew;
+}
+
+static bool
+primes_consensus_special_cases(T, Tnew)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ free_cube(p);
+
+ A = primes_consensus(T);
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+ *Tnew = A;
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+static pcover
+primes_consensus_merge(Tl, Tr, cl, cr)
+pcover Tl, Tr;
+pcube cl, cr;
+{
+ register pcube pl, pr, lastl, lastr, pt;
+ pcover T, Tsave;
+
+ Tl = and_with_cofactor(Tl, cl);
+ Tr = and_with_cofactor(Tr, cr);
+
+ T = sf_new(500, Tl->sf_size);
+ pt = T->data;
+ Tsave = sf_contain(sf_join(Tl, Tr));
+
+ foreach_set(Tl, lastl, pl) {
+ foreach_set(Tr, lastr, pr) {
+ if (cdist01(pl, pr) == 1) {
+ consensus(pt, pl, pr);
+ if (++T->count >= T->capacity) {
+ Tsave = sf_union(Tsave, sf_contain(T));
+ T = sf_new(500, Tl->sf_size);
+ pt = T->data;
+ } else {
+ pt += T->wsize;
+ }
+ }
+ }
+ }
+ free_cover(Tl);
+ free_cover(Tr);
+
+ Tsave = sf_union(Tsave, sf_contain(T));
+ return Tsave;
+}
+
+
+static pcover
+and_with_cofactor(A, cof)
+pset_family A;
+register pset cof;
+{
+ register pset last, p;
+
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, cof);
+ if (cdist(p, cube.fullset) > 0) {
+ RESET(p, ACTIVE);
+ } else {
+ SET(p, ACTIVE);
+ }
+ }
+ return sf_inactive(A);
+}
diff --git a/src/misc/espresso/reduce.c b/src/misc/espresso/reduce.c
new file mode 100644
index 00000000..00e4507f
--- /dev/null
+++ b/src/misc/espresso/reduce.c
@@ -0,0 +1,258 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: reduce.c
+ purpose: Perform the Espresso-II reduction step
+
+ Reduction is a technique used to explore larger regions of the
+ optimization space. We replace each cube of F with a smaller
+ cube while still maintaining a cover of the same logic function.
+*/
+
+#include "espresso.h"
+
+static bool toggle = TRUE;
+
+
+/*
+ reduce -- replace each cube in F with its reduction
+
+ The reduction of a cube is the smallest cube contained in the cube
+ which can replace the cube in the original cover without changing
+ the cover. This is equivalent to the super cube of all of the
+ essential points in the cube. This can be computed directly.
+
+ The problem is that the order in which the cubes are reduced can
+ greatly affect the final result. We alternate between two ordering
+ strategies:
+
+ (1) Order the cubes in ascending order of distance from the
+ largest cube breaking ties by ordering cubes of equal distance
+ in descending order of size (sort_reduce)
+
+ (2) Order the cubes in descending order of the inner-product of
+ the cube and the column sums (mini_sort)
+
+ The real workhorse of this section is the routine SCCC which is
+ used to find the Smallest Cube Containing the Complement of a cover.
+ Reduction as proposed by Espresso-II takes a cube and computes its
+ maximal reduction as the intersection between the cube and the
+ smallest cube containing the complement of (F u D - {c}) cofactored
+ against c.
+
+ As usual, the unate-recursive paradigm is used to compute SCCC.
+ The SCCC of a unate cover is trivial to compute, and thus we perform
+ Shannon Cofactor expansion attempting to drive the cover to be unate
+ as fast as possible.
+*/
+
+pcover reduce(F, D)
+INOUT pcover F;
+IN pcover D;
+{
+ register pcube last, p, cunder, *FD;
+
+ /* Order the cubes */
+ if (use_random_order)
+ F = random_order(F);
+ else {
+ F = toggle ? sort_reduce(F) : mini_sort(F, descend);
+ toggle = ! toggle;
+ }
+
+ /* Try to reduce each cube */
+ FD = cube2list(F, D);
+ foreach_set(F, last, p) {
+ cunder = reduce_cube(FD, p); /* reduce the cube */
+ if (setp_equal(cunder, p)) { /* see if it actually did */
+ SET(p, ACTIVE); /* cube remains active */
+ SET(p, PRIME); /* cube remains prime ? */
+ } else {
+ if (debug & REDUCE) {
+ printf("REDUCE: %s to %s %s\n",
+ pc1(p), pc2(cunder), print_time(ptime()));
+ }
+ set_copy(p, cunder); /* save reduced version */
+ RESET(p, PRIME); /* cube is no longer prime */
+ if (setp_empty(cunder))
+ RESET(p, ACTIVE); /* if null, kill the cube */
+ else
+ SET(p, ACTIVE); /* cube is active */
+ }
+ free_cube(cunder);
+ }
+ free_cubelist(FD);
+
+ /* Delete any cubes of F which reduced to the empty cube */
+ return sf_inactive(F);
+}
+
+/* reduce_cube -- find the maximal reduction of a cube */
+pcube reduce_cube(FD, p)
+IN pcube *FD, p;
+{
+ pcube cunder;
+
+ cunder = sccc(cofactor(FD, p));
+ return set_and(cunder, cunder, p);
+}
+
+
+/* sccc -- find Smallest Cube Containing the Complement of a cover */
+pcube sccc(T)
+INOUT pcube *T; /* T will be disposed of */
+{
+ pcube r;
+ register pcube cl, cr;
+ register int best;
+ static int sccc_level = 0;
+
+ if (debug & REDUCE1) {
+ debug_print(T, "SCCC", sccc_level++);
+ }
+
+ if (sccc_special_cases(T, &r) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, REDUCE1);
+ r = sccc_merge(sccc(scofactor(T, cl, best)),
+ sccc(scofactor(T, cr, best)), cl, cr);
+ free_cubelist(T);
+ }
+
+ if (debug & REDUCE1)
+ printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r));
+ return r;
+}
+
+
+pcube sccc_merge(left, right, cl, cr)
+INOUT register pcube left, right; /* will be disposed of ... */
+INOUT register pcube cl, cr; /* will be disposed of ... */
+{
+ INLINEset_and(left, left, cl);
+ INLINEset_and(right, right, cr);
+ INLINEset_or(left, left, right);
+ free_cube(right);
+ free_cube(cl);
+ free_cube(cr);
+ return left;
+}
+
+
+/*
+ sccc_cube -- find the smallest cube containing the complement of a cube
+
+ By DeMorgan's law and the fact that the smallest cube containing a
+ cover is the "or" of the positional cubes, it is simple to see that
+ the SCCC is the universe if the cube has more than two active
+ variables. If there is only a single active variable, then the
+ SCCC is merely the bitwise complement of the cube in that
+ variable. A last special case is no active variables, in which
+ case the SCCC is empty.
+
+ This is "anded" with the incoming cube result.
+*/
+pcube sccc_cube(result, p)
+register pcube result, p;
+{
+ register pcube temp=cube.temp[0], mask;
+ int var;
+
+ if ((var = cactive(p)) >= 0) {
+ mask = cube.var_mask[var];
+ INLINEset_xor(temp, p, mask);
+ INLINEset_and(result, result, temp);
+ }
+ return result;
+}
+
+/*
+ * sccc_special_cases -- check the special cases for sccc
+ */
+
+bool sccc_special_cases(T, result)
+INOUT pcube *T; /* will be disposed if answer is determined */
+OUT pcube *result; /* returned only if answer determined */
+{
+ register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0];
+ pcube *A, *B;
+
+ /* empty cover => complement is universe => SCCC is universe */
+ if (T[2] == NULL) {
+ *result = set_save(cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* row of 1's => complement is empty => SCCC is empty */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *result = new_cube();
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If cover is unate (or single cube), apply simple rules to find SCCCU */
+ if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) {
+ *result = set_save(cube.fullset);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ (void) sccc_cube(*result, set_or(temp, p, cof));
+ }
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for column of 0's (which can be easily factored( */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ *result = sccc_cube(set_save(cube.fullset), ceil);
+ if (setp_equal(*result, cube.fullset)) {
+ free_cube(ceil);
+ } else {
+ *result = sccc_merge(sccc(cofactor(T,ceil)),
+ set_save(cube.fullset), ceil, *result);
+ }
+ free_cubelist(T);
+ return TRUE;
+ }
+ free_cube(ceil);
+
+ /* Single active column at this point => tautology => SCCC is empty */
+ if (cdata.vars_active == 1) {
+ *result = new_cube();
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for components */
+ if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) {
+ if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) {
+ return MAYBE;
+ } else {
+ free_cubelist(T);
+ *result = sccc(A);
+ ceil = sccc(B);
+ (void) set_and(*result, *result, ceil);
+ set_free(ceil);
+ return TRUE;
+ }
+ }
+
+ /* Not much we can do about it */
+ return MAYBE;
+}
diff --git a/src/misc/espresso/rows.c b/src/misc/espresso/rows.c
new file mode 100644
index 00000000..bf0c0baa
--- /dev/null
+++ b/src/misc/espresso/rows.c
@@ -0,0 +1,314 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+
+/*
+ * allocate a new row vector
+ */
+sm_row *
+sm_row_alloc()
+{
+ 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(prow)
+register 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(prow)
+register 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(prow, col)
+register sm_row *prow;
+register 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(prow, col)
+register sm_row *prow;
+register 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(prow, col)
+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(p1, p2)
+sm_row *p1, *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(p1, p2)
+sm_row *p1, *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(p1, p2)
+sm_row *p1, *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(p1, p2)
+sm_row *p1, *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(prow, modulus)
+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(prow, p)
+register sm_row *prow;
+register 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(fp, prow)
+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);
+ }
+}
diff --git a/src/misc/espresso/set.c b/src/misc/espresso/set.c
new file mode 100644
index 00000000..fce88288
--- /dev/null
+++ b/src/misc/espresso/set.c
@@ -0,0 +1,820 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * set.c -- routines for maniuplating sets and set families
+ */
+
+/* LINTLIBRARY */
+
+#include "espresso.h"
+static pset_family set_family_garbage = NULL;
+
+static int intcpy(d, s, n)
+register unsigned int *d, *s;
+register long n;
+{
+ register int i;
+ for(i = 0; i < n; i++) {
+ *d++ = *s++;
+ }
+}
+
+
+/* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */
+int bit_index(a)
+register unsigned int a;
+{
+ register int i;
+ if (a == 0)
+ return -1;
+ for(i = 0; (a & 1) == 0; a >>= 1, i++)
+ ;
+ return i;
+}
+
+
+/* set_ord -- count number of elements in a set */
+int set_ord(a)
+register pset a;
+{
+ register int i, sum = 0;
+ register unsigned int val;
+ for(i = LOOP(a); i > 0; i--)
+ if ((val = a[i]) != 0)
+ sum += count_ones(val);
+ return sum;
+}
+
+/* set_dist -- distance between two sets (# elements in common) */
+int set_dist(a, b)
+register pset a, b;
+{
+ register int i, sum = 0;
+ register unsigned int val;
+ for(i = LOOP(a); i > 0; i--)
+ if ((val = a[i] & b[i]) != 0)
+ sum += count_ones(val);
+ return sum;
+}
+
+/* set_clear -- make "r" the empty set of "size" elements */
+pset set_clear(r, size)
+register pset r;
+int size;
+{
+ register int i = LOOPINIT(size);
+ *r = i; do r[i] = 0; while (--i > 0);
+ return r;
+}
+
+/* set_fill -- make "r" the universal set of "size" elements */
+pset set_fill(r, size)
+register pset r;
+register int size;
+{
+ register int i = LOOPINIT(size);
+ *r = i;
+ r[i] = ~ (unsigned) 0;
+ r[i] >>= i * BPI - size;
+ while (--i > 0)
+ r[i] = ~ (unsigned) 0;
+ return r;
+}
+
+/* set_copy -- copy set a into set r */
+pset set_copy(r, a)
+register pset r, a;
+{
+ register int i = LOOPCOPY(a);
+ do r[i] = a[i]; while (--i >= 0);
+ return r;
+}
+
+/* set_and -- compute intersection of sets "a" and "b" */
+pset set_and(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_or -- compute union of sets "a" and "b" */
+pset set_or(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_diff -- compute difference of sets "a" and "b" */
+pset set_diff(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_xor -- compute exclusive-or of sets "a" and "b" */
+pset set_xor(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+#ifdef IBM_WATC
+ PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0);
+#else
+ PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0);
+#endif
+ return r;
+}
+
+/* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */
+pset set_merge(r, a, b, mask)
+register pset r, a, b, mask;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0);
+ return r;
+}
+
+/* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */
+bool set_andp(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ register unsigned int x = 0;
+ PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0);
+ return x != 0;
+}
+
+/* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */
+bool set_orp(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ register unsigned int x = 0;
+ PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0);
+ return x != 0;
+}
+
+/* setp_empty -- check if the set "a" is empty */
+bool setp_empty(a)
+register pset a;
+{
+ register int i = LOOP(a);
+ do if (a[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_full -- check if the set "a" is the full set of "size" elements */
+bool setp_full(a, size)
+register pset a;
+register int size;
+{
+ register int i = LOOP(a);
+ register unsigned int test;
+ test = ~ (unsigned) 0;
+ test >>= i * BPI - size;
+ if (a[i] != test)
+ return FALSE;
+ while (--i > 0)
+ if (a[i] != (~(unsigned) 0))
+ return FALSE;
+ return TRUE;
+}
+
+/* setp_equal -- check if the set "a" equals set "b" */
+bool setp_equal(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] != b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_disjoint -- check if intersection of "a" and "b" is empty */
+bool setp_disjoint(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] & b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_implies -- check if "a" implies "b" ("b" contains "a") */
+bool setp_implies(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] & ~b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* sf_or -- form the "or" of all sets in a set family */
+pset sf_or(A)
+pset_family A;
+{
+ register pset or, last, p;
+
+ or = set_new(A->sf_size);
+ foreach_set(A, last, p)
+ INLINEset_or(or, or, p);
+ return or;
+}
+
+/* sf_and -- form the "and" of all sets in a set family */
+pset sf_and(A)
+pset_family A;
+{
+ register pset and, last, p;
+
+ and = set_fill(set_new(A->sf_size), A->sf_size);
+ foreach_set(A, last, p)
+ INLINEset_and(and, and, p);
+ return and;
+}
+
+/* sf_active -- make all members of the set family active */
+pset_family sf_active(A)
+pset_family A;
+{
+ register pset p, last;
+ foreach_set(A, last, p) {
+ SET(p, ACTIVE);
+ }
+ A->active_count = A->count;
+ return A;
+}
+
+
+/* sf_inactive -- remove all inactive cubes in a set family */
+pset_family sf_inactive(A)
+pset_family A;
+{
+ register pset p, last, pdest;
+
+ pdest = A->data;
+ foreach_set(A, last, p) {
+ if (TESTP(p, ACTIVE)) {
+ if (pdest != p) {
+ INLINEset_copy(pdest, p);
+ }
+ pdest += A->wsize;
+ } else {
+ A->count--;
+ }
+ }
+ return A;
+}
+
+
+/* sf_copy -- copy a set family */
+pset_family sf_copy(R, A)
+pset_family R, A;
+{
+ R->sf_size = A->sf_size;
+ R->wsize = A->wsize;
+/*R->capacity = A->count;*/
+/*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/
+ R->count = A->count;
+ R->active_count = A->active_count;
+ intcpy(R->data, A->data, (long) A->wsize * A->count);
+ return R;
+}
+
+
+/* sf_join -- join A and B into a single set_family */
+pset_family sf_join(A, B)
+pset_family A, B;
+{
+ pset_family R;
+ long asize = A->count * A->wsize;
+ long bsize = B->count * B->wsize;
+
+ if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch");
+ R = sf_new(A->count + B->count, A->sf_size);
+ R->count = A->count + B->count;
+ R->active_count = A->active_count + B->active_count;
+ intcpy(R->data, A->data, asize);
+ intcpy(R->data + asize, B->data, bsize);
+ return R;
+}
+
+
+/* sf_append -- append the sets of B to the end of A, and dispose of B */
+pset_family sf_append(A, B)
+pset_family A, B;
+{
+ long asize = A->count * A->wsize;
+ long bsize = B->count * B->wsize;
+
+ if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch");
+ A->capacity = A->count + B->count;
+ A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+ intcpy(A->data + asize, B->data, bsize);
+ A->count += B->count;
+ A->active_count += B->active_count;
+ sf_free(B);
+ return A;
+}
+
+
+/* sf_new -- allocate "num" sets of "size" elements each */
+pset_family sf_new(num, size)
+int num, size;
+{
+ pset_family A;
+ if (set_family_garbage == NULL) {
+ A = ALLOC(set_family_t, 1);
+ } else {
+ A = set_family_garbage;
+ set_family_garbage = A->next;
+ }
+ A->sf_size = size;
+ A->wsize = SET_SIZE(size);
+ A->capacity = num;
+ A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize);
+ A->count = 0;
+ A->active_count = 0;
+ return A;
+}
+
+
+/* sf_save -- create a duplicate copy of a set family */
+pset_family sf_save(A)
+register pset_family A;
+{
+ return sf_copy(sf_new(A->count, A->sf_size), A);
+}
+
+
+/* sf_free -- free the storage allocated for a set family */
+void sf_free(A)
+pset_family A;
+{
+ FREE(A->data);
+ A->next = set_family_garbage;
+ set_family_garbage = A;
+}
+
+
+/* sf_cleanup -- free all of the set families from the garbage list */
+void sf_cleanup()
+{
+ register pset_family p, pnext;
+ for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) {
+ pnext = p->next;
+ FREE(p);
+ }
+ set_family_garbage = (pset_family) NULL;
+}
+
+
+/* sf_addset -- add a set to the end of a set family */
+pset_family sf_addset(A, s)
+pset_family A;
+pset s;
+{
+ register pset p;
+
+ if (A->count >= A->capacity) {
+ A->capacity = A->capacity + A->capacity/2 + 1;
+ A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+ }
+ p = GETSET(A, A->count++);
+ INLINEset_copy(p, s);
+ return A;
+}
+
+/* sf_delset -- delete a set from a set family */
+void sf_delset(A, i)
+pset_family A;
+int i;
+{ (void) set_copy(GETSET(A,i), GETSET(A, --A->count));}
+
+/* sf_print -- print a set_family as a set (list the element numbers) */
+void sf_print(A)
+pset_family A;
+{
+ char *ps1();
+ register pset p;
+ register int i;
+ foreachi_set(A, i, p)
+ printf("A[%d] = %s\n", i, ps1(p));
+}
+
+/* sf_bm_print -- print a set_family as a bit-matrix */
+void sf_bm_print(A)
+pset_family A;
+{
+ char *pbv1();
+ register pset p;
+ register int i;
+ foreachi_set(A, i, p)
+ printf("[%4d] %s\n", i, pbv1(p, A->sf_size));
+}
+
+
+/* sf_write -- output a set family in an unintelligable manner */
+void sf_write(fp, A)
+FILE *fp;
+pset_family A;
+{
+ register pset p, last;
+ (void) fprintf(fp, "%d %d\n", A->count, A->sf_size);
+ foreach_set(A, last, p)
+ set_write(fp, p);
+ (void) fflush(fp);
+}
+
+
+/* sf_read -- read a set family written by sf_write */
+pset_family sf_read(fp)
+FILE *fp;
+{
+ int i, j;
+ register pset p, last;
+ pset_family A;
+
+ (void) fscanf(fp, "%d %d\n", &i, &j);
+ A = sf_new(i, j);
+ A->count = i;
+ foreach_set(A, last, p) {
+ (void) fscanf(fp, "%x", p);
+ for(j = 1; j <= LOOP(p); j++)
+ (void) fscanf(fp, "%x", p+j);
+ }
+ return A;
+}
+
+
+/* set_write -- output a set in an unintelligable manner */
+void set_write(fp, a)
+register FILE *fp;
+register pset a;
+{
+ register int n = LOOP(a), j;
+
+ for(j = 0; j <= n; j++) {
+ (void) fprintf(fp, "%x ", a[j]);
+ if ((j+1) % 8 == 0 && j != n)
+ (void) fprintf(fp, "\n\t");
+ }
+ (void) fprintf(fp, "\n");
+}
+
+
+/* sf_bm_read -- read a set family written by sf_bm_print (almost) */
+pset_family sf_bm_read(fp)
+FILE *fp;
+{
+ int i, j, rows, cols;
+ register pset pdest;
+ pset_family A;
+
+ (void) fscanf(fp, "%d %d\n", &rows, &cols);
+ A = sf_new(rows, cols);
+ for(i = 0; i < rows; i++) {
+ pdest = GETSET(A, A->count++);
+ (void) set_clear(pdest, A->sf_size);
+ for(j = 0; j < cols; j++) {
+ switch(getc(fp)) {
+ case '0':
+ break;
+ case '1':
+ set_insert(pdest, j);
+ break;
+ default:
+ fatal("Error reading set family");
+ }
+ }
+ if (getc(fp) != '\n') {
+ fatal("Error reading set family (at end of line)");
+ }
+ }
+ return A;
+}
+
+
+
+/* ps1 -- convert a set into a printable string */
+#define largest_string 120
+static char s1[largest_string];
+char *ps1(a)
+register pset a;
+{
+ register int i, num, l, len = 0, n = NELEM(a);
+ char temp[20];
+ bool first = TRUE;
+
+ s1[len++] = '[';
+ for(i = 0; i < n; i++)
+ if (is_in_set(a,i)) {
+ if (! first)
+ s1[len++] = ',';
+ first = FALSE; num = i;
+ /* Generate digits (reverse order) */
+ l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0);
+ /* Copy them back in correct order */
+ do s1[len++] = temp[--l]; while (l > 0);
+ if (len > largest_string-15) {
+ s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.';
+ break;
+ }
+ }
+
+ s1[len++] = ']';
+ s1[len++] = '\0';
+ return s1;
+}
+
+/* pbv1 -- print bit-vector */
+char *pbv1(s, n)
+pset s;
+int n;
+{
+ register int i;
+ for(i = 0; i < n; i++)
+ s1[i] = is_in_set(s,i) ? '1' : '0';
+ s1[n] = '\0';
+ return s1;
+}
+
+
+/* set_adjcnt -- adjust the counts for a set by "weight" */
+void
+set_adjcnt(a, count, weight)
+register pset a;
+register int *count, weight;
+{
+ register int i, base;
+ register unsigned int val;
+
+ for(i = LOOP(a); i > 0; ) {
+ for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base] += weight;
+ }
+ }
+ }
+}
+
+
+
+/* sf_count -- perform a column sum over a set family */
+int *sf_count(A)
+pset_family A;
+{
+ register pset p, last;
+ register int i, base, *count;
+ register unsigned int val;
+
+ count = ALLOC(int, A->sf_size);
+ for(i = A->sf_size - 1; i >= 0; i--) {
+ count[i] = 0;
+ }
+
+ foreach_set(A, last, p) {
+ for(i = LOOP(p); i > 0; ) {
+ for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base]++;
+ }
+ }
+ }
+ }
+ return count;
+}
+
+
+/* sf_count_restricted -- perform a column sum over a set family, restricting
+ * to only the columns which are in r; also, the columns are weighted by the
+ * number of elements which are in each row
+ */
+int *sf_count_restricted(A, r)
+pset_family A;
+register pset r;
+{
+ register pset p;
+ register int i, base, *count;
+ register unsigned int val;
+ int weight;
+ pset last;
+
+ count = ALLOC(int, A->sf_size);
+ for(i = A->sf_size - 1; i >= 0; i--) {
+ count[i] = 0;
+ }
+
+ /* Loop for each set */
+ foreach_set(A, last, p) {
+ weight = 1024 / (set_ord(p) - 1);
+ for(i = LOOP(p); i > 0; ) {
+ for(val=p[i]&r[i], base= --i<<LOGBPI; val!=0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base] += weight;
+ }
+ }
+ }
+ }
+ return count;
+}
+
+
+/*
+ * sf_delc -- delete columns first ... last of A
+ */
+pset_family sf_delc(A, first, last)
+pset_family A;
+int first, last;
+{
+ return sf_delcol(A, first, last-first + 1);
+}
+
+
+/*
+ * sf_addcol -- add columns to a set family; includes a quick check to see
+ * if there is already enough room (and hence, can avoid copying)
+ */
+pset_family sf_addcol(A, firstcol, n)
+pset_family A;
+int firstcol, n;
+{
+ int maxsize;
+
+ /* Check if adding columns at the end ... */
+ if (firstcol == A->sf_size) {
+ /* If so, check if there is already enough room */
+ maxsize = BPI * LOOPINIT(A->sf_size);
+ if ((A->sf_size + n) <= maxsize) {
+ A->sf_size += n;
+ return A;
+ }
+ }
+ return sf_delcol(A, firstcol, -n);
+}
+
+/*
+ * sf_delcol -- add/delete columns to/from a set family
+ *
+ * if n > 0 then n columns starting from firstcol are deleted if n < 0
+ * then n blank columns are inserted starting at firstcol
+ * (i.e., the first new column number is firstcol)
+ *
+ * This is done by copying columns in the array which is a relatively
+ * slow operation.
+ */
+pset_family sf_delcol(A, firstcol, n)
+pset_family A;
+register int firstcol, n;
+{
+ register pset p, last, pdest;
+ register int i;
+ pset_family B;
+
+ B = sf_new(A->count, A->sf_size - n);
+ foreach_set(A, last, p) {
+ pdest = GETSET(B, B->count++);
+ INLINEset_clear(pdest, B->sf_size);
+ for(i = 0; i < firstcol; i++)
+ if (is_in_set(p, i))
+ set_insert(pdest, i);
+ for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++)
+ if (is_in_set(p, i))
+ set_insert(pdest, i - n);
+ }
+ sf_free(A);
+ return B;
+}
+
+
+/*
+ * sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst"
+ */
+pset_family sf_copy_col(dst, dstcol, src, srccol)
+pset_family dst, src;
+int dstcol, srccol;
+{
+ register pset last, p, pdest;
+ register int word_test, word_set;
+ unsigned int bit_set, bit_test;
+
+ /* CHEAT! form these constants outside the loop */
+ word_test = WHICH_WORD(srccol);
+ bit_test = 1 << WHICH_BIT(srccol);
+ word_set = WHICH_WORD(dstcol);
+ bit_set = 1 << WHICH_BIT(dstcol);
+
+ pdest = dst->data;
+ foreach_set(src, last, p) {
+ if ((p[word_test] & bit_test) != 0)
+ pdest[word_set] |= bit_set;
+/*
+ * equivalent code for this is ...
+ * if (is_in_set(p, srccol)) set_insert(pdest, destcol);
+ */
+ pdest += dst->wsize;
+ }
+ return dst;
+}
+
+
+
+/*
+ * sf_compress -- delete columns from a matrix
+ */
+pset_family sf_compress(A, c)
+pset_family A; /* will be freed */
+register pset c;
+{
+ register pset p;
+ register int i, bcol;
+ pset_family B;
+
+ /* create a clean set family for the result */
+ B = sf_new(A->count, set_ord(c));
+ for(i = 0; i < A->count; i++) {
+ p = GETSET(B, B->count++);
+ INLINEset_clear(p, B->sf_size);
+ }
+
+ /* copy each column of A which has a 1 in c */
+ bcol = 0;
+ for(i = 0; i < A->sf_size; i++) {
+ if (is_in_set(c, i)) {
+ (void) sf_copy_col(B, bcol++, A, i);
+ }
+ }
+ sf_free(A);
+ return B;
+}
+
+
+
+/*
+ * sf_transpose -- transpose a bit matrix
+ *
+ * There are trickier ways of doing this, but this works.
+ */
+pset_family sf_transpose(A)
+pset_family A;
+{
+ pset_family B;
+ register pset p;
+ register int i, j;
+
+ B = sf_new(A->sf_size, A->count);
+ B->count = A->sf_size;
+ foreachi_set(B, i, p) {
+ INLINEset_clear(p, B->sf_size);
+ }
+ foreachi_set(A, i, p) {
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(p, j)) {
+ set_insert(GETSET(B, j), i);
+ }
+ }
+ }
+ sf_free(A);
+ return B;
+}
+
+
+/*
+ * sf_permute -- permute the columns of a set_family
+ *
+ * permute is an array of integers containing column numbers of A which
+ * are to be retained.
+ */
+pset_family sf_permute(A, permute, npermute)
+pset_family A;
+register int *permute, npermute;
+{
+ pset_family B;
+ register pset p, last, pdest;
+ register int j;
+
+ B = sf_new(A->count, npermute);
+ B->count = A->count;
+ foreach_set(B, last, p)
+ INLINEset_clear(p, npermute);
+
+ pdest = B->data;
+ foreach_set(A, last, p) {
+ for(j = 0; j < npermute; j++)
+ if (is_in_set(p, permute[j]))
+ set_insert(pdest, j);
+ pdest += B->wsize;
+ }
+ sf_free(A);
+ return B;
+}
diff --git a/src/misc/espresso/setc.c b/src/misc/espresso/setc.c
new file mode 100644
index 00000000..a6112ebc
--- /dev/null
+++ b/src/misc/espresso/setc.c
@@ -0,0 +1,483 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ setc.c -- massive bit-hacking for performing special "cube"-type
+ operations on a set
+
+ The basic trick used for binary valued variables is the following:
+
+ If a[w] and b[w] contain a full word of binary variables, then:
+
+ 1) to get the full word of their intersection, we use
+
+ x = a[w] & b[w];
+
+
+ 2) to see if the intersection is null in any variables, we examine
+
+ x = ~(x | x >> 1) & DISJOINT;
+
+ this will have a single 1 in each binary variable for which
+ the intersection is null. In particular, if this is zero,
+ then there are no disjoint variables; or, if this is nonzero,
+ then there is at least one disjoint variable. A "count_ones"
+ over x will tell in how many variables they have an null
+ intersection.
+
+
+ 3) to get a mask which selects the disjoint variables, we use
+
+ (x | x << 1)
+
+ this provides a selector which can be used to see where
+ they have an null intersection
+
+
+ cdist return distance between two cubes
+ cdist0 return true if two cubes are distance 0 apart
+ cdist01 return distance, or 2 if distance exceeds 1
+ consensus compute consensus of two cubes distance 1 apart
+ force_lower expand hack (for now), related to consensus
+*/
+
+#include "espresso.h"
+
+/* see if the cube has a full row of 1's (with respect to cof) */
+bool full_row(p, cof)
+IN register pcube p, cof;
+{
+ register int i = LOOP(p);
+ do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/*
+ cdist0 -- return TRUE if a and b are distance 0 apart
+*/
+
+bool cdist0(a, b)
+register pcube a, b;
+{
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (~(x | x >> 1) & cube.inmask)
+ return FALSE; /* disjoint in some variable */
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (~(x | x >> 1) & DISJOINT)
+ return FALSE; /* disjoint in some variable */
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ return FALSE; /* disjoint in this variable */
+ nextvar: ;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ cdist01 -- return the "distance" between two cubes (defined as the
+ number of null variables in their intersection). If the distance
+ exceeds 1, the value 2 is returned.
+*/
+
+int cdist01(a, b)
+register pset a, b;
+{
+ int dist = 0;
+
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~ (x | x >> 1) & cube.inmask)
+ if ((dist = count_ones(x)) > 1)
+ return 2;
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~ (x | x >> 1) & DISJOINT)
+ if (dist == 1 || (dist += count_ones(x)) > 1)
+ return 2;
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ if (++dist > 1)
+ return 2;
+ nextvar: ;
+ }
+ }
+ return dist;
+}
+
+/*
+ cdist -- return the "distance" between two cubes (defined as the
+ number of null variables in their intersection).
+*/
+
+int cdist(a, b)
+register pset a, b;
+{
+ int dist = 0;
+
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~ (x | x >> 1) & cube.inmask)
+ dist = count_ones(x);
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~ (x | x >> 1) & DISJOINT)
+ dist += count_ones(x);
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ dist++;
+ nextvar: ;
+ }
+ }
+ return dist;
+}
+
+/*
+ force_lower -- Determine which variables of a do not intersect b.
+*/
+
+pset force_lower(xlower, a, b)
+INOUT pset xlower;
+IN register pset a, b;
+{
+
+ { /* Check binary variables (if any) */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~(x | x >> 1) & cube.inmask)
+ xlower[last] |= (x | (x << 1)) & a[last];
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~(x | x >> 1) & DISJOINT)
+ xlower[w] |= (x | (x << 1)) & a[w];
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ for(w = cube.first_word[var]; w <= last; w++)
+ xlower[w] |= a[w] & mask[w];
+ nextvar: ;
+ }
+ }
+ return xlower;
+}
+
+/*
+ consensus -- multiple-valued consensus
+
+ Although this looks very messy, the idea is to compute for r the
+ "and" of the cubes a and b for each variable, unless the "and" is
+ null in a variable, in which case the "or" of a and b is computed
+ for this variable.
+
+ Because we don't check how many variables are null in the
+ intersection of a and b, the returned value for r really only
+ represents the consensus when a and b are distance 1 apart.
+*/
+
+void consensus(r, a, b)
+INOUT pcube r;
+IN register pcube a, b;
+{
+ INLINEset_clear(r, cube.size);
+
+ { /* Check binary variables (if any) */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ r[last] = x = a[last] & b[last];
+ if (x = ~(x | x >> 1) & cube.inmask)
+ r[last] |= (x | (x << 1)) & (a[last] | b[last]);
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ r[w] = x = a[w] & b[w];
+ if (x = ~(x | x >> 1) & DISJOINT)
+ r[w] |= (x | (x << 1)) & (a[w] | b[w]);
+ }
+ }
+ }
+
+
+ { /* Check the multiple-valued variables */
+ bool empty; int var; unsigned int x;
+ register int w, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ last = cube.last_word[var];
+ empty = TRUE;
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (x = a[w] & b[w] & mask[w])
+ empty = FALSE, r[w] |= x;
+ if (empty)
+ for(w = cube.first_word[var]; w <= last; w++)
+ r[w] |= mask[w] & (a[w] | b[w]);
+ }
+ }
+}
+
+/*
+ cactive -- return the index of the single active variable in
+ the cube, or return -1 if there are none or more than 2.
+*/
+
+int cactive(a)
+register pcube a;
+{
+ int active = -1, dist = 0, bit_index();
+
+ { /* Check binary variables */
+ register int w, last;
+ register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last];
+ if (x = ~ (x & x >> 1) & cube.inmask) {
+ if ((dist = count_ones(x)) > 1)
+ return -1; /* more than 2 active variables */
+ active = (last-1)*(BPI/2) + bit_index(x) / 2;
+ }
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w];
+ if (x = ~ (x & x >> 1) & DISJOINT) {
+ if ((dist += count_ones(x)) > 1)
+ return -1; /* more than 2 active variables */
+ active = (w-1)*(BPI/2) + bit_index(x) / 2;
+ }
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last;
+ register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~ a[w]) {
+ if (++dist > 1)
+ return -1;
+ active = var;
+ break;
+ }
+ }
+ }
+ return active;
+}
+
+/*
+ ccommon -- return TRUE if a and b are share "active" variables
+ active variables include variables that are empty;
+*/
+
+bool ccommon(a, b, cof)
+register pcube a, b, cof;
+{
+ { /* Check binary variables */
+ int last;
+ register int w;
+ register unsigned int x, y;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] | cof[last];
+ y = b[last] | cof[last];
+ if (~(x & x>>1) & ~(y & y>>1) & cube.inmask)
+ return TRUE;
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] | cof[w];
+ y = b[w] | cof[w];
+ if (~(x & x>>1) & ~(y & y>>1) & DISJOINT)
+ return TRUE;
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ int var;
+ register int w, last;
+ register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ /* Check for some part missing from a */
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~a[w] & ~cof[w]) {
+
+ /* If so, check for some part missing from b */
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~b[w] & ~cof[w])
+ return TRUE; /* both active */
+ break;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ These routines compare two sets (cubes) for the qsort() routine and
+ return:
+
+ -1 if set a is to precede set b
+ 0 if set a and set b are equal
+ 1 if set a is to follow set b
+
+ Usually the SIZE field of the set is assumed to contain the size
+ of the set (which will save recomputing the set size during the
+ sort). For distance-1 merging, the global variable cube.temp[0] is
+ a mask which mask's-out the merging variable.
+*/
+
+/* descend -- comparison for descending sort on set size */
+int descend(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ if (SIZE(a1) > SIZE(b1)) return -1;
+ else if (SIZE(a1) < SIZE(b1)) return 1;
+ else {
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+ while (--i > 0);
+ }
+ return 0;
+}
+
+/* ascend -- comparison for ascending sort on set size */
+int ascend(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ if (SIZE(a1) > SIZE(b1)) return 1;
+ else if (SIZE(a1) < SIZE(b1)) return -1;
+ else {
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1;
+ while (--i > 0);
+ }
+ return 0;
+}
+
+
+/* lex_order -- comparison for "lexical" ordering of cubes */
+int lex_order(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+ while (--i > 0);
+ return 0;
+}
+
+
+/* d1_order -- comparison for distance-1 merge routine */
+int d1_order(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b, c1 = cube.temp[0];
+ register int i = LOOP(a1);
+ register unsigned int x1, x2;
+ do
+ if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1;
+ else if (x1 < x2) return 1;
+ while (--i > 0);
+ return 0;
+}
+
+
+/* desc1 -- comparison (without indirection) for descending sort */
+/* also has effect of handling NULL pointers,and a NULL pointer has smallest
+order */
+int desc1(a, b)
+register pset a, b;
+{
+ if (a == (pset) NULL)
+ return (b == (pset) NULL) ? 0 : 1;
+ else if (b == (pset) NULL)
+ return -1;
+ if (SIZE(a) > SIZE(b)) return -1;
+ else if (SIZE(a) < SIZE(b)) return 1;
+ else {
+ register int i = LOOP(a);
+ do
+ if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1;
+ while (--i > 0);
+ }
+ return 0;
+}
diff --git a/src/misc/espresso/sharp.c b/src/misc/espresso/sharp.c
new file mode 100644
index 00000000..53435078
--- /dev/null
+++ b/src/misc/espresso/sharp.c
@@ -0,0 +1,247 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ sharp.c -- perform sharp, disjoint sharp, and intersection
+*/
+
+#include "espresso.h"
+
+long start_time;
+
+
+/* cv_sharp -- form the sharp product between two covers */
+pcover cv_sharp(A, B)
+pcover A, B;
+{
+ pcube last, p;
+ pcover T;
+
+ T = new_cover(0);
+ foreach_set(A, last, p)
+ T = sf_union(T, cb_sharp(p, B));
+ return T;
+}
+
+
+/* cb_sharp -- form the sharp product between a cube and a cover */
+pcover cb_sharp(c, T)
+pcube c;
+pcover T;
+{
+ if (T->count == 0) {
+ T = sf_addset(new_cover(1), c);
+ } else {
+ start_time = ptime();
+ T = cb_recur_sharp(c, T, 0, T->count-1, 0);
+ }
+ return T;
+}
+
+
+/* recursive formulation to provide balanced merging */
+pcover cb_recur_sharp(c, T, first, last, level)
+pcube c;
+pcover T;
+int first, last, level;
+{
+ pcover temp, left, right;
+ int middle;
+
+ if (first == last) {
+ temp = sharp(c, GETSET(T, first));
+ } else {
+ middle = (first + last) / 2;
+ left = cb_recur_sharp(c, T, first, middle, level+1);
+ right = cb_recur_sharp(c, T, middle+1, last, level+1);
+ temp = cv_intersect(left, right);
+ if ((debug & SHARP) && level < 4) {
+ printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n",
+ level, temp->count, left->count, right->count,
+ print_time(ptime() - start_time));
+ (void) fflush(stdout);
+ }
+ free_cover(left);
+ free_cover(right);
+ }
+ return temp;
+}
+
+
+/* sharp -- form the sharp product between two cubes */
+pcover sharp(a, b)
+pcube a, b;
+{
+ register int var;
+ register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2];
+ pcover r = new_cover(cube.num_vars);
+
+ if (cdist0(a, b)) {
+ set_diff(d, a, b);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) {
+ set_diff(temp1, a, cube.var_mask[var]);
+ set_or(GETSET(r, r->count++), temp, temp1);
+ }
+ }
+ } else {
+ r = sf_addset(r, a);
+ }
+ return r;
+}
+
+pcover make_disjoint(A)
+pcover A;
+{
+ pcover R, new;
+ register pset last, p;
+
+ R = new_cover(0);
+ foreach_set(A, last, p) {
+ new = cb_dsharp(p, R);
+ R = sf_append(R, new);
+ }
+ return R;
+}
+
+
+/* cv_dsharp -- disjoint-sharp product between two covers */
+pcover cv_dsharp(A, B)
+pcover A, B;
+{
+ register pcube last, p;
+ pcover T;
+
+ T = new_cover(0);
+ foreach_set(A, last, p) {
+ T = sf_union(T, cb_dsharp(p, B));
+ }
+ return T;
+}
+
+
+/* cb1_dsharp -- disjoint-sharp product between a cover and a cube */
+pcover cb1_dsharp(T, c)
+pcover T;
+pcube c;
+{
+ pcube last, p;
+ pcover R;
+
+ R = new_cover(T->count);
+ foreach_set(T, last, p) {
+ R = sf_union(R, dsharp(p, c));
+ }
+ return R;
+}
+
+
+/* cb_dsharp -- disjoint-sharp product between a cube and a cover */
+pcover cb_dsharp(c, T)
+pcube c;
+pcover T;
+{
+ pcube last, p;
+ pcover Y, Y1;
+
+ if (T->count == 0) {
+ Y = sf_addset(new_cover(1), c);
+ } else {
+ Y = new_cover(T->count);
+ set_copy(GETSET(Y,Y->count++), c);
+ foreach_set(T, last, p) {
+ Y1 = cb1_dsharp(Y, p);
+ free_cover(Y);
+ Y = Y1;
+ }
+ }
+ return Y;
+}
+
+
+/* dsharp -- form the disjoint-sharp product between two cubes */
+pcover dsharp(a, b)
+pcube a, b;
+{
+ register pcube mask, diff, and, temp, temp1 = cube.temp[0];
+ int var;
+ pcover r;
+
+ r = new_cover(cube.num_vars);
+
+ if (cdist0(a, b)) {
+ diff = set_diff(new_cube(), a, b);
+ and = set_and(new_cube(), a, b);
+ mask = new_cube();
+ for(var = 0; var < cube.num_vars; var++) {
+ /* check if position var of "a and not b" is not empty */
+ if (! setp_disjoint(diff, cube.var_mask[var])) {
+
+ /* coordinate var equals the difference between a and b */
+ temp = GETSET(r, r->count++);
+ (void) set_and(temp, diff, cube.var_mask[var]);
+
+ /* coordinates 0 ... var-1 equal the intersection */
+ INLINEset_and(temp1, and, mask);
+ INLINEset_or(temp, temp, temp1);
+
+ /* coordinates var+1 .. cube.num_vars equal a */
+ set_or(mask, mask, cube.var_mask[var]);
+ INLINEset_diff(temp1, a, mask);
+ INLINEset_or(temp, temp, temp1);
+ }
+ }
+ free_cube(diff);
+ free_cube(and);
+ free_cube(mask);
+ } else {
+ r = sf_addset(r, a);
+ }
+ return r;
+}
+
+/* cv_intersect -- form the intersection of two covers */
+
+#define MAGIC 500 /* save 500 cubes before containment */
+
+pcover cv_intersect(A, B)
+pcover A, B;
+{
+ register pcube pi, pj, lasti, lastj, pt;
+ pcover T, Tsave = NULL;
+
+ /* How large should each temporary result cover be ? */
+ T = new_cover(MAGIC);
+ pt = T->data;
+
+ /* Form pairwise intersection of each cube of A with each cube of B */
+ foreach_set(A, lasti, pi) {
+ foreach_set(B, lastj, pj) {
+ if (cdist0(pi, pj)) {
+ (void) set_and(pt, pi, pj);
+ if (++T->count >= T->capacity) {
+ if (Tsave == NULL)
+ Tsave = sf_contain(T);
+ else
+ Tsave = sf_union(Tsave, sf_contain(T));
+ T = new_cover(MAGIC);
+ pt = T->data;
+ } else
+ pt += T->wsize;
+ }
+ }
+ }
+
+
+ if (Tsave == NULL)
+ Tsave = sf_contain(T);
+ else
+ Tsave = sf_union(Tsave, sf_contain(T));
+ return Tsave;
+}
diff --git a/src/misc/espresso/sminterf.c b/src/misc/espresso/sminterf.c
new file mode 100644
index 00000000..50a6db4e
--- /dev/null
+++ b/src/misc/espresso/sminterf.c
@@ -0,0 +1,44 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+pset
+do_sm_minimum_cover(A)
+pset_family A;
+{
+ sm_matrix *M;
+ sm_row *sparse_cover;
+ sm_element *pe;
+ pset cover;
+ register int i, base, rownum;
+ register unsigned val;
+ register pset last, p;
+
+ M = sm_alloc();
+ rownum = 0;
+ foreach_set(A, last, p) {
+ foreach_set_element(p, i, val, base) {
+ (void) sm_insert(M, rownum, base);
+ }
+ rownum++;
+ }
+
+ sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0);
+ sm_free(M);
+
+ cover = set_new(A->sf_size);
+ sm_foreach_row_element(sparse_cover, pe) {
+ set_insert(cover, pe->col_num);
+ }
+ sm_row_free(sparse_cover);
+
+ return cover;
+}
diff --git a/src/misc/espresso/solution.c b/src/misc/espresso/solution.c
new file mode 100644
index 00000000..26119185
--- /dev/null
+++ b/src/misc/espresso/solution.c
@@ -0,0 +1,114 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+solution_t *
+solution_alloc()
+{
+ solution_t *sol;
+
+ sol = ALLOC(solution_t, 1);
+ sol->cost = 0;
+ sol->row = sm_row_alloc();
+ return sol;
+}
+
+
+void
+solution_free(sol)
+solution_t *sol;
+{
+ sm_row_free(sol->row);
+ FREE(sol);
+}
+
+
+solution_t *
+solution_dup(sol)
+solution_t *sol;
+{
+ solution_t *new_sol;
+
+ new_sol = ALLOC(solution_t, 1);
+ new_sol->cost = sol->cost;
+ new_sol->row = sm_row_dup(sol->row);
+ return new_sol;
+}
+
+
+void
+solution_add(sol, weight, col)
+solution_t *sol;
+int *weight;
+int col;
+{
+ (void) sm_row_insert(sol->row, col);
+ sol->cost += WEIGHT(weight, col);
+}
+
+
+void
+solution_accept(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+ register sm_element *p, *pnext;
+ sm_col *pcol;
+
+ solution_add(sol, weight, col);
+
+ /* delete rows covered by this column */
+ pcol = sm_get_col(A, col);
+ for(p = pcol->first_row; p != 0; p = pnext) {
+ pnext = p->next_row; /* grab it before it disappears */
+ sm_delrow(A, p->row_num);
+ }
+}
+
+
+/* ARGSUSED */
+void
+solution_reject(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+ sm_delcol(A, col);
+}
+
+
+solution_t *
+solution_choose_best(best1, best2)
+solution_t *best1, *best2;
+{
+ if (best1 != NIL(solution_t)) {
+ if (best2 != NIL(solution_t)) {
+ if (best1->cost <= best2->cost) {
+ solution_free(best2);
+ return best1;
+ } else {
+ solution_free(best1);
+ return best2;
+ }
+ } else {
+ return best1;
+ }
+ } else {
+ if (best2 != NIL(solution_t)) {
+ return best2;
+ } else {
+ return NIL(solution_t);
+ }
+ }
+}
diff --git a/src/misc/espresso/sparse.c b/src/misc/espresso/sparse.c
new file mode 100644
index 00000000..137ce7c1
--- /dev/null
+++ b/src/misc/espresso/sparse.c
@@ -0,0 +1,146 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: sparse.c
+
+ make_sparse is a last-step cleanup to reduce the total number
+ of literals in the cover.
+
+ This is done by reducing the "sparse" variables (using a modified
+ version of irredundant rather than reduce), followed by expanding
+ the "dense" variables (using modified version of expand).
+*/
+
+#include "espresso.h"
+
+pcover make_sparse(F, D, R)
+pcover F, D, R;
+{
+ cost_t cost, best_cost;
+
+ cover_cost(F, &best_cost);
+
+ do {
+ EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost);
+ if (cost.total == best_cost.total)
+ break;
+ copy_cost(&cost, &best_cost);
+
+ EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost);
+ if (cost.total == best_cost.total)
+ break;
+ copy_cost(&cost, &best_cost);
+ } while (force_irredundant);
+
+ return F;
+}
+
+/*
+ mv_reduce -- perform an "optimal" reduction of the variables which
+ we desire to be sparse
+
+ This could be done using "reduce" and then saving just the desired
+ part of the reduction. Instead, this version uses IRRED to find
+ which cubes of an output are redundant. Note that this gets around
+ the cube-ordering problem.
+
+ In normal use, it is expected that the cover is irredundant and
+ hence no cubes will be reduced to the empty cube (however, this is
+ checked for and such cubes will be deleted)
+*/
+
+pcover
+mv_reduce(F, D)
+pcover F, D;
+{
+ register int i, var;
+ register pcube p, p1, last;
+ int index;
+ pcover F1, D1;
+ pcube *F_cube_table;
+
+ /* loop for each multiple-valued variable */
+ for(var = 0; var < cube.num_vars; var++) {
+
+ if (cube.sparse[var]) {
+
+ /* loop for each part of the variable */
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+
+ /* remember mapping of F1 cubes back to F cubes */
+ F_cube_table = ALLOC(pcube, F->count);
+
+ /* 'cofactor' against part #i of variable #var */
+ F1 = new_cover(F->count);
+ foreach_set(F, last, p) {
+ if (is_in_set(p, i)) {
+ F_cube_table[F1->count] = p;
+ p1 = GETSET(F1, F1->count++);
+ (void) set_diff(p1, p, cube.var_mask[var]);
+ set_insert(p1, i);
+ }
+ }
+
+ /* 'cofactor' against part #i of variable #var */
+ /* not really necessary -- just more efficient ? */
+ D1 = new_cover(D->count);
+ foreach_set(D, last, p) {
+ if (is_in_set(p, i)) {
+ p1 = GETSET(D1, D1->count++);
+ (void) set_diff(p1, p, cube.var_mask[var]);
+ set_insert(p1, i);
+ }
+ }
+
+ mark_irredundant(F1, D1);
+
+ /* now remove part i from cubes which are redundant */
+ index = 0;
+ foreach_set(F1, last, p1) {
+ if (! TESTP(p1, ACTIVE)) {
+ p = F_cube_table[index];
+
+ /* don't reduce a variable which is full
+ * (unless it is the output variable)
+ */
+ if (var == cube.num_vars-1 ||
+ ! setp_implies(cube.var_mask[var], p)) {
+ set_remove(p, i);
+ }
+ RESET(p, PRIME);
+ }
+ index++;
+ }
+
+ free_cover(F1);
+ free_cover(D1);
+ FREE(F_cube_table);
+ }
+ }
+ }
+
+ /* Check if any cubes disappeared */
+ (void) sf_active(F);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cube.sparse[var]) {
+ foreach_active_set(F, last, p) {
+ if (setp_disjoint(p, cube.var_mask[var])) {
+ RESET(p, ACTIVE);
+ F->active_count--;
+ }
+ }
+ }
+ }
+
+ if (F->count != F->active_count) {
+ F = sf_inactive(F);
+ }
+ return F;
+}
diff --git a/src/misc/espresso/sparse.h b/src/misc/espresso/sparse.h
new file mode 100644
index 00000000..212a32ed
--- /dev/null
+++ b/src/misc/espresso/sparse.h
@@ -0,0 +1,135 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#ifndef SPARSE_H
+#define SPARSE_H
+
+/*
+ * 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->first_col; p != 0; p = p->next_col)
+
+#define sm_foreach_col_element(pcol, p) \
+ for(p = 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_alloc(), *sm_alloc_size(), *sm_dup();
+extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize();
+extern void sm_write(), sm_print(), sm_dump(), sm_cleanup();
+extern void sm_copy_row(), sm_copy_col();
+extern void sm_remove(), sm_remove_element();
+extern sm_element *sm_insert(), *sm_find();
+extern sm_row *sm_longest_row();
+extern sm_col *sm_longest_col();
+extern int sm_read(), sm_read_compressed();
+
+extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and();
+extern void sm_row_free(), sm_row_remove(), sm_row_print();
+extern sm_element *sm_row_insert(), *sm_row_find();
+extern int sm_row_contains(), sm_row_intersects();
+extern int sm_row_compare(), sm_row_hash();
+
+extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and();
+extern void sm_col_free(), sm_col_remove(), sm_col_print();
+extern sm_element *sm_col_insert(), *sm_col_find();
+extern int sm_col_contains(), sm_col_intersects();
+extern int sm_col_compare(), sm_col_hash();
+
+extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition();
+
+#endif
diff --git a/src/misc/espresso/sparse_int.h b/src/misc/espresso/sparse_int.h
new file mode 100644
index 00000000..49b2509a
--- /dev/null
+++ b/src/misc/espresso/sparse_int.h
@@ -0,0 +1,121 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+
+#include "util_hack.h" // added
+
+
+
+/*
+ * 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();
+extern void sm_col_remove_element();
+
+/* LINTLIBRARY */
diff --git a/src/misc/espresso/unate.c b/src/misc/espresso/unate.c
new file mode 100644
index 00000000..bd71207f
--- /dev/null
+++ b/src/misc/espresso/unate.c
@@ -0,0 +1,441 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * unate.c -- routines for dealing with unate functions
+ */
+
+#include "espresso.h"
+
+static pset_family abs_covered();
+static pset_family abs_covered_many();
+static int abs_select_restricted();
+
+pcover map_cover_to_unate(T)
+pcube *T;
+{
+ register unsigned int word_test, word_set, bit_test, bit_set;
+ register pcube p, pA;
+ pset_family A;
+ pcube *T1;
+ int ncol, i;
+
+ A = sf_new(CUBELISTSIZE(T), cdata.vars_unate);
+ A->count = CUBELISTSIZE(T);
+ foreachi_set(A, i, p) {
+ (void) set_clear(p, A->sf_size);
+ }
+ ncol = 0;
+
+ for(i = 0; i < cube.size; i++) {
+ if (cdata.part_zeros[i] > 0) {
+ assert(ncol <= cdata.vars_unate);
+
+ /* Copy a column from T to A */
+ word_test = WHICH_WORD(i);
+ bit_test = 1 << WHICH_BIT(i);
+ word_set = WHICH_WORD(ncol);
+ bit_set = 1 << WHICH_BIT(ncol);
+
+ pA = A->data;
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if ((p[word_test] & bit_test) == 0) {
+ pA[word_set] |= bit_set;
+ }
+ pA += A->wsize;
+ }
+
+ ncol++;
+ }
+ }
+
+ return A;
+}
+
+pcover map_unate_to_cover(A)
+pset_family A;
+{
+ register int i, ncol, lp;
+ register pcube p, pB;
+ int var, nunate, *unate;
+ pcube last;
+ pset_family B;
+
+ B = sf_new(A->count, cube.size);
+ B->count = A->count;
+
+ /* Find the unate variables */
+ unate = ALLOC(int, cube.num_vars);
+ nunate = 0;
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ unate[nunate++] = var;
+ }
+ }
+
+ /* Loop for each set of A */
+ pB = B->data;
+ foreach_set(A, last, p) {
+
+ /* Initialize this set of B */
+ INLINEset_fill(pB, cube.size);
+
+ /* Now loop for the unate variables; if the part is in A,
+ * then this variable of B should be a single 1 in the unate
+ * part.
+ */
+ for(ncol = 0; ncol < nunate; ncol++) {
+ if (is_in_set(p, ncol)) {
+ lp = cube.last_part[unate[ncol]];
+ for(i = cube.first_part[unate[ncol]]; i <= lp; i++) {
+ if (cdata.part_zeros[i] == 0) {
+ set_remove(pB, i);
+ }
+ }
+ }
+ }
+ pB += B->wsize;
+ }
+
+ FREE(unate);
+ return B;
+}
+
+/*
+ * unate_compl
+ */
+
+pset_family unate_compl(A)
+pset_family A;
+{
+ register pset p, last;
+
+ /* Make sure A is single-cube containment minimal */
+/* A = sf_rev_contain(A);*/
+
+ foreach_set(A, last, p) {
+ PUTSIZE(p, set_ord(p));
+ }
+
+ /* Recursively find the complement */
+ A = unate_complement(A);
+
+ /* Now, we can guarantee a minimal result by containing the result */
+ A = sf_rev_contain(A);
+ return A;
+}
+
+
+/*
+ * Assume SIZE(p) records the size of each set
+ */
+pset_family unate_complement(A)
+pset_family A; /* disposes of A */
+{
+ pset_family Abar;
+ register pset p, p1, restrict;
+ register int i;
+ int max_i, min_set_ord, j;
+
+ /* Check for no sets in the matrix -- complement is the universe */
+ if (A->count == 0) {
+ sf_free(A);
+ Abar = sf_new(1, A->sf_size);
+ (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+
+ /* Check for a single set in the maxtrix -- compute de Morgan complement */
+ } else if (A->count == 1) {
+ p = A->data;
+ Abar = sf_new(A->sf_size, A->sf_size);
+ for(i = 0; i < A->sf_size; i++) {
+ if (is_in_set(p, i)) {
+ p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+ set_insert(p1, i);
+ }
+ }
+ sf_free(A);
+
+ } else {
+
+ /* Select splitting variable as the variable which belongs to a set
+ * of the smallest size, and which has greatest column count
+ */
+ restrict = set_new(A->sf_size);
+ min_set_ord = A->sf_size + 1;
+ foreachi_set(A, i, p) {
+ if (SIZE(p) < min_set_ord) {
+ set_copy(restrict, p);
+ min_set_ord = SIZE(p);
+ } else if (SIZE(p) == min_set_ord) {
+ set_or(restrict, restrict, p);
+ }
+ }
+
+ /* Check for no data (shouldn't happen ?) */
+ if (min_set_ord == 0) {
+ A->count = 0;
+ Abar = A;
+
+ /* Check for "essential" columns */
+ } else if (min_set_ord == 1) {
+ Abar = unate_complement(abs_covered_many(A, restrict));
+ sf_free(A);
+ foreachi_set(Abar, i, p) {
+ set_or(p, p, restrict);
+ }
+
+ /* else, recur as usual */
+ } else {
+ max_i = abs_select_restricted(A, restrict);
+
+ /* Select those rows of A which are not covered by max_i,
+ * recursively find all minimal covers of these rows, and
+ * then add back in max_i
+ */
+ Abar = unate_complement(abs_covered(A, max_i));
+ foreachi_set(Abar, i, p) {
+ set_insert(p, max_i);
+ }
+
+ /* Now recur on A with all zero's on column max_i */
+ foreachi_set(A, i, p) {
+ if (is_in_set(p, max_i)) {
+ set_remove(p, max_i);
+ j = SIZE(p) - 1;
+ PUTSIZE(p, j);
+ }
+ }
+
+ Abar = sf_append(Abar, unate_complement(A));
+ }
+ set_free(restrict);
+ }
+
+ return Abar;
+}
+
+pset_family exact_minimum_cover(T)
+IN pset_family T;
+{
+ register pset p, last, p1;
+ register int i, n;
+ int lev, lvl;
+ pset nlast;
+ pset_family temp;
+ long start = ptime();
+ struct {
+ pset_family sf;
+ int level;
+ } stack[32]; /* 32 suffices for 2 ** 32 cubes ! */
+
+ if (T->count <= 0)
+ return sf_new(1, T->sf_size);
+ for(n = T->count, lev = 0; n != 0; n >>= 1, lev++) ;
+
+ /* A simple heuristic ordering */
+ T = lex_sort(sf_save(T));
+
+ /* Push a full set on the stack to get things started */
+ n = 1;
+ stack[0].sf = sf_new(1, T->sf_size);
+ stack[0].level = lev;
+ set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size);
+
+ nlast = GETSET(T, T->count - 1);
+ foreach_set(T, last, p) {
+
+ /* "unstack" the set into a family */
+ temp = sf_new(set_ord(p), T->sf_size);
+ for(i = 0; i < T->sf_size; i++)
+ if (is_in_set(p, i)) {
+ p1 = set_fill(GETSET(temp, temp->count++), T->sf_size);
+ set_remove(p1, i);
+ }
+ stack[n].sf = temp;
+ stack[n++].level = lev;
+
+ /* Pop the stack and perform (leveled) intersections */
+ while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) {
+ temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE);
+ lvl = MIN(stack[n-1].level, stack[n-2].level) - 1;
+ if (debug & MINCOV && lvl < 10) {
+ printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n",
+ lvl, temp->count, stack[n-1].sf->count,
+ stack[n-2].sf->count, print_time(ptime() - start));
+ (void) fflush(stdout);
+ }
+ sf_free(stack[n-2].sf);
+ sf_free(stack[n-1].sf);
+ stack[n-2].sf = temp;
+ stack[n-2].level = lvl;
+ n--;
+ }
+ }
+
+ temp = stack[0].sf;
+ p1 = set_fill(set_new(T->sf_size), T->sf_size);
+ foreach_set(temp, last, p)
+ INLINEset_diff(p, p1, p);
+ set_free(p1);
+ if (debug & MINCOV1) {
+ printf("MINCOV: family of all minimal coverings is\n");
+ sf_print(temp);
+ }
+ sf_free(T); /* this is the copy of T we made ... */
+ return temp;
+}
+
+/*
+ * unate_intersect -- intersect two unate covers
+ *
+ * If largest_only is TRUE, then only the largest cube(s) are returned
+ */
+
+#define MAGIC 500 /* save 500 cubes before containment */
+
+pset_family unate_intersect(A, B, largest_only)
+pset_family A, B;
+bool largest_only;
+{
+ register pset pi, pj, lasti, lastj, pt;
+ pset_family T, Tsave;
+ bool save;
+ int maxord, ord;
+
+ /* How large should each temporary result cover be ? */
+ T = sf_new(MAGIC, A->sf_size);
+ Tsave = NULL;
+ maxord = 0;
+ pt = T->data;
+
+ /* Form pairwise intersection of each set of A with each cube of B */
+ foreach_set(A, lasti, pi) {
+
+ foreach_set(B, lastj, pj) {
+
+ save = set_andp(pt, pi, pj);
+
+ /* Check if we want the largest only */
+ if (save && largest_only) {
+ if ((ord = set_ord(pt)) > maxord) {
+ /* discard Tsave and T */
+ if (Tsave != NULL) {
+ sf_free(Tsave);
+ Tsave = NULL;
+ }
+ pt = T->data;
+ T->count = 0;
+ /* Re-create pt (which was just thrown away) */
+ (void) set_and(pt, pi, pj);
+ maxord = ord;
+ } else if (ord < maxord) {
+ save = FALSE;
+ }
+ }
+
+ if (save) {
+ if (++T->count >= T->capacity) {
+ T = sf_contain(T);
+ Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+ T = sf_new(MAGIC, A->sf_size);
+ pt = T->data;
+ } else {
+ pt += T->wsize;
+ }
+ }
+ }
+ }
+
+
+ /* Contain the final result and merge it into Tsave */
+ T = sf_contain(T);
+ Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+
+ return Tsave;
+}
+
+/*
+ * abs_covered -- after selecting a new column for the selected set,
+ * create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered(A, pick)
+pset_family A;
+register int pick;
+{
+ register pset last, p, pdest;
+ register pset_family Aprime;
+
+ Aprime = sf_new(A->count, A->sf_size);
+ pdest = Aprime->data;
+ foreach_set(A, last, p)
+ if (! is_in_set(p, pick)) {
+ INLINEset_copy(pdest, p);
+ Aprime->count++;
+ pdest += Aprime->wsize;
+ }
+ return Aprime;
+}
+
+
+/*
+ * abs_covered_many -- after selecting many columns for ther selected set,
+ * create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered_many(A, pick_set)
+pset_family A;
+register pset pick_set;
+{
+ register pset last, p, pdest;
+ register pset_family Aprime;
+
+ Aprime = sf_new(A->count, A->sf_size);
+ pdest = Aprime->data;
+ foreach_set(A, last, p)
+ if (setp_disjoint(p, pick_set)) {
+ INLINEset_copy(pdest, p);
+ Aprime->count++;
+ pdest += Aprime->wsize;
+ }
+ return Aprime;
+}
+
+
+/*
+ * abs_select_restricted -- select the column of maximum column count which
+ * also belongs to the set "restrict"; weight each column of a set as
+ * 1 / (set_ord(p) - 1).
+ */
+static int
+abs_select_restricted(A, restrict)
+pset_family A;
+pset restrict;
+{
+ register int i, best_var, best_count, *count;
+
+ /* Sum the elements in these columns */
+ count = sf_count_restricted(A, restrict);
+
+ /* Find which variable has maximum weight */
+ best_var = -1;
+ best_count = 0;
+ for(i = 0; i < A->sf_size; i++) {
+ if (count[i] > best_count) {
+ best_var = i;
+ best_count = count[i];
+ }
+ }
+ FREE(count);
+
+ if (best_var == -1)
+ fatal("abs_select_restricted: should not have best_var == -1");
+
+ return best_var;
+}
diff --git a/src/misc/espresso/util_old.h b/src/misc/espresso/util_old.h
new file mode 100644
index 00000000..5451cbe9
--- /dev/null
+++ b/src/misc/espresso/util_old.h
@@ -0,0 +1,301 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/util/RCS/util.h,v $
+ * $Author: sis $
+ * $Revision: 1.9 $
+ * $Date: 1993/06/07 21:04:07 $
+ *
+ */
+#ifndef UTIL_H
+#define UTIL_H
+
+#if defined(_IBMR2)
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE /* Argh! IBM strikes again */
+#endif
+#ifndef _ALL_SOURCE
+#define _ALL_SOURCE /* Argh! IBM strikes again */
+#endif
+#ifndef _ANSI_C_SOURCE
+#define _ANSI_C_SOURCE /* Argh! IBM strikes again */
+#endif
+#endif
+
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__)
+#include <unistd.h>
+#endif
+
+#if defined(_IBMR2) && !defined(__STDC__)
+#define _BSD
+#endif
+
+#include "ansi.h" /* since some files don't include sis.h */
+
+/* This was taken out and defined at compile time in the SIS Makefile
+ that uses the OctTools. When the OctTools are used, USE_MM is defined,
+ because the OctTools contain libmm.a. Otherwise, USE_MM is not defined,
+ since the mm package is not distributed with SIS, only with Oct. */
+
+/* #define USE_MM */ /* choose libmm.a as the memory allocator */
+
+#define NIL(type) ((type *) 0)
+
+#ifdef USE_MM
+/*
+ * assumes the memory manager is libmm.a
+ * - 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((char *) obj, sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) \
+ ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#else
+/*
+ * enforce strict semantics on the memory allocator
+ * - when in doubt, delete the '#define USE_MM' above
+ */
+#define ALLOC(type, num) \
+ ((type *) MMalloc((long) sizeof(type) * (long) (num)))
+#define REALLOC(type, obj, num) \
+ ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num)))
+#define FREE(obj) \
+ ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
+#endif
+
+
+/* Ultrix (and SABER) have 'fixed' certain functions which used to be int */
+#if defined(ultrix) || defined(SABER) || defined(aiws) || defined(__hpux) || defined(__STDC__) || defined(apollo)
+#define VOID_HACK void
+#else
+#define VOID_HACK int
+#endif
+
+
+/* No machines seem to have much of a problem with these */
+#include <stdio.h>
+#include <ctype.h>
+
+
+/* Some machines fail to define some functions in stdio.h */
+#if !defined(__STDC__) && !defined(sprite) && !defined(_IBMR2) && !defined(__osf__)
+extern FILE *popen(), *tmpfile();
+extern int pclose();
+#ifndef clearerr /* is a macro on many machines, but not all */
+extern VOID_HACK clearerr();
+#endif
+#ifndef rewind
+extern VOID_HACK rewind();
+#endif
+#endif
+
+#ifndef PORT_H
+#include <sys/types.h>
+#include <signal.h>
+#if defined(ultrix)
+#if defined(_SIZE_T_)
+#define ultrix4
+#else
+#if defined(SIGLOST)
+#define ultrix3
+#else
+#define ultrix2
+#endif
+#endif
+#endif
+#endif
+
+/* most machines don't give us a header file for these */
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) || defined(sunos4) || defined(__hpux)
+#include <stdlib.h>
+#if defined(__hpux)
+#include <errno.h> /* For perror() defininition */
+#endif /* __hpux */
+#else
+extern VOID_HACK abort(), free(), exit(), perror();
+extern char *getenv();
+#ifdef ultrix4
+extern void *malloc(), *realloc(), *calloc();
+#else
+extern char *malloc(), *realloc(), *calloc();
+#endif
+#if defined(aiws)
+extern int sprintf();
+#else
+#ifndef _IBMR2
+extern char *sprintf();
+#endif
+#endif
+extern int system();
+extern double atof();
+#endif
+
+#ifndef PORT_H
+#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) || defined(__STDC__)
+#define SIGNAL_FN void
+#else
+/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */
+#define SIGNAL_FN int
+#endif
+#endif
+
+/* some call it strings.h, some call it string.h; others, also have memory.h */
+#if defined(__STDC__) || defined(sprite)
+#include <string.h>
+#else
+#if defined(ultrix4) || defined(__hpux)
+#include <strings.h>
+#else
+#if defined(_IBMR2) || defined(__osf__)
+#include<string.h>
+#include<strings.h>
+#else
+/* ANSI C string.h -- 1/11/88 Draft Standard */
+/* ugly, awful hack */
+#ifndef PORT_H
+extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror();
+extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr();
+extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn();
+extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset();
+extern int memcmp(), strcmp();
+#endif
+#endif
+#endif
+#endif
+
+/* a few extras */
+#if defined(__hpux)
+#define random() lrand48()
+#define srandom(a) srand48(a)
+#define bzero(a,b) memset(a, 0, b)
+#else
+#if !defined(__osf__) && !defined(linux)
+/* these are defined as macros in stdlib.h */
+extern VOID_HACK srandom();
+extern long random();
+#endif
+#endif
+
+/* code from sis-1.3 commented out below
+#if defined(__STDC__) || defined(sprite)
+#include <assert.h>
+#else
+#ifndef NDEBUG
+#define assert(ex) {\
+ if (! (ex)) {\
+ (void) fprintf(stderr,\
+ "Assertion failed: file %s, line %d\n\"%s\"\n",\
+ __FILE__, __LINE__, "ex");\
+ (void) fflush(stdout);\
+ abort();\
+ }\
+}
+#else
+#define assert(ex) {ex;}
+#endif
+#endif
+*/
+
+ /* Sunil 5/3/97:
+ sis-1.4: dont let the assert call go to the OS, since
+ much of the code in SIS has actual computation done in
+ the assert function. %$#$@@#! The OS version of assert
+ will do nothing if NDEBUG is set. We cant let that happen...
+ */
+# ifdef NDEBUG
+# define assert(ex) {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
+
+
+#define fail(why) {\
+ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+ __FILE__, __LINE__, why);\
+ (void) fflush(stdout);\
+ abort();\
+}
+
+
+#ifdef lint
+#undef putc /* correct lint '_flsbuf' bug */
+#undef ALLOC /* allow for lint -h flag */
+#undef REALLOC
+#define ALLOC(type, num) (((type *) 0) + (num))
+#define REALLOC(type, obj, num) ((obj) + (num))
+#endif
+
+/*
+#if !defined(__osf__)
+#define MAXPATHLEN 1024
+#endif
+*/
+
+/* These arguably do NOT belong in util.h */
+#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
+
+
+#ifndef USE_MM
+EXTERN void MMout_of_memory ARGS((long));
+EXTERN char *MMalloc ARGS((long));
+EXTERN char *MMrealloc ARGS((char *, long));
+EXTERN void MMfree ARGS((char *));
+#endif
+
+EXTERN void util_print_cpu_stats ARGS((FILE *));
+EXTERN long util_cpu_time ARGS((void));
+EXTERN void util_getopt_reset ARGS((void));
+EXTERN int util_getopt ARGS((int, char **, char *));
+EXTERN char *util_path_search ARGS((char *));
+EXTERN char *util_file_search ARGS((char *, char *, char *));
+EXTERN int util_pipefork ARGS((char **, FILE **, FILE **, int *));
+EXTERN char *util_print_time ARGS((long));
+EXTERN int util_save_image ARGS((char *, char *));
+EXTERN char *util_strsav ARGS((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 long getSoftDataLimit();
+
+#define ptime() util_cpu_time()
+#define print_time(t) util_print_time(t)
+
+/* util_getopt() global variables (ack !) */
+extern int util_optind;
+extern char *util_optarg;
+
+#include <math.h>
+#ifndef HUGE_VAL
+#ifndef HUGE
+#define HUGE 8.9884656743115790e+307
+#endif
+#define HUGE_VAL HUGE
+#endif
+#ifndef MAXINT
+#define MAXINT (1 << 30)
+#endif
+
+#include <varargs.h>
+#endif
diff --git a/src/misc/espresso/verify.c b/src/misc/espresso/verify.c
new file mode 100644
index 00000000..64342787
--- /dev/null
+++ b/src/misc/espresso/verify.c
@@ -0,0 +1,193 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ */
+
+#include "espresso.h"
+
+/*
+ * verify -- check that all minterms of F are contained in (Fold u Dold)
+ * and that all minterms of Fold are contained in (F u Dold).
+ */
+bool verify(F, Fold, Dold)
+pcover F, Fold, Dold;
+{
+ pcube p, last, *FD;
+ bool verify_error = FALSE;
+
+ /* Make sure the function didn't grow too large */
+ FD = cube2list(Fold, Dold);
+ foreach_set(F, last, p)
+ if (! cube_is_covered(FD, p)) {
+ printf("some minterm in F is not covered by Fold u Dold\n");
+ verify_error = TRUE;
+ if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ }
+ free_cubelist(FD);
+
+ /* Make sure minimized function covers the original function */
+ FD = cube2list(F, Dold);
+ foreach_set(Fold, last, p)
+ if (! cube_is_covered(FD, p)) {
+ printf("some minterm in Fold is not covered by F u Dold\n");
+ verify_error = TRUE;
+ if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ }
+ free_cubelist(FD);
+
+ return verify_error;
+}
+
+
+
+/*
+ * PLA_verify -- verify that two PLA's are identical
+ *
+ * If names are given, row and column permutations are done to make
+ * the comparison meaningful.
+ *
+ */
+bool PLA_verify(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+ /* Check if both have names given; if so, attempt to permute to
+ * match the names
+ */
+ if (PLA1->label != NULL && PLA1->label[0] != NULL &&
+ PLA2->label != NULL && PLA2->label[0] != NULL) {
+ PLA_permute(PLA1, PLA2);
+ } else {
+ (void) fprintf(stderr, "Warning: cannot permute columns without names\n");
+ return TRUE;
+ }
+
+ if (PLA1->F->sf_size != PLA2->F->sf_size) {
+ (void) fprintf(stderr, "PLA_verify: PLA's are not the same size\n");
+ return TRUE;
+ }
+
+ return verify(PLA2->F, PLA1->F, PLA1->D);
+}
+
+
+
+/*
+ * Permute the columns of PLA1 so that they match the order of PLA2
+ * Discard any columns of PLA1 which are not in PLA2
+ * Association is strictly by the names of the columns of the cover.
+ */
+PLA_permute(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+ register int i, j, *permute, npermute;
+ register char *labi;
+ char **label;
+
+ /* determine which columns of PLA1 to save, and place these in the list
+ * "permute"; the order in this list is the final output order
+ */
+ npermute = 0;
+ permute = ALLOC(int, PLA2->F->sf_size);
+ for(i = 0; i < PLA2->F->sf_size; i++) {
+ labi = PLA2->label[i];
+ for(j = 0; j < PLA1->F->sf_size; j++) {
+ if (strcmp(labi, PLA1->label[j]) == 0) {
+ permute[npermute++] = j;
+ break;
+ }
+ }
+ }
+
+ /* permute columns */
+ if (PLA1->F != NULL) {
+ PLA1->F = sf_permute(PLA1->F, permute, npermute);
+ }
+ if (PLA1->R != NULL) {
+ PLA1->R = sf_permute(PLA1->R, permute, npermute);
+ }
+ if (PLA1->D != NULL) {
+ PLA1->D = sf_permute(PLA1->D, permute, npermute);
+ }
+
+ /* permute the labels */
+ label = ALLOC(char *, cube.size);
+ for(i = 0; i < npermute; i++) {
+ label[i] = PLA1->label[permute[i]];
+ }
+ for(i = npermute; i < cube.size; i++) {
+ label[i] = NULL;
+ }
+ FREE(PLA1->label);
+ PLA1->label = label;
+
+ FREE(permute);
+}
+
+
+
+/*
+ * check_consistency -- test that the ON-set, OFF-set and DC-set form
+ * a partition of the boolean space.
+ */
+bool check_consistency(PLA)
+pPLA PLA;
+{
+ bool verify_error = FALSE;
+ pcover T;
+
+ T = cv_intersect(PLA->F, PLA->D);
+ if (T->count == 0)
+ printf("ON-SET and DC-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ T = cv_intersect(PLA->F, PLA->R);
+ if (T->count == 0)
+ printf("ON-SET and OFF-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ T = cv_intersect(PLA->D, PLA->R);
+ if (T->count == 0)
+ printf("DC-SET and OFF-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ if (tautology(cube3list(PLA->F, PLA->D, PLA->R)))
+ printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n");
+ else {
+ T = complement(cube3list(PLA->F, PLA->D, PLA->R));
+ printf("There are minterms left unspecified !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ free_cover(T);
+ }
+ (void) fflush(stdout);
+ return verify_error;
+}
diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h
new file mode 100644
index 00000000..314257a2
--- /dev/null
+++ b/src/misc/extra/extra.h
@@ -0,0 +1,626 @@
+/**CFile****************************************************************
+
+ FileName [extra.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Various reusable software utilities.]
+
+ Description [This library contains a number of operators and
+ traversal routines developed to extend the functionality of
+ CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/)
+ To compile your code with the library, #include "extra.h"
+ in your source files and link your project to CUDD and this
+ library. Use the library at your own risk and with caution.
+ Note that debugging of some operators still continues.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extra.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __EXTRA_H__
+#define __EXTRA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes */
+/*---------------------------------------------------------------------------*/
+
+// this include should be the first one in the list
+// it is used to catch memory leaks on Windows
+#include "leaks.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include "st.h"
+#include "cuddInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+#ifdef WIN32
+typedef unsigned __int64 uint64;
+#else
+typedef unsigned long long uint64;
+#endif
+
+/* constants of the manager */
+#define b0 Cudd_Not((dd)->one)
+#define b1 (dd)->one
+#define z0 (dd)->zero
+#define z1 (dd)->one
+#define a0 (dd)->zero
+#define a1 (dd)->one
+
+// hash key macros
+#define hashKey1(a,TSIZE) \
+((unsigned)(a) % TSIZE)
+
+#define hashKey2(a,b,TSIZE) \
+(((unsigned)(a) + (unsigned)(b) * DD_P1) % TSIZE)
+
+#define hashKey3(a,b,c,TSIZE) \
+(((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 ) % TSIZE)
+
+#define hashKey4(a,b,c,d,TSIZE) \
+((((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 + \
+ (unsigned)(d)) * DD_P3) % TSIZE)
+
+#define hashKey5(a,b,c,d,e,TSIZE) \
+(((((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 + \
+ (unsigned)(d)) * DD_P3 + (unsigned)(e)) * DD_P1) % TSIZE)
+
+#ifndef PRT
+#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
+#define PRTn(a,t) printf("%s = ", (a)); printf("%6.2f sec ", (float)(t)/(float)(CLOCKS_PER_SEC))
+#endif
+
+#ifndef PRTP
+#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0)
+#endif
+
+/*===========================================================================*/
+/* Various Utilities */
+/*===========================================================================*/
+
+/*=== extraBddAuto.c ========================================================*/
+
+extern DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc );
+extern DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG );
+extern DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG );
+extern DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc );
+extern DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc );
+extern DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc );
+extern DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc );
+
+extern DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace );
+extern DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace );
+
+extern DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace );
+extern DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace );
+extern DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace );
+extern DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace );
+extern DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace );
+
+extern DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA );
+extern DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA );
+extern DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA );
+extern DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA );
+
+extern DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars );
+extern DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations );
+
+/*=== extraBddCas.c =============================================================*/
+
+/* performs the binary encoding of the set of function using the given vars */
+extern DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars );
+/* solves the column encoding problem using a sophisticated method */
+extern DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple );
+/* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */
+extern st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel );
+/* collects the nodes under the cut starting from the given set of ADD nodes */
+extern int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel );
+/* find the profile of a DD (the number of edges crossing each level) */
+extern int Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel );
+
+/*=== extraBddMisc.c ========================================================*/
+
+extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute );
+extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f );
+extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF );
+extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int fShiftUp );
+extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag );
+extern void Extra_StopManager( DdManager * dd );
+extern void Extra_bddPrint( DdManager * dd, DdNode * F );
+extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 );
+extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp );
+extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar );
+extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 );
+extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax );
+extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall );
+extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support );
+extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support );
+extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF );
+extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc );
+extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop );
+extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst );
+extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f );
+extern int Extra_bddIsVar( DdNode * bFunc );
+extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars );
+extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars );
+extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars );
+extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F );
+extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut );
+
+/*=== extraBddKmap.c ================================================================*/
+
+/* displays the Karnaugh Map of a function */
+extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames );
+/* displays the Karnaugh Map of a relation */
+extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars );
+
+/*=== extraBddSymm.c =================================================================*/
+
+typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t;
+struct Extra_SymmInfo_t_ {
+ int nVars; // the number of variables in the support
+ int nVarsMax; // the number of variables in the DD manager
+ int nSymms; // the number of pair-wise symmetries
+ int nNodes; // the number of nodes in a ZDD (if applicable)
+ int * pVars; // the list of all variables present in the support
+ char ** pSymms; // the symmetry information
+};
+
+/* computes the classical symmetry information for the function - recursive */
+extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc );
+/* computes the classical symmetry information for the function - using naive approach */
+extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc );
+extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 );
+
+/* allocates the data structure */
+extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars );
+/* deallocates the data structure */
+extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * );
+/* print the contents the data structure */
+extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * );
+/* converts the ZDD into the Extra_SymmInfo_t structure */
+extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars );
+
+/* computes the classical symmetry information as a ZDD */
+extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */
+extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars );
+extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars );
+/* converts a set of variables into a set of singleton subsets */
+extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars );
+extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars );
+/* filters the set of variables using the support of the function */
+extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF );
+extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF );
+
+/* checks the possibility that the two vars are symmetric */
+extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 );
+extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars );
+
+/* build the set of all tuples of K variables out of N from the BDD cube */
+extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN );
+extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN );
+/* selects one subset from a ZDD representing the set of subsets */
+extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS );
+extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS );
+
+/*=== extraBddUnate.c =================================================================*/
+
+typedef struct Extra_UnateVar_t_ Extra_UnateVar_t;
+struct Extra_UnateVar_t_ {
+ unsigned iVar : 30; // index of the variable
+ unsigned Pos : 1; // 1 if positive unate
+ unsigned Neg : 1; // 1 if negative unate
+};
+
+typedef struct Extra_UnateInfo_t_ Extra_UnateInfo_t;
+struct Extra_UnateInfo_t_ {
+ int nVars; // the number of variables in the support
+ int nVarsMax; // the number of variables in the DD manager
+ int nUnate; // the number of unate variables
+ Extra_UnateVar_t * pVars; // the array of variables present in the support
+};
+
+/* allocates the data structure */
+extern Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars );
+/* deallocates the data structure */
+extern void Extra_UnateInfoDissolve( Extra_UnateInfo_t * );
+/* print the contents the data structure */
+extern void Extra_UnateInfoPrint( Extra_UnateInfo_t * );
+/* converts the ZDD into the Extra_SymmInfo_t structure */
+extern Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars );
+/* naive check of unateness of one variable */
+extern int Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar );
+
+/* computes the unateness information for the function */
+extern Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc );
+extern Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc );
+
+/* computes the classical symmetry information as a ZDD */
+extern DdNode * Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+extern DdNode * extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+
+/* converts a set of variables into a set of singleton subsets */
+extern DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars );
+extern DdNode * extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars );
+
+/*=== extraUtilBitMatrix.c ================================================================*/
+
+typedef struct Extra_BitMat_t_ Extra_BitMat_t;
+extern Extra_BitMat_t * Extra_BitMatrixStart( int nSize );
+extern void Extra_BitMatrixClean( Extra_BitMat_t * p );
+extern void Extra_BitMatrixStop( Extra_BitMat_t * p );
+extern void Extra_BitMatrixPrint( Extra_BitMat_t * p );
+extern int Extra_BitMatrixReadSize( Extra_BitMat_t * p );
+extern void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k );
+extern int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k );
+extern void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k );
+extern void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k );
+extern int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k );
+extern void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k );
+extern void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo );
+extern void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j );
+extern int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p );
+extern int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 );
+extern int Extra_BitMatrixIsClique( Extra_BitMat_t * p );
+
+/*=== extraUtilFile.c ========================================================*/
+
+extern char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 );
+extern char * Extra_FileNameExtension( char * FileName );
+extern char * Extra_FileNameAppend( char * pBase, char * pSuffix );
+extern char * Extra_FileNameGeneric( char * FileName );
+extern int Extra_FileSize( char * pFileName );
+extern char * Extra_FileRead( FILE * pFile );
+extern char * Extra_TimeStamp();
+extern char * Extra_StringAppend( char * pStrGiven, char * pStrAdd );
+extern unsigned Extra_ReadBinary( char * Buffer );
+extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits );
+extern int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars );
+extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars );
+extern void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars );
+extern void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars );
+extern void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine );
+
+/*=== extraUtilReader.c ========================================================*/
+
+typedef struct Extra_FileReader_t_ Extra_FileReader_t;
+extern Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName,
+ char * pCharsComment, char * pCharsStop, char * pCharsClean );
+extern void Extra_FileReaderFree( Extra_FileReader_t * p );
+extern char * Extra_FileReaderGetFileName( Extra_FileReader_t * p );
+extern int Extra_FileReaderGetFileSize( Extra_FileReader_t * p );
+extern int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p );
+extern void * Extra_FileReaderGetTokens( Extra_FileReader_t * p );
+extern int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken );
+
+/*=== extraUtilMemory.c ========================================================*/
+
+typedef struct Extra_MmFixed_t_ Extra_MmFixed_t;
+typedef struct Extra_MmFlex_t_ Extra_MmFlex_t;
+typedef struct Extra_MmStep_t_ Extra_MmStep_t;
+
+// fixed-size-block memory manager
+extern Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize );
+extern void Extra_MmFixedStop( Extra_MmFixed_t * p );
+extern char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p );
+extern void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry );
+extern void Extra_MmFixedRestart( Extra_MmFixed_t * p );
+extern int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p );
+extern int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p );
+// flexible-size-block memory manager
+extern Extra_MmFlex_t * Extra_MmFlexStart();
+extern void Extra_MmFlexStop( Extra_MmFlex_t * p );
+extern void Extra_MmFlexPrint( Extra_MmFlex_t * p );
+extern char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes );
+extern int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p );
+// hierarchical memory manager
+extern Extra_MmStep_t * Extra_MmStepStart( int nSteps );
+extern void Extra_MmStepStop( Extra_MmStep_t * p );
+extern char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes );
+extern void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes );
+extern int Extra_MmStepReadMemUsage( Extra_MmStep_t * p );
+
+/*=== extraUtilMisc.c ========================================================*/
+
+/* finds the smallest integer larger or equal than the logarithm */
+extern int Extra_Base2Log( unsigned Num );
+extern int Extra_Base2LogDouble( double Num );
+extern int Extra_Base10Log( unsigned Num );
+/* returns the power of two as a double */
+extern double Extra_Power2( int Num );
+extern int Extra_Power3( int Num );
+/* the number of combinations of k elements out of n */
+extern int Extra_NumCombinations( int k, int n );
+extern int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits );
+/* counts the number of 1s in the bitstring */
+extern int Extra_CountOnes( unsigned char * pBytes, int nBytes );
+/* the factorial of number */
+extern int Extra_Factorial( int n );
+/* the permutation of the given number of elements */
+extern char ** Extra_Permutations( int n );
+/* permutation and complementation of a truth table */
+unsigned Extra_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse );
+unsigned Extra_TruthPolarize( unsigned uTruth, int Polarity, int nVars );
+/* canonical forms of a truth table */
+extern unsigned Extra_TruthCanonN( unsigned uTruth, int nVars );
+extern unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars );
+extern unsigned Extra_TruthCanonP( unsigned uTruth, int nVars );
+extern unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars );
+extern unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars );
+/* canonical forms of 4-variable functions */
+extern void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap );
+extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax );
+/* permutation mapping */
+extern unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase );
+extern unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase );
+extern void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes );
+extern void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR );
+/* precomputing tables for permutation mapping */
+extern void ** Extra_ArrayAlloc( int nCols, int nRows, int Size );
+extern unsigned short ** Extra_TruthPerm43();
+extern unsigned ** Extra_TruthPerm53();
+extern unsigned ** Extra_TruthPerm54();
+/* bubble sort for small number of entries */
+extern void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing );
+/* for independence from CUDD */
+extern unsigned int Cudd_PrimeCopy( unsigned int p );
+
+/*=== extraUtilCanon.c ========================================================*/
+
+/* fast computation of N-canoninical form up to 6 inputs */
+extern int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes );
+
+/*=== extraUtilProgress.c ================================================================*/
+
+typedef struct ProgressBarStruct ProgressBar;
+
+extern ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal );
+extern void Extra_ProgressBarStop( ProgressBar * p );
+extern void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString );
+
+static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char * pString )
+{ if ( p && nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); }
+
+/*=== extraUtilTruth.c ================================================================*/
+
+static inline int Extra_Float2Int( float Val ) { return *((int *)&Val); }
+static inline float Extra_Int2Float( int Num ) { return *((float *)&Num); }
+static inline int Extra_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); }
+static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+
+static inline void Extra_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); }
+static inline void Extra_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); }
+static inline int Extra_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; }
+
+static inline int Extra_WordCountOnes( unsigned uWord )
+{
+ uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+ uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+ uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+ uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+ return (uWord & 0x0000FFFF) + (uWord>>16);
+}
+static inline int Extra_TruthCountOnes( unsigned * pIn, int nVars )
+{
+ int w, Counter = 0;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ Counter += Extra_WordCountOnes(pIn[w]);
+ return Counter;
+}
+static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn0[w] != pIn1[w] )
+ return 0;
+ return 1;
+}
+static inline int Extra_TruthIsConst0( unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn[w] )
+ return 0;
+ return 1;
+}
+static inline int Extra_TruthIsConst1( unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn[w] != ~(unsigned)0 )
+ return 0;
+ return 1;
+}
+static inline int Extra_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn1[w] & ~pIn2[w] )
+ return 0;
+ return 1;
+}
+static inline void Extra_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn[w];
+}
+static inline void Extra_TruthClear( unsigned * pOut, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = 0;
+}
+static inline void Extra_TruthFill( unsigned * pOut, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~(unsigned)0;
+}
+static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~pIn[w];
+}
+static inline void Extra_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & pIn1[w];
+}
+static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & ~pIn1[w];
+}
+static inline void Extra_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~(pIn0[w] & pIn1[w]);
+}
+static inline void Extra_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 )
+{
+ int w;
+ if ( fCompl0 && fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~(pIn0[w] | pIn1[w]);
+ }
+ else if ( fCompl0 && !fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~pIn0[w] & pIn1[w];
+ }
+ else if ( !fCompl0 && fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & ~pIn1[w];
+ }
+ else // if ( !fCompl0 && !fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & pIn1[w];
+ }
+}
+
+extern unsigned ** Extra_TruthElementary( int nVars );
+extern void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start );
+extern void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase );
+extern void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase );
+extern int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar );
+extern int Extra_TruthSupportSize( unsigned * pTruth, int nVars );
+extern int Extra_TruthSupport( unsigned * pTruth, int nVars );
+extern void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar );
+extern void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar );
+extern int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin );
+extern void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore );
+extern unsigned Extra_TruthHash( unsigned * pIn, int nWords );
+extern unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore );
+
+/*=== extraUtilUtil.c ================================================================*/
+
+#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
+
+#ifndef ALLOC
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#endif
+
+#ifndef FREE
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#endif
+
+#ifndef REALLOC
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+#endif
+
+
+extern long Extra_CpuTime();
+extern int Extra_GetSoftDataLimit();
+extern void Extra_UtilGetoptReset();
+extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring );
+extern char * Extra_UtilPrintTime( long t );
+extern char * Extra_UtilStrsav( char *s );
+extern char * Extra_UtilTildeExpand( char *fname );
+extern char * Extra_UtilFileSearch( char *file, char *path, char *mode );
+extern void (*Extra_UtilMMoutOfMemory)();
+
+extern char * globalUtilOptarg;
+extern int globalUtilOptind;
+
+/**AutomaticEnd***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EXTRA_H__ */
diff --git a/src/misc/extra/extraBddAuto.c b/src/misc/extra/extraBddAuto.c
new file mode 100644
index 00000000..21a969ba
--- /dev/null
+++ b/src/misc/extra/extraBddAuto.c
@@ -0,0 +1,1558 @@
+/**CFile****************************************************************
+
+ FileName [extraBddAuto.c]
+
+ PackageName [extra]
+
+ Synopsis [Computation of autosymmetries.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*
+ LinearSpace(f) = Space(f,f)
+
+ Space(f,g)
+ {
+ if ( f = const )
+ {
+ if ( f = g ) return 1;
+ else return 0;
+ }
+ if ( g = const ) return 0;
+ return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx');
+ }
+
+ Equations(s) = Pos(s) + Neg(s);
+
+ Pos(s)
+ {
+ if ( s = 0 ) return 1;
+ if ( s = 1 ) return 0;
+ if ( sx'= 0 ) return Pos(sx) + x;
+ if ( sx = 0 ) return Pos(sx');
+ return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)];
+ }
+
+ Neg(s)
+ {
+ if ( s = 0 ) return 1;
+ if ( s = 1 ) return 0;
+ if ( sx'= 0 ) return Neg(sx);
+ if ( sx = 0 ) return Neg(sx') + x;
+ return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)];
+ }
+
+
+ SpaceP(A)
+ {
+ if ( A = 0 ) return 1;
+ if ( A = 1 ) return 1;
+ return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax);
+ }
+
+ SpaceN(A)
+ {
+ if ( A = 0 ) return 1;
+ if ( A = 1 ) return 0;
+ return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax);
+ }
+
+
+ LinInd(A)
+ {
+ if ( A = const ) return 1;
+ if ( !LinInd(Ax') ) return 0;
+ if ( !LinInd(Ax) ) return 0;
+ if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0;
+ if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0;
+ return 1;
+ }
+
+ LinSumOdd(A)
+ {
+ if ( A = 0 ) return 0; // Odd0 ---e-- Odd1
+ if ( A = 1 ) return 1; // \ o
+ Odd0 = LinSumOdd(Ax'); // x is absent // \
+ Even0 = LinSumEven(Ax'); // x is absent // / o
+ Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1
+ Even1 = LinSumEven(Ax); // x is absent
+ return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)];
+ }
+
+ LinSumEven(A)
+ {
+ if ( A = 0 ) return 0;
+ if ( A = 1 ) return 0;
+ Odd0 = LinSumOdd(Ax'); // x is absent
+ Even0 = LinSumEven(Ax'); // x is absent
+ Odd1 = LinSumOdd(Ax); // x is present
+ Even1 = LinSumEven(Ax); // x is absent
+ return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)];
+ }
+
+*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc )
+{
+ int * pSupport;
+ int * pPermute;
+ int * pPermuteBack;
+ DdNode ** pCompose;
+ DdNode * bCube, * bTemp;
+ DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift;
+ int nSupp, Counter;
+ int i, lev;
+
+ // get the support
+ pSupport = ALLOC( int, ddMax(dd->size,dd->sizeZ) );
+ Extra_SupportArray( dd, bFunc, pSupport );
+ nSupp = 0;
+ for ( i = 0; i < dd->size; i++ )
+ if ( pSupport[i] )
+ nSupp++;
+
+ // make sure the manager has enough variables
+ if ( 2*nSupp > dd->size )
+ {
+ printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" );
+ fflush( stdout );
+ free( pSupport );
+ return NULL;
+ }
+
+ // create the permutation arrays
+ pPermute = ALLOC( int, dd->size );
+ pPermuteBack = ALLOC( int, dd->size );
+ pCompose = ALLOC( DdNode *, dd->size );
+ for ( i = 0; i < dd->size; i++ )
+ {
+ pPermute[i] = i;
+ pPermuteBack[i] = i;
+ pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] );
+ }
+
+ // remap the function in such a way that the variables are interleaved
+ Counter = 0;
+ bCube = b1; Cudd_Ref( bCube );
+ for ( lev = 0; lev < dd->size; lev++ )
+ if ( pSupport[ dd->invperm[lev] ] )
+ { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter;
+ pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter];
+ // var from level 2*Counter+1 should go back to the place of this var
+ pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev];
+ // the permutation should be defined in such a way that variable
+ // on level 2*Counter is replaced by an EXOR of itself and var on the next level
+ Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] );
+ pCompose[ dd->invperm[2*Counter] ] =
+ Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] );
+ Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] );
+ // add this variable to the cube
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // increment the counter
+ Counter ++;
+ }
+
+ // permute the functions
+ bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 );
+ // compose to gate the function depending on both vars
+ bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 );
+ // gate the vector space
+ // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] )
+ bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift );
+ bSpaceShift = Cudd_Not( bSpaceShift );
+ // permute the space back into the original mapping
+ bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ Cudd_RecursiveDeref( dd, bFunc2 );
+ Cudd_RecursiveDeref( dd, bSpaceShift );
+ Cudd_RecursiveDeref( dd, bCube );
+
+ for ( i = 0; i < dd->size; i++ )
+ Cudd_RecursiveDeref( dd, pCompose[i] );
+ free( pPermute );
+ free( pPermuteBack );
+ free( pCompose );
+ free( pSupport );
+
+ Cudd_Deref( bSpace );
+ return bSpace;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromFunction( dd, bF, bG );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromFunctionPos( dd, bFunc );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromFunctionNeg( dd, bFunc );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceCanonVars( dd, bSpace );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars )
+{
+ DdNode * bNegCube;
+ DdNode * bResult;
+ bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube );
+ bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bNegCube );
+ Cudd_Deref( bResult );
+ return bResult;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * zRes;
+ DdNode * zEquPos;
+ DdNode * zEquNeg;
+ zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos );
+ zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg );
+ zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes );
+ Cudd_RecursiveDerefZdd( dd, zEquPos );
+ Cudd_RecursiveDerefZdd( dd, zEquNeg );
+ Cudd_Deref( zRes );
+ return zRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * zRes;
+ do {
+ dd->reordered = 0;
+ zRes = extraBddSpaceEquationsPos( dd, bSpace );
+ } while (dd->reordered == 1);
+ return zRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * zRes;
+ do {
+ dd->reordered = 0;
+ zRes = extraBddSpaceEquationsNeg( dd, bSpace );
+ } while (dd->reordered == 1);
+ return zRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromMatrixPos( dd, zA );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromMatrixNeg( dd, zA );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of literals in one combination.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb )
+{
+ int Counter;
+ if ( zComb == z0 )
+ return 0;
+ Counter = 0;
+ for ( ; zComb != z1; zComb = cuddT(zComb) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description [Returns the array of ZDDs with the number equal to the number of
+ vars in the DD manager. If the given var is non-canonical, this array contains
+ the referenced ZDD representing literals in the corresponding EXOR equation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations )
+{
+ DdNode ** pzRes;
+ int * pVarsNonCan;
+ DdNode * zEquRem;
+ int iVarNonCan;
+ DdNode * zExor, * zTemp;
+
+ // get the set of non-canonical variables
+ pVarsNonCan = ALLOC( int, ddMax(dd->size,dd->sizeZ) );
+ Extra_SupportArray( dd, bFuncRed, pVarsNonCan );
+
+ // allocate storage for the EXOR sets
+ pzRes = ALLOC( DdNode *, dd->size );
+ memset( pzRes, 0, sizeof(DdNode *) * dd->size );
+
+ // go through all the equations
+ zEquRem = zEquations; Cudd_Ref( zEquRem );
+ while ( zEquRem != z0 )
+ {
+ // extract one product
+ zExor = Extra_zddSelectOneSubset( dd, zEquRem ); Cudd_Ref( zExor );
+ // remove it from the set
+ zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor ); Cudd_Ref( zEquRem );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+
+ // locate the non-canonical variable
+ iVarNonCan = -1;
+ for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) )
+ {
+ if ( pVarsNonCan[zTemp->index/2] == 1 )
+ {
+ assert( iVarNonCan == -1 );
+ iVarNonCan = zTemp->index/2;
+ }
+ }
+ assert( iVarNonCan != -1 );
+
+ if ( Extra_zddLitCountComb( dd, zExor ) > 1 )
+ pzRes[ iVarNonCan ] = zExor; // takes ref
+ else
+ Cudd_RecursiveDerefZdd( dd, zExor );
+ }
+ Cudd_RecursiveDerefZdd( dd, zEquRem );
+
+ free( pVarsNonCan );
+ return pzRes;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG )
+{
+ DdNode * bRes;
+ DdNode * bFR, * bGR;
+
+ bFR = Cudd_Regular( bF );
+ bGR = Cudd_Regular( bG );
+ if ( cuddIsConstant(bFR) )
+ {
+ if ( bF == bG )
+ return b1;
+ else
+ return b0;
+ }
+ if ( cuddIsConstant(bGR) )
+ return b0;
+ // both bFunc and bCore are not constants
+
+ // the operation is commutative - normalize the problem
+ if ( (unsigned)bF > (unsigned)bG )
+ return extraBddSpaceFromFunction(dd, bG, bF);
+
+
+ if ( bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bG0, * bG1;
+ DdNode * bTemp1, * bTemp2;
+ DdNode * bRes0, * bRes1;
+ int LevelF, LevelG;
+ int index;
+
+ LevelF = dd->perm[bFR->index];
+ LevelG = dd->perm[bGR->index];
+ if ( LevelF <= LevelG )
+ {
+ index = dd->invperm[LevelF];
+ if ( bFR != bF )
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+ }
+ else
+ {
+ index = dd->invperm[LevelG];
+ bF0 = bF1 = bF;
+ }
+
+ if ( LevelG <= LevelF )
+ {
+ if ( bGR != bG )
+ {
+ bG0 = Cudd_Not( cuddE(bGR) );
+ bG1 = Cudd_Not( cuddT(bGR) );
+ }
+ else
+ {
+ bG0 = cuddE(bGR);
+ bG1 = cuddT(bGR);
+ }
+ }
+ else
+ bG0 = bG1 = bG;
+
+ bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 );
+ if ( bTemp1 == NULL )
+ return NULL;
+ cuddRef( bTemp1 );
+
+ bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 );
+ if ( bTemp2 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ return NULL;
+ }
+ cuddRef( bTemp2 );
+
+
+ bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+
+
+ bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 );
+ if ( bTemp1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bTemp1 );
+
+ bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 );
+ if ( bTemp2 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ return NULL;
+ }
+ cuddRef( bTemp2 );
+
+ bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0));
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, index, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ // insert the result into cache
+ cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes);
+ return bRes;
+ }
+} /* end of extraBddSpaceFromFunction */
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF )
+{
+ DdNode * bRes, * bFR;
+ statLine( dd );
+
+ bFR = Cudd_Regular(bF);
+ if ( cuddIsConstant(bFR) )
+ return b1;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bPos0, * bPos1;
+ DdNode * bNeg0, * bNeg1;
+ DdNode * bRes0, * bRes1;
+
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+
+ bPos0 = extraBddSpaceFromFunctionPos( dd, bF0 );
+ if ( bPos0 == NULL )
+ return NULL;
+ cuddRef( bPos0 );
+
+ bPos1 = extraBddSpaceFromFunctionPos( dd, bF1 );
+ if ( bPos1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ return NULL;
+ }
+ cuddRef( bPos1 );
+
+ bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+
+
+ bNeg0 = extraBddSpaceFromFunctionNeg( dd, bF0 );
+ if ( bNeg0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bNeg0 );
+
+ bNeg1 = extraBddSpaceFromFunctionNeg( dd, bF1 );
+ if ( bNeg1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ return NULL;
+ }
+ cuddRef( bNeg1 );
+
+ bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes );
+ return bRes;
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF )
+{
+ DdNode * bRes, * bFR;
+ statLine( dd );
+
+ bFR = Cudd_Regular(bF);
+ if ( cuddIsConstant(bFR) )
+ return b0;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bPos0, * bPos1;
+ DdNode * bNeg0, * bNeg1;
+ DdNode * bRes0, * bRes1;
+
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+
+ bPos0 = extraBddSpaceFromFunctionNeg( dd, bF0 );
+ if ( bPos0 == NULL )
+ return NULL;
+ cuddRef( bPos0 );
+
+ bPos1 = extraBddSpaceFromFunctionNeg( dd, bF1 );
+ if ( bPos1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ return NULL;
+ }
+ cuddRef( bPos1 );
+
+ bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+
+
+ bNeg0 = extraBddSpaceFromFunctionPos( dd, bF0 );
+ if ( bNeg0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bNeg0 );
+
+ bNeg1 = extraBddSpaceFromFunctionPos( dd, bF1 );
+ if ( bNeg1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ return NULL;
+ }
+ cuddRef( bNeg1 );
+
+ bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes );
+ return bRes;
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceCanonVars().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF )
+{
+ DdNode * bRes, * bFR;
+ statLine( dd );
+
+ bFR = Cudd_Regular(bF);
+ if ( cuddIsConstant(bFR) )
+ return bF;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bRes, * bRes0;
+
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ if ( bF0 == b0 )
+ {
+ bRes = extraBddSpaceCanonVars( dd, bF1 );
+ if ( bRes == NULL )
+ return NULL;
+ }
+ else if ( bF1 == b0 )
+ {
+ bRes = extraBddSpaceCanonVars( dd, bF0 );
+ if ( bRes == NULL )
+ return NULL;
+ }
+ else
+ {
+ bRes0 = extraBddSpaceCanonVars( dd, bF0 );
+ if ( bRes0 == NULL )
+ return NULL;
+ cuddRef( bRes0 );
+
+ bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( dd,bRes0 );
+ return NULL;
+ }
+ cuddDeref( bRes0 );
+ }
+
+ cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes );
+ return bRes;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceEquationsPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF )
+{
+ DdNode * zRes;
+ statLine( dd );
+
+ if ( bF == b0 )
+ return z1;
+ if ( bF == b1 )
+ return z0;
+
+ if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF) )
+ return zRes;
+ else
+ {
+ DdNode * bFR, * bF0, * bF1;
+ DdNode * zPos0, * zPos1, * zNeg1;
+ DdNode * zRes, * zRes0, * zRes1;
+
+ bFR = Cudd_Regular(bF);
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ if ( bF0 == b0 )
+ {
+ zRes1 = extraBddSpaceEquationsPos( dd, bF1 );
+ if ( zRes1 == NULL )
+ return NULL;
+ cuddRef( zRes1 );
+
+ // add the current element to the set
+ zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes1);
+ return NULL;
+ }
+ cuddDeref( zRes1 );
+ }
+ else if ( bF1 == b0 )
+ {
+ zRes = extraBddSpaceEquationsPos( dd, bF0 );
+ if ( zRes == NULL )
+ return NULL;
+ }
+ else
+ {
+ zPos0 = extraBddSpaceEquationsPos( dd, bF0 );
+ if ( zPos0 == NULL )
+ return NULL;
+ cuddRef( zPos0 );
+
+ zPos1 = extraBddSpaceEquationsPos( dd, bF1 );
+ if ( zPos1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ return NULL;
+ }
+ cuddRef( zPos1 );
+
+ zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 );
+ if ( zNeg1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zNeg1 );
+
+
+ zRes0 = cuddZddIntersect( dd, zPos0, zPos1 );
+ if ( zRes0 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes0 );
+
+ zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes1 );
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ // only zRes0 and zRes1 are refed at this point
+
+ zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zRes1);
+ return NULL;
+ }
+ cuddDeref( zRes0 );
+ cuddDeref( zRes1 );
+ }
+
+ cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes );
+ return zRes;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF )
+{
+ DdNode * zRes;
+ statLine( dd );
+
+ if ( bF == b0 )
+ return z1;
+ if ( bF == b1 )
+ return z0;
+
+ if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF) )
+ return zRes;
+ else
+ {
+ DdNode * bFR, * bF0, * bF1;
+ DdNode * zPos0, * zPos1, * zNeg1;
+ DdNode * zRes, * zRes0, * zRes1;
+
+ bFR = Cudd_Regular(bF);
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ if ( bF0 == b0 )
+ {
+ zRes = extraBddSpaceEquationsNeg( dd, bF1 );
+ if ( zRes == NULL )
+ return NULL;
+ }
+ else if ( bF1 == b0 )
+ {
+ zRes0 = extraBddSpaceEquationsNeg( dd, bF0 );
+ if ( zRes0 == NULL )
+ return NULL;
+ cuddRef( zRes0 );
+
+ // add the current element to the set
+ zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ return NULL;
+ }
+ cuddDeref( zRes0 );
+ }
+ else
+ {
+ zPos0 = extraBddSpaceEquationsNeg( dd, bF0 );
+ if ( zPos0 == NULL )
+ return NULL;
+ cuddRef( zPos0 );
+
+ zPos1 = extraBddSpaceEquationsNeg( dd, bF1 );
+ if ( zPos1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ return NULL;
+ }
+ cuddRef( zPos1 );
+
+ zNeg1 = extraBddSpaceEquationsPos( dd, bF1 );
+ if ( zNeg1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zNeg1 );
+
+
+ zRes0 = cuddZddIntersect( dd, zPos0, zPos1 );
+ if ( zRes0 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes0 );
+
+ zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes1 );
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ // only zRes0 and zRes1 are refed at this point
+
+ zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zRes1);
+ return NULL;
+ }
+ cuddDeref( zRes0 );
+ cuddDeref( zRes1 );
+ }
+
+ cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes );
+ return zRes;
+ }
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ statLine( dd );
+
+ if ( zA == z0 )
+ return b1;
+ if ( zA == z1 )
+ return b1;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA) )
+ return bRes;
+ else
+ {
+ DdNode * bP0, * bP1;
+ DdNode * bN0, * bN1;
+ DdNode * bRes0, * bRes1;
+
+ bP0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) );
+ if ( bP0 == NULL )
+ return NULL;
+ cuddRef( bP0 );
+
+ bP1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) );
+ if ( bP1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ return NULL;
+ }
+ cuddRef( bP1 );
+
+ bRes0 = cuddBddAndRecur( dd, bP0, bP1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+
+
+ bN0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) );
+ if ( bN0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bN0 );
+
+ bN1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) );
+ if ( bN1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ return NULL;
+ }
+ cuddRef( bN1 );
+
+ bRes1 = cuddBddAndRecur( dd, bN0, bN1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes );
+ return bRes;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ statLine( dd );
+
+ if ( zA == z0 )
+ return b1;
+ if ( zA == z1 )
+ return b0;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA) )
+ return bRes;
+ else
+ {
+ DdNode * bP0, * bP1;
+ DdNode * bN0, * bN1;
+ DdNode * bRes0, * bRes1;
+
+ bP0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
+ if ( bP0 == NULL )
+ return NULL;
+ cuddRef( bP0 );
+
+ bP1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) );
+ if ( bP1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ return NULL;
+ }
+ cuddRef( bP1 );
+
+ bRes0 = cuddBddAndRecur( dd, bP0, bP1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+
+
+ bN0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
+ if ( bN0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bN0 );
+
+ bN1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) );
+ if ( bN1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ return NULL;
+ }
+ cuddRef( bN1 );
+
+ bRes1 = cuddBddAndRecur( dd, bN0, bN1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes );
+ return bRes;
+ }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions */
+/*---------------------------------------------------------------------------*/
+
diff --git a/src/misc/extra/extraBddCas.c b/src/misc/extra/extraBddCas.c
new file mode 100644
index 00000000..29382bfb
--- /dev/null
+++ b/src/misc/extra/extraBddCas.c
@@ -0,0 +1,1230 @@
+/**CFile****************************************************************
+
+ FileName [extraBddCas.c]
+
+ PackageName [extra]
+
+ Synopsis [Procedures related to LUT cascade synthesis.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+// the table to store cofactor operations
+#define _TABLESIZE_COF 51113
+typedef struct
+{
+ unsigned Sign;
+ DdNode * Arg1;
+} _HashEntry_cof;
+_HashEntry_cof HHTable1[_TABLESIZE_COF];
+
+// the table to store the result of computation of the number of minterms
+#define _TABLESIZE_MINT 15113
+typedef struct
+{
+ DdNode * Arg1;
+ unsigned Arg2;
+ unsigned Res;
+} _HashEntry_mint;
+_HashEntry_mint HHTable2[_TABLESIZE_MINT];
+
+typedef struct
+{
+ int nEdges; // the number of in-coming edges of the node
+ DdNode * bSum; // the sum of paths of the incoming edges
+} traventry;
+
+// the signature used for hashing
+static unsigned s_Signature = 1;
+
+static int s_CutLevel = 0;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+// because the proposed solution to the optimal encoding problem has exponential complexity
+// we limit the depth of the branch and bound procedure to 5 levels
+static int s_MaxDepth = 5;
+
+static int s_nVarsBest; // the number of vars in the best ordering
+static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding"
+static int s_VarOrderCur[32]; // storing the current ordering of vars
+
+// the place to store the supports of the encoded function
+static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth
+static DdNode * s_Encoded; // this is the original function
+static DdNode * s_VarAll; // the set of all column variables
+static int s_MultiStart; // the total number of encoding variables used
+// the array field now stores the supports
+
+static DdNode ** s_pbTemp; // the temporary storage for the columns
+
+static int s_BackTracks;
+static int s_BackTrackLimit = 100;
+
+static DdNode * s_Terminal; // the terminal value for counting minterms
+
+
+static int s_EncodingVarsLevel;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars );
+static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level );
+// functions called from EvaluateEncodings_rec()
+static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
+static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
+unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll );
+static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max );
+
+static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited );
+static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs the binary encoding of the set of function using the given vars.]
+
+ Description [Performs a straight binary encoding of the set of functions using
+ the variable cubes formed from the given set of variables. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+Extra_bddEncodingBinary(
+ DdManager * dd,
+ DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded
+ int nFuncs, // nFuncs is the number of columns in the array
+ DdNode ** pbVars, // pbVars is the array of variables to use for the codes
+ int nVars ) // nVars is the column multiplicity, [log2(nFuncs)]
+{
+ int i;
+ DdNode * bResult;
+ DdNode * bCube, * bTemp, * bProd;
+
+ assert( nVars >= Extra_Base2Log(nFuncs) );
+
+ bResult = b0; Cudd_Ref( bResult );
+ for ( i = 0; i < nFuncs; i++ )
+ {
+ bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube );
+ bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bCube );
+
+ bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+
+ Cudd_Deref( bResult );
+ return bResult;
+} /* end of Extra_bddEncodingBinary */
+
+
+/**Function********************************************************************
+
+ Synopsis [Solves the column encoding problem using a sophisticated method.]
+
+ Description [The encoding is based on the idea of deriving functions which
+ depend on only one variable, which corresponds to the case of non-disjoint
+ decompostion. It is assumed that the variables pCVars are ordered below the variables
+ representing the solumns, and the first variable pCVars[0] is the topmost one.]
+
+ SideEffects []
+
+ SeeAlso [Extra_bddEncodingBinary]
+
+******************************************************************************/
+
+DdNode *
+Extra_bddEncodingNonStrict(
+ DdManager * dd,
+ DdNode ** pbColumns, // pbColumns is the array of columns to be encoded;
+ int nColumns, // nColumns is the number of columns in the array
+ DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend
+ DdNode ** pCVars, // pCVars is the array of variables to use for the codes
+ int nMulti, // nMulti is the column multiplicity, [log2(nColumns)]
+ int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change
+{
+ DdNode * bEncoded, * bResult;
+ int nVarsCol = Cudd_SupportSize(dd,bVarsCol);
+ long clk;
+
+ // cannot work with more that 32-bit codes
+ assert( nMulti < 32 );
+
+ // perform the preliminary encoding using the straight binary code
+ bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded );
+ //printf( "Node count = %d", Cudd_DagSize(bEncoded) );
+
+ // set the backgroup value for counting minterms
+ s_Terminal = b0;
+ // set the level of the encoding variables
+ s_EncodingVarsLevel = dd->invperm[pCVars[0]->index];
+
+ // the current number of backtracks
+ s_BackTracks = 0;
+ // the variables that are cofactored on the topmost level where everything starts (no vars)
+ s_Field[0][0] = b1;
+ // the size of the best set of "simple" encoding variables found so far
+ s_nVarsBest = 0;
+
+ // set the relation to be accessible to traversal procedures
+ s_Encoded = bEncoded;
+ // the set of all vars to be accessible to traversal procedures
+ s_VarAll = bVarsCol;
+ // the column multiplicity
+ s_MultiStart = nMulti;
+
+
+ clk = clock();
+ // find the simplest encoding
+ if ( nColumns > 2 )
+ EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 );
+// printf( "The number of backtracks = %d\n", s_BackTracks );
+// s_EncSearchTime += clock() - clk;
+
+ // allocate the temporary storage for the columns
+ s_pbTemp = (DdNode **) malloc( nColumns * sizeof(DdNode *) );
+
+// clk = clock();
+ bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult );
+// s_EncComputeTime += clock() - clk;
+
+ // delocate the preliminarily encoded set
+ Cudd_RecursiveDeref( dd, bEncoded );
+// Cudd_RecursiveDeref( dd, aEncoded );
+
+ free( s_pbTemp );
+
+ *pSimple = s_nVarsBest;
+ Cudd_Deref( bResult );
+ return bResult;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.]
+
+ Description [The table returned contains the set of BDD nodes pointed to under the cut
+ and, for each node, the BDD of the sum of paths leading to this node from the root
+ The sums of paths in the table are referenced. CutLevel is the first DD level
+ considered to be under the cut.]
+
+ SideEffects []
+
+ SeeAlso [Extra_bddNodePaths]
+
+******************************************************************************/
+st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel )
+{
+ st_table * Visited; // temporary table to remember the visited nodes
+ st_table * CutNodes; // the result goes here
+ st_table * Result; // the result goes here
+ DdNode * aFunc;
+
+ s_CutLevel = CutLevel;
+
+ Result = st_init_table(st_ptrcmp,st_ptrhash);
+ // the terminal cases
+ if ( Cudd_IsConstant( bFunc ) )
+ {
+ if ( bFunc == b1 )
+ {
+ st_insert( Result, (char*)b1, (char*)b1 );
+ Cudd_Ref( b1 );
+ Cudd_Ref( b1 );
+ }
+ else
+ {
+ st_insert( Result, (char*)b0, (char*)b0 );
+ Cudd_Ref( b0 );
+ Cudd_Ref( b0 );
+ }
+ return Result;
+ }
+
+ // create the ADD to simplify processing (no complemented edges)
+ aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc );
+
+ // Step 1: Start the tables and collect information about the nodes above the cut
+ // this information tells how many edges point to each node
+ Visited = st_init_table(st_ptrcmp,st_ptrhash);
+ CutNodes = st_init_table(st_ptrcmp,st_ptrhash);
+
+ CountNodeVisits_rec( dd, aFunc, Visited );
+
+ // Step 2: Traverse the BDD using the visited table and compute the sum of paths
+ CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes );
+
+ // at this point the table of cut nodes is ready and the table of visited is useless
+ {
+ st_generator * gen;
+ DdNode * aNode;
+ traventry * p;
+ st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p )
+ {
+ Cudd_RecursiveDeref( dd, p->bSum );
+ free( p );
+ }
+ st_free_table( Visited );
+ }
+
+ // go through the table CutNodes and create the BDD and the path to be returned
+ {
+ st_generator * gen;
+ DdNode * aNode, * bNode, * bSum;
+ st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum)
+ {
+ // aNode is not referenced, because aFunc is holding it
+ bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode );
+ st_insert( Result, (char*)bNode, (char*)bSum );
+ // the new table takes both refs
+ }
+ st_free_table( CutNodes );
+ }
+
+ // dereference the ADD
+ Cudd_RecursiveDeref( dd, aFunc );
+
+ // return the table
+ return Result;
+
+} /* end of Extra_bddNodePathsUnderCut */
+
+/**Function********************************************************************
+
+ Synopsis [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.]
+
+ Description [Takes the array, paNodes, of ADD nodes to start the traversal,
+ the array, pbCubes, of BDD cubes to start the traversal with in each node,
+ and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes.
+ Returns the number of columns found. Fills in paNodesRes (pbCubesRes)
+ with the set of ADD columns (BDD paths). These arrays should be allocated
+ by the user.]
+
+ SideEffects []
+
+ SeeAlso [Extra_bddNodePaths]
+
+******************************************************************************/
+int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel )
+{
+ st_table * Visited; // temporary table to remember the visited nodes
+ st_table * CutNodes; // the nodes under the cut go here
+ int i, Counter;
+
+ s_CutLevel = CutLevel;
+
+ // there should be some nodes
+ assert( nNodes > 0 );
+ if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) )
+ {
+ if ( paNodes[0] == a1 )
+ {
+ paNodesRes[0] = a1; Cudd_Ref( a1 );
+ pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] );
+ }
+ else
+ {
+ paNodesRes[0] = a0; Cudd_Ref( a0 );
+ pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] );
+ }
+ return 1;
+ }
+
+ // Step 1: Start the table and collect information about the nodes above the cut
+ // this information tells how many edges point to each node
+ CutNodes = st_init_table(st_ptrcmp,st_ptrhash);
+ Visited = st_init_table(st_ptrcmp,st_ptrhash);
+
+ for ( i = 0; i < nNodes; i++ )
+ CountNodeVisits_rec( dd, paNodes[i], Visited );
+
+ // Step 2: Traverse the BDD using the visited table and compute the sum of paths
+ for ( i = 0; i < nNodes; i++ )
+ CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes );
+
+ // at this point, the table of cut nodes is ready and the table of visited is useless
+ {
+ st_generator * gen;
+ DdNode * aNode;
+ traventry * p;
+ st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p )
+ {
+ Cudd_RecursiveDeref( dd, p->bSum );
+ free( p );
+ }
+ st_free_table( Visited );
+ }
+
+ // go through the table CutNodes and create the BDD and the path to be returned
+ {
+ st_generator * gen;
+ DdNode * aNode, * bSum;
+ Counter = 0;
+ st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum)
+ {
+ paNodesRes[Counter] = aNode; Cudd_Ref( aNode );
+ pbCubesRes[Counter] = bSum;
+ Counter++;
+ }
+ st_free_table( CutNodes );
+ }
+
+ // return the number of cofactors found
+ return Counter;
+
+} /* end of Extra_bddNodePathsUnderCutArray */
+
+/**Function*************************************************************
+
+ Synopsis [Collects all the BDD nodes into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void extraCollectNodes( DdNode * Func, st_table * tNodes )
+{
+ DdNode * FuncR;
+ FuncR = Cudd_Regular(Func);
+ if ( st_find_or_add( tNodes, (char*)FuncR, NULL ) )
+ return;
+ if ( cuddIsConstant(FuncR) )
+ return;
+ extraCollectNodes( cuddE(FuncR), tNodes );
+ extraCollectNodes( cuddT(FuncR), tNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects all the nodes of one DD into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+st_table * Extra_CollectNodes( DdNode * Func )
+{
+ st_table * tNodes;
+ tNodes = st_init_table( st_ptrcmp, st_ptrhash );
+ extraCollectNodes( Func, tNodes );
+ return tNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the topmost level from which the given node is referenced.]
+
+ Description [Takes the table which maps each BDD nodes (including the constants)
+ into the topmost level on which this node counts as a cofactor. Takes the topmost
+ level, on which this node counts as a cofactor (see Extra_ProfileWidthFast().
+ Takes the node, for which the table entry should be updated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void extraProfileUpdateTopLevel( st_table * tNodeTopRef, int TopLevelNew, DdNode * node )
+{
+ int * pTopLevel;
+
+ if ( st_find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) )
+ { // the node is already referenced
+ // the current top level should be updated if it is larger than the new level
+ if ( *pTopLevel > TopLevelNew )
+ *pTopLevel = TopLevelNew;
+ }
+ else
+ { // the node is not referenced
+ // its level should be set to the current new level
+ *pTopLevel = TopLevelNew;
+ }
+}
+/**Function*************************************************************
+
+ Synopsis [Fast computation of the BDD profile.]
+
+ Description [The array to store the profile is given by the user and should
+ contain at least as many entries as there is the maximum of the BDD/ZDD
+ size of the manager PLUS ONE.
+ When we say that the widths of the DD on level L is W, we mean the following.
+ Let us create the cut between the level L-1 and the level L and count the number
+ of different DD nodes pointed to across the cut. This number is the width W.
+ From this it follows the on level 0, the width is equal to the number of external
+ pointers to the considered DDs. If there is only one DD, then the profile on
+ level 0 is always 1. If this DD is rooted in the topmost variable, then the width
+ on level 1 is always 2, etc. The width at the level equal to dd->size is the
+ number of terminal nodes in the DD. (Because we consider the first level #0
+ and the last level #dd->size, the profile array should contain dd->size+1 entries.)
+ ]
+
+ SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs]
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel )
+{
+ st_generator * gen;
+ st_table * tNodeTopRef; // this table stores the top level from which this node is pointed to
+ st_table * tNodes;
+ DdNode * node;
+ DdNode * nodeR;
+ int LevelStart, Limit;
+ int i, size;
+ int WidthMax;
+
+ // start the mapping table
+ tNodeTopRef = st_init_table(st_ptrcmp,st_ptrhash);
+ // add the topmost node to the profile
+ extraProfileUpdateTopLevel( tNodeTopRef, 0, Func );
+
+ // collect all nodes
+ tNodes = Extra_CollectNodes( Func );
+ // go though all the nodes and set the top level the cofactors are pointed from
+// Cudd_ForeachNode( dd, Func, genDD, node )
+ st_foreach_item( tNodes, gen, (char**)&node, NULL )
+ {
+// assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges)
+ nodeR = Cudd_Regular(node);
+ if ( cuddIsConstant(nodeR) )
+ continue;
+ // this node is not a constant - consider its cofactors
+ extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) );
+ extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) );
+ }
+ st_free_table( tNodes );
+
+ // clean the profile
+ size = ddMax(dd->size, dd->sizeZ) + 1;
+ for ( i = 0; i < size; i++ )
+ pProfile[i] = 0;
+
+ // create the profile
+ st_foreach_item( tNodeTopRef, gen, (char**)&node, (char**)&LevelStart )
+ {
+ nodeR = Cudd_Regular(node);
+ Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index];
+ for ( i = LevelStart; i <= Limit; i++ )
+ pProfile[i]++;
+ }
+
+ if ( CutLevel != -1 && CutLevel != 0 )
+ size = CutLevel;
+
+ // get the max width
+ WidthMax = 0;
+ for ( i = 0; i < size; i++ )
+ if ( WidthMax < pProfile[i] )
+ WidthMax = pProfile[i];
+
+ // deref the table
+ st_free_table( tNodeTopRef );
+
+ return WidthMax;
+} /* end of Extra_ProfileWidth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Computes the non-strict codes when evaluation is finished.]
+
+ Description [The information about the best code is stored in s_VarOrderBest,
+ which has s_nVarsBest entries.]
+
+ SideEffects [None]
+
+******************************************************************************/
+DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars )
+// bEncoded is the preliminarily encoded set of columns
+// Level is the current level in the recursion
+// pCVars are the variables to be used for encoding
+{
+ DdNode * bRes;
+ if ( Level == s_nVarsBest )
+ { // the terminal case, when we need to remap the encoded function
+ // from the preliminary encoded variables to the new ones
+ st_table * CutNodes;
+ int nCols;
+// double nMints;
+/*
+#ifdef _DEBUG
+
+ {
+ DdNode * bTemp;
+ // make sure that the given number of variables is enough
+ bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp );
+// nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart );
+ nMints = Extra_CountMintermsSimple( bTemp, (1<<s_MultiStart) );
+ if ( nMints > Extra_Power2( s_MultiStart-Level ) )
+ { // the number of minterms is too large to encode the columns
+ // using the given minimum number of encoding variables
+ assert( 0 );
+ }
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+#endif
+*/
+ // get the columns to be re-encoded
+ CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel );
+ // LUT size is the cut level because because the temporary encoding variables
+ // are above the functional variables - this is not true!!!
+ // the temporary variables are below!
+
+ // put the entries from the table into the temporary array
+ {
+ st_generator * gen;
+ DdNode * bColumn, * bCode;
+ nCols = 0;
+ st_foreach_item( CutNodes, gen, (char**)&bCode, (char**)&bColumn )
+ {
+ if ( bCode == b0 )
+ { // the unused part of the columns
+ Cudd_RecursiveDeref( dd, bColumn );
+ Cudd_RecursiveDeref( dd, bCode );
+ continue;
+ }
+ else
+ {
+ s_pbTemp[ nCols ] = bColumn; // takes ref
+ Cudd_RecursiveDeref( dd, bCode );
+ nCols++;
+ }
+ }
+ st_free_table( CutNodes );
+// assert( nCols == (int)nMints );
+ }
+
+ // encode the columns
+ if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion
+ {
+ assert( nCols == 1 );
+// assert( (int)nMints == 1 );
+ bRes = s_pbTemp[0]; Cudd_Ref( bRes );
+ }
+ else
+ {
+ bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes );
+ }
+
+ // deref the columns
+ {
+ int i;
+ for ( i = 0; i < nCols; i++ )
+ Cudd_RecursiveDeref( dd, s_pbTemp[i] );
+ }
+ }
+ else
+ {
+ // cofactor the problem as specified in the best solution
+ DdNode * bCof0, * bCof1;
+ DdNode * bRes0, * bRes1;
+ DdNode * bProd0, * bProd1;
+ DdNode * bTemp;
+ DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ];
+
+ bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 );
+ bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 );
+
+ // call recursively
+ bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 );
+ bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 );
+
+ Cudd_RecursiveDeref( dd, bCof0 );
+ Cudd_RecursiveDeref( dd, bCof1 );
+
+ // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong!
+ // compose the result as follows: x'y'F0 + xyF1
+ bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 );
+ bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 );
+
+ bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bRes0 );
+
+ bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bRes1 );
+
+ bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes );
+
+ Cudd_RecursiveDeref( dd, bProd0 );
+ Cudd_RecursiveDeref( dd, bProd1 );
+ }
+ Cudd_Deref( bRes );
+ return bRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the current set of variables and counts the number of minterms.]
+
+ Description [Old implementation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level )
+// bVarsCol is the set of remaining variables
+// nVarsCol is the number of remaining variables
+// nMulti is the number of encoding variables to be used
+// Level is the level of recursion, from which this function is called
+// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved
+{
+ int i, k;
+ int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level
+ DdNode * bVars0, * bVars1; // the cofactors
+ unsigned nMint0, nMint1; // the number of minterms
+ DdNode * bTempV;
+ DdNode * bVarTop;
+ int fBreak;
+
+
+ // there is no need to search above this level
+ if ( Level > s_MaxDepth )
+ return;
+
+ // if there are no variables left, quit the research
+ if ( bVarsCol == b1 )
+ return;
+
+ if ( s_BackTracks > s_BackTrackLimit )
+ return;
+
+ s_BackTracks++;
+
+ // otherwise, go through the remaining variables
+ for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) )
+ {
+ // the currently tested variable
+ bVarTop = dd->vars[bTempV->index];
+
+ // put it into the array
+ s_VarOrderCur[Level-1] = bTempV->index;
+
+ // go through the entries and fill them out by cofactoring
+ fBreak = 0;
+ for ( i = 0; i < nEntries; i++ )
+ {
+ bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 );
+ Cudd_Ref( bVars0 );
+
+ if ( nMint0 > Extra_Power2( nMulti-1 ) )
+ {
+ // there is no way to encode - dereference and return
+ Cudd_RecursiveDeref( dd, bVars0 );
+ fBreak = 1;
+ break;
+ }
+
+ bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 );
+ Cudd_Ref( bVars1 );
+
+ if ( nMint1 > Extra_Power2( nMulti-1 ) )
+ {
+ // there is no way to encode - dereference and return
+ Cudd_RecursiveDeref( dd, bVars0 );
+ Cudd_RecursiveDeref( dd, bVars1 );
+ fBreak = 1;
+ break;
+ }
+
+ // otherwise, add these two cofactors
+ s_Field[Level][2*i + 0] = bVars0; // takes ref
+ s_Field[Level][2*i + 1] = bVars1; // takes ref
+ }
+
+ if ( !fBreak )
+ {
+ DdNode * bVarsRem;
+ // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition
+ // save this situation
+ if ( s_nVarsBest < Level )
+ {
+ s_nVarsBest = Level;
+ // copy the variable assignment
+ for ( k = 0; k < Level; k++ )
+ s_VarOrderBest[k] = s_VarOrderCur[k];
+ }
+
+ // call recursively
+ // get the new variable set
+ if ( nMulti-1 > 0 )
+ {
+ bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem );
+ EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 );
+ Cudd_RecursiveDeref( dd, bVarsRem );
+ }
+ }
+
+ // deref the contents of the array
+ for ( k = 0; k < i; k++ )
+ {
+ Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] );
+ Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] );
+ }
+
+ // if the solution is found, there is no need to continue
+ if ( s_nVarsBest == s_MaxDepth )
+ return;
+
+ // if the solution is found, there is no need to continue
+ if ( s_nVarsBest == s_MultiStart )
+ return;
+ }
+ // at this point, we have tried all possible directions in the space of variables
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the current set of variables and counts the number of minterms.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
+// takes bVars - the variables cofactored so far (some of them may be in negative polarity)
+// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity)
+// returns the cost and the new set of variables (bVars & bVarTop)
+{
+ DdNode * bVarsRes;
+
+ // get the resulting set of variables
+ bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes );
+
+ // increment signature before calling Cudd_CountCofactorMinterms()
+ s_Signature++;
+ *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll );
+
+ Cudd_Deref( bVarsRes );
+// s_CountCalls++;
+ return bVarsRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the current set of variables and counts the number of minterms.]
+
+ Description [The old implementation, which is approximately 4 times slower.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
+{
+ DdNode * bVarsRes;
+ DdNode * bCof, * bFun;
+
+ bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes );
+
+ bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof );
+ bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun );
+ *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart );
+ Cudd_RecursiveDeref( dd, bFun );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ Cudd_Deref( bVarsRes );
+// s_CountCalls++;
+ return bVarsRes;
+}
+
+
+/**Function********************************************************************
+
+ Synopsis [Counts the number of encoding minterms pointed to by the cofactor of the function.]
+
+ Description []
+
+ SideEffects [None]
+
+******************************************************************************/
+unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll )
+// this function computes how many minterms depending on the encoding variables
+// are there in the cofactor of bFunc w.r.t. variables bVarsCof
+// bFunc is assumed to depend on variables s_VarsAll
+// the variables s_VarsAll should be ordered above the encoding variables
+{
+ unsigned HKey;
+ DdNode * bFuncR;
+
+ // if the function is zero, there are no minterms
+// if ( bFunc == b0 )
+// return 0;
+
+// if ( st_lookup(Visited, (char*)bFunc, NULL) )
+// return 0;
+
+// HKey = hashKey2c( s_Signature, bFuncR );
+// if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
+// return 0;
+
+
+ // check the hash-table
+ bFuncR = Cudd_Regular(bFunc);
+// HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF );
+ HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF );
+ for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF )
+// if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
+ if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited
+ return 0;
+
+
+ // if the function is already the code
+ if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel )
+ {
+// st_insert(Visited, (char*)bFunc, NULL);
+
+// HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+
+ assert( HHTable1[HKey].Sign != s_Signature );
+ HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+ HHTable1[HKey].Arg1 = bFunc;
+
+ return Extra_CountMintermsSimple( bFunc, (1<<s_MultiStart) );
+ }
+ else
+ {
+ DdNode * bFunc0, * bFunc1;
+ DdNode * bVarsCof0, * bVarsCof1;
+ DdNode * bVarsCofR = Cudd_Regular(bVarsCof);
+ unsigned Res;
+
+ // get the levels
+ int LevelF = dd->perm[bFuncR->index];
+ int LevelC = cuddI(dd,bVarsCofR->index);
+ int LevelA = dd->perm[bVarsAll->index];
+
+ int LevelTop = LevelF;
+
+ if ( LevelTop > LevelC )
+ LevelTop = LevelC;
+
+ if ( LevelTop > LevelA )
+ LevelTop = LevelA;
+
+ // the top var in the function or in cofactoring vars always belongs to the set of all vars
+ assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA );
+
+ // cofactor the function
+ if ( LevelTop == LevelF )
+ {
+ if ( bFuncR != bFunc ) // bFunc is complemented
+ {
+ bFunc0 = Cudd_Not( cuddE(bFuncR) );
+ bFunc1 = Cudd_Not( cuddT(bFuncR) );
+ }
+ else
+ {
+ bFunc0 = cuddE(bFuncR);
+ bFunc1 = cuddT(bFuncR);
+ }
+ }
+ else // bVars is higher in the variable order
+ bFunc0 = bFunc1 = bFunc;
+
+ // cofactor the cube
+ if ( LevelTop == LevelC )
+ {
+ if ( bVarsCofR != bVarsCof ) // bFunc is complemented
+ {
+ bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) );
+ bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) );
+ }
+ else
+ {
+ bVarsCof0 = cuddE(bVarsCofR);
+ bVarsCof1 = cuddT(bVarsCofR);
+ }
+ }
+ else // bVars is higher in the variable order
+ bVarsCof0 = bVarsCof1 = bVarsCof;
+
+ // there are two cases:
+ // (1) the top variable belongs to the cofactoring variables
+ // (2) the top variable does not belong to the cofactoring variables
+
+ // (1) the top variable belongs to the cofactoring variables
+ Res = 0;
+ if ( LevelTop == LevelC )
+ {
+ if ( bVarsCof1 == b0 ) // this is a negative cofactor
+ {
+ if ( bFunc0 != b0 )
+ Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
+ }
+ else // this is a positive cofactor
+ {
+ if ( bFunc1 != b0 )
+ Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
+ }
+ }
+ else
+ {
+ if ( bFunc0 != b0 )
+ Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
+
+ if ( bFunc1 != b0 )
+ Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
+ }
+
+// st_insert(Visited, (char*)bFunc, NULL);
+
+// HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+
+ // skip through the entries with the same signatures
+ // (these might have been created at the time of recursive calls)
+ for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF );
+ assert( HHTable1[HKey].Sign != s_Signature );
+ HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+ HHTable1[HKey].Arg1 = bFunc;
+
+ return Res;
+ }
+}
+
+/**Function********************************************************************
+
+ Synopsis [Counts the number of minterms.]
+
+ Description [This function counts minterms for functions up to 32 variables
+ using a local cache. The terminal value (s_Termina) should be adjusted for
+ BDDs and ADDs.]
+
+ SideEffects [None]
+
+******************************************************************************/
+unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max )
+{
+ unsigned HKey;
+
+ // normalize
+ if ( Cudd_IsComplement(bFunc) )
+ return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max );
+
+ // now it is known that the function is not complemented
+ if ( cuddIsConstant(bFunc) )
+ return ((bFunc==s_Terminal)? 0: max);
+
+ // check cache
+ HKey = hashKey2( bFunc, max, _TABLESIZE_MINT );
+ if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max )
+ return HHTable2[HKey].Res;
+ else
+ {
+ // min = min0/2 + min1/2;
+ unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) +
+ (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1);
+
+ HHTable2[HKey].Arg1 = bFunc;
+ HHTable2[HKey].Arg2 = max;
+ HHTable2[HKey].Res = min;
+
+ return min;
+ }
+} /* end of Extra_CountMintermsSimple */
+
+
+/**Function********************************************************************
+
+ Synopsis [Visits the nodes.]
+
+ Description [Visits the nodes above the cut and the nodes pointed to below the cut;
+ collects the visited nodes, counts how many times each node is visited, and sets
+ the path-sum to be the constant zero BDD.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited )
+
+{
+ traventry * p;
+ char **slot;
+ if ( st_find_or_add(Visited, (char*)aFunc, &slot) )
+ { // the entry already exists
+ p = (traventry*) *slot;
+ // increment the counter of incoming edges
+ p->nEdges++;
+ return;
+ }
+ // this node has not been visited
+ assert( !Cudd_IsComplement(aFunc) );
+
+ // create the new traversal entry
+ p = (traventry *) malloc( sizeof(traventry) );
+ // set the initial sum of edges to zero BDD
+ p->bSum = b0; Cudd_Ref( b0 );
+ // set the starting number of incoming edges
+ p->nEdges = 1;
+ // set this entry into the slot
+ *slot = (char*)p;
+
+ // recur if the node is above the cut
+ if ( cuddI(dd,aFunc->index) < s_CutLevel )
+ {
+ CountNodeVisits_rec( dd, cuddE(aFunc), Visited );
+ CountNodeVisits_rec( dd, cuddT(aFunc), Visited );
+ }
+} /* end of CountNodeVisits_rec */
+
+
+/**Function********************************************************************
+
+ Synopsis [Revisits the nodes and computes the paths.]
+
+ Description [This function visits the nodes above the cut having the goal of
+ summing all the incomming BDD edges; when this function comes across the node
+ below the cut, it saves this node in the CutNode table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes )
+{
+ // find the node in the visited table
+ DdNode * bTemp;
+ traventry * p;
+ char **slot;
+ if ( st_find_or_add(Visited, (char*)aFunc, &slot) )
+ { // the node is found
+ // get the pointer to the traversal entry
+ p = (traventry*) *slot;
+
+ // make sure that the counter of incoming edges is positive
+ assert( p->nEdges > 0 );
+
+ // add the cube to the currently accumulated cubes
+ p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum );
+ Cudd_RecursiveDeref( dd, bTemp );
+
+ // decrement the number of visits
+ p->nEdges--;
+
+ // if more visits to this node are expected, return
+ if ( p->nEdges )
+ return;
+ else // if ( p->nEdges == 0 )
+ { // this is the last visit - propagate the cube
+
+ // check where this node is
+ if ( cuddI(dd,aFunc->index) < s_CutLevel )
+ { // the node is above the cut
+ DdNode * bCube0, * bCube1;
+
+ // get the top-most variable
+ DdNode * bVarTop = dd->vars[aFunc->index];
+
+ // compute the propagated cubes
+ bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 );
+ bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 );
+
+ // call recursively
+ CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes );
+ CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes );
+
+ // dereference the cubes
+ Cudd_RecursiveDeref( dd, bCube0 );
+ Cudd_RecursiveDeref( dd, bCube1 );
+ return;
+ }
+ else
+ { // the node is below the cut
+ // add this node to the cut node table, if it is not yet there
+
+// DdNode * bNode;
+// bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode );
+ if ( st_find_or_add(CutNodes, (char*)aFunc, &slot) )
+ { // the node exists - should never happen
+ assert( 0 );
+ }
+ *slot = (char*) p->bSum; Cudd_Ref( p->bSum );
+ // the table takes the reference of bNode
+ return;
+ }
+ }
+ }
+
+ // the node does not exist in the visited table - should never happen
+ assert(0);
+
+} /* end of CollectNodesAndComputePaths_rec */
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/misc/extra/extraBddKmap.c b/src/misc/extra/extraBddKmap.c
new file mode 100644
index 00000000..bb43db68
--- /dev/null
+++ b/src/misc/extra/extraBddKmap.c
@@ -0,0 +1,783 @@
+/**CFile****************************************************************
+
+ FileName [extraBddKmap.c]
+
+ PackageName [extra]
+
+ Synopsis [Visualizing the K-map.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+/// K-map visualization using pseudo graphics ///
+/// Version 1.0. Started - August 20, 2000 ///
+/// Version 2.0. Added to EXTRA - July 17, 2001 ///
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+// the maximum number of variables in the Karnaugh Map
+#define MAXVARS 20
+
+/*
+// single line
+#define SINGLE_VERTICAL (char)179
+#define SINGLE_HORIZONTAL (char)196
+#define SINGLE_TOP_LEFT (char)218
+#define SINGLE_TOP_RIGHT (char)191
+#define SINGLE_BOT_LEFT (char)192
+#define SINGLE_BOT_RIGHT (char)217
+
+// double line
+#define DOUBLE_VERTICAL (char)186
+#define DOUBLE_HORIZONTAL (char)205
+#define DOUBLE_TOP_LEFT (char)201
+#define DOUBLE_TOP_RIGHT (char)187
+#define DOUBLE_BOT_LEFT (char)200
+#define DOUBLE_BOT_RIGHT (char)188
+
+// line intersections
+#define SINGLES_CROSS (char)197
+#define DOUBLES_CROSS (char)206
+#define S_HOR_CROSS_D_VER (char)215
+#define S_VER_CROSS_D_HOR (char)216
+
+// single line joining
+#define S_JOINS_S_VER_LEFT (char)180
+#define S_JOINS_S_VER_RIGHT (char)195
+#define S_JOINS_S_HOR_TOP (char)193
+#define S_JOINS_S_HOR_BOT (char)194
+
+// double line joining
+#define D_JOINS_D_VER_LEFT (char)185
+#define D_JOINS_D_VER_RIGHT (char)204
+#define D_JOINS_D_HOR_TOP (char)202
+#define D_JOINS_D_HOR_BOT (char)203
+
+// single line joining double line
+#define S_JOINS_D_VER_LEFT (char)182
+#define S_JOINS_D_VER_RIGHT (char)199
+#define S_JOINS_D_HOR_TOP (char)207
+#define S_JOINS_D_HOR_BOT (char)209
+*/
+
+// single line
+#define SINGLE_VERTICAL (char)'|'
+#define SINGLE_HORIZONTAL (char)'-'
+#define SINGLE_TOP_LEFT (char)'+'
+#define SINGLE_TOP_RIGHT (char)'+'
+#define SINGLE_BOT_LEFT (char)'+'
+#define SINGLE_BOT_RIGHT (char)'+'
+
+// double line
+#define DOUBLE_VERTICAL (char)'|'
+#define DOUBLE_HORIZONTAL (char)'-'
+#define DOUBLE_TOP_LEFT (char)'+'
+#define DOUBLE_TOP_RIGHT (char)'+'
+#define DOUBLE_BOT_LEFT (char)'+'
+#define DOUBLE_BOT_RIGHT (char)'+'
+
+// line intersections
+#define SINGLES_CROSS (char)'+'
+#define DOUBLES_CROSS (char)'+'
+#define S_HOR_CROSS_D_VER (char)'+'
+#define S_VER_CROSS_D_HOR (char)'+'
+
+// single line joining
+#define S_JOINS_S_VER_LEFT (char)'+'
+#define S_JOINS_S_VER_RIGHT (char)'+'
+#define S_JOINS_S_HOR_TOP (char)'+'
+#define S_JOINS_S_HOR_BOT (char)'+'
+
+// double line joining
+#define D_JOINS_D_VER_LEFT (char)'+'
+#define D_JOINS_D_VER_RIGHT (char)'+'
+#define D_JOINS_D_HOR_TOP (char)'+'
+#define D_JOINS_D_HOR_BOT (char)'+'
+
+// single line joining double line
+#define S_JOINS_D_VER_LEFT (char)'+'
+#define S_JOINS_D_VER_RIGHT (char)'+'
+#define S_JOINS_D_HOR_TOP (char)'+'
+#define S_JOINS_D_HOR_BOT (char)'+'
+
+
+// other symbols
+#define UNDERSCORE (char)95
+//#define SYMBOL_ZERO (char)248 // degree sign
+//#define SYMBOL_ZERO (char)'o'
+#define SYMBOL_ZERO (char)' '
+#define SYMBOL_ONE (char)'1'
+#define SYMBOL_DC (char)'-'
+#define SYMBOL_OVERLAP (char)'?'
+
+// full cells and half cells
+#define CELL_FREE (char)32
+#define CELL_FULL (char)219
+#define HALF_UPPER (char)223
+#define HALF_LOWER (char)220
+#define HALF_LEFT (char)221
+#define HALF_RIGHT (char)222
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+// the array of BDD variables used internally
+static DdNode * s_XVars[MAXVARS];
+
+// flag which determines where the horizontal variable names are printed
+static int fHorizontalVarNamesPrintedAbove = 1;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+// Oleg's way of generating the gray code
+static int GrayCode( int BinCode );
+static int BinCode ( int GrayCode );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+ Synopsis [Prints the K-map of the function.]
+
+ Description [If the pointer to the array of variables XVars is NULL,
+ fSuppType determines how the support will be determined.
+ fSuppType == 0 -- takes the first nVars of the manager
+ fSuppType == 1 -- takes the topmost nVars of the manager
+ fSuppType == 2 -- determines support from the on-set and the offset
+ ]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_PrintKMap(
+ FILE * Output, /* the output stream */
+ DdManager * dd,
+ DdNode * OnSet,
+ DdNode * OffSet,
+ int nVars,
+ DdNode ** XVars,
+ int fSuppType, /* the flag which determines how support is computed */
+ char ** pVarNames )
+{
+ int d, p, n, s, v, h, w;
+ int nVarsVer;
+ int nVarsHor;
+ int nCellsVer;
+ int nCellsHor;
+ int nSkipSpaces;
+
+ // make sure that on-set and off-set do not overlap
+ if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) )
+ {
+ fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" );
+ return;
+ }
+/*
+ if ( OnSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 1\n" );
+ return;
+ }
+ if ( OffSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 0\n" );
+ return;
+ }
+*/
+ if ( nVars < 0 || nVars > MAXVARS )
+ {
+ fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS );
+ return;
+ }
+
+ // determine the support if it is not given
+ if ( XVars == NULL )
+ {
+ if ( fSuppType == 0 )
+ { // assume that the support includes the first nVars of the manager
+ assert( nVars );
+ for ( v = 0; v < nVars; v++ )
+ s_XVars[v] = Cudd_bddIthVar( dd, v );
+ }
+ else if ( fSuppType == 1 )
+ { // assume that the support includes the topmost nVars of the manager
+ assert( nVars );
+ for ( v = 0; v < nVars; v++ )
+ s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] );
+ }
+ else // determine the support
+ {
+ DdNode * SuppOn, * SuppOff, * Supp;
+ int cVars = 0;
+ DdNode * TempSupp;
+
+ // determine support
+ SuppOn = Cudd_Support( dd, OnSet ); Cudd_Ref( SuppOn );
+ SuppOff = Cudd_Support( dd, OffSet ); Cudd_Ref( SuppOff );
+ Supp = Cudd_bddAnd( dd, SuppOn, SuppOff ); Cudd_Ref( Supp );
+ Cudd_RecursiveDeref( dd, SuppOn );
+ Cudd_RecursiveDeref( dd, SuppOff );
+
+ nVars = Cudd_SupportSize( dd, Supp );
+ if ( nVars > MAXVARS )
+ {
+ fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS );
+ Cudd_RecursiveDeref( dd, Supp );
+ return;
+ }
+
+ // assign variables
+ for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ )
+ s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index );
+
+ Cudd_RecursiveDeref( dd, TempSupp );
+ }
+ }
+ else
+ {
+ // copy variables
+ assert( XVars );
+ for ( v = 0; v < nVars; v++ )
+ s_XVars[v] = XVars[v];
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // determine the Karnaugh map parameters
+ nVarsVer = nVars/2;
+ nVarsHor = nVars - nVarsVer;
+ nCellsVer = (1<<nVarsVer);
+ nCellsHor = (1<<nVarsHor);
+ nSkipSpaces = nVarsVer + 1;
+
+ ////////////////////////////////////////////////////////////////////
+ // print variable names
+ fprintf( Output, "\n" );
+ for ( w = 0; w < nVarsVer; w++ )
+ if ( pVarNames == NULL )
+ fprintf( Output, "%c", 'a'+nVarsHor+w );
+ else
+ fprintf( Output, " %s", pVarNames[nVarsHor+w] );
+
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ fprintf( Output, " \\ " );
+ for ( w = 0; w < nVarsHor; w++ )
+ if ( pVarNames == NULL )
+ fprintf( Output, "%c", 'a'+w );
+ else
+ fprintf( Output, "%s ", pVarNames[w] );
+ }
+ fprintf( Output, "\n" );
+
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the upper line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_TOP_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_BOT );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_BOT );
+ }
+ fprintf( Output, "%c", DOUBLE_TOP_RIGHT );
+ fprintf( Output, "\n" );
+
+ ////////////////////////////////////////////////////////////////////
+ // print the map
+ for ( v = 0; v < nCellsVer; v++ )
+ {
+ DdNode * CubeVerBDD;
+
+ // print horizontal digits
+// for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nVarsVer; n++ )
+ if ( GrayCode(v) & (1<<(nVarsVer-1-n)) )
+ fprintf( Output, "1" );
+ else
+ fprintf( Output, "0" );
+ fprintf( Output, " " );
+
+ // find vertical cube
+ CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nVarsVer, s_XVars+nVarsHor, 1 ); Cudd_Ref( CubeVerBDD );
+
+ // print text line
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ for ( h = 0; h < nCellsHor; h++ )
+ {
+ DdNode * CubeHorBDD, * Prod, * ValueOnSet, * ValueOffSet;
+
+ fprintf( Output, " " );
+// fprintf( Output, "x" );
+ ///////////////////////////////////////////////////////////////
+ // determine what should be printed
+ CubeHorBDD = Extra_bddBitsToCube( dd, GrayCode(h), nVarsHor, s_XVars, 1 ); Cudd_Ref( CubeHorBDD );
+ Prod = Cudd_bddAnd( dd, CubeHorBDD, CubeVerBDD ); Cudd_Ref( Prod );
+ Cudd_RecursiveDeref( dd, CubeHorBDD );
+
+ ValueOnSet = Cudd_Cofactor( dd, OnSet, Prod ); Cudd_Ref( ValueOnSet );
+ ValueOffSet = Cudd_Cofactor( dd, OffSet, Prod ); Cudd_Ref( ValueOffSet );
+ Cudd_RecursiveDeref( dd, Prod );
+
+ if ( ValueOnSet == b1 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_ONE );
+ else if ( ValueOnSet == b0 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_ZERO );
+ else if ( ValueOnSet == b0 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_DC );
+ else if ( ValueOnSet == b1 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_OVERLAP );
+ else
+ assert(0);
+
+ Cudd_RecursiveDeref( dd, ValueOnSet );
+ Cudd_RecursiveDeref( dd, ValueOffSet );
+ ///////////////////////////////////////////////////////////////
+ fprintf( Output, " " );
+
+ if ( h != nCellsHor-1 )
+ if ( h&1 )
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ else
+ fprintf( Output, "%c", SINGLE_VERTICAL );
+ }
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ fprintf( Output, "\n" );
+
+ Cudd_RecursiveDeref( dd, CubeVerBDD );
+
+ if ( v != nCellsVer-1 )
+ // print separator line
+ {
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ if ( v&1 )
+ {
+ fprintf( Output, "%c", D_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", DOUBLES_CROSS );
+ else
+ fprintf( Output, "%c", S_VER_CROSS_D_HOR );
+ }
+ fprintf( Output, "%c", D_JOINS_D_VER_LEFT );
+ }
+ else
+ {
+ fprintf( Output, "%c", S_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", S_HOR_CROSS_D_VER );
+ else
+ fprintf( Output, "%c", SINGLES_CROSS );
+ }
+ fprintf( Output, "%c", S_JOINS_D_VER_LEFT );
+ }
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the lower line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_BOT_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_TOP );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_TOP );
+ }
+ fprintf( Output, "%c", DOUBLE_BOT_RIGHT );
+ fprintf( Output, "\n" );
+
+ if ( !fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+
+ /////////////////////////////////
+ fprintf( Output, "%c", (char)('a'+d) );
+ /////////////////////////////////
+ fprintf( Output, "\n" );
+ }
+ }
+}
+
+
+
+/**Function********************************************************************
+
+ Synopsis [Prints the K-map of the relation.]
+
+ Description [Assumes that the relation depends the first nXVars of XVars and
+ the first nYVars of YVars. Draws X and Y vars and vertical and horizontal vars.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_PrintKMapRelation(
+ FILE * Output, /* the output stream */
+ DdManager * dd,
+ DdNode * OnSet,
+ DdNode * OffSet,
+ int nXVars,
+ int nYVars,
+ DdNode ** XVars,
+ DdNode ** YVars ) /* the flag which determines how support is computed */
+{
+ int d, p, n, s, v, h, w;
+ int nVars;
+ int nVarsVer;
+ int nVarsHor;
+ int nCellsVer;
+ int nCellsHor;
+ int nSkipSpaces;
+
+ // make sure that on-set and off-set do not overlap
+ if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) )
+ {
+ fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" );
+ return;
+ }
+
+ if ( OnSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 1\n" );
+ return;
+ }
+ if ( OffSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 0\n" );
+ return;
+ }
+
+ nVars = nXVars + nYVars;
+ if ( nVars < 0 || nVars > MAXVARS )
+ {
+ fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS );
+ return;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////
+ // determine the Karnaugh map parameters
+ nVarsVer = nXVars;
+ nVarsHor = nYVars;
+ nCellsVer = (1<<nVarsVer);
+ nCellsHor = (1<<nVarsHor);
+ nSkipSpaces = nVarsVer + 1;
+
+ ////////////////////////////////////////////////////////////////////
+ // print variable names
+ fprintf( Output, "\n" );
+ for ( w = 0; w < nVarsVer; w++ )
+ fprintf( Output, "%c", 'a'+nVarsHor+w );
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ fprintf( Output, " \\ " );
+ for ( w = 0; w < nVarsHor; w++ )
+ fprintf( Output, "%c", 'a'+w );
+ }
+ fprintf( Output, "\n" );
+
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the upper line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_TOP_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_BOT );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_BOT );
+ }
+ fprintf( Output, "%c", DOUBLE_TOP_RIGHT );
+ fprintf( Output, "\n" );
+
+ ////////////////////////////////////////////////////////////////////
+ // print the map
+ for ( v = 0; v < nCellsVer; v++ )
+ {
+ DdNode * CubeVerBDD;
+
+ // print horizontal digits
+// for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nVarsVer; n++ )
+ if ( GrayCode(v) & (1<<(nVarsVer-1-n)) )
+ fprintf( Output, "1" );
+ else
+ fprintf( Output, "0" );
+ fprintf( Output, " " );
+
+ // find vertical cube
+// CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nVarsVer, s_XVars+nVarsHor ); Cudd_Ref( CubeVerBDD );
+ CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nXVars, XVars, 1 ); Cudd_Ref( CubeVerBDD );
+
+ // print text line
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ for ( h = 0; h < nCellsHor; h++ )
+ {
+ DdNode * CubeHorBDD, * Prod, * ValueOnSet, * ValueOffSet;
+
+ fprintf( Output, " " );
+// fprintf( Output, "x" );
+ ///////////////////////////////////////////////////////////////
+ // determine what should be printed
+// CubeHorBDD = Extra_bddBitsToCube( dd, GrayCode(h), nVarsHor, s_XVars ); Cudd_Ref( CubeHorBDD );
+ CubeHorBDD = Extra_bddBitsToCube( dd, GrayCode(h), nYVars, YVars, 1 ); Cudd_Ref( CubeHorBDD );
+ Prod = Cudd_bddAnd( dd, CubeHorBDD, CubeVerBDD ); Cudd_Ref( Prod );
+ Cudd_RecursiveDeref( dd, CubeHorBDD );
+
+ ValueOnSet = Cudd_Cofactor( dd, OnSet, Prod ); Cudd_Ref( ValueOnSet );
+ ValueOffSet = Cudd_Cofactor( dd, OffSet, Prod ); Cudd_Ref( ValueOffSet );
+ Cudd_RecursiveDeref( dd, Prod );
+
+ if ( ValueOnSet == b1 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_ONE );
+ else if ( ValueOnSet == b0 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_ZERO );
+ else if ( ValueOnSet == b0 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_DC );
+ else if ( ValueOnSet == b1 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_OVERLAP );
+ else
+ assert(0);
+
+ Cudd_RecursiveDeref( dd, ValueOnSet );
+ Cudd_RecursiveDeref( dd, ValueOffSet );
+ ///////////////////////////////////////////////////////////////
+ fprintf( Output, " " );
+
+ if ( h != nCellsHor-1 )
+ if ( h&1 )
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ else
+ fprintf( Output, "%c", SINGLE_VERTICAL );
+ }
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ fprintf( Output, "\n" );
+
+ Cudd_RecursiveDeref( dd, CubeVerBDD );
+
+ if ( v != nCellsVer-1 )
+ // print separator line
+ {
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ if ( v&1 )
+ {
+ fprintf( Output, "%c", D_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", DOUBLES_CROSS );
+ else
+ fprintf( Output, "%c", S_VER_CROSS_D_HOR );
+ }
+ fprintf( Output, "%c", D_JOINS_D_VER_LEFT );
+ }
+ else
+ {
+ fprintf( Output, "%c", S_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", S_HOR_CROSS_D_VER );
+ else
+ fprintf( Output, "%c", SINGLES_CROSS );
+ }
+ fprintf( Output, "%c", S_JOINS_D_VER_LEFT );
+ }
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the lower line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_BOT_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_TOP );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_TOP );
+ }
+ fprintf( Output, "%c", DOUBLE_BOT_RIGHT );
+ fprintf( Output, "\n" );
+
+ if ( !fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+
+ /////////////////////////////////
+ fprintf( Output, "%c", (char)('a'+d) );
+ /////////////////////////////////
+ fprintf( Output, "\n" );
+ }
+ }
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int GrayCode ( int BinCode )
+{
+ return BinCode ^ ( BinCode >> 1 );
+}
+
+/**Function********************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int BinCode ( int GrayCode )
+{
+ int bc = GrayCode;
+ while( GrayCode >>= 1 ) bc ^= GrayCode;
+ return bc;
+}
+
+
diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c
new file mode 100644
index 00000000..a3320ad3
--- /dev/null
+++ b/src/misc/extra/extraBddMisc.c
@@ -0,0 +1,1614 @@
+/**CFile****************************************************************
+
+ FileName [extraBddMisc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [DD-based utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+// file "extraDdTransfer.c"
+static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute );
+static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute );
+static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) );
+
+// file "cuddUtils.c"
+static void ddSupportStep(DdNode *f, int *support);
+static void ddClearFlag(DdNode *f);
+
+static DdNode* extraZddPrimes( DdManager *dd, DdNode* F );
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.]
+
+ Description [Convert a {A,B}DD from a manager to another one. The orders of the
+ variables in the two managers may be different. Returns a
+ pointer to the {A,B}DD in the destination manager if successful; NULL
+ otherwise. The i-th entry in the array Permute tells what is the index
+ of the i-th variable from the old manager in the new manager.]
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute )
+{
+ DdNode * bRes;
+ do
+ {
+ ddDestination->reordered = 0;
+ bRes = extraTransferPermute( ddSource, ddDestination, f, Permute );
+ }
+ while ( ddDestination->reordered == 1 );
+ return ( bRes );
+
+} /* end of Extra_TransferPermute */
+
+/**Function********************************************************************
+
+ Synopsis [Transfers the BDD from one manager into another level by level.]
+
+ Description [Transfers the BDD from one manager into another while
+ preserving the correspondence between variables level by level.]
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f )
+{
+ DdNode * bRes;
+ int * pPermute;
+ int nMin, nMax, i;
+
+ nMin = ddMin(ddSource->size, ddDestination->size);
+ nMax = ddMax(ddSource->size, ddDestination->size);
+ pPermute = ALLOC( int, nMax );
+ // set up the variable permutation
+ for ( i = 0; i < nMin; i++ )
+ pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i];
+ if ( ddSource->size > ddDestination->size )
+ {
+ for ( ; i < nMax; i++ )
+ pPermute[ ddSource->invperm[i] ] = -1;
+ }
+ bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute );
+ FREE( pPermute );
+ return bRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Remaps the function to depend on the topmost variables on the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddRemapUp(
+ DdManager * dd,
+ DdNode * bF )
+{
+ int * pPermute;
+ DdNode * bSupp, * bTemp, * bRes;
+ int Counter;
+
+ pPermute = ALLOC( int, dd->size );
+
+ // get support
+ bSupp = Cudd_Support( dd, bF ); Cudd_Ref( bSupp );
+
+ // create the variable map
+ // to remap the DD into the upper part of the manager
+ Counter = 0;
+ for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) )
+ pPermute[bTemp->index] = dd->invperm[Counter++];
+
+ // transfer the BDD and remap it
+ bRes = Cudd_bddPermute( dd, bF, pPermute ); Cudd_Ref( bRes );
+
+ // remove support
+ Cudd_RecursiveDeref( dd, bSupp );
+
+ // return
+ Cudd_Deref( bRes );
+ free( pPermute );
+ return bRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Moves the BDD by the given number of variables up or down.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso [Extra_bddShift]
+
+******************************************************************************/
+DdNode * Extra_bddMove(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ int nVars)
+{
+ DdNode * res;
+ DdNode * bVars;
+ if ( nVars == 0 )
+ return bF;
+ if ( Cudd_IsConstant(bF) )
+ return bF;
+ assert( nVars <= dd->size );
+ if ( nVars > 0 )
+ bVars = dd->vars[nVars];
+ else
+ bVars = Cudd_Not(dd->vars[-nVars]);
+
+ do {
+ dd->reordered = 0;
+ res = extraBddMove( dd, bF, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_bddMove */
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_StopManager( DdManager * dd )
+{
+ int RetValue;
+ // check for remaining references in the package
+ RetValue = Cudd_CheckZeroRef( dd );
+ if ( RetValue > 0 )
+ printf( "\nThe number of referenced nodes = %d\n\n", RetValue );
+// Cudd_PrintInfo( dd, stdout );
+ Cudd_Quit( dd );
+}
+
+/**Function********************************************************************
+
+ Synopsis [Outputs the BDD in a readable format.]
+
+ Description []
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_bddPrint( DdManager * dd, DdNode * F )
+{
+ DdGen * Gen;
+ int * Cube;
+ CUDD_VALUE_TYPE Value;
+ int nVars = dd->size;
+ int fFirstCube = 1;
+ int i;
+
+ if ( F == NULL )
+ {
+ printf("NULL");
+ return;
+ }
+ if ( F == b0 )
+ {
+ printf("Constant 0");
+ return;
+ }
+ if ( F == b1 )
+ {
+ printf("Constant 1");
+ return;
+ }
+
+ Cudd_ForeachCube( dd, F, Gen, Cube, Value )
+ {
+ if ( fFirstCube )
+ fFirstCube = 0;
+ else
+// Output << " + ";
+ printf( " + " );
+
+ for ( i = 0; i < nVars; i++ )
+ if ( Cube[i] == 0 )
+ printf( "[%d]'", i );
+// printf( "%c'", (char)('a'+i) );
+ else if ( Cube[i] == 1 )
+ printf( "[%d]", i );
+// printf( "%c", (char)('a'+i) );
+ }
+
+// printf("\n");
+}
+/**Function********************************************************************
+
+ Synopsis [Returns the size of the support.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp )
+{
+ int Counter = 0;
+ while ( bSupp != b1 )
+ {
+ assert( !Cudd_IsComplement(bSupp) );
+ assert( cuddE(bSupp) == b0 );
+
+ bSupp = cuddT(bSupp);
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Returns 1 if the support contains the given BDD variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar )
+{
+ for( ; bS != b1; bS = cuddT(bS) )
+ if ( bS->index == bVar->index )
+ return 1;
+ return 0;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Returns 1 if two supports represented as BDD cubes are overlapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 )
+{
+ while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX )
+ {
+ // if the top vars are the same, they intersect
+ if ( S1->index == S2->index )
+ return 1;
+ // if the top vars are different, skip the one, which is higher
+ if ( dd->perm[S1->index] < dd->perm[S2->index] )
+ S1 = cuddT(S1);
+ else
+ S2 = cuddT(S2);
+ }
+ return 0;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Returns the number of different vars in two supports.]
+
+ Description [Counts the number of variables that appear in one support and
+ does not appear in other support. If the number exceeds DiffMax, returns DiffMax.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax )
+{
+ int Result = 0;
+ while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX )
+ {
+ // if the top vars are the same, this var is the same
+ if ( S1->index == S2->index )
+ {
+ S1 = cuddT(S1);
+ S2 = cuddT(S2);
+ continue;
+ }
+ // the top var is different
+ Result++;
+
+ if ( Result >= DiffMax )
+ return DiffMax;
+
+ // if the top vars are different, skip the one, which is higher
+ if ( dd->perm[S1->index] < dd->perm[S2->index] )
+ S1 = cuddT(S1);
+ else
+ S2 = cuddT(S2);
+ }
+
+ // consider the remaining variables
+ if ( S1->index != CUDD_CONST_INDEX )
+ Result += Extra_bddSuppSize(dd,S1);
+ else if ( S2->index != CUDD_CONST_INDEX )
+ Result += Extra_bddSuppSize(dd,S2);
+
+ if ( Result >= DiffMax )
+ return DiffMax;
+ return Result;
+}
+
+
+/**Function********************************************************************
+
+ Synopsis [Checks the support containment.]
+
+ Description [This function returns 1 if one support is contained in another.
+ In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support.
+ If the supports are identical, return 0 and does not assign the supports!]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall )
+{
+ DdNode * bSL = bL;
+ DdNode * bSH = bH;
+ int fLcontainsH = 1;
+ int fHcontainsL = 1;
+ int TopVar;
+
+ if ( bSL == bSH )
+ return 0;
+
+ while ( bSL != b1 || bSH != b1 )
+ {
+ if ( bSL == b1 )
+ { // Low component has no vars; High components has some vars
+ fLcontainsH = 0;
+ if ( fHcontainsL == 0 )
+ return 0;
+ else
+ break;
+ }
+
+ if ( bSH == b1 )
+ { // similarly
+ fHcontainsL = 0;
+ if ( fLcontainsH == 0 )
+ return 0;
+ else
+ break;
+ }
+
+ // determine the topmost var of the supports by comparing their levels
+ if ( dd->perm[bSL->index] < dd->perm[bSH->index] )
+ TopVar = bSL->index;
+ else
+ TopVar = bSH->index;
+
+ if ( TopVar == bSL->index && TopVar == bSH->index )
+ { // they are on the same level
+ // it does not tell us anything about their containment
+ // skip this var
+ bSL = cuddT(bSL);
+ bSH = cuddT(bSH);
+ }
+ else if ( TopVar == bSL->index ) // and TopVar != bSH->index
+ { // Low components is higher and contains more vars
+ // it is not possible that High component contains Low
+ fHcontainsL = 0;
+ // skip this var
+ bSL = cuddT(bSL);
+ }
+ else // if ( TopVar == bSH->index ) // and TopVar != bSL->index
+ { // similarly
+ fLcontainsH = 0;
+ // skip this var
+ bSH = cuddT(bSH);
+ }
+
+ // check the stopping condition
+ if ( !fHcontainsL && !fLcontainsH )
+ return 0;
+ }
+ // only one of them can be true at the same time
+ assert( !fHcontainsL || !fLcontainsH );
+ if ( fHcontainsL )
+ {
+ *bLarge = bH;
+ *bSmall = bL;
+ }
+ else // fLcontainsH
+ {
+ *bLarge = bL;
+ *bSmall = bH;
+ }
+ return 1;
+}
+
+
+/**Function********************************************************************
+
+ Synopsis [Finds variables on which the DD depends and returns them as am array.]
+
+ Description [Finds the variables on which the DD depends. Returns an array
+ with entries set to 1 for those variables that belong to the support;
+ NULL otherwise. The array is allocated by the user and should have at least
+ as many entries as the maximum number of variables in BDD and ZDD parts of
+ the manager.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport]
+
+******************************************************************************/
+int *
+Extra_SupportArray(
+ DdManager * dd, /* manager */
+ DdNode * f, /* DD whose support is sought */
+ int * support ) /* array allocated by the user */
+{
+ int i, size;
+
+ /* Initialize support array for ddSupportStep. */
+ size = ddMax(dd->size, dd->sizeZ);
+ 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 Extra_SupportArray */
+
+/**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]
+
+******************************************************************************/
+int *
+Extra_VectorSupportArray(
+ DdManager * dd, /* manager */
+ DdNode ** F, /* array of DDs whose support is sought */
+ int n, /* size of the array */
+ int * support ) /* array allocated by the user */
+{
+ int i, size;
+
+ /* Allocate and initialize support array for ddSupportStep. */
+ size = ddMax( dd->size, dd->sizeZ );
+ 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;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Find any cube belonging to the on-set of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF )
+{
+ char * s_Temp;
+ DdNode * bCube, * bTemp;
+ int v;
+
+ // get the vector of variables in the cube
+ s_Temp = ALLOC( char, dd->size );
+ Cudd_bddPickOneCube( dd, bF, s_Temp );
+
+ // start the cube
+ bCube = b1; Cudd_Ref( bCube );
+ for ( v = 0; v < dd->size; v++ )
+ if ( s_Temp[v] == 0 )
+ {
+// Cube &= !s_XVars[v];
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ else if ( s_Temp[v] == 1 )
+ {
+// Cube &= s_XVars[v];
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[v] ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref(bCube);
+ free( s_Temp );
+ return bCube;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Returns one cube contained in the given BDD.]
+
+ Description [This function returns the cube with the smallest
+ bits-to-integer value.]
+
+ SideEffects []
+
+******************************************************************************/
+DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bFuncR, * bFunc0, * bFunc1;
+ DdNode * bRes0, * bRes1, * bRes;
+
+ bFuncR = Cudd_Regular(bFunc);
+ if ( cuddIsConstant(bFuncR) )
+ return bFunc;
+
+ // cofactor
+ if ( Cudd_IsComplement(bFunc) )
+ {
+ bFunc0 = Cudd_Not( cuddE(bFuncR) );
+ bFunc1 = Cudd_Not( cuddT(bFuncR) );
+ }
+ else
+ {
+ bFunc0 = cuddE(bFuncR);
+ bFunc1 = cuddT(bFuncR);
+ }
+
+ // try to find the cube with the negative literal
+ bRes0 = Extra_bddGetOneCube( dd, bFunc0 ); Cudd_Ref( bRes0 );
+
+ if ( bRes0 != b0 )
+ {
+ bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bRes0 );
+ }
+ else
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ // try to find the cube with the positive literal
+ bRes1 = Extra_bddGetOneCube( dd, bFunc1 ); Cudd_Ref( bRes1 );
+ assert( bRes1 != b0 );
+ bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bRes1 );
+ }
+
+ Cudd_Deref( bRes );
+ return bRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Performs the reordering-sensitive step of Extra_bddMove().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop )
+{
+ DdNode * bTemp, * bProd;
+ int i;
+ assert( iStart <= iStop );
+ assert( iStart >= 0 && iStart <= dd->size );
+ assert( iStop >= 0 && iStop <= dd->size );
+ bProd = b1; Cudd_Ref( bProd );
+ for ( i = iStart; i < iStop; i++ )
+ {
+ bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bProd );
+ return bProd;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code]
+
+ Description [Returns a bdd composed of elementary bdds found in array BddVars[] such
+ that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1,
+ the most significant bit is encoded with the first bdd variable). If the variables
+ BddVars are not specified, takes the first CodeWidth variables of the manager]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst )
+{
+ int z;
+ DdNode * bTemp, * bVar, * bVarBdd, * bResult;
+
+ bResult = b1; Cudd_Ref( bResult );
+ for ( z = 0; z < CodeWidth; z++ )
+ {
+ bVarBdd = (pbVars)? pbVars[z]: dd->vars[z];
+ if ( fMsbFirst )
+ bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 );
+ else
+ bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 );
+ bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bResult );
+
+ return bResult;
+} /* end of Extra_bddBitsToCube */
+
+/**Function********************************************************************
+
+ Synopsis [Finds the support as a negative polarity cube.]
+
+ Description [Finds the variables on which a DD depends. Returns a BDD
+ consisting of the product of the variables in the negative polarity
+ if successful; NULL otherwise.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_VectorSupport Cudd_Support]
+
+******************************************************************************/
+DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f )
+{
+ 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 )
+ {
+ var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) );
+ //////////////////////////////////////////////////////////////////
+ var = Cudd_Not(var);
+ //////////////////////////////////////////////////////////////////
+ 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 Extra_SupportNeg */
+
+/**Function********************************************************************
+
+ Synopsis [Returns 1 if the BDD is the BDD of elementary variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddIsVar( DdNode * bFunc )
+{
+ bFunc = Cudd_Regular( bFunc );
+ if ( cuddIsConstant(bFunc) )
+ return 0;
+ return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) );
+}
+
+/**Function********************************************************************
+
+ Synopsis [Creates AND composed of the first nVars of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc );
+ for ( i = 0; i < nVars; i++ )
+ {
+ bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Creates OR composed of the first nVars of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddCreateOr( DdManager * dd, int nVars )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc );
+ for ( i = 0; i < nVars; i++ )
+ {
+ bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Creates EXOR composed of the first nVars of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddCreateExor( DdManager * dd, int nVars )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc );
+ for ( i = 0; i < nVars; i++ )
+ {
+ bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the set of primes as a ZDD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F )
+{
+ DdNode *res;
+ do {
+ dd->reordered = 0;
+ res = extraZddPrimes(dd, F);
+ if ( dd->reordered == 1 )
+ printf("\nReordering in Extra_zddPrimes()\n");
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddPrimes */
+
+/**Function********************************************************************
+
+ Synopsis [Permutes the variables of the array of BDDs.]
+
+ 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.
+ The DDs in the resulting array are already referenced.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_addPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut )
+{
+ DdHashTable *table;
+ int i, k;
+ do
+ {
+ manager->reordered = 0;
+ table = cuddHashTableInit( manager, 1, 2 );
+
+ /* permute the output functions one-by-one */
+ for ( i = 0; i < nNodes; i++ )
+ {
+ bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut );
+ if ( bNodesOut[i] == NULL )
+ {
+ /* deref the array of the already computed outputs */
+ for ( k = 0; k < i; k++ )
+ Cudd_RecursiveDeref( manager, bNodesOut[k] );
+ break;
+ }
+ cuddRef( bNodesOut[i] );
+ }
+ /* Dispose of local cache. */
+ cuddHashTableQuit( table );
+ }
+ while ( manager->reordered == 1 );
+} /* end of Extra_bddPermuteArray */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs the reordering-sensitive step of Extra_bddMove().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraBddMove(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ DdNode * bDist)
+{
+ DdNode * bRes;
+
+ if ( Cudd_IsConstant(bF) )
+ return bF;
+
+ if ( bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist) )
+ return bRes;
+ else
+ {
+ DdNode * bRes0, * bRes1;
+ DdNode * bF0, * bF1;
+ DdNode * bFR = Cudd_Regular(bF);
+ int VarNew;
+
+ if ( Cudd_IsComplement(bDist) )
+ VarNew = bFR->index - Cudd_Not(bDist)->index;
+ else
+ VarNew = bFR->index + bDist->index;
+ assert( VarNew < dd->size );
+
+ // cofactor the functions
+ if ( bFR != bF ) // bFunc is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ bRes0 = extraBddMove( dd, bF0, bDist );
+ if ( bRes0 == NULL )
+ return NULL;
+ cuddRef( bRes0 );
+
+ bRes1 = extraBddMove( dd, bF1, bDist );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+
+ /* only bRes0 and bRes1 are referenced at this point */
+ bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bRes1 );
+ return NULL;
+ }
+ cuddRef( bRes );
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bRes1 );
+
+ /* insert the result into cache */
+ cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes );
+ cuddDeref( bRes );
+ return bRes;
+ }
+} /* end of extraBddMove */
+
+
+/**Function********************************************************************
+
+ Synopsis [Finds three cofactors of the cover w.r.t. to the topmost variable.]
+
+ Description [Finds three cofactors of the cover w.r.t. to the topmost variable.
+ Does not check the cover for being a constant. Assumes that ZDD variables encoding
+ positive and negative polarities are adjacent in the variable order. Is different
+ from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the
+ given variable but takes the cofactors with respent to the topmost variable.
+ This function is more efficient when used in recursive procedures because it does
+ not require referencing of the resulting cofactors (compare cuddZddProduct()
+ and extraZddPrimeProduct()).]
+
+ SideEffects [None]
+
+ SeeAlso [cuddZddGetCofactors3]
+
+******************************************************************************/
+void
+extraDecomposeCover(
+ DdManager* dd, /* the manager */
+ DdNode* zC, /* the cover */
+ DdNode** zC0, /* the pointer to the negative var cofactor */
+ DdNode** zC1, /* the pointer to the positive var cofactor */
+ DdNode** zC2 ) /* the pointer to the cofactor without var */
+{
+ if ( (zC->index & 1) == 0 )
+ { /* the top variable is present in positive polarity and maybe in negative */
+
+ DdNode *Temp = cuddE( zC );
+ *zC1 = cuddT( zC );
+ if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 )
+ { /* Temp is not a terminal node
+ * top var is present in negative polarity */
+ *zC2 = cuddE( Temp );
+ *zC0 = cuddT( Temp );
+ }
+ else
+ { /* top var is not present in negative polarity */
+ *zC2 = Temp;
+ *zC0 = dd->zero;
+ }
+ }
+ else
+ { /* the top variable is present only in negative */
+ *zC1 = dd->zero;
+ *zC2 = cuddE( zC );
+ *zC0 = cuddT( zC );
+ }
+} /* extraDecomposeCover */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static 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 [Extra_TransferPermute]
+
+******************************************************************************/
+DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute )
+{
+ 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 = extraTransferPermuteRecur( ddS, ddD, f, table, Permute );
+ 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, ( char ** ) &key, ( char ** ) &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 extraTransferPermute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive step of Extra_TransferPermute.]
+
+ Description [Performs the recursive step of Extra_TransferPermute.
+ Returns a pointer to the result if successful; NULL otherwise.]
+
+ SideEffects [None]
+
+ SeeAlso [extraTransferPermute]
+
+******************************************************************************/
+static DdNode *
+extraTransferPermuteRecur(
+ DdManager * ddS,
+ DdManager * ddD,
+ DdNode * f,
+ st_table * table,
+ int * Permute )
+{
+ 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, ( char * ) f, ( char ** ) &res ) )
+ return ( Cudd_NotCond( res, comple ) );
+
+ /* Recursive step. */
+ if ( Permute )
+ index = Permute[f->index];
+ else
+ index = f->index;
+
+ ft = cuddT( f );
+ fe = cuddE( f );
+
+ t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute );
+ if ( t == NULL )
+ {
+ return ( NULL );
+ }
+ cuddRef( t );
+
+ e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute );
+ if ( e == NULL )
+ {
+ Cudd_RecursiveDeref( ddD, t );
+ return ( NULL );
+ }
+ cuddRef( e );
+
+ zero = Cudd_Not(ddD->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 extraTransferPermuteRecur */
+
+/**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 [Composed three subcovers into one ZDD.]
+
+ Description []
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+extraComposeCover(
+ DdManager* dd, /* the manager */
+ DdNode* zC0, /* the pointer to the negative var cofactor */
+ DdNode* zC1, /* the pointer to the positive var cofactor */
+ DdNode* zC2, /* the pointer to the cofactor without var */
+ int TopVar) /* the index of the positive ZDD var */
+{
+ DdNode * zRes, * zTemp;
+ /* compose with-neg-var and without-var using the neg ZDD var */
+ zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 );
+ if ( zTemp == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zC0);
+ Cudd_RecursiveDerefZdd(dd, zC1);
+ Cudd_RecursiveDerefZdd(dd, zC2);
+ return NULL;
+ }
+ cuddRef( zTemp );
+ cuddDeref( zC0 );
+ cuddDeref( zC2 );
+
+ /* compose with-pos-var and previous result using the pos ZDD var */
+ zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zC1);
+ Cudd_RecursiveDerefZdd(dd, zTemp);
+ return NULL;
+ }
+ cuddDeref( zC1 );
+ cuddDeref( zTemp );
+ return zRes;
+} /* extraComposeCover */
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive step of prime computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode* extraZddPrimes( DdManager *dd, DdNode* F )
+{
+ DdNode *zRes;
+
+ if ( F == Cudd_Not( dd->one ) )
+ return dd->zero;
+ if ( F == dd->one )
+ return dd->one;
+
+ /* check cache */
+ zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F);
+ if (zRes)
+ return(zRes);
+ {
+ /* temporary variables */
+ DdNode *bF01, *zP0, *zP1;
+ /* three components of the prime set */
+ DdNode *zResE, *zResP, *zResN;
+ int fIsComp = Cudd_IsComplement( F );
+
+ /* find cofactors of F */
+ DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp );
+ DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp );
+
+ /* find the intersection of cofactors */
+ bF01 = cuddBddAndRecur( dd, bF0, bF1 );
+ if ( bF01 == NULL ) return NULL;
+ cuddRef( bF01 );
+
+ /* solve the problems for cofactors */
+ zP0 = extraZddPrimes( dd, bF0 );
+ if ( zP0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bF01 );
+ return NULL;
+ }
+ cuddRef( zP0 );
+
+ zP1 = extraZddPrimes( dd, bF1 );
+ if ( zP1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bF01 );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ return NULL;
+ }
+ cuddRef( zP1 );
+
+ /* check for local unateness */
+ if ( bF01 == bF0 ) /* unate increasing */
+ {
+ /* intersection is useless */
+ cuddDeref( bF01 );
+ /* the primes of intersection are the primes of F0 */
+ zResE = zP0;
+ /* there are no primes with negative var */
+ zResN = dd->zero;
+ cuddRef( zResN );
+ /* primes with positive var are primes of F1 that are not primes of F01 */
+ zResP = cuddZddDiff( dd, zP1, zP0 );
+ if ( zResP == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zResN );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResP );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ }
+ else if ( bF01 == bF1 ) /* unate decreasing */
+ {
+ /* intersection is useless */
+ cuddDeref( bF01 );
+ /* the primes of intersection are the primes of F1 */
+ zResE = zP1;
+ /* there are no primes with positive var */
+ zResP = dd->zero;
+ cuddRef( zResP );
+ /* primes with negative var are primes of F0 that are not primes of F01 */
+ zResN = cuddZddDiff( dd, zP0, zP1 );
+ if ( zResN == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zResP );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ return NULL;
+ }
+ cuddRef( zResN );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ }
+ else /* not unate */
+ {
+ /* primes without the top var are primes of F10 */
+ zResE = extraZddPrimes( dd, bF01 );
+ if ( zResE == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, bF01 );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResE );
+ Cudd_RecursiveDeref( dd, bF01 );
+
+ /* primes with the negative top var are those of P0 that are not in F10 */
+ zResN = cuddZddDiff( dd, zP0, zResE );
+ if ( zResN == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResN );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+
+ /* primes with the positive top var are those of P1 that are not in F10 */
+ zResP = cuddZddDiff( dd, zP1, zResE );
+ if ( zResP == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zResN );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResP );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ }
+
+ zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index );
+ if ( zRes == NULL ) return NULL;
+
+ /* insert the result into cache */
+ cuddCacheInsert1(dd, extraZddPrimes, F, zRes);
+ return zRes;
+ }
+} /* end of extraZddPrimes */
+
+/**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 */
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraBddSymm.c b/src/misc/extra/extraBddSymm.c
new file mode 100644
index 00000000..358402b0
--- /dev/null
+++ b/src/misc/extra/extraBddSymm.c
@@ -0,0 +1,1469 @@
+/**CFile****************************************************************
+
+ FileName [extraBddSymm.c]
+
+ PackageName [extra]
+
+ Synopsis [Efficient methods to compute the information about
+ symmetric variables using the algorithm presented in the paper:
+ A. Mishchenko. Fast Computation of Symmetries in Boolean Functions.
+ Transactions on CAD, Nov. 2003.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+#define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical symmetry information for the function.]
+
+ Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.]
+
+ SideEffects [If the ZDD variables are not derived from BDD variables with
+ multiplicity 2, this function may derive them in a wrong way.]
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsCompute(
+ DdManager * dd, /* the manager */
+ DdNode * bFunc) /* the function whose symmetries are computed */
+{
+ DdNode * bSupp;
+ DdNode * zRes;
+ Extra_SymmInfo_t * p;
+
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes );
+
+ p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp );
+
+ Cudd_RecursiveDeref( dd, bSupp );
+ Cudd_RecursiveDerefZdd( dd, zRes );
+
+ return p;
+
+} /* end of Extra_SymmPairsCompute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical symmetry information as a ZDD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddSymmPairsCompute(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ DdNode * bVars)
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraZddSymmPairsCompute( dd, bF, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddSymmPairsCompute */
+
+/**Function********************************************************************
+
+ Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddGetSymmetricVars(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF, /* the first function - originally, the positive cofactor */
+ DdNode * bG, /* the second fucntion - originally, the negative cofactor */
+ DdNode * bVars) /* the set of variables, on which F and G depend */
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraZddGetSymmetricVars( dd, bF, bG, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddGetSymmetricVars */
+
+
+/**Function********************************************************************
+
+ Synopsis [Converts a set of variables into a set of singleton subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddGetSingletons(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars) /* the set of variables */
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraZddGetSingletons( dd, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddGetSingletons */
+
+/**Function********************************************************************
+
+ Synopsis [Filters the set of variables using the support of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddReduceVarSet(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars, /* the set of variables to be reduced */
+ DdNode * bF) /* the function whose support is used for reduction */
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraBddReduceVarSet( dd, bVars, bF );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_bddReduceVarSet */
+
+
+/**Function********************************************************************
+
+ Synopsis [Allocates symmetry information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars )
+{
+ int i;
+ Extra_SymmInfo_t * p;
+
+ // allocate and clean the storage for symmetry info
+ p = ALLOC( Extra_SymmInfo_t, 1 );
+ memset( p, 0, sizeof(Extra_SymmInfo_t) );
+ p->nVars = nVars;
+ p->pVars = ALLOC( int, nVars );
+ p->pSymms = ALLOC( char *, nVars );
+ p->pSymms[0] = ALLOC( char , nVars * nVars );
+ memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) );
+
+ for ( i = 1; i < nVars; i++ )
+ p->pSymms[i] = p->pSymms[i-1] + nVars;
+
+ return p;
+} /* end of Extra_SymmPairsAllocate */
+
+/**Function********************************************************************
+
+ Synopsis [Deallocates symmetry information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p )
+{
+ free( p->pVars );
+ free( p->pSymms[0] );
+ free( p->pSymms );
+ free( p );
+} /* end of Extra_SymmPairsDissolve */
+
+/**Function********************************************************************
+
+ Synopsis [Allocates symmetry information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_SymmPairsPrint( Extra_SymmInfo_t * p )
+{
+ int i, k;
+ printf( "\n" );
+ for ( i = 0; i < p->nVars; i++ )
+ {
+ for ( k = 0; k <= i; k++ )
+ printf( " " );
+ for ( k = i+1; k < p->nVars; k++ )
+ if ( p->pSymms[i][k] )
+ printf( "1" );
+ else
+ printf( "." );
+ printf( "\n" );
+ }
+} /* end of Extra_SymmPairsPrint */
+
+
+/**Function********************************************************************
+
+ Synopsis [Creates the symmetry information structure from ZDD.]
+
+ Description [ZDD representation of symmetries is the set of cubes, each
+ of which has two variables in the positive polarity. These variables correspond
+ to the symmetric variable pair.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp )
+{
+ int i;
+ int nSuppSize;
+ Extra_SymmInfo_t * p;
+ int * pMapVars2Nums;
+ DdNode * bTemp;
+ DdNode * zSet, * zCube, * zTemp;
+ int iVar1, iVar2;
+
+ nSuppSize = Extra_bddSuppSize( dd, bSupp );
+
+ // allocate and clean the storage for symmetry info
+ p = Extra_SymmPairsAllocate( nSuppSize );
+
+ // allocate the storage for the temporary map
+ pMapVars2Nums = ALLOC( int, dd->size );
+ memset( pMapVars2Nums, 0, dd->size * sizeof(int) );
+
+ // assign the variables
+ p->nVarsMax = dd->size;
+// p->nNodes = Cudd_DagSize( zPairs );
+ p->nNodes = 0;
+ for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+ {
+ p->pVars[i] = bTemp->index;
+ pMapVars2Nums[bTemp->index] = i;
+ }
+
+ // write the symmetry info into the structure
+ zSet = zPairs; Cudd_Ref( zSet );
+ while ( zSet != z0 )
+ {
+ // get the next cube
+ zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube );
+
+ // add these two variables to the data structure
+ assert( cuddT( cuddT(zCube) ) == z1 );
+ iVar1 = zCube->index/2;
+ iVar2 = cuddT(zCube)->index/2;
+ if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] )
+ p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1;
+ else
+ p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1;
+ // count the symmetric pairs
+ p->nSymms ++;
+
+ // update the cuver and deref the cube
+ zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zCube );
+
+ } // for each cube
+ Cudd_RecursiveDerefZdd( dd, zSet );
+
+ FREE( pMapVars2Nums );
+ return p;
+
+} /* end of Extra_SymmPairsCreateFromZdd */
+
+
+/**Function********************************************************************
+
+ Synopsis [Checks the possibility of two variables being symmetric.]
+
+ Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddCheckVarsSymmetric(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ int iVar1,
+ int iVar2)
+{
+ DdNode * bVars;
+ int Res;
+
+// return 1;
+
+ assert( iVar1 != iVar2 );
+ assert( iVar1 < dd->size );
+ assert( iVar2 < dd->size );
+
+ bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars );
+
+ Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 );
+
+ Cudd_RecursiveDeref( dd, bVars );
+
+ return Res;
+} /* end of Extra_bddCheckVarsSymmetric */
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical symmetry information for the function.]
+
+ Description [Uses the naive way of comparing cofactors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bSupp, * bTemp;
+ int nSuppSize;
+ Extra_SymmInfo_t * p;
+ int i, k;
+
+ // compute the support
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ nSuppSize = Extra_bddSuppSize( dd, bSupp );
+//printf( "Support = %d. ", nSuppSize );
+//Extra_bddPrint( dd, bSupp );
+//printf( "%d ", nSuppSize );
+
+ // allocate the storage for symmetry info
+ p = Extra_SymmPairsAllocate( nSuppSize );
+
+ // assign the variables
+ p->nVarsMax = dd->size;
+ for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+ p->pVars[i] = bTemp->index;
+
+ // go through the candidate pairs and check using Idea1
+ for ( i = 0; i < nSuppSize; i++ )
+ for ( k = i+1; k < nSuppSize; k++ )
+ {
+ p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] );
+ if ( p->pSymms[i][k] )
+ p->nSymms++;
+ }
+
+ Cudd_RecursiveDeref( dd, bSupp );
+ return p;
+
+} /* end of Extra_SymmPairsComputeNaive */
+
+/**Function********************************************************************
+
+ Synopsis [Checks if the two variables are symmetric.]
+
+ Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddCheckVarsSymmetricNaive(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ int iVar1,
+ int iVar2)
+{
+ DdNode * bCube1, * bCube2;
+ DdNode * bCof01, * bCof10;
+ int Res;
+
+ assert( iVar1 != iVar2 );
+ assert( iVar1 < dd->size );
+ assert( iVar2 < dd->size );
+
+ bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 );
+ bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 );
+
+ bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 );
+ bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 );
+
+ Res = (int)( bCof10 == bCof01 );
+
+ Cudd_RecursiveDeref( dd, bCof01 );
+ Cudd_RecursiveDeref( dd, bCof10 );
+ Cudd_RecursiveDeref( dd, bCube1 );
+ Cudd_RecursiveDeref( dd, bCube2 );
+
+ return Res;
+} /* end of Extra_bddCheckVarsSymmetricNaive */
+
+
+/**Function********************************************************************
+
+ Synopsis [Builds ZDD representing the set of fixed-size variable tuples.]
+
+ Description [Creates ZDD of all combinations of variables in Support that
+ is represented by a BDD.]
+
+ SideEffects [New ZDD variables are created if indices of the variables
+ present in the combination are larger than the currently
+ allocated number of ZDD variables.]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode* Extra_zddTuplesFromBdd(
+ DdManager * dd, /* the DD manager */
+ int K, /* the number of variables in tuples */
+ DdNode * bVarsN) /* the set of all variables represented as a BDD */
+{
+ DdNode *zRes;
+ int autoDynZ;
+
+ autoDynZ = dd->autoDynZ;
+ dd->autoDynZ = 0;
+
+ do {
+ /* transform the numeric arguments (K) into a DdNode* argument;
+ * this allows us to use the standard internal CUDD cache */
+ DdNode *bVarSet = bVarsN, *bVarsK = bVarsN;
+ int nVars = 0, i;
+
+ /* determine the number of variables in VarSet */
+ while ( bVarSet != b1 )
+ {
+ nVars++;
+ /* make sure that the VarSet is a cube */
+ if ( cuddE( bVarSet ) != b0 )
+ return NULL;
+ bVarSet = cuddT( bVarSet );
+ }
+ /* make sure that the number of variables in VarSet is less or equal
+ that the number of variables that should be present in the tuples
+ */
+ if ( K > nVars )
+ return NULL;
+
+ /* the second argument in the recursive call stannds for <n>;
+ /* reate the first argument, which stands for <k>
+ * as when we are talking about the tuple of <k> out of <n> */
+ for ( i = 0; i < nVars-K; i++ )
+ bVarsK = cuddT( bVarsK );
+
+ dd->reordered = 0;
+ zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN );
+
+ } while (dd->reordered == 1);
+ dd->autoDynZ = autoDynZ;
+ return zRes;
+
+} /* end of Extra_zddTuplesFromBdd */
+
+/**Function********************************************************************
+
+ Synopsis [Selects one subset from the set of subsets represented by a ZDD.]
+
+ Description []
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode* Extra_zddSelectOneSubset(
+ DdManager * dd, /* the DD manager */
+ DdNode * zS) /* the ZDD */
+{
+ DdNode *res;
+ do {
+ dd->reordered = 0;
+ res = extraZddSelectOneSubset(dd, zS);
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddSelectOneSubset */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_SymmPairsCompute.]
+
+ Description [Returns the set of symmetric variable pairs represented as a set
+ of two-literal ZDD cubes. Both variables always appear in the positive polarity
+ in the cubes. This function works without building new BDD nodes. Some relatively
+ small number of ZDD nodes may be built to ensure proper bookkeeping of the
+ symmetry information.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+extraZddSymmPairsCompute(
+ DdManager * dd, /* the manager */
+ DdNode * bFunc, /* the function whose symmetries are computed */
+ DdNode * bVars ) /* the set of variables on which this function depends */
+{
+ DdNode * zRes;
+ DdNode * bFR = Cudd_Regular(bFunc);
+
+ if ( cuddIsConstant(bFR) )
+ {
+ int nVars, i;
+
+ // determine how many vars are in the bVars
+ nVars = Extra_bddSuppSize( dd, bVars );
+ if ( nVars < 2 )
+ return z0;
+ else
+ {
+ DdNode * bVarsK;
+
+ // create the BDD bVarsK corresponding to K = 2;
+ bVarsK = bVars;
+ for ( i = 0; i < nVars-2; i++ )
+ bVarsK = cuddT( bVarsK );
+ return extraZddTuplesFromBdd( dd, bVarsK, bVars );
+ }
+ }
+ assert( bVars != b1 );
+
+ if ( zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars) )
+ return zRes;
+ else
+ {
+ DdNode * zRes0, * zRes1;
+ DdNode * zTemp, * zPlus, * zSymmVars;
+ DdNode * bF0, * bF1;
+ DdNode * bVarsNew;
+ int nVarsExtra;
+ int LevelF;
+
+ // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
+ // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
+ // count how many extra vars are there in bVars
+ nVarsExtra = 0;
+ LevelF = dd->perm[bFR->index];
+ for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+ nVarsExtra++;
+ // the indexes (level) of variables should be synchronized now
+ assert( bFR->index == bVarsNew->index );
+
+ // cofactor the function
+ if ( bFR != bFunc ) // bFunc is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ // solve subproblems
+ zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) );
+ if ( zRes0 == NULL )
+ return NULL;
+ cuddRef( zRes0 );
+
+ // if there is no symmetries in the negative cofactor
+ // there is no need to test the positive cofactor
+ if ( zRes0 == z0 )
+ zRes = zRes0; // zRes takes reference
+ else
+ {
+ zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ return NULL;
+ }
+ cuddRef( zRes1 );
+
+ // only those variables are pair-wise symmetric
+ // that are pair-wise symmetric in both cofactors
+ // therefore, intersect the solutions
+ zRes = cuddZddIntersect( dd, zRes0, zRes1 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ }
+
+ // consider the current top-most variable and find all the vars
+ // that are pairwise symmetric with it
+ // these variables are returned as a set of ZDD singletons
+ zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) );
+ if ( zSymmVars == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zSymmVars );
+
+ // attach the topmost variable to the set, to get the variable pairs
+ // use the positive polarity ZDD variable for the purpose
+
+ // there is no need to do so, if zSymmVars is empty
+ if ( zSymmVars == z0 )
+ Cudd_RecursiveDerefZdd( dd, zSymmVars );
+ else
+ {
+ zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ Cudd_RecursiveDerefZdd( dd, zSymmVars );
+ return NULL;
+ }
+ cuddRef( zPlus );
+ cuddDeref( zSymmVars );
+
+ // add these variable pairs to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+
+ // only zRes is referenced at this point
+
+ // if we skipped some variables, these variables cannot be symmetric with
+ // any variables that are currently in the support of bF, but they can be
+ // symmetric with the variables that are in bVars but not in the support of bF
+ if ( nVarsExtra )
+ {
+ // it is possible to improve this step:
+ // (1) there is no need to enter here, if nVarsExtra < 2
+
+ // create the set of topmost nVarsExtra in bVars
+ DdNode * bVarsExtra;
+ int nVars;
+
+ // remove from bVars all the variable that are in the support of bFunc
+ bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc );
+ if ( bVarsExtra == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( bVarsExtra );
+
+ // determine how many vars are in the bVarsExtra
+ nVars = Extra_bddSuppSize( dd, bVarsExtra );
+ if ( nVars < 2 )
+ {
+ Cudd_RecursiveDeref( dd, bVarsExtra );
+ }
+ else
+ {
+ int i;
+ DdNode * bVarsK;
+
+ // create the BDD bVarsK corresponding to K = 2;
+ bVarsK = bVarsExtra;
+ for ( i = 0; i < nVars-2; i++ )
+ bVarsK = cuddT( bVarsK );
+
+ // create the 2 variable tuples
+ zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bVarsExtra );
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+ Cudd_RecursiveDeref( dd, bVarsExtra );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+ }
+ cuddDeref( zRes );
+
+
+ /* insert the result into cache */
+ cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes);
+ return zRes;
+ }
+} /* end of extraZddSymmPairsCompute */
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.]
+
+ Description [Returns the set of ZDD singletons, containing those positive
+ ZDD variables that correspond to BDD variables x, for which it is true
+ that bF(x=0) == bG(x=1).]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraZddGetSymmetricVars(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF, /* the first function - originally, the positive cofactor */
+ DdNode * bG, /* the second function - originally, the negative cofactor */
+ DdNode * bVars) /* the set of variables, on which F and G depend */
+{
+ DdNode * zRes;
+ DdNode * bFR = Cudd_Regular(bF);
+ DdNode * bGR = Cudd_Regular(bG);
+
+ if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) )
+ {
+ if ( bF == bG )
+ return extraZddGetSingletons( dd, bVars );
+ else
+ return z0;
+ }
+ assert( bVars != b1 );
+
+ if ( zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars) )
+ return zRes;
+ else
+ {
+ DdNode * zRes0, * zRes1;
+ DdNode * zPlus, * zTemp;
+ DdNode * bF0, * bF1;
+ DdNode * bG0, * bG1;
+ DdNode * bVarsNew;
+
+ int LevelF = cuddI(dd,bFR->index);
+ int LevelG = cuddI(dd,bGR->index);
+ int LevelFG;
+
+ if ( LevelF < LevelG )
+ LevelFG = LevelF;
+ else
+ LevelFG = LevelG;
+
+ // at least one of the arguments is not a constant
+ assert( LevelFG < dd->size );
+
+ // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV
+ // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG
+ for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) );
+ assert( LevelFG == dd->perm[bVarsNew->index] );
+
+ // cofactor the functions
+ if ( LevelF == LevelFG )
+ {
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+ }
+ else
+ bF0 = bF1 = bF;
+
+ if ( LevelG == LevelFG )
+ {
+ if ( bGR != bG ) // bG is complemented
+ {
+ bG0 = Cudd_Not( cuddE(bGR) );
+ bG1 = Cudd_Not( cuddT(bGR) );
+ }
+ else
+ {
+ bG0 = cuddE(bGR);
+ bG1 = cuddT(bGR);
+ }
+ }
+ else
+ bG0 = bG1 = bG;
+
+ // solve subproblems
+ zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) );
+ if ( zRes0 == NULL )
+ return NULL;
+ cuddRef( zRes0 );
+
+ // if there is not symmetries in the negative cofactor
+ // there is no need to test the positive cofactor
+ if ( zRes0 == z0 )
+ zRes = zRes0; // zRes takes reference
+ else
+ {
+ zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ return NULL;
+ }
+ cuddRef( zRes1 );
+
+ // only those variables should belong to the resulting set
+ // for which the property is true for both cofactors
+ zRes = cuddZddIntersect( dd, zRes0, zRes1 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ }
+
+ // add one more singleton if the property is true for this variable
+ if ( bF0 == bG1 )
+ {
+ zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these variable pairs to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+
+ if ( bF == bG && bVars != bVarsNew )
+ {
+ // if the functions are equal, so are their cofactors
+ // add those variables from V that are above F and G
+
+ DdNode * bVarsExtra;
+
+ assert( LevelFG > dd->perm[bVars->index] );
+
+ // create the BDD of the extra variables
+ bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew );
+ if ( bVarsExtra == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( bVarsExtra );
+
+ zPlus = extraZddGetSingletons( dd, bVarsExtra );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bVarsExtra );
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+ Cudd_RecursiveDeref( dd, bVarsExtra );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+ cuddDeref( zRes );
+
+ cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes );
+ return zRes;
+ }
+} /* end of extraZddGetSymmetricVars */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_zddGetSingletons.]
+
+ Description [Returns the set of ZDD singletons, containing those positive
+ polarity ZDD variables that correspond to the BDD variables in bVars.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraZddGetSingletons(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars) /* the set of variables */
+{
+ DdNode * zRes;
+
+ if ( bVars == b1 )
+// if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004
+ return z1;
+
+ if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars) )
+ return zRes;
+ else
+ {
+ DdNode * zTemp, * zPlus;
+
+ // solve subproblem
+ zRes = extraZddGetSingletons( dd, cuddT(bVars) );
+ if ( zRes == NULL )
+ return NULL;
+ cuddRef( zRes );
+
+ zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ cuddDeref( zRes );
+
+ cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes );
+ return zRes;
+ }
+} /* end of extraZddGetSingletons */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_bddReduceVarSet.]
+
+ Description [Returns the set of all variables in the given set that are not in the
+ support of the given function.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraBddReduceVarSet(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars, /* the set of variables to be reduced */
+ DdNode * bF) /* the function whose support is used for reduction */
+{
+ DdNode * bRes;
+ DdNode * bFR = Cudd_Regular(bF);
+
+ if ( cuddIsConstant(bFR) || bVars == b1 )
+ return bVars;
+
+ if ( bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bVarsThis, * bVarsLower, * bTemp;
+ int LevelF;
+
+ // if LevelF is below LevelV, scroll through the vars in bVars
+ LevelF = dd->perm[bFR->index];
+ for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) );
+ // scroll also through the current var, because it should be not be added
+ if ( LevelF == cuddI(dd,bVarsThis->index) )
+ bVarsLower = cuddT(bVarsThis);
+ else
+ bVarsLower = bVarsThis;
+
+ // cofactor the function
+ if ( bFR != bF ) // bFunc is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ // solve subproblems
+ bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 );
+ if ( bRes == NULL )
+ return NULL;
+ cuddRef( bRes );
+
+ bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ return NULL;
+ }
+ cuddRef( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+
+ // the current var should not be added
+ // add the skipped vars
+ if ( bVarsThis != bVars )
+ {
+ DdNode * bVarsExtra;
+
+ // extract the skipped variables
+ bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis );
+ if ( bVarsExtra == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes );
+ return NULL;
+ }
+ cuddRef( bVarsExtra );
+
+ // add these variables
+ bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bVarsExtra );
+ return NULL;
+ }
+ cuddRef( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bVarsExtra );
+ }
+ cuddDeref( bRes );
+
+ cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes );
+ return bRes;
+ }
+} /* end of extraBddReduceVarSet */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().]
+
+ Description [Returns b0 if the variables are not symmetric. Returns b1 if the
+ variables can be symmetric. The variables are represented in the form of a
+ two-variable cube. In case the cube contains one variable (below Var1 level),
+ the cube's pointer is complemented if the variable Var1 occurred on the
+ current path; otherwise, the cube's pointer is regular. Uses additional
+ complemented bit (Hash_Not) to mark the result if in the BDD rooted that this
+ node there is a branch passing though the node labeled with Var2.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraBddCheckVarsSymmetric(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ DdNode * bVars)
+{
+ DdNode * bRes;
+
+ if ( bF == b0 )
+ return b1;
+
+ assert( bVars != b1 );
+
+ if ( bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars) )
+ return bRes;
+ else
+ {
+ DdNode * bRes0, * bRes1;
+ DdNode * bF0, * bF1;
+ DdNode * bFR = Cudd_Regular(bF);
+ int LevelF = cuddI(dd,bFR->index);
+
+ DdNode * bVarsR = Cudd_Regular(bVars);
+ int fVar1Pres;
+ int iLev1;
+ int iLev2;
+
+ if ( bVarsR != bVars ) // cube's pointer is complemented
+ {
+ assert( cuddT(bVarsR) == b1 );
+ fVar1Pres = 1; // the first var is present on the path
+ iLev1 = -1; // we are already below the first var level
+ iLev2 = dd->perm[bVarsR->index]; // the level of the second var
+ }
+ else // cube's pointer is NOT complemented
+ {
+ fVar1Pres = 0; // the first var is absent on the path
+ if ( cuddT(bVars) == b1 )
+ {
+ iLev1 = -1; // we are already below the first var level
+ iLev2 = dd->perm[bVars->index]; // the level of the second var
+ }
+ else
+ {
+ assert( cuddT(cuddT(bVars)) == b1 );
+ iLev1 = dd->perm[bVars->index]; // the level of the first var
+ iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var
+ }
+ }
+
+ // cofactor the function
+ // the cofactors are needed only if we are above the second level
+ if ( LevelF < iLev2 )
+ {
+ if ( bFR != bF ) // bFunc is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+ }
+ else
+ bF0 = bF1 = NULL;
+
+ // consider five cases:
+ // (1) F is above iLev1
+ // (2) F is on the level iLev1
+ // (3) F is between iLev1 and iLev2
+ // (4) F is on the level iLev2
+ // (5) F is below iLev2
+
+ // (1) F is above iLev1
+ if ( LevelF < iLev1 )
+ {
+ // the returned result cannot have the hash attribute
+ // because we still did not reach the level of Var1;
+ // the attribute never travels above the level of Var1
+ bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
+// assert( !Hash_IsComplement( bRes0 ) );
+ assert( bRes0 != z0 );
+ if ( bRes0 == b0 )
+ bRes = b0;
+ else
+ bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars );
+// assert( !Hash_IsComplement( bRes ) );
+ assert( bRes != z0 );
+ }
+ // (2) F is on the level iLev1
+ else if ( LevelF == iLev1 )
+ {
+ bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) );
+ if ( bRes0 == b0 )
+ bRes = b0;
+ else
+ {
+ bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) );
+ if ( bRes1 == b0 )
+ bRes = b0;
+ else
+ {
+// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
+ if ( bRes0 == z0 || bRes1 == z0 )
+ bRes = b1;
+ else
+ bRes = b0;
+ }
+ }
+ }
+ // (3) F is between iLev1 and iLev2
+ else if ( LevelF < iLev2 )
+ {
+ bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
+ if ( bRes0 == b0 )
+ bRes = b0;
+ else
+ {
+ bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars );
+ if ( bRes1 == b0 )
+ bRes = b0;
+ else
+ {
+// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
+// bRes = Hash_Not( b1 );
+ if ( bRes0 == z0 || bRes1 == z0 )
+ bRes = z0;
+ else
+ bRes = b1;
+ }
+ }
+ }
+ // (4) F is on the level iLev2
+ else if ( LevelF == iLev2 )
+ {
+ // this is the only place where the hash attribute (Hash_Not) can be added
+ // to the result; it can be added only if the path came through the node
+ // lebeled with Var1; therefore, the hash attribute cannot be returned
+ // to the caller function
+ if ( fVar1Pres )
+// bRes = Hash_Not( b1 );
+ bRes = z0;
+ else
+ bRes = b0;
+ }
+ // (5) F is below iLev2
+ else // if ( LevelF > iLev2 )
+ {
+ // it is possible that the path goes through the node labeled by Var1
+ // and still everything is okay; we do not label with Hash_Not here
+ // because the path does not go through node labeled by Var2
+ bRes = b1;
+ }
+
+ cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes);
+ return bRes;
+ }
+} /* end of extraBddCheckVarsSymmetric */
+
+/**Function********************************************************************
+
+ Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().]
+
+ Description [Generates in a bottom-up fashion ZDD for all combinations
+ composed of k variables out of variables belonging to Support.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode* extraZddTuplesFromBdd(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVarsK, /* the number of variables in tuples */
+ DdNode * bVarsN) /* the set of all variables */
+{
+ DdNode *zRes, *zRes0, *zRes1;
+ statLine(dd);
+
+ /* terminal cases */
+/* if ( k < 0 || k > n )
+ * return dd->zero;
+ * if ( n == 0 )
+ * return dd->one;
+ */
+ if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) )
+ return z0;
+ if ( bVarsN == b1 )
+ return z1;
+
+ /* check cache */
+ zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN);
+ if (zRes)
+ return(zRes);
+
+ /* ZDD in which this variable is 0 */
+/* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */
+ zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) );
+ if ( zRes0 == NULL )
+ return NULL;
+ cuddRef( zRes0 );
+
+ /* ZDD in which this variable is 1 */
+/* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */
+ if ( bVarsK == b1 )
+ {
+ zRes1 = z0;
+ cuddRef( zRes1 );
+ }
+ else
+ {
+ zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ return NULL;
+ }
+ cuddRef( zRes1 );
+ }
+
+ /* compose Res0 and Res1 with the given ZDD variable */
+ zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ return NULL;
+ }
+ cuddDeref( zRes0 );
+ cuddDeref( zRes1 );
+
+ /* insert the result into cache */
+ cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes);
+ return zRes;
+
+} /* end of extraZddTuplesFromBdd */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.]
+
+ Description []
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraZddSelectOneSubset(
+ DdManager * dd,
+ DdNode * zS )
+// selects one subset from the ZDD zS
+// returns z0 if and only if zS is an empty set of cubes
+{
+ DdNode * zRes;
+
+ if ( zS == z0 ) return z0;
+ if ( zS == z1 ) return z1;
+
+ // check cache
+ if ( zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS ) )
+ return zRes;
+ else
+ {
+ DdNode * zS0, * zS1, * zTemp;
+
+ zS0 = cuddE(zS);
+ zS1 = cuddT(zS);
+
+ if ( zS0 != z0 )
+ {
+ zRes = extraZddSelectOneSubset( dd, zS0 );
+ if ( zRes == NULL )
+ return NULL;
+ }
+ else // if ( zS0 == z0 )
+ {
+ assert( zS1 != z0 );
+ zRes = extraZddSelectOneSubset( dd, zS1 );
+ if ( zRes == NULL )
+ return NULL;
+ cuddRef( zRes );
+
+ zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ return NULL;
+ }
+ cuddDeref( zTemp );
+ }
+
+ // insert the result into cache
+ cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes );
+ return zRes;
+ }
+} /* end of extraZddSelectOneSubset */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions */
+/*---------------------------------------------------------------------------*/
diff --git a/src/misc/extra/extraBddUnate.c b/src/misc/extra/extraBddUnate.c
new file mode 100644
index 00000000..b0297c77
--- /dev/null
+++ b/src/misc/extra/extraBddUnate.c
@@ -0,0 +1,641 @@
+/**CFile****************************************************************
+
+ FileName [extraBddUnate.c]
+
+ PackageName [extra]
+
+ Synopsis [Efficient methods to compute the information about
+ unate variables using an algorithm that is conceptually similar to
+ the algorithm for two-variable symmetry computation presented in:
+ A. Mishchenko. Fast Computation of Symmetries in Boolean Functions.
+ Transactions on CAD, Nov. 2003.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical symmetry information for the function.]
+
+ Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.]
+
+ SideEffects [If the ZDD variables are not derived from BDD variables with
+ multiplicity 2, this function may derive them in a wrong way.]
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateComputeFast(
+ DdManager * dd, /* the manager */
+ DdNode * bFunc) /* the function whose symmetries are computed */
+{
+ DdNode * bSupp;
+ DdNode * zRes;
+ Extra_UnateInfo_t * p;
+
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ zRes = Extra_zddUnateInfoCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes );
+
+ p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp );
+
+ Cudd_RecursiveDeref( dd, bSupp );
+ Cudd_RecursiveDerefZdd( dd, zRes );
+
+ return p;
+
+} /* end of Extra_UnateInfoCompute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical symmetry information as a ZDD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddUnateInfoCompute(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ DdNode * bVars)
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraZddUnateInfoCompute( dd, bF, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddUnateInfoCompute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Converts a set of variables into a set of singleton subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddGetSingletonsBoth(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars) /* the set of variables */
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraZddGetSingletonsBoth( dd, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddGetSingletonsBoth */
+
+/**Function********************************************************************
+
+ Synopsis [Allocates unateness information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars )
+{
+ Extra_UnateInfo_t * p;
+ // allocate and clean the storage for unateness info
+ p = ALLOC( Extra_UnateInfo_t, 1 );
+ memset( p, 0, sizeof(Extra_UnateInfo_t) );
+ p->nVars = nVars;
+ p->pVars = ALLOC( Extra_UnateVar_t, nVars );
+ memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) );
+ return p;
+} /* end of Extra_UnateInfoAllocate */
+
+/**Function********************************************************************
+
+ Synopsis [Deallocates symmetry information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p )
+{
+ free( p->pVars );
+ free( p );
+} /* end of Extra_UnateInfoDissolve */
+
+/**Function********************************************************************
+
+ Synopsis [Allocates symmetry information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_UnateInfoPrint( Extra_UnateInfo_t * p )
+{
+ char * pBuffer;
+ int i;
+ pBuffer = ALLOC( char, p->nVarsMax+1 );
+ memset( pBuffer, ' ', p->nVarsMax );
+ pBuffer[p->nVarsMax] = 0;
+ for ( i = 0; i < p->nVars; i++ )
+ if ( p->pVars[i].Neg )
+ pBuffer[ p->pVars[i].iVar ] = 'n';
+ else if ( p->pVars[i].Pos )
+ pBuffer[ p->pVars[i].iVar ] = 'p';
+ else
+ pBuffer[ p->pVars[i].iVar ] = '.';
+ printf( "%s\n", pBuffer );
+ free( pBuffer );
+} /* end of Extra_UnateInfoPrint */
+
+
+/**Function********************************************************************
+
+ Synopsis [Creates the symmetry information structure from ZDD.]
+
+ Description [ZDD representation of symmetries is the set of cubes, each
+ of which has two variables in the positive polarity. These variables correspond
+ to the symmetric variable pair.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp )
+{
+ Extra_UnateInfo_t * p;
+ DdNode * bTemp, * zSet, * zCube, * zTemp;
+ int * pMapVars2Nums;
+ int i, nSuppSize;
+
+ nSuppSize = Extra_bddSuppSize( dd, bSupp );
+
+ // allocate and clean the storage for symmetry info
+ p = Extra_UnateInfoAllocate( nSuppSize );
+
+ // allocate the storage for the temporary map
+ pMapVars2Nums = ALLOC( int, dd->size );
+ memset( pMapVars2Nums, 0, dd->size * sizeof(int) );
+
+ // assign the variables
+ p->nVarsMax = dd->size;
+ for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+ {
+ p->pVars[i].iVar = bTemp->index;
+ pMapVars2Nums[bTemp->index] = i;
+ }
+
+ // write the symmetry info into the structure
+ zSet = zPairs; Cudd_Ref( zSet );
+// Cudd_zddPrintCover( dd, zPairs ); printf( "\n" );
+ while ( zSet != z0 )
+ {
+ // get the next cube
+ zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube );
+
+ // add this var to the data structure
+ assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 );
+ if ( zCube->index & 1 ) // neg
+ p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1;
+ else
+ p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1;
+ // count the unate vars
+ p->nUnate++;
+
+ // update the cuver and deref the cube
+ zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zCube );
+
+ } // for each cube
+ Cudd_RecursiveDerefZdd( dd, zSet );
+ FREE( pMapVars2Nums );
+ return p;
+
+} /* end of Extra_UnateInfoCreateFromZdd */
+
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical unateness information for the function.]
+
+ Description [Uses the naive way of comparing cofactors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc )
+{
+ int nSuppSize;
+ DdNode * bSupp, * bTemp;
+ Extra_UnateInfo_t * p;
+ int i, Res;
+
+ // compute the support
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ nSuppSize = Extra_bddSuppSize( dd, bSupp );
+//printf( "Support = %d. ", nSuppSize );
+//Extra_bddPrint( dd, bSupp );
+//printf( "%d ", nSuppSize );
+
+ // allocate the storage for symmetry info
+ p = Extra_UnateInfoAllocate( nSuppSize );
+
+ // assign the variables
+ p->nVarsMax = dd->size;
+ for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+ {
+ Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index );
+ p->pVars[i].iVar = bTemp->index;
+ if ( Res == -1 )
+ p->pVars[i].Neg = 1;
+ else if ( Res == 1 )
+ p->pVars[i].Pos = 1;
+ p->nUnate += (Res != 0);
+ }
+ Cudd_RecursiveDeref( dd, bSupp );
+ return p;
+
+} /* end of Extra_UnateComputeSlow */
+
+/**Function********************************************************************
+
+ Synopsis [Checks if the two variables are symmetric.]
+
+ Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddCheckUnateNaive(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ int iVar)
+{
+ DdNode * bCof0, * bCof1;
+ int Res;
+
+ assert( iVar < dd->size );
+
+ bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) ); Cudd_Ref( bCof0 );
+ bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) ); Cudd_Ref( bCof1 );
+
+ if ( Cudd_bddLeq( dd, bCof0, bCof1 ) )
+ Res = 1;
+ else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) )
+ Res =-1;
+ else
+ Res = 0;
+
+ Cudd_RecursiveDeref( dd, bCof0 );
+ Cudd_RecursiveDeref( dd, bCof1 );
+ return Res;
+} /* end of Extra_bddCheckUnateNaive */
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_UnateInfoCompute.]
+
+ Description [Returns the set of symmetric variable pairs represented as a set
+ of two-literal ZDD cubes. Both variables always appear in the positive polarity
+ in the cubes. This function works without building new BDD nodes. Some relatively
+ small number of ZDD nodes may be built to ensure proper bookkeeping of the
+ symmetry information.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+extraZddUnateInfoCompute(
+ DdManager * dd, /* the manager */
+ DdNode * bFunc, /* the function whose symmetries are computed */
+ DdNode * bVars ) /* the set of variables on which this function depends */
+{
+ DdNode * zRes;
+ DdNode * bFR = Cudd_Regular(bFunc);
+
+ if ( cuddIsConstant(bFR) )
+ {
+ if ( cuddIsConstant(bVars) )
+ return z0;
+ return extraZddGetSingletonsBoth( dd, bVars );
+ }
+ assert( bVars != b1 );
+
+ if ( zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars) )
+ return zRes;
+ else
+ {
+ DdNode * zRes0, * zRes1;
+ DdNode * zTemp, * zPlus;
+ DdNode * bF0, * bF1;
+ DdNode * bVarsNew;
+ int nVarsExtra;
+ int LevelF;
+ int AddVar;
+
+ // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
+ // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
+ // count how many extra vars are there in bVars
+ nVarsExtra = 0;
+ LevelF = dd->perm[bFR->index];
+ for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+ nVarsExtra++;
+ // the indexes (level) of variables should be synchronized now
+ assert( bFR->index == bVarsNew->index );
+
+ // cofactor the function
+ if ( bFR != bFunc ) // bFunc is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ // solve subproblems
+ zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) );
+ if ( zRes0 == NULL )
+ return NULL;
+ cuddRef( zRes0 );
+
+ // if there is no symmetries in the negative cofactor
+ // there is no need to test the positive cofactor
+ if ( zRes0 == z0 )
+ zRes = zRes0; // zRes takes reference
+ else
+ {
+ zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ return NULL;
+ }
+ cuddRef( zRes1 );
+
+ // only those variables are pair-wise symmetric
+ // that are pair-wise symmetric in both cofactors
+ // therefore, intersect the solutions
+ zRes = cuddZddIntersect( dd, zRes0, zRes1 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ }
+
+ // consider the current top-most variable
+ AddVar = -1;
+ if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos
+ AddVar = 0;
+ else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg
+ AddVar = 1;
+ if ( AddVar >= 0 )
+ {
+ // create the singleton
+ zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+ // only zRes is referenced at this point
+
+ // if we skipped some variables, these variables cannot be symmetric with
+ // any variables that are currently in the support of bF, but they can be
+ // symmetric with the variables that are in bVars but not in the support of bF
+ for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+ {
+ // create the negative singleton
+ zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+
+
+ // create the positive singleton
+ zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+ cuddDeref( zRes );
+
+ /* insert the result into cache */
+ cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes);
+ return zRes;
+ }
+} /* end of extraZddUnateInfoCompute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_zddGetSingletons.]
+
+ Description [Returns the set of ZDD singletons, containing those pos/neg
+ polarity ZDD variables that correspond to the BDD variables in bVars.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraZddGetSingletonsBoth(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars) /* the set of variables */
+{
+ DdNode * zRes;
+
+ if ( bVars == b1 )
+ return z1;
+
+ if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars) )
+ return zRes;
+ else
+ {
+ DdNode * zTemp, * zPlus;
+
+ // solve subproblem
+ zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) );
+ if ( zRes == NULL )
+ return NULL;
+ cuddRef( zRes );
+
+
+ // create the negative singleton
+ zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+
+
+ // create the positive singleton
+ zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+
+ cuddDeref( zRes );
+ cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes );
+ return zRes;
+ }
+} /* end of extraZddGetSingletonsBoth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions */
+/*---------------------------------------------------------------------------*/
diff --git a/src/misc/extra/extraUtilBitMatrix.c b/src/misc/extra/extraUtilBitMatrix.c
new file mode 100644
index 00000000..b860a538
--- /dev/null
+++ b/src/misc/extra/extraUtilBitMatrix.c
@@ -0,0 +1,415 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilBitMatrix.c]
+
+ PackageName [extra]
+
+ Synopsis [Various reusable software utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraUtilBitMatrix.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+struct Extra_BitMat_t_
+{
+ unsigned ** ppData; // bit data
+ int nSize; // the number of bits in one dimension
+ int nWords; // the number of words in one dimension
+ int nBitShift; // the number of bits to shift to get words
+ unsigned uMask; // the mask to get the number of bits in the word
+ int nLookups; // the number of lookups
+ int nInserts; // the number of inserts
+ int nDeletes; // the number of deletions
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Starts the bit matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Extra_BitMat_t * Extra_BitMatrixStart( int nSize )
+{
+ Extra_BitMat_t * p;
+ int i;
+ p = ALLOC( Extra_BitMat_t, 1 );
+ memset( p, 0, sizeof(Extra_BitMat_t) );
+ p->nSize = nSize;
+ p->nBitShift = (sizeof(unsigned) == 4) ? 5: 6;
+ p->uMask = (sizeof(unsigned) == 4) ? 31: 63;
+ p->nWords = nSize / (8 * sizeof(unsigned)) + ((nSize % (8 * sizeof(unsigned))) > 0);
+ p->ppData = ALLOC( unsigned *, nSize );
+ p->ppData[0] = ALLOC( unsigned, nSize * p->nWords );
+ memset( p->ppData[0], 0, sizeof(unsigned) * nSize * p->nWords );
+ for ( i = 1; i < nSize; i++ )
+ p->ppData[i] = p->ppData[i-1] + p->nWords;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the bit matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixClean( Extra_BitMat_t * p )
+{
+ memset( p->ppData[0], 0, sizeof(unsigned) * p->nSize * p->nWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the bit matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixStop( Extra_BitMat_t * p )
+{
+ FREE( p->ppData[0] );
+ FREE( p->ppData );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the bit-matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixPrint( Extra_BitMat_t * pMat )
+{
+ int i, k, nVars;
+ printf( "\n" );
+ nVars = Extra_BitMatrixReadSize( pMat );
+ for ( i = 0; i < nVars; i++ )
+ {
+ for ( k = 0; k <= i; k++ )
+ printf( " " );
+ for ( k = i+1; k < nVars; k++ )
+ if ( Extra_BitMatrixLookup1( pMat, i, k ) )
+ printf( "1" );
+ else
+ printf( "." );
+ printf( "\n" );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reads the matrix size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_BitMatrixReadSize( Extra_BitMat_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k )
+{
+ p->nInserts++;
+ if ( i < k )
+ p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask));
+ else
+ p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k )
+{
+ p->nLookups++;
+ if ( i < k )
+ return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0);
+ else
+ return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k )
+{
+ p->nDeletes++;
+ if ( i < k )
+ p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask));
+ else
+ p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask));
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k )
+{
+ p->nInserts++;
+ if ( i > k )
+ p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask));
+ else
+ p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k )
+{
+ p->nLookups++;
+ if ( i > k )
+ return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0);
+ else
+ return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k )
+{
+ p->nDeletes++;
+ if ( i > k )
+ p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask));
+ else
+ p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask));
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo )
+{
+ int w;
+ for ( w = 0; w < p->nWords; w++ )
+ p->ppData[i][w] |= pInfo[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the element into the upper part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j )
+{
+ int w;
+ for ( w = 0; w < p->nWords; w++ )
+ p->ppData[i][w] = p->ppData[j][w] = (p->ppData[i][w] | p->ppData[j][w]);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1's in the upper rectangle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p )
+{
+ int i, k, nTotal = 0;
+ for ( i = 0; i < p->nSize; i++ )
+ for ( k = i + 1; k < p->nSize; k++ )
+ nTotal += ( (p->ppData[i][k>>5] & (1 << (k&31))) > 0 );
+ return nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the matrices have no entries in common.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 )
+{
+ int i, w;
+ assert( p1->nSize == p2->nSize );
+ for ( i = 0; i < p1->nSize; i++ )
+ for ( w = 0; w < p1->nWords; w++ )
+ if ( p1->ppData[i][w] & p2->ppData[i][w] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the matrix is a set of cliques.]
+
+ Description [For example pairwise symmetry info should satisfy this property.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_BitMatrixIsClique( Extra_BitMat_t * pMat )
+{
+ int v, u, i;
+ for ( v = 0; v < pMat->nSize; v++ )
+ for ( u = v+1; u < pMat->nSize; u++ )
+ {
+ if ( !Extra_BitMatrixLookup1( pMat, v, u ) )
+ continue;
+ // v and u are symmetric
+ for ( i = 0; i < pMat->nSize; i++ )
+ {
+ if ( i == v || i == u )
+ continue;
+ // i is neither v nor u
+ // the symmetry status of i is the same w.r.t. to v and u
+ if ( Extra_BitMatrixLookup1( pMat, i, v ) != Extra_BitMatrixLookup1( pMat, i, u ) )
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilCanon.c b/src/misc/extra/extraUtilCanon.c
new file mode 100644
index 00000000..fcc7d84d
--- /dev/null
+++ b/src/misc/extra/extraUtilCanon.c
@@ -0,0 +1,701 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilMisc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Computing canonical forms of Boolean functions using truth tables.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+static unsigned s_Truths3[256];
+static char s_Phases3[256][9];
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+static int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag );
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Computes the N-canonical form of the Boolean function up to 6 inputs.]
+
+ Description [The N-canonical form is defined as the truth table with
+ the minimum integer value. This function exhaustively enumerates
+ through the complete set of 2^N phase assignments.
+ Returns pointers to the static storage to the truth table and phases.
+ This data should be used before the function is called again.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes )
+{
+ static unsigned uTruthStore6[2];
+ int RetValue;
+ assert( nVarsMax <= 6 );
+ assert( nVarsReal <= nVarsMax );
+ RetValue = Extra_TruthCanonN_rec( nVarsReal <= 3? 3: nVarsReal, (unsigned char *)pt, pptRes, ppfRes, 0 );
+ if ( nVarsMax == 6 && nVarsReal < nVarsMax )
+ {
+ uTruthStore6[0] = **pptRes;
+ uTruthStore6[1] = **pptRes;
+ *pptRes = uTruthStore6;
+ }
+ return RetValue;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Recursive implementation of the above.]
+
+ Description []
+
+ SideEffects [This procedure has a bug, which shows on Solaris.
+ Most likely has something to do with the casts, i.g *((unsigned *)pt0)]
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag )
+{
+ static unsigned uTruthStore[7][2][2];
+ static char uPhaseStore[7][2][64];
+
+ unsigned char * pt0, * pt1;
+ unsigned * ptRes0, * ptRes1, * ptRes;
+ unsigned uInit0, uInit1, uTruth0, uTruth1, uTemp;
+ char * pfRes0, * pfRes1, * pfRes;
+ int nf0, nf1, nfRes, i, nVarsN;
+
+ // table lookup for three vars
+ if ( nVars == 3 )
+ {
+ *pptRes = &s_Truths3[*pt];
+ *ppfRes = s_Phases3[*pt]+1;
+ return s_Phases3[*pt][0];
+ }
+
+ // number of vars for the next call
+ nVarsN = nVars-1;
+ // truth table for the next call
+ pt0 = pt;
+ pt1 = pt + (1 << nVarsN) / 8;
+ // 5-var truth tables for this call
+// uInit0 = *((unsigned *)pt0);
+// uInit1 = *((unsigned *)pt1);
+ if ( nVarsN == 3 )
+ {
+ uInit0 = (pt0[0] << 24) | (pt0[0] << 16) | (pt0[0] << 8) | pt0[0];
+ uInit1 = (pt1[0] << 24) | (pt1[0] << 16) | (pt1[0] << 8) | pt1[0];
+ }
+ else if ( nVarsN == 4 )
+ {
+ uInit0 = (pt0[1] << 24) | (pt0[0] << 16) | (pt0[1] << 8) | pt0[0];
+ uInit1 = (pt1[1] << 24) | (pt1[0] << 16) | (pt1[1] << 8) | pt1[0];
+ }
+ else
+ {
+ uInit0 = (pt0[3] << 24) | (pt0[2] << 16) | (pt0[1] << 8) | pt0[0];
+ uInit1 = (pt1[3] << 24) | (pt1[2] << 16) | (pt1[1] << 8) | pt1[0];
+ }
+
+ // storage for truth tables and phases
+ ptRes = uTruthStore[nVars][Flag];
+ pfRes = uPhaseStore[nVars][Flag];
+
+ // solve trivial cases
+ if ( uInit1 == 0 )
+ {
+ nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 );
+ uTruth1 = uInit1;
+ uTruth0 = *ptRes0;
+ nfRes = 0;
+ for ( i = 0; i < nf0; i++ )
+ pfRes[nfRes++] = pfRes0[i];
+ goto finish;
+ }
+ if ( uInit0 == 0 )
+ {
+ nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 );
+ uTruth1 = uInit0;
+ uTruth0 = *ptRes1;
+ nfRes = 0;
+ for ( i = 0; i < nf1; i++ )
+ pfRes[nfRes++] = pfRes1[i] | (1<<nVarsN);
+ goto finish;
+ }
+
+ if ( uInit1 == 0xFFFFFFFF )
+ {
+ nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 );
+ uTruth1 = *ptRes0;
+ uTruth0 = uInit1;
+ nfRes = 0;
+ for ( i = 0; i < nf0; i++ )
+ pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+ goto finish;
+ }
+ if ( uInit0 == 0xFFFFFFFF )
+ {
+ nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 );
+ uTruth1 = *ptRes1;
+ uTruth0 = uInit0;
+ nfRes = 0;
+ for ( i = 0; i < nf1; i++ )
+ pfRes[nfRes++] = pfRes1[i];
+ goto finish;
+ }
+
+ // solve the problem for cofactors
+ nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 );
+ nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 );
+
+ // combine the result
+ if ( *ptRes1 < *ptRes0 )
+ {
+ uTruth0 = 0xFFFFFFFF;
+ nfRes = 0;
+ for ( i = 0; i < nf1; i++ )
+ {
+ uTemp = Extra_TruthPolarize( uInit0, pfRes1[i], nVarsN );
+ if ( uTruth0 > uTemp )
+ {
+ nfRes = 0;
+ uTruth0 = uTemp;
+ pfRes[nfRes++] = pfRes1[i];
+ }
+ else if ( uTruth0 == uTemp )
+ pfRes[nfRes++] = pfRes1[i];
+ }
+ uTruth1 = *ptRes1;
+ }
+ else if ( *ptRes1 > *ptRes0 )
+ {
+ uTruth0 = 0xFFFFFFFF;
+ nfRes = 0;
+ for ( i = 0; i < nf0; i++ )
+ {
+ uTemp = Extra_TruthPolarize( uInit1, pfRes0[i], nVarsN );
+ if ( uTruth0 > uTemp )
+ {
+ nfRes = 0;
+ uTruth0 = uTemp;
+ pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+ }
+ else if ( uTruth0 == uTemp )
+ pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+ }
+ uTruth1 = *ptRes0;
+ }
+ else
+ {
+ assert( nf0 == nf1 );
+ nfRes = 0;
+ for ( i = 0; i < nf1; i++ )
+ pfRes[nfRes++] = pfRes1[i];
+ for ( i = 0; i < nf0; i++ )
+ pfRes[nfRes++] = pfRes0[i] | (1<<nVarsN);
+ uTruth0 = Extra_TruthPolarize( uInit0, pfRes1[0], nVarsN );
+ uTruth1 = *ptRes0;
+ }
+
+finish :
+ if ( nVarsN == 3 )
+ {
+ uTruth0 &= 0xFF;
+ uTruth1 &= 0xFF;
+ uTemp = (uTruth1 << 8) | uTruth0;
+ *ptRes = (uTemp << 16) | uTemp;
+ }
+ else if ( nVarsN == 4 )
+ {
+ uTruth0 &= 0xFFFF;
+ uTruth1 &= 0xFFFF;
+ *ptRes = (uTruth1 << 16) | uTruth0;
+ }
+ else if ( nVarsN == 5 )
+ {
+ *(ptRes+0) = uTruth0;
+ *(ptRes+1) = uTruth1;
+ }
+
+ *pptRes = ptRes;
+ *ppfRes = pfRes;
+ return nfRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_Var3Print()
+{
+ extern void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters );
+
+ unsigned * uCanons;
+ char ** uPhases;
+ char * pCounters;
+ int i, k;
+
+ Extra_Truth3VarN( &uCanons, &uPhases, &pCounters );
+
+ for ( i = 0; i < 256; i++ )
+ {
+ if ( i % 8 == 0 )
+ printf( "\n" );
+ Extra_PrintHex( stdout, uCanons[i], 5 );
+ printf( ", " );
+ }
+ printf( "\n" );
+
+ for ( i = 0; i < 256; i++ )
+ {
+ printf( "%3d */ { %2d, ", i, pCounters[i] );
+ for ( k = 0; k < pCounters[i]; k++ )
+ printf( "%s%d", k? ", ":"", uPhases[i][k] );
+ printf( " }\n" );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_Var3Test()
+{
+ extern void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters );
+
+ unsigned * uCanons;
+ char ** uPhases;
+ char * pCounters;
+ int i;
+ unsigned * ptRes;
+ char * pfRes;
+ unsigned uTruth;
+ int Count;
+
+ Extra_Truth3VarN( &uCanons, &uPhases, &pCounters );
+
+ for ( i = 0; i < 256; i++ )
+ {
+ uTruth = i;
+ Count = Extra_TruthCanonFastN( 5, 3, &uTruth, &ptRes, &pfRes );
+ if ( *ptRes != uCanons[i] || Count != pCounters[i] )
+ {
+ int k = 0;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_Var4Test()
+{
+ extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int PhaseMax );
+
+ unsigned short * uCanons;
+ char ** uPhases;
+ char * pCounters;
+ int i, k;
+ unsigned * ptRes;
+ char * pfRes;
+ unsigned uTruth;
+ int Count;
+
+ Extra_Truth4VarN( &uCanons, &uPhases, &pCounters, 16 );
+
+ for ( i = 0; i < 256*256; i++ )
+ {
+ uTruth = i;
+ Count = Extra_TruthCanonFastN( 5, 4, &uTruth, &ptRes, &pfRes );
+ if ( (*ptRes & 0xFFFF) != uCanons[i] || Count != pCounters[i] )
+ {
+ int k = 0;
+ }
+ for ( k = 0; k < Count; k++ )
+ if ( uPhases[i][k] != pfRes[k] )
+ {
+ int v = 0;
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions */
+/*---------------------------------------------------------------------------*/
+
+static unsigned s_Truths3[256] =
+{
+ 0x00000000, 0x01010101, 0x01010101, 0x03030303, 0x01010101, 0x05050505, 0x06060606, 0x07070707,
+ 0x01010101, 0x06060606, 0x05050505, 0x07070707, 0x03030303, 0x07070707, 0x07070707, 0x0f0f0f0f,
+ 0x01010101, 0x11111111, 0x12121212, 0x13131313, 0x14141414, 0x15151515, 0x16161616, 0x17171717,
+ 0x18181818, 0x19191919, 0x1a1a1a1a, 0x1b1b1b1b, 0x1c1c1c1c, 0x1d1d1d1d, 0x1e1e1e1e, 0x1f1f1f1f,
+ 0x01010101, 0x12121212, 0x11111111, 0x13131313, 0x18181818, 0x1a1a1a1a, 0x19191919, 0x1b1b1b1b,
+ 0x14141414, 0x16161616, 0x15151515, 0x17171717, 0x1c1c1c1c, 0x1e1e1e1e, 0x1d1d1d1d, 0x1f1f1f1f,
+ 0x03030303, 0x13131313, 0x13131313, 0x33333333, 0x1c1c1c1c, 0x35353535, 0x36363636, 0x37373737,
+ 0x1c1c1c1c, 0x36363636, 0x35353535, 0x37373737, 0x3c3c3c3c, 0x3d3d3d3d, 0x3d3d3d3d, 0x3f3f3f3f,
+ 0x01010101, 0x14141414, 0x18181818, 0x1c1c1c1c, 0x11111111, 0x15151515, 0x19191919, 0x1d1d1d1d,
+ 0x12121212, 0x16161616, 0x1a1a1a1a, 0x1e1e1e1e, 0x13131313, 0x17171717, 0x1b1b1b1b, 0x1f1f1f1f,
+ 0x05050505, 0x15151515, 0x1a1a1a1a, 0x35353535, 0x15151515, 0x55555555, 0x56565656, 0x57575757,
+ 0x1a1a1a1a, 0x56565656, 0x5a5a5a5a, 0x5b5b5b5b, 0x35353535, 0x57575757, 0x5b5b5b5b, 0x5f5f5f5f,
+ 0x06060606, 0x16161616, 0x19191919, 0x36363636, 0x19191919, 0x56565656, 0x66666666, 0x67676767,
+ 0x16161616, 0x69696969, 0x56565656, 0x6b6b6b6b, 0x36363636, 0x6b6b6b6b, 0x67676767, 0x6f6f6f6f,
+ 0x07070707, 0x17171717, 0x1b1b1b1b, 0x37373737, 0x1d1d1d1d, 0x57575757, 0x67676767, 0x77777777,
+ 0x1e1e1e1e, 0x6b6b6b6b, 0x5b5b5b5b, 0x7b7b7b7b, 0x3d3d3d3d, 0x7d7d7d7d, 0x7e7e7e7e, 0x7f7f7f7f,
+ 0x01010101, 0x18181818, 0x14141414, 0x1c1c1c1c, 0x12121212, 0x1a1a1a1a, 0x16161616, 0x1e1e1e1e,
+ 0x11111111, 0x19191919, 0x15151515, 0x1d1d1d1d, 0x13131313, 0x1b1b1b1b, 0x17171717, 0x1f1f1f1f,
+ 0x06060606, 0x19191919, 0x16161616, 0x36363636, 0x16161616, 0x56565656, 0x69696969, 0x6b6b6b6b,
+ 0x19191919, 0x66666666, 0x56565656, 0x67676767, 0x36363636, 0x67676767, 0x6b6b6b6b, 0x6f6f6f6f,
+ 0x05050505, 0x1a1a1a1a, 0x15151515, 0x35353535, 0x1a1a1a1a, 0x5a5a5a5a, 0x56565656, 0x5b5b5b5b,
+ 0x15151515, 0x56565656, 0x55555555, 0x57575757, 0x35353535, 0x5b5b5b5b, 0x57575757, 0x5f5f5f5f,
+ 0x07070707, 0x1b1b1b1b, 0x17171717, 0x37373737, 0x1e1e1e1e, 0x5b5b5b5b, 0x6b6b6b6b, 0x7b7b7b7b,
+ 0x1d1d1d1d, 0x67676767, 0x57575757, 0x77777777, 0x3d3d3d3d, 0x7e7e7e7e, 0x7d7d7d7d, 0x7f7f7f7f,
+ 0x03030303, 0x1c1c1c1c, 0x1c1c1c1c, 0x3c3c3c3c, 0x13131313, 0x35353535, 0x36363636, 0x3d3d3d3d,
+ 0x13131313, 0x36363636, 0x35353535, 0x3d3d3d3d, 0x33333333, 0x37373737, 0x37373737, 0x3f3f3f3f,
+ 0x07070707, 0x1d1d1d1d, 0x1e1e1e1e, 0x3d3d3d3d, 0x17171717, 0x57575757, 0x6b6b6b6b, 0x7d7d7d7d,
+ 0x1b1b1b1b, 0x67676767, 0x5b5b5b5b, 0x7e7e7e7e, 0x37373737, 0x77777777, 0x7b7b7b7b, 0x7f7f7f7f,
+ 0x07070707, 0x1e1e1e1e, 0x1d1d1d1d, 0x3d3d3d3d, 0x1b1b1b1b, 0x5b5b5b5b, 0x67676767, 0x7e7e7e7e,
+ 0x17171717, 0x6b6b6b6b, 0x57575757, 0x7d7d7d7d, 0x37373737, 0x7b7b7b7b, 0x77777777, 0x7f7f7f7f,
+ 0x0f0f0f0f, 0x1f1f1f1f, 0x1f1f1f1f, 0x3f3f3f3f, 0x1f1f1f1f, 0x5f5f5f5f, 0x6f6f6f6f, 0x7f7f7f7f,
+ 0x1f1f1f1f, 0x6f6f6f6f, 0x5f5f5f5f, 0x7f7f7f7f, 0x3f3f3f3f, 0x7f7f7f7f, 0x7f7f7f7f, 0xffffffff
+};
+
+static char s_Phases3[256][9] =
+{
+/* 0 */ { 8, 0, 1, 2, 3, 4, 5, 6, 7 },
+/* 1 */ { 1, 0 },
+/* 2 */ { 1, 1 },
+/* 3 */ { 2, 0, 1 },
+/* 4 */ { 1, 2 },
+/* 5 */ { 2, 0, 2 },
+/* 6 */ { 2, 0, 3 },
+/* 7 */ { 1, 0 },
+/* 8 */ { 1, 3 },
+/* 9 */ { 2, 1, 2 },
+/* 10 */ { 2, 1, 3 },
+/* 11 */ { 1, 1 },
+/* 12 */ { 2, 2, 3 },
+/* 13 */ { 1, 2 },
+/* 14 */ { 1, 3 },
+/* 15 */ { 4, 0, 1, 2, 3 },
+/* 16 */ { 1, 4 },
+/* 17 */ { 2, 0, 4 },
+/* 18 */ { 2, 0, 5 },
+/* 19 */ { 1, 0 },
+/* 20 */ { 2, 0, 6 },
+/* 21 */ { 1, 0 },
+/* 22 */ { 1, 0 },
+/* 23 */ { 1, 0 },
+/* 24 */ { 2, 0, 7 },
+/* 25 */ { 1, 0 },
+/* 26 */ { 1, 0 },
+/* 27 */ { 1, 0 },
+/* 28 */ { 1, 0 },
+/* 29 */ { 1, 0 },
+/* 30 */ { 1, 0 },
+/* 31 */ { 1, 0 },
+/* 32 */ { 1, 5 },
+/* 33 */ { 2, 1, 4 },
+/* 34 */ { 2, 1, 5 },
+/* 35 */ { 1, 1 },
+/* 36 */ { 2, 1, 6 },
+/* 37 */ { 1, 1 },
+/* 38 */ { 1, 1 },
+/* 39 */ { 1, 1 },
+/* 40 */ { 2, 1, 7 },
+/* 41 */ { 1, 1 },
+/* 42 */ { 1, 1 },
+/* 43 */ { 1, 1 },
+/* 44 */ { 1, 1 },
+/* 45 */ { 1, 1 },
+/* 46 */ { 1, 1 },
+/* 47 */ { 1, 1 },
+/* 48 */ { 2, 4, 5 },
+/* 49 */ { 1, 4 },
+/* 50 */ { 1, 5 },
+/* 51 */ { 4, 0, 1, 4, 5 },
+/* 52 */ { 1, 6 },
+/* 53 */ { 1, 0 },
+/* 54 */ { 1, 0 },
+/* 55 */ { 1, 0 },
+/* 56 */ { 1, 7 },
+/* 57 */ { 1, 1 },
+/* 58 */ { 1, 1 },
+/* 59 */ { 1, 1 },
+/* 60 */ { 4, 0, 1, 6, 7 },
+/* 61 */ { 1, 0 },
+/* 62 */ { 1, 1 },
+/* 63 */ { 2, 0, 1 },
+/* 64 */ { 1, 6 },
+/* 65 */ { 2, 2, 4 },
+/* 66 */ { 2, 2, 5 },
+/* 67 */ { 1, 2 },
+/* 68 */ { 2, 2, 6 },
+/* 69 */ { 1, 2 },
+/* 70 */ { 1, 2 },
+/* 71 */ { 1, 2 },
+/* 72 */ { 2, 2, 7 },
+/* 73 */ { 1, 2 },
+/* 74 */ { 1, 2 },
+/* 75 */ { 1, 2 },
+/* 76 */ { 1, 2 },
+/* 77 */ { 1, 2 },
+/* 78 */ { 1, 2 },
+/* 79 */ { 1, 2 },
+/* 80 */ { 2, 4, 6 },
+/* 81 */ { 1, 4 },
+/* 82 */ { 1, 5 },
+/* 83 */ { 1, 4 },
+/* 84 */ { 1, 6 },
+/* 85 */ { 4, 0, 2, 4, 6 },
+/* 86 */ { 1, 0 },
+/* 87 */ { 1, 0 },
+/* 88 */ { 1, 7 },
+/* 89 */ { 1, 2 },
+/* 90 */ { 4, 0, 2, 5, 7 },
+/* 91 */ { 1, 0 },
+/* 92 */ { 1, 6 },
+/* 93 */ { 1, 2 },
+/* 94 */ { 1, 2 },
+/* 95 */ { 2, 0, 2 },
+/* 96 */ { 2, 4, 7 },
+/* 97 */ { 1, 4 },
+/* 98 */ { 1, 5 },
+/* 99 */ { 1, 4 },
+/* 100 */ { 1, 6 },
+/* 101 */ { 1, 4 },
+/* 102 */ { 4, 0, 3, 4, 7 },
+/* 103 */ { 1, 0 },
+/* 104 */ { 1, 7 },
+/* 105 */ { 4, 0, 3, 5, 6 },
+/* 106 */ { 1, 7 },
+/* 107 */ { 1, 0 },
+/* 108 */ { 1, 7 },
+/* 109 */ { 1, 3 },
+/* 110 */ { 1, 3 },
+/* 111 */ { 2, 0, 3 },
+/* 112 */ { 1, 4 },
+/* 113 */ { 1, 4 },
+/* 114 */ { 1, 5 },
+/* 115 */ { 1, 4 },
+/* 116 */ { 1, 6 },
+/* 117 */ { 1, 4 },
+/* 118 */ { 1, 4 },
+/* 119 */ { 2, 0, 4 },
+/* 120 */ { 1, 7 },
+/* 121 */ { 1, 5 },
+/* 122 */ { 1, 5 },
+/* 123 */ { 2, 0, 5 },
+/* 124 */ { 1, 6 },
+/* 125 */ { 2, 0, 6 },
+/* 126 */ { 2, 0, 7 },
+/* 127 */ { 1, 0 },
+/* 128 */ { 1, 7 },
+/* 129 */ { 2, 3, 4 },
+/* 130 */ { 2, 3, 5 },
+/* 131 */ { 1, 3 },
+/* 132 */ { 2, 3, 6 },
+/* 133 */ { 1, 3 },
+/* 134 */ { 1, 3 },
+/* 135 */ { 1, 3 },
+/* 136 */ { 2, 3, 7 },
+/* 137 */ { 1, 3 },
+/* 138 */ { 1, 3 },
+/* 139 */ { 1, 3 },
+/* 140 */ { 1, 3 },
+/* 141 */ { 1, 3 },
+/* 142 */ { 1, 3 },
+/* 143 */ { 1, 3 },
+/* 144 */ { 2, 5, 6 },
+/* 145 */ { 1, 4 },
+/* 146 */ { 1, 5 },
+/* 147 */ { 1, 5 },
+/* 148 */ { 1, 6 },
+/* 149 */ { 1, 6 },
+/* 150 */ { 4, 1, 2, 4, 7 },
+/* 151 */ { 1, 1 },
+/* 152 */ { 1, 7 },
+/* 153 */ { 4, 1, 2, 5, 6 },
+/* 154 */ { 1, 5 },
+/* 155 */ { 1, 1 },
+/* 156 */ { 1, 6 },
+/* 157 */ { 1, 2 },
+/* 158 */ { 1, 2 },
+/* 159 */ { 2, 1, 2 },
+/* 160 */ { 2, 5, 7 },
+/* 161 */ { 1, 4 },
+/* 162 */ { 1, 5 },
+/* 163 */ { 1, 5 },
+/* 164 */ { 1, 6 },
+/* 165 */ { 4, 1, 3, 4, 6 },
+/* 166 */ { 1, 3 },
+/* 167 */ { 1, 1 },
+/* 168 */ { 1, 7 },
+/* 169 */ { 1, 1 },
+/* 170 */ { 4, 1, 3, 5, 7 },
+/* 171 */ { 1, 1 },
+/* 172 */ { 1, 7 },
+/* 173 */ { 1, 3 },
+/* 174 */ { 1, 3 },
+/* 175 */ { 2, 1, 3 },
+/* 176 */ { 1, 5 },
+/* 177 */ { 1, 4 },
+/* 178 */ { 1, 5 },
+/* 179 */ { 1, 5 },
+/* 180 */ { 1, 6 },
+/* 181 */ { 1, 4 },
+/* 182 */ { 1, 4 },
+/* 183 */ { 2, 1, 4 },
+/* 184 */ { 1, 7 },
+/* 185 */ { 1, 5 },
+/* 186 */ { 1, 5 },
+/* 187 */ { 2, 1, 5 },
+/* 188 */ { 1, 7 },
+/* 189 */ { 2, 1, 6 },
+/* 190 */ { 2, 1, 7 },
+/* 191 */ { 1, 1 },
+/* 192 */ { 2, 6, 7 },
+/* 193 */ { 1, 4 },
+/* 194 */ { 1, 5 },
+/* 195 */ { 4, 2, 3, 4, 5 },
+/* 196 */ { 1, 6 },
+/* 197 */ { 1, 2 },
+/* 198 */ { 1, 3 },
+/* 199 */ { 1, 2 },
+/* 200 */ { 1, 7 },
+/* 201 */ { 1, 2 },
+/* 202 */ { 1, 3 },
+/* 203 */ { 1, 3 },
+/* 204 */ { 4, 2, 3, 6, 7 },
+/* 205 */ { 1, 2 },
+/* 206 */ { 1, 3 },
+/* 207 */ { 2, 2, 3 },
+/* 208 */ { 1, 6 },
+/* 209 */ { 1, 4 },
+/* 210 */ { 1, 5 },
+/* 211 */ { 1, 4 },
+/* 212 */ { 1, 6 },
+/* 213 */ { 1, 6 },
+/* 214 */ { 1, 7 },
+/* 215 */ { 2, 2, 4 },
+/* 216 */ { 1, 7 },
+/* 217 */ { 1, 6 },
+/* 218 */ { 1, 7 },
+/* 219 */ { 2, 2, 5 },
+/* 220 */ { 1, 6 },
+/* 221 */ { 2, 2, 6 },
+/* 222 */ { 2, 2, 7 },
+/* 223 */ { 1, 2 },
+/* 224 */ { 1, 7 },
+/* 225 */ { 1, 4 },
+/* 226 */ { 1, 5 },
+/* 227 */ { 1, 5 },
+/* 228 */ { 1, 6 },
+/* 229 */ { 1, 6 },
+/* 230 */ { 1, 7 },
+/* 231 */ { 2, 3, 4 },
+/* 232 */ { 1, 7 },
+/* 233 */ { 1, 6 },
+/* 234 */ { 1, 7 },
+/* 235 */ { 2, 3, 5 },
+/* 236 */ { 1, 7 },
+/* 237 */ { 2, 3, 6 },
+/* 238 */ { 2, 3, 7 },
+/* 239 */ { 1, 3 },
+/* 240 */ { 4, 4, 5, 6, 7 },
+/* 241 */ { 1, 4 },
+/* 242 */ { 1, 5 },
+/* 243 */ { 2, 4, 5 },
+/* 244 */ { 1, 6 },
+/* 245 */ { 2, 4, 6 },
+/* 246 */ { 2, 4, 7 },
+/* 247 */ { 1, 4 },
+/* 248 */ { 1, 7 },
+/* 249 */ { 2, 5, 6 },
+/* 250 */ { 2, 5, 7 },
+/* 251 */ { 1, 5 },
+/* 252 */ { 2, 6, 7 },
+/* 253 */ { 1, 6 },
+/* 254 */ { 1, 7 },
+/* 255 */ { 8, 0, 1, 2, 3, 4, 5, 6, 7 }
+};
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c
new file mode 100644
index 00000000..4c51b8b5
--- /dev/null
+++ b/src/misc/extra/extraUtilFile.c
@@ -0,0 +1,495 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilFile.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [File management utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilFile.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find a file name with a different extension.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 )
+{
+ FILE * pFile;
+ char * pFileNameOther;
+ char * pFileGen;
+
+ if ( pS1 == NULL )
+ return NULL;
+
+ // get the generic file name
+ pFileGen = Extra_FileNameGeneric( pFileNameWrong );
+ pFileNameOther = Extra_FileNameAppend( pFileGen, pS1 );
+ pFile = fopen( pFileNameOther, "r" );
+ if ( pFile == NULL && pS2 )
+ { // try one more
+ pFileNameOther = Extra_FileNameAppend( pFileGen, pS2 );
+ pFile = fopen( pFileNameOther, "r" );
+ if ( pFile == NULL && pS3 )
+ { // try one more
+ pFileNameOther = Extra_FileNameAppend( pFileGen, pS3 );
+ pFile = fopen( pFileNameOther, "r" );
+ if ( pFile == NULL && pS4 )
+ { // try one more
+ pFileNameOther = Extra_FileNameAppend( pFileGen, pS4 );
+ pFile = fopen( pFileNameOther, "r" );
+ if ( pFile == NULL && pS5 )
+ { // try one more
+ pFileNameOther = Extra_FileNameAppend( pFileGen, pS5 );
+ pFile = fopen( pFileNameOther, "r" );
+ }
+ }
+ }
+ }
+ FREE( pFileGen );
+ if ( pFile )
+ {
+ fclose( pFile );
+ return pFileNameOther;
+ }
+ // did not find :(
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the file extension.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_FileNameExtension( char * FileName )
+{
+ char * pDot;
+ // find the last "dot" in the file name, if it is present
+ for ( pDot = FileName + strlen(FileName)-1; pDot >= FileName; pDot-- )
+ if ( *pDot == '.' )
+ return pDot + 1;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the composite name of the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_FileNameAppend( char * pBase, char * pSuffix )
+{
+ static char Buffer[500];
+ sprintf( Buffer, "%s%s", pBase, pSuffix );
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_FileNameGeneric( char * FileName )
+{
+ char * pDot;
+ char * pUnd;
+ char * pRes;
+
+ // find the generic name of the file
+ pRes = Extra_UtilStrsav( FileName );
+ // find the pointer to the "." symbol in the file name
+// pUnd = strstr( FileName, "_" );
+ pUnd = NULL;
+ pDot = strstr( FileName, "." );
+ if ( pUnd )
+ pRes[pUnd - FileName] = 0;
+ else if ( pDot )
+ pRes[pDot - FileName] = 0;
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the file size.]
+
+ Description [The file should be closed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_FileSize( char * pFileName )
+{
+ FILE * pFile;
+ int nFileSize;
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Extra_FileSize(): The file is unavailable (absent or open).\n" );
+ return 0;
+ }
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ fclose( pFile );
+ return nFileSize;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Read the file into the internal buffer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_FileRead( FILE * pFile )
+{
+ int nFileSize;
+ char * pBuffer;
+ // get the file size, in bytes
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ // move the file current reading position to the beginning
+ rewind( pFile );
+ // load the contents of the file into memory
+ pBuffer = ALLOC( char, nFileSize + 3 );
+ fread( pBuffer, nFileSize, 1, pFile );
+ // terminate the string with '\0'
+ pBuffer[ nFileSize + 0] = '\n';
+ pBuffer[ nFileSize + 1] = '\0';
+ return pBuffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the time stamp.]
+
+ Description [The file should be closed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_TimeStamp()
+{
+ static char Buffer[100];
+ char * TimeStamp;
+ time_t ltime;
+ // get the current time
+ time( &ltime );
+ TimeStamp = asctime( localtime( &ltime ) );
+ TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
+ strcpy( Buffer, TimeStamp );
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_ReadBinary( char * Buffer )
+{
+ unsigned Result;
+ int i;
+
+ Result = 0;
+ for ( i = 0; Buffer[i]; i++ )
+ if ( Buffer[i] == '0' || Buffer[i] == '1' )
+ Result = Result * 2 + Buffer[i] - '0';
+ else
+ {
+ assert( 0 );
+ }
+ return Result;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the bit string.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits )
+{
+ int Remainder, nWords;
+ int w, i;
+
+ Remainder = (nBits%(sizeof(unsigned)*8));
+ nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0);
+
+ for ( w = nWords-1; w >= 0; w-- )
+ for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- )
+ fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1<<i)) > 0) );
+
+// fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the hex unsigned into the bit-string.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars )
+{
+ int nWords, nDigits, Digit, k, c;
+ nWords = Extra_TruthWordNum( nVars );
+ for ( k = 0; k < nWords; k++ )
+ Sign[k] = 0;
+ // read the number from the string
+ nDigits = (1 << nVars) / 4;
+ if ( nDigits == 0 )
+ nDigits = 1;
+ for ( k = 0; k < nDigits; k++ )
+ {
+ c = nDigits-1-k;
+ if ( pString[c] >= '0' && pString[c] <= '9' )
+ Digit = pString[c] - '0';
+ else if ( pString[c] >= 'A' && pString[c] <= 'F' )
+ Digit = pString[c] - 'A' + 10;
+ else if ( pString[c] >= 'a' && pString[c] <= 'f' )
+ Digit = pString[c] - 'a' + 10;
+ else { assert( 0 ); return 0; }
+ Sign[k/8] |= ( (Digit & 15) << ((k%8) * 4) );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the hex unsigned into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars )
+{
+ int nDigits, Digit, k;
+ // write the number into the file
+ nDigits = (1 << nVars) / 4;
+ for ( k = nDigits - 1; k >= 0; k-- )
+ {
+ Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15);
+ if ( Digit < 10 )
+ fprintf( pFile, "%d", Digit );
+ else
+ fprintf( pFile, "%c", 'a' + Digit-10 );
+ }
+// fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the hex unsigned into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars )
+{
+ int nDigits, Digit, k;
+ // write the number into the file
+ nDigits = (1 << nVars) / 4;
+ for ( k = nDigits - 1; k >= 0; k-- )
+ {
+ Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15);
+ if ( Digit < 10 )
+ *pString++ = '0' + Digit;
+ else
+ *pString++ = 'a' + Digit-10;
+ }
+// fprintf( pFile, "\n" );
+ *pString = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the hex unsigned into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars )
+{
+ int nMints, nDigits, Digit, k;
+
+ // write the number into the file
+ fprintf( pFile, "0x" );
+ nMints = (1 << nVars);
+ nDigits = nMints / 4;
+ for ( k = nDigits - 1; k >= 0; k-- )
+ {
+ Digit = ((uTruth >> (k * 4)) & 15);
+ if ( Digit < 10 )
+ fprintf( pFile, "%d", Digit );
+ else
+ fprintf( pFile, "%c", 'a' + Digit-10 );
+ }
+// fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the composite name of the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine )
+{
+ int i;
+ for ( i = 0; i < nTimes; i++ )
+ printf( "%c", Char );
+ if ( fPrintNewLine )
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Appends the string.]
+
+ Description [Assumes that the given string (pStrGiven) has been allocated
+ before using malloc(). The additional string has not been allocated.
+ Allocs more root, appends the additional part, frees the old given string.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_StringAppend( char * pStrGiven, char * pStrAdd )
+{
+ char * pTemp;
+ if ( pStrGiven )
+ {
+ pTemp = ALLOC( char, strlen(pStrGiven) + strlen(pStrAdd) + 2 );
+ sprintf( pTemp, "%s%s", pStrGiven, pStrAdd );
+ free( pStrGiven );
+ }
+ else
+ pTemp = Extra_UtilStrsav( pStrAdd );
+ return pTemp;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions */
+/*---------------------------------------------------------------------------*/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilMemory.c b/src/misc/extra/extraUtilMemory.c
new file mode 100644
index 00000000..6eccf015
--- /dev/null
+++ b/src/misc/extra/extraUtilMemory.c
@@ -0,0 +1,625 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilMemory.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Memory managers.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilMemory.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+struct Extra_MmFixed_t_
+{
+ // information about individual entries
+ int nEntrySize; // the size of one entry
+ int nEntriesAlloc; // the total number of entries allocated
+ int nEntriesUsed; // the number of entries in use
+ int nEntriesMax; // the max number of entries in use
+ char * pEntriesFree; // the linked list of free entries
+
+ // this is where the memory is stored
+ int nChunkSize; // the size of one chunk
+ int nChunksAlloc; // the maximum number of memory chunks
+ int nChunks; // the current number of memory chunks
+ char ** pChunks; // the allocated memory
+
+ // statistics
+ int nMemoryUsed; // memory used in the allocated entries
+ int nMemoryAlloc; // memory allocated
+};
+
+struct Extra_MmFlex_t_
+{
+ // information about individual entries
+ int nEntriesUsed; // the number of entries allocated
+ char * pCurrent; // the current pointer to free memory
+ char * pEnd; // the first entry outside the free memory
+
+ // this is where the memory is stored
+ int nChunkSize; // the size of one chunk
+ int nChunksAlloc; // the maximum number of memory chunks
+ int nChunks; // the current number of memory chunks
+ char ** pChunks; // the allocated memory
+
+ // statistics
+ int nMemoryUsed; // memory used in the allocated entries
+ int nMemoryAlloc; // memory allocated
+};
+
+
+struct Extra_MmStep_t_
+{
+ int nMems; // the number of fixed memory managers employed
+ Extra_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc
+ int nMapSize; // the size of the memory array
+ Extra_MmFixed_t ** pMap; // maps the number of bytes into its memory manager
+ int nLargeChunksAlloc; // the maximum number of large memory chunks
+ int nLargeChunks; // the current number of large memory chunks
+ void ** pLargeChunks; // the allocated large memory chunks
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Allocates memory pieces of fixed size.]
+
+ Description [The size of the chunk is computed as the minimum of
+ 1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize )
+{
+ Extra_MmFixed_t * p;
+
+ p = ALLOC( Extra_MmFixed_t, 1 );
+ memset( p, 0, sizeof(Extra_MmFixed_t) );
+
+ p->nEntrySize = nEntrySize;
+ p->nEntriesAlloc = 0;
+ p->nEntriesUsed = 0;
+ p->pEntriesFree = NULL;
+
+ if ( nEntrySize * (1 << 10) < (1<<16) )
+ p->nChunkSize = (1 << 10);
+ else
+ p->nChunkSize = (1<<16) / nEntrySize;
+ if ( p->nChunkSize < 8 )
+ p->nChunkSize = 8;
+
+ p->nChunksAlloc = 64;
+ p->nChunks = 0;
+ p->pChunks = ALLOC( char *, p->nChunksAlloc );
+
+ p->nMemoryUsed = 0;
+ p->nMemoryAlloc = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFixedPrint( Extra_MmFixed_t * p )
+{
+ printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+ p->nEntrySize, p->nChunkSize, p->nChunks );
+ printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+ p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFixedStop( Extra_MmFixed_t * p )
+{
+ int i;
+ if ( p == NULL )
+ return;
+ for ( i = 0; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ free( p->pChunks );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p )
+{
+ char * pTemp;
+ int i;
+
+ // check if there are still free entries
+ if ( p->nEntriesUsed == p->nEntriesAlloc )
+ { // need to allocate more entries
+ assert( p->pEntriesFree == NULL );
+ if ( p->nChunks == p->nChunksAlloc )
+ {
+ p->nChunksAlloc *= 2;
+ p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
+ }
+ p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize );
+ p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+ // transform these entries into a linked list
+ pTemp = p->pEntriesFree;
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // add the chunk to the chunk storage
+ p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+ // add to the number of entries allocated
+ p->nEntriesAlloc += p->nChunkSize;
+ }
+ // incrememt the counter of used entries
+ p->nEntriesUsed++;
+ if ( p->nEntriesMax < p->nEntriesUsed )
+ p->nEntriesMax = p->nEntriesUsed;
+ // return the first entry in the free entry list
+ pTemp = p->pEntriesFree;
+ p->pEntriesFree = *((char **)pTemp);
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry )
+{
+ // decrement the counter of used entries
+ p->nEntriesUsed--;
+ // add the entry to the linked list of free entries
+ *((char **)pEntry) = p->pEntriesFree;
+ p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description [Relocates all the memory except the first chunk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFixedRestart( Extra_MmFixed_t * p )
+{
+ int i;
+ char * pTemp;
+
+ // deallocate all chunks except the first one
+ for ( i = 1; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ p->nChunks = 1;
+ // transform these entries into a linked list
+ pTemp = p->pChunks[0];
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // set the free entry list
+ p->pEntriesFree = p->pChunks[0];
+ // set the correct statistics
+ p->nMemoryAlloc = p->nEntrySize * p->nChunkSize;
+ p->nMemoryUsed = 0;
+ p->nEntriesAlloc = p->nChunkSize;
+ p->nEntriesUsed = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
+{
+ return p->nMemoryAlloc;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p )
+{
+ return p->nEntriesMax;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates entries of flexible size.]
+
+ Description [Can only work with entry size at least 4 byte long.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Extra_MmFlex_t * Extra_MmFlexStart()
+{
+ Extra_MmFlex_t * p;
+//printf( "allocing flex\n" );
+ p = ALLOC( Extra_MmFlex_t, 1 );
+ memset( p, 0, sizeof(Extra_MmFlex_t) );
+
+ p->nEntriesUsed = 0;
+ p->pCurrent = NULL;
+ p->pEnd = NULL;
+
+ p->nChunkSize = (1 << 10);
+ p->nChunksAlloc = 64;
+ p->nChunks = 0;
+ p->pChunks = ALLOC( char *, p->nChunksAlloc );
+
+ p->nMemoryUsed = 0;
+ p->nMemoryAlloc = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFlexPrint( Extra_MmFlex_t * p )
+{
+ printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+ p->nChunkSize, p->nChunks );
+ printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+ p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFlexStop( Extra_MmFlex_t * p )
+{
+ int i;
+ if ( p == NULL )
+ return;
+//printf( "deleting flex\n" );
+ for ( i = 0; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ free( p->pChunks );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes )
+{
+ char * pTemp;
+ // check if there are still free entries
+ if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+ { // need to allocate more entries
+ if ( p->nChunks == p->nChunksAlloc )
+ {
+ p->nChunksAlloc *= 2;
+ p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
+ }
+ if ( nBytes > p->nChunkSize )
+ {
+ // resize the chunk size if more memory is requested than it can give
+ // (ideally, this should never happen)
+ p->nChunkSize = 2 * nBytes;
+ }
+ p->pCurrent = ALLOC( char, p->nChunkSize );
+ p->pEnd = p->pCurrent + p->nChunkSize;
+ p->nMemoryAlloc += p->nChunkSize;
+ // add the chunk to the chunk storage
+ p->pChunks[ p->nChunks++ ] = p->pCurrent;
+ }
+ assert( p->pCurrent + nBytes <= p->pEnd );
+ // increment the counter of used entries
+ p->nEntriesUsed++;
+ // keep track of the memory used
+ p->nMemoryUsed += nBytes;
+ // return the next entry
+ pTemp = p->pCurrent;
+ p->pCurrent += nBytes;
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p )
+{
+ return p->nMemoryAlloc;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the hierarchical memory manager.]
+
+ Description [This manager can allocate entries of any size.
+ Iternally they are mapped into the entries with the number of bytes
+ equal to the power of 2. The smallest entry size is 8 bytes. The
+ next one is 16 bytes etc. So, if the user requests 6 bytes, he gets
+ 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+ The input parameters "nSteps" says how many fixed memory managers
+ are employed internally. Calling this procedure with nSteps equal
+ to 10 results in 10 hierarchically arranged internal memory managers,
+ which can allocate up to 4096 (1Kb) entries. Requests for larger
+ entries are handed over to malloc() and then free()ed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Extra_MmStep_t * Extra_MmStepStart( int nSteps )
+{
+ Extra_MmStep_t * p;
+ int i, k;
+ p = ALLOC( Extra_MmStep_t, 1 );
+ memset( p, 0, sizeof(Extra_MmStep_t) );
+ p->nMems = nSteps;
+ // start the fixed memory managers
+ p->pMems = ALLOC( Extra_MmFixed_t *, p->nMems );
+ for ( i = 0; i < p->nMems; i++ )
+ p->pMems[i] = Extra_MmFixedStart( (8<<i) );
+ // set up the mapping of the required memory size into the corresponding manager
+ p->nMapSize = (4<<p->nMems);
+ p->pMap = ALLOC( Extra_MmFixed_t *, p->nMapSize+1 );
+ p->pMap[0] = NULL;
+ for ( k = 1; k <= 4; k++ )
+ p->pMap[k] = p->pMems[0];
+ for ( i = 0; i < p->nMems; i++ )
+ for ( k = (4<<i)+1; k <= (8<<i); k++ )
+ p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmStepStop( Extra_MmStep_t * p )
+{
+ int i;
+ for ( i = 0; i < p->nMems; i++ )
+ Extra_MmFixedStop( p->pMems[i] );
+// if ( p->pLargeChunks )
+// {
+// for ( i = 0; i < p->nLargeChunks; i++ )
+// free( p->pLargeChunks[i] );
+// free( p->pLargeChunks );
+// }
+ free( p->pMems );
+ free( p->pMap );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes )
+{
+ if ( nBytes == 0 )
+ return NULL;
+ if ( nBytes > p->nMapSize )
+ {
+// printf( "Allocating %d bytes.\n", nBytes );
+/*
+ if ( p->nLargeChunks == p->nLargeChunksAlloc )
+ {
+ if ( p->nLargeChunksAlloc == 0 )
+ p->nLargeChunksAlloc = 5;
+ p->nLargeChunksAlloc *= 2;
+ p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc );
+ }
+ p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes );
+ return p->pLargeChunks[ p->nLargeChunks - 1 ];
+*/
+ return ALLOC( char, nBytes );
+ }
+ return Extra_MmFixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes )
+{
+ if ( nBytes == 0 )
+ return;
+ if ( nBytes > p->nMapSize )
+ {
+ free( pEntry );
+ return;
+ }
+ Extra_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_MmStepReadMemUsage( Extra_MmStep_t * p )
+{
+ int i, nMemTotal = 0;
+ for ( i = 0; i < p->nMems; i++ )
+ nMemTotal += p->pMems[i]->nMemoryAlloc;
+ return nMemTotal;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions */
+/*---------------------------------------------------------------------------*/
+
diff --git a/src/misc/extra/extraUtilMisc.c b/src/misc/extra/extraUtilMisc.c
new file mode 100644
index 00000000..dff774bc
--- /dev/null
+++ b/src/misc/extra/extraUtilMisc.c
@@ -0,0 +1,2235 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilMisc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Misc procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+static void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] );
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+ Synopsis [Finds the smallest integer larger of equal than the logarithm.]
+
+ Description [Returns [Log2(Num)].]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_Base2Log( unsigned Num )
+{
+ int Res;
+ assert( Num >= 0 );
+ if ( Num == 0 ) return 0;
+ if ( Num == 1 ) return 1;
+ for ( Res = 0, Num--; Num; Num >>= 1, Res++ );
+ return Res;
+} /* end of Extra_Base2Log */
+
+/**Function********************************************************************
+
+ Synopsis [Finds the smallest integer larger of equal than the logarithm.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_Base2LogDouble( double Num )
+{
+ double Res;
+ int ResInt;
+
+ Res = log(Num)/log(2.0);
+ ResInt = (int)Res;
+ if ( ResInt == Res )
+ return ResInt;
+ else
+ return ResInt+1;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Finds the smallest integer larger of equal than the logarithm.]
+
+ Description [Returns [Log10(Num)].]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_Base10Log( unsigned Num )
+{
+ int Res;
+ assert( Num >= 0 );
+ if ( Num == 0 ) return 0;
+ if ( Num == 1 ) return 1;
+ for ( Res = 0, Num--; Num; Num /= 10, Res++ );
+ return Res;
+} /* end of Extra_Base2Log */
+
+/**Function********************************************************************
+
+ Synopsis [Returns the power of two as a double.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+double Extra_Power2( int Degree )
+{
+ double Res;
+ assert( Degree >= 0 );
+ if ( Degree < 32 )
+ return (double)(01<<Degree);
+ for ( Res = 1.0; Degree; Res *= 2.0, Degree-- );
+ return Res;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_Power3( int Num )
+{
+ int i;
+ int Res;
+ Res = 1;
+ for ( i = 0; i < Num; i++ )
+ Res *= 3;
+ return Res;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Finds the number of combinations of k elements out of n.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_NumCombinations( int k, int n )
+{
+ int i, Res = 1;
+ for ( i = 1; i <= k; i++ )
+ Res = Res * (n-i+1) / i;
+ return Res;
+} /* end of Extra_NumCombinations */
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits )
+{
+ static int Code[100];
+ int i;
+ assert( nDigits < 100 );
+ for ( i = 0; i < nDigits; i++ )
+ {
+ Code[i] = Number % Radix;
+ Number = Number / Radix;
+ }
+ assert( Number == 0 );
+ return Code;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of ones in the bitstring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_CountOnes( unsigned char * pBytes, int nBytes )
+{
+ static int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+ };
+
+ int i, Counter;
+ Counter = 0;
+ for ( i = 0; i < nBytes; i++ )
+ Counter += bit_count[ *(pBytes+i) ];
+ return Counter;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the factorial.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_Factorial( int n )
+{
+ int i, Res = 1;
+ for ( i = 1; i <= n; i++ )
+ Res *= i;
+ return Res;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the set of all permutations.]
+
+ Description [The number of permutations in the array is n!. The number of
+ entries in each permutation is n. Therefore, the resulting array is a
+ two-dimentional array of the size: n! x n. To free the resulting array,
+ call free() on the pointer returned by this procedure.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+char ** Extra_Permutations( int n )
+{
+ char Array[50];
+ char ** pRes;
+ int nFact, i;
+ // allocate memory
+ nFact = Extra_Factorial( n );
+ pRes = (char **)Extra_ArrayAlloc( nFact, n, sizeof(char) );
+ // fill in the permutations
+ for ( i = 0; i < n; i++ )
+ Array[i] = i;
+ Extra_Permutations_rec( pRes, nFact, n, Array );
+ // print the permutations
+/*
+ {
+ int i, k;
+ for ( i = 0; i < nFact; i++ )
+ {
+ printf( "{" );
+ for ( k = 0; k < n; k++ )
+ printf( " %d", pRes[i][k] );
+ printf( " }\n" );
+ }
+ }
+*/
+ return pRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Fills in the array of permutations.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] )
+{
+ char ** pNext;
+ int nFactNext;
+ int iTemp, iCur, iLast, k;
+
+ if ( n == 1 )
+ {
+ pRes[0][0] = Array[0];
+ return;
+ }
+
+ // get the next factorial
+ nFactNext = nFact / n;
+ // get the last entry
+ iLast = n - 1;
+
+ for ( iCur = 0; iCur < n; iCur++ )
+ {
+ // swap Cur and Last
+ iTemp = Array[iCur];
+ Array[iCur] = Array[iLast];
+ Array[iLast] = iTemp;
+
+ // get the pointer to the current section
+ pNext = pRes + (n - 1 - iCur) * nFactNext;
+
+ // set the last entry
+ for ( k = 0; k < nFactNext; k++ )
+ pNext[k][iLast] = Array[iLast];
+
+ // call recursively for this part
+ Extra_Permutations_rec( pNext, nFactNext, n - 1, Array );
+
+ // swap them back
+ iTemp = Array[iCur];
+ Array[iCur] = Array[iLast];
+ Array[iLast] = iTemp;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Permutes the given vector of minterms.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthPermute_int( int * pMints, int nMints, char * pPerm, int nVars, int * pMintsP )
+{
+ int m, v;
+ // clean the storage for minterms
+ memset( pMintsP, 0, sizeof(int) * nMints );
+ // go through minterms and add the variables
+ for ( m = 0; m < nMints; m++ )
+ for ( v = 0; v < nVars; v++ )
+ if ( pMints[m] & (1 << v) )
+ pMintsP[m] |= (1 << pPerm[v]);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Permutes the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse )
+{
+ unsigned Result;
+ int * pMints;
+ int * pMintsP;
+ int nMints;
+ int i, m;
+
+ assert( nVars < 6 );
+ nMints = (1 << nVars);
+ pMints = ALLOC( int, nMints );
+ pMintsP = ALLOC( int, nMints );
+ for ( i = 0; i < nMints; i++ )
+ pMints[i] = i;
+
+ Extra_TruthPermute_int( pMints, nMints, pPerms, nVars, pMintsP );
+
+ Result = 0;
+ if ( fReverse )
+ {
+ for ( m = 0; m < nMints; m++ )
+ if ( Truth & (1 << pMintsP[m]) )
+ Result |= (1 << m);
+ }
+ else
+ {
+ for ( m = 0; m < nMints; m++ )
+ if ( Truth & (1 << m) )
+ Result |= (1 << pMintsP[m]);
+ }
+
+ free( pMints );
+ free( pMintsP );
+
+ return Result;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Changes the phase of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthPolarize( unsigned uTruth, int Polarity, int nVars )
+{
+ // elementary truth tables
+ static unsigned Signs[5] = {
+ 0xAAAAAAAA, // 1010 1010 1010 1010 1010 1010 1010 1010
+ 0xCCCCCCCC, // 1010 1010 1010 1010 1010 1010 1010 1010
+ 0xF0F0F0F0, // 1111 0000 1111 0000 1111 0000 1111 0000
+ 0xFF00FF00, // 1111 1111 0000 0000 1111 1111 0000 0000
+ 0xFFFF0000 // 1111 1111 1111 1111 0000 0000 0000 0000
+ };
+ unsigned uTruthRes, uCof0, uCof1;
+ int nMints, Shift, v;
+ assert( nVars < 6 );
+ nMints = (1 << nVars);
+ uTruthRes = uTruth;
+ for ( v = 0; v < nVars; v++ )
+ if ( Polarity & (1 << v) )
+ {
+ uCof0 = uTruth & ~Signs[v];
+ uCof1 = uTruth & Signs[v];
+ Shift = (1 << v);
+ uCof0 <<= Shift;
+ uCof1 >>= Shift;
+ uTruth = uCof0 | uCof1;
+ }
+ return uTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes N-canonical form using brute-force methods.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthCanonN( unsigned uTruth, int nVars )
+{
+ unsigned uTruthMin, uPhase;
+ int nMints, i;
+ nMints = (1 << nVars);
+ uTruthMin = 0xFFFFFFFF;
+ for ( i = 0; i < nMints; i++ )
+ {
+ uPhase = Extra_TruthPolarize( uTruth, i, nVars );
+ if ( uTruthMin > uPhase )
+ uTruthMin = uPhase;
+ }
+ return uTruthMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes NN-canonical form using brute-force methods.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars )
+{
+ unsigned uTruthMin, uTruthC, uPhase;
+ int nMints, i;
+ nMints = (1 << nVars);
+ uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) );
+ uTruthMin = 0xFFFFFFFF;
+ for ( i = 0; i < nMints; i++ )
+ {
+ uPhase = Extra_TruthPolarize( uTruth, i, nVars );
+ if ( uTruthMin > uPhase )
+ uTruthMin = uPhase;
+ uPhase = Extra_TruthPolarize( uTruthC, i, nVars );
+ if ( uTruthMin > uPhase )
+ uTruthMin = uPhase;
+ }
+ return uTruthMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes P-canonical form using brute-force methods.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthCanonP( unsigned uTruth, int nVars )
+{
+ static int nVarsOld, nPerms;
+ static char ** pPerms = NULL;
+
+ unsigned uTruthMin, uPerm;
+ int k;
+
+ if ( pPerms == NULL )
+ {
+ nPerms = Extra_Factorial( nVars );
+ pPerms = Extra_Permutations( nVars );
+ nVarsOld = nVars;
+ }
+ else if ( nVarsOld != nVars )
+ {
+ free( pPerms );
+ nPerms = Extra_Factorial( nVars );
+ pPerms = Extra_Permutations( nVars );
+ nVarsOld = nVars;
+ }
+
+ uTruthMin = 0xFFFFFFFF;
+ for ( k = 0; k < nPerms; k++ )
+ {
+ uPerm = Extra_TruthPermute( uTruth, pPerms[k], nVars, 0 );
+ if ( uTruthMin > uPerm )
+ uTruthMin = uPerm;
+ }
+ return uTruthMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes NP-canonical form using brute-force methods.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars )
+{
+ static int nVarsOld, nPerms;
+ static char ** pPerms = NULL;
+
+ unsigned uTruthMin, uPhase, uPerm;
+ int nMints, k, i;
+
+ if ( pPerms == NULL )
+ {
+ nPerms = Extra_Factorial( nVars );
+ pPerms = Extra_Permutations( nVars );
+ nVarsOld = nVars;
+ }
+ else if ( nVarsOld != nVars )
+ {
+ free( pPerms );
+ nPerms = Extra_Factorial( nVars );
+ pPerms = Extra_Permutations( nVars );
+ nVarsOld = nVars;
+ }
+
+ nMints = (1 << nVars);
+ uTruthMin = 0xFFFFFFFF;
+ for ( i = 0; i < nMints; i++ )
+ {
+ uPhase = Extra_TruthPolarize( uTruth, i, nVars );
+ for ( k = 0; k < nPerms; k++ )
+ {
+ uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 );
+ if ( uTruthMin > uPerm )
+ uTruthMin = uPerm;
+ }
+ }
+ return uTruthMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes NPN-canonical form using brute-force methods.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars )
+{
+ static int nVarsOld, nPerms;
+ static char ** pPerms = NULL;
+
+ unsigned uTruthMin, uTruthC, uPhase, uPerm;
+ int nMints, k, i;
+
+ if ( pPerms == NULL )
+ {
+ nPerms = Extra_Factorial( nVars );
+ pPerms = Extra_Permutations( nVars );
+ nVarsOld = nVars;
+ }
+ else if ( nVarsOld != nVars )
+ {
+ free( pPerms );
+ nPerms = Extra_Factorial( nVars );
+ pPerms = Extra_Permutations( nVars );
+ nVarsOld = nVars;
+ }
+
+ nMints = (1 << nVars);
+ uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) );
+ uTruthMin = 0xFFFFFFFF;
+ for ( i = 0; i < nMints; i++ )
+ {
+ uPhase = Extra_TruthPolarize( uTruth, i, nVars );
+ for ( k = 0; k < nPerms; k++ )
+ {
+ uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 );
+ if ( uTruthMin > uPerm )
+ uTruthMin = uPerm;
+ }
+ uPhase = Extra_TruthPolarize( uTruthC, i, nVars );
+ for ( k = 0; k < nPerms; k++ )
+ {
+ uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 );
+ if ( uTruthMin > uPerm )
+ uTruthMin = uPerm;
+ }
+ }
+ return uTruthMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes NPN canonical forms for 4-variable functions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap )
+{
+ unsigned short * uCanons;
+ unsigned char * uMap;
+ unsigned uTruth, uPhase, uPerm;
+ char ** pPerms4, * uPhases, * uPerms;
+ int nFuncs, nClasses;
+ int i, k;
+
+ nFuncs = (1 << 16);
+ uCanons = ALLOC( unsigned short, nFuncs );
+ uPhases = ALLOC( char, nFuncs );
+ uPerms = ALLOC( char, nFuncs );
+ uMap = ALLOC( unsigned char, nFuncs );
+ memset( uCanons, 0, sizeof(unsigned short) * nFuncs );
+ memset( uPhases, 0, sizeof(char) * nFuncs );
+ memset( uPerms, 0, sizeof(char) * nFuncs );
+ memset( uMap, 0, sizeof(unsigned char) * nFuncs );
+ pPerms4 = Extra_Permutations( 4 );
+
+ nClasses = 1;
+ nFuncs = (1 << 15);
+ for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ )
+ {
+ // skip already assigned
+ if ( uCanons[uTruth] )
+ {
+ assert( uTruth > uCanons[uTruth] );
+ uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]];
+ continue;
+ }
+ uMap[uTruth] = nClasses++;
+ for ( i = 0; i < 16; i++ )
+ {
+ uPhase = Extra_TruthPolarize( uTruth, i, 4 );
+ for ( k = 0; k < 24; k++ )
+ {
+ uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 );
+ if ( uCanons[uPerm] == 0 )
+ {
+ uCanons[uPerm] = uTruth;
+ uPhases[uPerm] = i;
+ uPerms[uPerm] = k;
+
+ uPerm = ~uPerm & 0xFFFF;
+ uCanons[uPerm] = uTruth;
+ uPhases[uPerm] = i | 16;
+ uPerms[uPerm] = k;
+ }
+ else
+ assert( uCanons[uPerm] == uTruth );
+ }
+ uPhase = Extra_TruthPolarize( ~uTruth & 0xFFFF, i, 4 );
+ for ( k = 0; k < 24; k++ )
+ {
+ uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 );
+ if ( uCanons[uPerm] == 0 )
+ {
+ uCanons[uPerm] = uTruth;
+ uPhases[uPerm] = i;
+ uPerms[uPerm] = k;
+
+ uPerm = ~uPerm & 0xFFFF;
+ uCanons[uPerm] = uTruth;
+ uPhases[uPerm] = i | 16;
+ uPerms[uPerm] = k;
+ }
+ else
+ assert( uCanons[uPerm] == uTruth );
+ }
+ }
+ }
+ uPhases[(1<<16)-1] = 16;
+ assert( nClasses == 222 );
+ free( pPerms4 );
+ if ( puCanons )
+ *puCanons = uCanons;
+ else
+ free( uCanons );
+ if ( puPhases )
+ *puPhases = uPhases;
+ else
+ free( uPhases );
+ if ( puPerms )
+ *puPerms = uPerms;
+ else
+ free( uPerms );
+ if ( puMap )
+ *puMap = uMap;
+ else
+ free( uMap );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes NPN canonical forms for 4-variable functions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters )
+{
+ int nPhasesMax = 8;
+ unsigned * uCanons;
+ unsigned uTruth, uPhase, uTruth32;
+ char ** uPhases, * pCounters;
+ int nFuncs, nClasses, i;
+
+ nFuncs = (1 << 8);
+ uCanons = ALLOC( unsigned, nFuncs );
+ memset( uCanons, 0, sizeof(unsigned) * nFuncs );
+ pCounters = ALLOC( char, nFuncs );
+ memset( pCounters, 0, sizeof(char) * nFuncs );
+ uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) );
+ nClasses = 0;
+ for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ )
+ {
+ // skip already assigned
+ uTruth32 = ((uTruth << 24) | (uTruth << 16) | (uTruth << 8) | uTruth);
+ if ( uCanons[uTruth] )
+ {
+ assert( uTruth32 > uCanons[uTruth] );
+ continue;
+ }
+ nClasses++;
+ for ( i = 0; i < 8; i++ )
+ {
+ uPhase = Extra_TruthPolarize( uTruth, i, 3 );
+ if ( uCanons[uPhase] == 0 && (uTruth || i==0) )
+ {
+ uCanons[uPhase] = uTruth32;
+ uPhases[uPhase][0] = i;
+ pCounters[uPhase] = 1;
+ }
+ else
+ {
+ assert( uCanons[uPhase] == uTruth32 );
+ if ( pCounters[uPhase] < nPhasesMax )
+ uPhases[uPhase][ pCounters[uPhase]++ ] = i;
+ }
+ }
+ }
+ if ( puCanons )
+ *puCanons = uCanons;
+ else
+ free( uCanons );
+ if ( puPhases )
+ *puPhases = uPhases;
+ else
+ free( uPhases );
+ if ( ppCounters )
+ *ppCounters = pCounters;
+ else
+ free( pCounters );
+// printf( "The number of 3N-classes = %d.\n", nClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes NPN canonical forms for 4-variable functions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax )
+{
+ unsigned short * uCanons;
+ unsigned uTruth, uPhase;
+ char ** uPhases, * pCounters;
+ int nFuncs, nClasses, i;
+
+ nFuncs = (1 << 16);
+ uCanons = ALLOC( unsigned short, nFuncs );
+ memset( uCanons, 0, sizeof(unsigned short) * nFuncs );
+ pCounters = ALLOC( char, nFuncs );
+ memset( pCounters, 0, sizeof(char) * nFuncs );
+ uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) );
+ nClasses = 0;
+ for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ )
+ {
+ // skip already assigned
+ if ( uCanons[uTruth] )
+ {
+ assert( uTruth > uCanons[uTruth] );
+ continue;
+ }
+ nClasses++;
+ for ( i = 0; i < 16; i++ )
+ {
+ uPhase = Extra_TruthPolarize( uTruth, i, 4 );
+ if ( uCanons[uPhase] == 0 && (uTruth || i==0) )
+ {
+ uCanons[uPhase] = uTruth;
+ uPhases[uPhase][0] = i;
+ pCounters[uPhase] = 1;
+ }
+ else
+ {
+ assert( uCanons[uPhase] == uTruth );
+ if ( pCounters[uPhase] < nPhasesMax )
+ uPhases[uPhase][ pCounters[uPhase]++ ] = i;
+ }
+ }
+ }
+ if ( puCanons )
+ *puCanons = uCanons;
+ else
+ free( uCanons );
+ if ( puPhases )
+ *puPhases = uPhases;
+ else
+ free( uPhases );
+ if ( ppCounters )
+ *ppCounters = pCounters;
+ else
+ free( pCounters );
+// printf( "The number of 4N-classes = %d.\n", nClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocated one-memory-chunk array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void ** Extra_ArrayAlloc( int nCols, int nRows, int Size )
+{
+ char ** pRes;
+ char * pBuffer;
+ int i;
+ assert( nCols > 0 && nRows > 0 && Size > 0 );
+ pBuffer = ALLOC( char, nCols * (sizeof(void *) + nRows * Size) );
+ pRes = (char **)pBuffer;
+ pRes[0] = pBuffer + nCols * sizeof(void *);
+ for ( i = 1; i < nCols; i++ )
+ pRes[i] = pRes[0] + i * nRows * Size;
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes a phase of the 3-var function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase )
+{
+ // cases
+ static unsigned short Cases[16] = {
+ 0, // 0000 - skip
+ 0, // 0001 - skip
+ 0xCCCC, // 0010 - single var
+ 0, // 0011 - skip
+ 0xF0F0, // 0100 - single var
+ 1, // 0101
+ 1, // 0110
+ 0, // 0111 - skip
+ 0xFF00, // 1000 - single var
+ 1, // 1001
+ 1, // 1010
+ 1, // 1011
+ 1, // 1100
+ 1, // 1101
+ 1, // 1110
+ 0 // 1111 - skip
+ };
+ // permutations
+ static int Perms[16][4] = {
+ { 0, 0, 0, 0 }, // 0000 - skip
+ { 0, 0, 0, 0 }, // 0001 - skip
+ { 0, 0, 0, 0 }, // 0010 - single var
+ { 0, 0, 0, 0 }, // 0011 - skip
+ { 0, 0, 0, 0 }, // 0100 - single var
+ { 0, 2, 1, 3 }, // 0101
+ { 2, 0, 1, 3 }, // 0110
+ { 0, 0, 0, 0 }, // 0111 - skip
+ { 0, 0, 0, 0 }, // 1000 - single var
+ { 0, 2, 3, 1 }, // 1001
+ { 2, 0, 3, 1 }, // 1010
+ { 0, 1, 3, 2 }, // 1011
+ { 2, 3, 0, 1 }, // 1100
+ { 0, 3, 1, 2 }, // 1101
+ { 3, 0, 1, 2 }, // 1110
+ { 0, 0, 0, 0 } // 1111 - skip
+ };
+ int i, k, iRes;
+ unsigned uTruthRes;
+ assert( Phase >= 0 && Phase < 16 );
+ if ( Cases[Phase] == 0 )
+ return uTruth;
+ if ( Cases[Phase] > 1 )
+ return Cases[Phase];
+ uTruthRes = 0;
+ for ( i = 0; i < 16; i++ )
+ if ( uTruth & (1 << i) )
+ {
+ for ( iRes = 0, k = 0; k < 4; k++ )
+ if ( i & (1 << Perms[Phase][k]) )
+ iRes |= (1 << k);
+ uTruthRes |= (1 << iRes);
+ }
+ return uTruthRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes a phase of the 3-var function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase )
+{
+ // cases
+ static unsigned Cases[32] = {
+ 0, // 00000 - skip
+ 0, // 00001 - skip
+ 0xCCCCCCCC, // 00010 - single var
+ 0, // 00011 - skip
+ 0xF0F0F0F0, // 00100 - single var
+ 1, // 00101
+ 1, // 00110
+ 0, // 00111 - skip
+ 0xFF00FF00, // 01000 - single var
+ 1, // 01001
+ 1, // 01010
+ 1, // 01011
+ 1, // 01100
+ 1, // 01101
+ 1, // 01110
+ 0, // 01111 - skip
+ 0xFFFF0000, // 10000 - skip
+ 1, // 10001
+ 1, // 10010
+ 1, // 10011
+ 1, // 10100
+ 1, // 10101
+ 1, // 10110
+ 1, // 10111 - four var
+ 1, // 11000
+ 1, // 11001
+ 1, // 11010
+ 1, // 11011 - four var
+ 1, // 11100
+ 1, // 11101 - four var
+ 1, // 11110 - four var
+ 0 // 11111 - skip
+ };
+ // permutations
+ static int Perms[32][5] = {
+ { 0, 0, 0, 0, 0 }, // 00000 - skip
+ { 0, 0, 0, 0, 0 }, // 00001 - skip
+ { 0, 0, 0, 0, 0 }, // 00010 - single var
+ { 0, 0, 0, 0, 0 }, // 00011 - skip
+ { 0, 0, 0, 0, 0 }, // 00100 - single var
+ { 0, 2, 1, 3, 4 }, // 00101
+ { 2, 0, 1, 3, 4 }, // 00110
+ { 0, 0, 0, 0, 0 }, // 00111 - skip
+ { 0, 0, 0, 0, 0 }, // 01000 - single var
+ { 0, 2, 3, 1, 4 }, // 01001
+ { 2, 0, 3, 1, 4 }, // 01010
+ { 0, 1, 3, 2, 4 }, // 01011
+ { 2, 3, 0, 1, 4 }, // 01100
+ { 0, 3, 1, 2, 4 }, // 01101
+ { 3, 0, 1, 2, 4 }, // 01110
+ { 0, 0, 0, 0, 0 }, // 01111 - skip
+ { 0, 0, 0, 0, 0 }, // 10000 - single var
+ { 0, 4, 2, 3, 1 }, // 10001
+ { 4, 0, 2, 3, 1 }, // 10010
+ { 0, 1, 3, 4, 2 }, // 10011
+ { 2, 3, 0, 4, 1 }, // 10100
+ { 0, 3, 1, 4, 2 }, // 10101
+ { 3, 0, 1, 4, 2 }, // 10110
+ { 0, 1, 2, 4, 3 }, // 10111 - four var
+ { 2, 3, 4, 0, 1 }, // 11000
+ { 0, 3, 4, 1, 2 }, // 11001
+ { 3, 0, 4, 1, 2 }, // 11010
+ { 0, 1, 4, 2, 3 }, // 11011 - four var
+ { 3, 4, 0, 1, 2 }, // 11100
+ { 0, 4, 1, 2, 3 }, // 11101 - four var
+ { 4, 0, 1, 2, 3 }, // 11110 - four var
+ { 0, 0, 0, 0, 0 } // 11111 - skip
+ };
+ int i, k, iRes;
+ unsigned uTruthRes;
+ assert( Phase >= 0 && Phase < 32 );
+ if ( Cases[Phase] == 0 )
+ return uTruth;
+ if ( Cases[Phase] > 1 )
+ return Cases[Phase];
+ uTruthRes = 0;
+ for ( i = 0; i < 32; i++ )
+ if ( uTruth & (1 << i) )
+ {
+ for ( iRes = 0, k = 0; k < 5; k++ )
+ if ( i & (1 << Perms[Phase][k]) )
+ iRes |= (1 << k);
+ uTruthRes |= (1 << iRes);
+ }
+ return uTruthRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes a phase of the 3-var function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes )
+{
+ // cases
+ static unsigned Cases[64] = {
+ 0, // 000000 - skip
+ 0, // 000001 - skip
+ 0xCCCCCCCC, // 000010 - single var
+ 0, // 000011 - skip
+ 0xF0F0F0F0, // 000100 - single var
+ 1, // 000101
+ 1, // 000110
+ 0, // 000111 - skip
+ 0xFF00FF00, // 001000 - single var
+ 1, // 001001
+ 1, // 001010
+ 1, // 001011
+ 1, // 001100
+ 1, // 001101
+ 1, // 001110
+ 0, // 001111 - skip
+ 0xFFFF0000, // 010000 - skip
+ 1, // 010001
+ 1, // 010010
+ 1, // 010011
+ 1, // 010100
+ 1, // 010101
+ 1, // 010110
+ 1, // 010111 - four var
+ 1, // 011000
+ 1, // 011001
+ 1, // 011010
+ 1, // 011011 - four var
+ 1, // 011100
+ 1, // 011101 - four var
+ 1, // 011110 - four var
+ 0, // 011111 - skip
+ 0xFFFFFFFF, // 100000 - single var
+ 1, // 100001
+ 1, // 100010
+ 1, // 100011
+ 1, // 100100
+ 1, // 100101
+ 1, // 100110
+ 1, // 100111
+ 1, // 101000
+ 1, // 101001
+ 1, // 101010
+ 1, // 101011
+ 1, // 101100
+ 1, // 101101
+ 1, // 101110
+ 1, // 101111
+ 1, // 110000
+ 1, // 110001
+ 1, // 110010
+ 1, // 110011
+ 1, // 110100
+ 1, // 110101
+ 1, // 110110
+ 1, // 110111
+ 1, // 111000
+ 1, // 111001
+ 1, // 111010
+ 1, // 111011
+ 1, // 111100
+ 1, // 111101
+ 1, // 111110
+ 0 // 111111 - skip
+ };
+ // permutations
+ static int Perms[64][6] = {
+ { 0, 0, 0, 0, 0, 0 }, // 000000 - skip
+ { 0, 0, 0, 0, 0, 0 }, // 000001 - skip
+ { 0, 0, 0, 0, 0, 0 }, // 000010 - single var
+ { 0, 0, 0, 0, 0, 0 }, // 000011 - skip
+ { 0, 0, 0, 0, 0, 0 }, // 000100 - single var
+ { 0, 2, 1, 3, 4, 5 }, // 000101
+ { 2, 0, 1, 3, 4, 5 }, // 000110
+ { 0, 0, 0, 0, 0, 0 }, // 000111 - skip
+ { 0, 0, 0, 0, 0, 0 }, // 001000 - single var
+ { 0, 2, 3, 1, 4, 5 }, // 001001
+ { 2, 0, 3, 1, 4, 5 }, // 001010
+ { 0, 1, 3, 2, 4, 5 }, // 001011
+ { 2, 3, 0, 1, 4, 5 }, // 001100
+ { 0, 3, 1, 2, 4, 5 }, // 001101
+ { 3, 0, 1, 2, 4, 5 }, // 001110
+ { 0, 0, 0, 0, 0, 0 }, // 001111 - skip
+ { 0, 0, 0, 0, 0, 0 }, // 010000 - skip
+ { 0, 4, 2, 3, 1, 5 }, // 010001
+ { 4, 0, 2, 3, 1, 5 }, // 010010
+ { 0, 1, 3, 4, 2, 5 }, // 010011
+ { 2, 3, 0, 4, 1, 5 }, // 010100
+ { 0, 3, 1, 4, 2, 5 }, // 010101
+ { 3, 0, 1, 4, 2, 5 }, // 010110
+ { 0, 1, 2, 4, 3, 5 }, // 010111 - four var
+ { 2, 3, 4, 0, 1, 5 }, // 011000
+ { 0, 3, 4, 1, 2, 5 }, // 011001
+ { 3, 0, 4, 1, 2, 5 }, // 011010
+ { 0, 1, 4, 2, 3, 5 }, // 011011 - four var
+ { 3, 4, 0, 1, 2, 5 }, // 011100
+ { 0, 4, 1, 2, 3, 5 }, // 011101 - four var
+ { 4, 0, 1, 2, 3, 5 }, // 011110 - four var
+ { 0, 0, 0, 0, 0, 0 }, // 011111 - skip
+ { 0, 0, 0, 0, 0, 0 }, // 100000 - single var
+ { 0, 2, 3, 4, 5, 1 }, // 100001
+ { 2, 0, 3, 4, 5, 1 }, // 100010
+ { 0, 1, 3, 4, 5, 2 }, // 100011
+ { 2, 3, 0, 4, 5, 1 }, // 100100
+ { 0, 3, 1, 4, 5, 2 }, // 100101
+ { 3, 0, 1, 4, 5, 2 }, // 100110
+ { 0, 1, 2, 4, 5, 3 }, // 100111
+ { 2, 3, 4, 0, 5, 1 }, // 101000
+ { 0, 3, 4, 1, 5, 2 }, // 101001
+ { 3, 0, 4, 1, 5, 2 }, // 101010
+ { 0, 1, 4, 2, 5, 3 }, // 101011
+ { 3, 4, 0, 1, 5, 2 }, // 101100
+ { 0, 4, 1, 2, 5, 3 }, // 101101
+ { 4, 0, 1, 2, 5, 3 }, // 101110
+ { 0, 1, 2, 3, 5, 4 }, // 101111
+ { 2, 3, 4, 5, 0, 1 }, // 110000
+ { 0, 3, 4, 5, 1, 2 }, // 110001
+ { 3, 0, 4, 5, 1, 2 }, // 110010
+ { 0, 1, 4, 5, 2, 3 }, // 110011
+ { 3, 4, 0, 5, 1, 2 }, // 110100
+ { 0, 4, 1, 5, 2, 3 }, // 110101
+ { 4, 0, 1, 5, 2, 3 }, // 110110
+ { 0, 1, 2, 5, 3, 4 }, // 110111
+ { 3, 4, 5, 0, 1, 2 }, // 111000
+ { 0, 4, 5, 1, 2, 3 }, // 111001
+ { 4, 0, 5, 1, 2, 3 }, // 111010
+ { 0, 1, 5, 2, 3, 4 }, // 111011
+ { 4, 5, 0, 1, 2, 3 }, // 111100
+ { 0, 5, 1, 2, 3, 4 }, // 111101
+ { 5, 0, 1, 2, 3, 4 }, // 111110
+ { 0, 0, 0, 0, 0, 0 } // 111111 - skip
+ };
+ int i, k, iRes;
+ assert( Phase >= 0 && Phase < 64 );
+ if ( Cases[Phase] == 0 )
+ {
+ uTruthRes[0] = uTruth[0];
+ uTruthRes[1] = uTruth[1];
+ return;
+ }
+ if ( Cases[Phase] > 1 )
+ {
+ if ( Phase == 32 )
+ {
+ uTruthRes[0] = 0x00000000;
+ uTruthRes[1] = 0xFFFFFFFF;
+ }
+ else
+ {
+ uTruthRes[0] = Cases[Phase];
+ uTruthRes[1] = Cases[Phase];
+ }
+ return;
+ }
+ uTruthRes[0] = 0;
+ uTruthRes[1] = 0;
+ for ( i = 0; i < 64; i++ )
+ {
+ if ( i < 32 )
+ {
+ if ( uTruth[0] & (1 << i) )
+ {
+ for ( iRes = 0, k = 0; k < 6; k++ )
+ if ( i & (1 << Perms[Phase][k]) )
+ iRes |= (1 << k);
+ if ( iRes < 32 )
+ uTruthRes[0] |= (1 << iRes);
+ else
+ uTruthRes[1] |= (1 << (iRes-32));
+ }
+ }
+ else
+ {
+ if ( uTruth[1] & (1 << (i-32)) )
+ {
+ for ( iRes = 0, k = 0; k < 6; k++ )
+ if ( i & (1 << Perms[Phase][k]) )
+ iRes |= (1 << k);
+ if ( iRes < 32 )
+ uTruthRes[0] |= (1 << iRes);
+ else
+ uTruthRes[1] |= (1 << (iRes-32));
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes a phase of the 8-var function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR )
+{
+ // elementary truth tables
+ static unsigned uTruths[8][8] = {
+ { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+ { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+ { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+ { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+ { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
+ { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
+ };
+ static char Cases[256] = {
+ 0, // 00000000
+ 0, // 00000001
+ 1, // 00000010
+ 0, // 00000011
+ 2, // 00000100
+ -1, // 00000101
+ -1, // 00000110
+ 0, // 00000111
+ 3, // 00001000
+ -1, // 00001001
+ -1, // 00001010
+ -1, // 00001011
+ -1, // 00001100
+ -1, // 00001101
+ -1, // 00001110
+ 0, // 00001111
+ 4, // 00010000
+ -1, // 00010001
+ -1, // 00010010
+ -1, // 00010011
+ -1, // 00010100
+ -1, // 00010101
+ -1, // 00010110
+ -1, // 00010111
+ -1, // 00011000
+ -1, // 00011001
+ -1, // 00011010
+ -1, // 00011011
+ -1, // 00011100
+ -1, // 00011101
+ -1, // 00011110
+ 0, // 00011111
+ 5, // 00100000
+ -1, // 00100001
+ -1, // 00100010
+ -1, // 00100011
+ -1, // 00100100
+ -1, // 00100101
+ -1, // 00100110
+ -1, // 00100111
+ -1, // 00101000
+ -1, // 00101001
+ -1, // 00101010
+ -1, // 00101011
+ -1, // 00101100
+ -1, // 00101101
+ -1, // 00101110
+ -1, // 00101111
+ -1, // 00110000
+ -1, // 00110001
+ -1, // 00110010
+ -1, // 00110011
+ -1, // 00110100
+ -1, // 00110101
+ -1, // 00110110
+ -1, // 00110111
+ -1, // 00111000
+ -1, // 00111001
+ -1, // 00111010
+ -1, // 00111011
+ -1, // 00111100
+ -1, // 00111101
+ -1, // 00111110
+ 0, // 00111111
+ 6, // 01000000
+ -1, // 01000001
+ -1, // 01000010
+ -1, // 01000011
+ -1, // 01000100
+ -1, // 01000101
+ -1, // 01000110
+ -1, // 01000111
+ -1, // 01001000
+ -1, // 01001001
+ -1, // 01001010
+ -1, // 01001011
+ -1, // 01001100
+ -1, // 01001101
+ -1, // 01001110
+ -1, // 01001111
+ -1, // 01010000
+ -1, // 01010001
+ -1, // 01010010
+ -1, // 01010011
+ -1, // 01010100
+ -1, // 01010101
+ -1, // 01010110
+ -1, // 01010111
+ -1, // 01011000
+ -1, // 01011001
+ -1, // 01011010
+ -1, // 01011011
+ -1, // 01011100
+ -1, // 01011101
+ -1, // 01011110
+ -1, // 01011111
+ -1, // 01100000
+ -1, // 01100001
+ -1, // 01100010
+ -1, // 01100011
+ -1, // 01100100
+ -1, // 01100101
+ -1, // 01100110
+ -1, // 01100111
+ -1, // 01101000
+ -1, // 01101001
+ -1, // 01101010
+ -1, // 01101011
+ -1, // 01101100
+ -1, // 01101101
+ -1, // 01101110
+ -1, // 01101111
+ -1, // 01110000
+ -1, // 01110001
+ -1, // 01110010
+ -1, // 01110011
+ -1, // 01110100
+ -1, // 01110101
+ -1, // 01110110
+ -1, // 01110111
+ -1, // 01111000
+ -1, // 01111001
+ -1, // 01111010
+ -1, // 01111011
+ -1, // 01111100
+ -1, // 01111101
+ -1, // 01111110
+ 0, // 01111111
+ 7, // 10000000
+ -1, // 10000001
+ -1, // 10000010
+ -1, // 10000011
+ -1, // 10000100
+ -1, // 10000101
+ -1, // 10000110
+ -1, // 10000111
+ -1, // 10001000
+ -1, // 10001001
+ -1, // 10001010
+ -1, // 10001011
+ -1, // 10001100
+ -1, // 10001101
+ -1, // 10001110
+ -1, // 10001111
+ -1, // 10010000
+ -1, // 10010001
+ -1, // 10010010
+ -1, // 10010011
+ -1, // 10010100
+ -1, // 10010101
+ -1, // 10010110
+ -1, // 10010111
+ -1, // 10011000
+ -1, // 10011001
+ -1, // 10011010
+ -1, // 10011011
+ -1, // 10011100
+ -1, // 10011101
+ -1, // 10011110
+ -1, // 10011111
+ -1, // 10100000
+ -1, // 10100001
+ -1, // 10100010
+ -1, // 10100011
+ -1, // 10100100
+ -1, // 10100101
+ -1, // 10100110
+ -1, // 10100111
+ -1, // 10101000
+ -1, // 10101001
+ -1, // 10101010
+ -1, // 10101011
+ -1, // 10101100
+ -1, // 10101101
+ -1, // 10101110
+ -1, // 10101111
+ -1, // 10110000
+ -1, // 10110001
+ -1, // 10110010
+ -1, // 10110011
+ -1, // 10110100
+ -1, // 10110101
+ -1, // 10110110
+ -1, // 10110111
+ -1, // 10111000
+ -1, // 10111001
+ -1, // 10111010
+ -1, // 10111011
+ -1, // 10111100
+ -1, // 10111101
+ -1, // 10111110
+ -1, // 10111111
+ -1, // 11000000
+ -1, // 11000001
+ -1, // 11000010
+ -1, // 11000011
+ -1, // 11000100
+ -1, // 11000101
+ -1, // 11000110
+ -1, // 11000111
+ -1, // 11001000
+ -1, // 11001001
+ -1, // 11001010
+ -1, // 11001011
+ -1, // 11001100
+ -1, // 11001101
+ -1, // 11001110
+ -1, // 11001111
+ -1, // 11010000
+ -1, // 11010001
+ -1, // 11010010
+ -1, // 11010011
+ -1, // 11010100
+ -1, // 11010101
+ -1, // 11010110
+ -1, // 11010111
+ -1, // 11011000
+ -1, // 11011001
+ -1, // 11011010
+ -1, // 11011011
+ -1, // 11011100
+ -1, // 11011101
+ -1, // 11011110
+ -1, // 11011111
+ -1, // 11100000
+ -1, // 11100001
+ -1, // 11100010
+ -1, // 11100011
+ -1, // 11100100
+ -1, // 11100101
+ -1, // 11100110
+ -1, // 11100111
+ -1, // 11101000
+ -1, // 11101001
+ -1, // 11101010
+ -1, // 11101011
+ -1, // 11101100
+ -1, // 11101101
+ -1, // 11101110
+ -1, // 11101111
+ -1, // 11110000
+ -1, // 11110001
+ -1, // 11110010
+ -1, // 11110011
+ -1, // 11110100
+ -1, // 11110101
+ -1, // 11110110
+ -1, // 11110111
+ -1, // 11111000
+ -1, // 11111001
+ -1, // 11111010
+ -1, // 11111011
+ -1, // 11111100
+ -1, // 11111101
+ -1, // 11111110
+ 0 // 11111111
+ };
+ static char Perms[256][8] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000000
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000001
+ { 1, 0, 2, 3, 4, 5, 6, 7 }, // 00000010
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000011
+ { 1, 2, 0, 3, 4, 5, 6, 7 }, // 00000100
+ { 0, 2, 1, 3, 4, 5, 6, 7 }, // 00000101
+ { 2, 0, 1, 3, 4, 5, 6, 7 }, // 00000110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000111
+ { 1, 2, 3, 0, 4, 5, 6, 7 }, // 00001000
+ { 0, 2, 3, 1, 4, 5, 6, 7 }, // 00001001
+ { 2, 0, 3, 1, 4, 5, 6, 7 }, // 00001010
+ { 0, 1, 3, 2, 4, 5, 6, 7 }, // 00001011
+ { 2, 3, 0, 1, 4, 5, 6, 7 }, // 00001100
+ { 0, 3, 1, 2, 4, 5, 6, 7 }, // 00001101
+ { 3, 0, 1, 2, 4, 5, 6, 7 }, // 00001110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00001111
+ { 1, 2, 3, 4, 0, 5, 6, 7 }, // 00010000
+ { 0, 2, 3, 4, 1, 5, 6, 7 }, // 00010001
+ { 2, 0, 3, 4, 1, 5, 6, 7 }, // 00010010
+ { 0, 1, 3, 4, 2, 5, 6, 7 }, // 00010011
+ { 2, 3, 0, 4, 1, 5, 6, 7 }, // 00010100
+ { 0, 3, 1, 4, 2, 5, 6, 7 }, // 00010101
+ { 3, 0, 1, 4, 2, 5, 6, 7 }, // 00010110
+ { 0, 1, 2, 4, 3, 5, 6, 7 }, // 00010111
+ { 2, 3, 4, 0, 1, 5, 6, 7 }, // 00011000
+ { 0, 3, 4, 1, 2, 5, 6, 7 }, // 00011001
+ { 3, 0, 4, 1, 2, 5, 6, 7 }, // 00011010
+ { 0, 1, 4, 2, 3, 5, 6, 7 }, // 00011011
+ { 3, 4, 0, 1, 2, 5, 6, 7 }, // 00011100
+ { 0, 4, 1, 2, 3, 5, 6, 7 }, // 00011101
+ { 4, 0, 1, 2, 3, 5, 6, 7 }, // 00011110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00011111
+ { 1, 2, 3, 4, 5, 0, 6, 7 }, // 00100000
+ { 0, 2, 3, 4, 5, 1, 6, 7 }, // 00100001
+ { 2, 0, 3, 4, 5, 1, 6, 7 }, // 00100010
+ { 0, 1, 3, 4, 5, 2, 6, 7 }, // 00100011
+ { 2, 3, 0, 4, 5, 1, 6, 7 }, // 00100100
+ { 0, 3, 1, 4, 5, 2, 6, 7 }, // 00100101
+ { 3, 0, 1, 4, 5, 2, 6, 7 }, // 00100110
+ { 0, 1, 2, 4, 5, 3, 6, 7 }, // 00100111
+ { 2, 3, 4, 0, 5, 1, 6, 7 }, // 00101000
+ { 0, 3, 4, 1, 5, 2, 6, 7 }, // 00101001
+ { 3, 0, 4, 1, 5, 2, 6, 7 }, // 00101010
+ { 0, 1, 4, 2, 5, 3, 6, 7 }, // 00101011
+ { 3, 4, 0, 1, 5, 2, 6, 7 }, // 00101100
+ { 0, 4, 1, 2, 5, 3, 6, 7 }, // 00101101
+ { 4, 0, 1, 2, 5, 3, 6, 7 }, // 00101110
+ { 0, 1, 2, 3, 5, 4, 6, 7 }, // 00101111
+ { 2, 3, 4, 5, 0, 1, 6, 7 }, // 00110000
+ { 0, 3, 4, 5, 1, 2, 6, 7 }, // 00110001
+ { 3, 0, 4, 5, 1, 2, 6, 7 }, // 00110010
+ { 0, 1, 4, 5, 2, 3, 6, 7 }, // 00110011
+ { 3, 4, 0, 5, 1, 2, 6, 7 }, // 00110100
+ { 0, 4, 1, 5, 2, 3, 6, 7 }, // 00110101
+ { 4, 0, 1, 5, 2, 3, 6, 7 }, // 00110110
+ { 0, 1, 2, 5, 3, 4, 6, 7 }, // 00110111
+ { 3, 4, 5, 0, 1, 2, 6, 7 }, // 00111000
+ { 0, 4, 5, 1, 2, 3, 6, 7 }, // 00111001
+ { 4, 0, 5, 1, 2, 3, 6, 7 }, // 00111010
+ { 0, 1, 5, 2, 3, 4, 6, 7 }, // 00111011
+ { 4, 5, 0, 1, 2, 3, 6, 7 }, // 00111100
+ { 0, 5, 1, 2, 3, 4, 6, 7 }, // 00111101
+ { 5, 0, 1, 2, 3, 4, 6, 7 }, // 00111110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00111111
+ { 1, 2, 3, 4, 5, 6, 0, 7 }, // 01000000
+ { 0, 2, 3, 4, 5, 6, 1, 7 }, // 01000001
+ { 2, 0, 3, 4, 5, 6, 1, 7 }, // 01000010
+ { 0, 1, 3, 4, 5, 6, 2, 7 }, // 01000011
+ { 2, 3, 0, 4, 5, 6, 1, 7 }, // 01000100
+ { 0, 3, 1, 4, 5, 6, 2, 7 }, // 01000101
+ { 3, 0, 1, 4, 5, 6, 2, 7 }, // 01000110
+ { 0, 1, 2, 4, 5, 6, 3, 7 }, // 01000111
+ { 2, 3, 4, 0, 5, 6, 1, 7 }, // 01001000
+ { 0, 3, 4, 1, 5, 6, 2, 7 }, // 01001001
+ { 3, 0, 4, 1, 5, 6, 2, 7 }, // 01001010
+ { 0, 1, 4, 2, 5, 6, 3, 7 }, // 01001011
+ { 3, 4, 0, 1, 5, 6, 2, 7 }, // 01001100
+ { 0, 4, 1, 2, 5, 6, 3, 7 }, // 01001101
+ { 4, 0, 1, 2, 5, 6, 3, 7 }, // 01001110
+ { 0, 1, 2, 3, 5, 6, 4, 7 }, // 01001111
+ { 2, 3, 4, 5, 0, 6, 1, 7 }, // 01010000
+ { 0, 3, 4, 5, 1, 6, 2, 7 }, // 01010001
+ { 3, 0, 4, 5, 1, 6, 2, 7 }, // 01010010
+ { 0, 1, 4, 5, 2, 6, 3, 7 }, // 01010011
+ { 3, 4, 0, 5, 1, 6, 2, 7 }, // 01010100
+ { 0, 4, 1, 5, 2, 6, 3, 7 }, // 01010101
+ { 4, 0, 1, 5, 2, 6, 3, 7 }, // 01010110
+ { 0, 1, 2, 5, 3, 6, 4, 7 }, // 01010111
+ { 3, 4, 5, 0, 1, 6, 2, 7 }, // 01011000
+ { 0, 4, 5, 1, 2, 6, 3, 7 }, // 01011001
+ { 4, 0, 5, 1, 2, 6, 3, 7 }, // 01011010
+ { 0, 1, 5, 2, 3, 6, 4, 7 }, // 01011011
+ { 4, 5, 0, 1, 2, 6, 3, 7 }, // 01011100
+ { 0, 5, 1, 2, 3, 6, 4, 7 }, // 01011101
+ { 5, 0, 1, 2, 3, 6, 4, 7 }, // 01011110
+ { 0, 1, 2, 3, 4, 6, 5, 7 }, // 01011111
+ { 2, 3, 4, 5, 6, 0, 1, 7 }, // 01100000
+ { 0, 3, 4, 5, 6, 1, 2, 7 }, // 01100001
+ { 3, 0, 4, 5, 6, 1, 2, 7 }, // 01100010
+ { 0, 1, 4, 5, 6, 2, 3, 7 }, // 01100011
+ { 3, 4, 0, 5, 6, 1, 2, 7 }, // 01100100
+ { 0, 4, 1, 5, 6, 2, 3, 7 }, // 01100101
+ { 4, 0, 1, 5, 6, 2, 3, 7 }, // 01100110
+ { 0, 1, 2, 5, 6, 3, 4, 7 }, // 01100111
+ { 3, 4, 5, 0, 6, 1, 2, 7 }, // 01101000
+ { 0, 4, 5, 1, 6, 2, 3, 7 }, // 01101001
+ { 4, 0, 5, 1, 6, 2, 3, 7 }, // 01101010
+ { 0, 1, 5, 2, 6, 3, 4, 7 }, // 01101011
+ { 4, 5, 0, 1, 6, 2, 3, 7 }, // 01101100
+ { 0, 5, 1, 2, 6, 3, 4, 7 }, // 01101101
+ { 5, 0, 1, 2, 6, 3, 4, 7 }, // 01101110
+ { 0, 1, 2, 3, 6, 4, 5, 7 }, // 01101111
+ { 3, 4, 5, 6, 0, 1, 2, 7 }, // 01110000
+ { 0, 4, 5, 6, 1, 2, 3, 7 }, // 01110001
+ { 4, 0, 5, 6, 1, 2, 3, 7 }, // 01110010
+ { 0, 1, 5, 6, 2, 3, 4, 7 }, // 01110011
+ { 4, 5, 0, 6, 1, 2, 3, 7 }, // 01110100
+ { 0, 5, 1, 6, 2, 3, 4, 7 }, // 01110101
+ { 5, 0, 1, 6, 2, 3, 4, 7 }, // 01110110
+ { 0, 1, 2, 6, 3, 4, 5, 7 }, // 01110111
+ { 4, 5, 6, 0, 1, 2, 3, 7 }, // 01111000
+ { 0, 5, 6, 1, 2, 3, 4, 7 }, // 01111001
+ { 5, 0, 6, 1, 2, 3, 4, 7 }, // 01111010
+ { 0, 1, 6, 2, 3, 4, 5, 7 }, // 01111011
+ { 5, 6, 0, 1, 2, 3, 4, 7 }, // 01111100
+ { 0, 6, 1, 2, 3, 4, 5, 7 }, // 01111101
+ { 6, 0, 1, 2, 3, 4, 5, 7 }, // 01111110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 01111111
+ { 1, 2, 3, 4, 5, 6, 7, 0 }, // 10000000
+ { 0, 2, 3, 4, 5, 6, 7, 1 }, // 10000001
+ { 2, 0, 3, 4, 5, 6, 7, 1 }, // 10000010
+ { 0, 1, 3, 4, 5, 6, 7, 2 }, // 10000011
+ { 2, 3, 0, 4, 5, 6, 7, 1 }, // 10000100
+ { 0, 3, 1, 4, 5, 6, 7, 2 }, // 10000101
+ { 3, 0, 1, 4, 5, 6, 7, 2 }, // 10000110
+ { 0, 1, 2, 4, 5, 6, 7, 3 }, // 10000111
+ { 2, 3, 4, 0, 5, 6, 7, 1 }, // 10001000
+ { 0, 3, 4, 1, 5, 6, 7, 2 }, // 10001001
+ { 3, 0, 4, 1, 5, 6, 7, 2 }, // 10001010
+ { 0, 1, 4, 2, 5, 6, 7, 3 }, // 10001011
+ { 3, 4, 0, 1, 5, 6, 7, 2 }, // 10001100
+ { 0, 4, 1, 2, 5, 6, 7, 3 }, // 10001101
+ { 4, 0, 1, 2, 5, 6, 7, 3 }, // 10001110
+ { 0, 1, 2, 3, 5, 6, 7, 4 }, // 10001111
+ { 2, 3, 4, 5, 0, 6, 7, 1 }, // 10010000
+ { 0, 3, 4, 5, 1, 6, 7, 2 }, // 10010001
+ { 3, 0, 4, 5, 1, 6, 7, 2 }, // 10010010
+ { 0, 1, 4, 5, 2, 6, 7, 3 }, // 10010011
+ { 3, 4, 0, 5, 1, 6, 7, 2 }, // 10010100
+ { 0, 4, 1, 5, 2, 6, 7, 3 }, // 10010101
+ { 4, 0, 1, 5, 2, 6, 7, 3 }, // 10010110
+ { 0, 1, 2, 5, 3, 6, 7, 4 }, // 10010111
+ { 3, 4, 5, 0, 1, 6, 7, 2 }, // 10011000
+ { 0, 4, 5, 1, 2, 6, 7, 3 }, // 10011001
+ { 4, 0, 5, 1, 2, 6, 7, 3 }, // 10011010
+ { 0, 1, 5, 2, 3, 6, 7, 4 }, // 10011011
+ { 4, 5, 0, 1, 2, 6, 7, 3 }, // 10011100
+ { 0, 5, 1, 2, 3, 6, 7, 4 }, // 10011101
+ { 5, 0, 1, 2, 3, 6, 7, 4 }, // 10011110
+ { 0, 1, 2, 3, 4, 6, 7, 5 }, // 10011111
+ { 2, 3, 4, 5, 6, 0, 7, 1 }, // 10100000
+ { 0, 3, 4, 5, 6, 1, 7, 2 }, // 10100001
+ { 3, 0, 4, 5, 6, 1, 7, 2 }, // 10100010
+ { 0, 1, 4, 5, 6, 2, 7, 3 }, // 10100011
+ { 3, 4, 0, 5, 6, 1, 7, 2 }, // 10100100
+ { 0, 4, 1, 5, 6, 2, 7, 3 }, // 10100101
+ { 4, 0, 1, 5, 6, 2, 7, 3 }, // 10100110
+ { 0, 1, 2, 5, 6, 3, 7, 4 }, // 10100111
+ { 3, 4, 5, 0, 6, 1, 7, 2 }, // 10101000
+ { 0, 4, 5, 1, 6, 2, 7, 3 }, // 10101001
+ { 4, 0, 5, 1, 6, 2, 7, 3 }, // 10101010
+ { 0, 1, 5, 2, 6, 3, 7, 4 }, // 10101011
+ { 4, 5, 0, 1, 6, 2, 7, 3 }, // 10101100
+ { 0, 5, 1, 2, 6, 3, 7, 4 }, // 10101101
+ { 5, 0, 1, 2, 6, 3, 7, 4 }, // 10101110
+ { 0, 1, 2, 3, 6, 4, 7, 5 }, // 10101111
+ { 3, 4, 5, 6, 0, 1, 7, 2 }, // 10110000
+ { 0, 4, 5, 6, 1, 2, 7, 3 }, // 10110001
+ { 4, 0, 5, 6, 1, 2, 7, 3 }, // 10110010
+ { 0, 1, 5, 6, 2, 3, 7, 4 }, // 10110011
+ { 4, 5, 0, 6, 1, 2, 7, 3 }, // 10110100
+ { 0, 5, 1, 6, 2, 3, 7, 4 }, // 10110101
+ { 5, 0, 1, 6, 2, 3, 7, 4 }, // 10110110
+ { 0, 1, 2, 6, 3, 4, 7, 5 }, // 10110111
+ { 4, 5, 6, 0, 1, 2, 7, 3 }, // 10111000
+ { 0, 5, 6, 1, 2, 3, 7, 4 }, // 10111001
+ { 5, 0, 6, 1, 2, 3, 7, 4 }, // 10111010
+ { 0, 1, 6, 2, 3, 4, 7, 5 }, // 10111011
+ { 5, 6, 0, 1, 2, 3, 7, 4 }, // 10111100
+ { 0, 6, 1, 2, 3, 4, 7, 5 }, // 10111101
+ { 6, 0, 1, 2, 3, 4, 7, 5 }, // 10111110
+ { 0, 1, 2, 3, 4, 5, 7, 6 }, // 10111111
+ { 2, 3, 4, 5, 6, 7, 0, 1 }, // 11000000
+ { 0, 3, 4, 5, 6, 7, 1, 2 }, // 11000001
+ { 3, 0, 4, 5, 6, 7, 1, 2 }, // 11000010
+ { 0, 1, 4, 5, 6, 7, 2, 3 }, // 11000011
+ { 3, 4, 0, 5, 6, 7, 1, 2 }, // 11000100
+ { 0, 4, 1, 5, 6, 7, 2, 3 }, // 11000101
+ { 4, 0, 1, 5, 6, 7, 2, 3 }, // 11000110
+ { 0, 1, 2, 5, 6, 7, 3, 4 }, // 11000111
+ { 3, 4, 5, 0, 6, 7, 1, 2 }, // 11001000
+ { 0, 4, 5, 1, 6, 7, 2, 3 }, // 11001001
+ { 4, 0, 5, 1, 6, 7, 2, 3 }, // 11001010
+ { 0, 1, 5, 2, 6, 7, 3, 4 }, // 11001011
+ { 4, 5, 0, 1, 6, 7, 2, 3 }, // 11001100
+ { 0, 5, 1, 2, 6, 7, 3, 4 }, // 11001101
+ { 5, 0, 1, 2, 6, 7, 3, 4 }, // 11001110
+ { 0, 1, 2, 3, 6, 7, 4, 5 }, // 11001111
+ { 3, 4, 5, 6, 0, 7, 1, 2 }, // 11010000
+ { 0, 4, 5, 6, 1, 7, 2, 3 }, // 11010001
+ { 4, 0, 5, 6, 1, 7, 2, 3 }, // 11010010
+ { 0, 1, 5, 6, 2, 7, 3, 4 }, // 11010011
+ { 4, 5, 0, 6, 1, 7, 2, 3 }, // 11010100
+ { 0, 5, 1, 6, 2, 7, 3, 4 }, // 11010101
+ { 5, 0, 1, 6, 2, 7, 3, 4 }, // 11010110
+ { 0, 1, 2, 6, 3, 7, 4, 5 }, // 11010111
+ { 4, 5, 6, 0, 1, 7, 2, 3 }, // 11011000
+ { 0, 5, 6, 1, 2, 7, 3, 4 }, // 11011001
+ { 5, 0, 6, 1, 2, 7, 3, 4 }, // 11011010
+ { 0, 1, 6, 2, 3, 7, 4, 5 }, // 11011011
+ { 5, 6, 0, 1, 2, 7, 3, 4 }, // 11011100
+ { 0, 6, 1, 2, 3, 7, 4, 5 }, // 11011101
+ { 6, 0, 1, 2, 3, 7, 4, 5 }, // 11011110
+ { 0, 1, 2, 3, 4, 7, 5, 6 }, // 11011111
+ { 3, 4, 5, 6, 7, 0, 1, 2 }, // 11100000
+ { 0, 4, 5, 6, 7, 1, 2, 3 }, // 11100001
+ { 4, 0, 5, 6, 7, 1, 2, 3 }, // 11100010
+ { 0, 1, 5, 6, 7, 2, 3, 4 }, // 11100011
+ { 4, 5, 0, 6, 7, 1, 2, 3 }, // 11100100
+ { 0, 5, 1, 6, 7, 2, 3, 4 }, // 11100101
+ { 5, 0, 1, 6, 7, 2, 3, 4 }, // 11100110
+ { 0, 1, 2, 6, 7, 3, 4, 5 }, // 11100111
+ { 4, 5, 6, 0, 7, 1, 2, 3 }, // 11101000
+ { 0, 5, 6, 1, 7, 2, 3, 4 }, // 11101001
+ { 5, 0, 6, 1, 7, 2, 3, 4 }, // 11101010
+ { 0, 1, 6, 2, 7, 3, 4, 5 }, // 11101011
+ { 5, 6, 0, 1, 7, 2, 3, 4 }, // 11101100
+ { 0, 6, 1, 2, 7, 3, 4, 5 }, // 11101101
+ { 6, 0, 1, 2, 7, 3, 4, 5 }, // 11101110
+ { 0, 1, 2, 3, 7, 4, 5, 6 }, // 11101111
+ { 4, 5, 6, 7, 0, 1, 2, 3 }, // 11110000
+ { 0, 5, 6, 7, 1, 2, 3, 4 }, // 11110001
+ { 5, 0, 6, 7, 1, 2, 3, 4 }, // 11110010
+ { 0, 1, 6, 7, 2, 3, 4, 5 }, // 11110011
+ { 5, 6, 0, 7, 1, 2, 3, 4 }, // 11110100
+ { 0, 6, 1, 7, 2, 3, 4, 5 }, // 11110101
+ { 6, 0, 1, 7, 2, 3, 4, 5 }, // 11110110
+ { 0, 1, 2, 7, 3, 4, 5, 6 }, // 11110111
+ { 5, 6, 7, 0, 1, 2, 3, 4 }, // 11111000
+ { 0, 6, 7, 1, 2, 3, 4, 5 }, // 11111001
+ { 6, 0, 7, 1, 2, 3, 4, 5 }, // 11111010
+ { 0, 1, 7, 2, 3, 4, 5, 6 }, // 11111011
+ { 6, 7, 0, 1, 2, 3, 4, 5 }, // 11111100
+ { 0, 7, 1, 2, 3, 4, 5, 6 }, // 11111101
+ { 7, 0, 1, 2, 3, 4, 5, 6 }, // 11111110
+ { 0, 1, 2, 3, 4, 5, 6, 7 } // 11111111
+ };
+
+ assert( uPhase > 0 && uPhase < (unsigned)(1 << nVars) );
+
+ // the same function
+ if ( Cases[uPhase] == 0 )
+ {
+ int i;
+ for ( i = 0; i < nWords; i++ )
+ puTruthR[i] = puTruth[i];
+ return;
+ }
+
+ // an elementary variable
+ if ( Cases[uPhase] > 0 )
+ {
+ int i;
+ for ( i = 0; i < nWords; i++ )
+ puTruthR[i] = uTruths[Cases[uPhase]][i];
+ return;
+ }
+
+ // truth table takes one word
+ if ( nWords == 1 )
+ {
+ int i, k, nMints, iRes;
+ char * pPerm = Perms[uPhase];
+ puTruthR[0] = 0;
+ nMints = (1 << nVars);
+ for ( i = 0; i < nMints; i++ )
+ if ( puTruth[0] & (1 << i) )
+ {
+ for ( iRes = 0, k = 0; k < nVars; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ puTruthR[0] |= (1 << iRes);
+ }
+ return;
+ }
+ else if ( nWords == 2 )
+ {
+ int i, k, iRes;
+ char * pPerm = Perms[uPhase];
+ puTruthR[0] = puTruthR[1] = 0;
+ for ( i = 0; i < 32; i++ )
+ {
+ if ( puTruth[0] & (1 << i) )
+ {
+ for ( iRes = 0, k = 0; k < 6; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ if ( iRes < 32 )
+ puTruthR[0] |= (1 << iRes);
+ else
+ puTruthR[1] |= (1 << (iRes-32));
+ }
+ }
+ for ( ; i < 64; i++ )
+ {
+ if ( puTruth[1] & (1 << (i-32)) )
+ {
+ for ( iRes = 0, k = 0; k < 6; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ if ( iRes < 32 )
+ puTruthR[0] |= (1 << iRes);
+ else
+ puTruthR[1] |= (1 << (iRes-32));
+ }
+ }
+ }
+ // truth table takes more than one word
+ else
+ {
+ int i, k, nMints, iRes;
+ char * pPerm = Perms[uPhase];
+ for ( i = 0; i < nWords; i++ )
+ puTruthR[i] = 0;
+ nMints = (1 << nVars);
+ for ( i = 0; i < nMints; i++ )
+ if ( puTruth[i>>5] & (1 << (i&31)) )
+ {
+ for ( iRes = 0, k = 0; k < 5; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ puTruthR[iRes>>5] |= (1 << (iRes&31));
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocated lookup table for truth table permutation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned short ** Extra_TruthPerm43()
+{
+ unsigned short ** pTable;
+ unsigned uTruth;
+ int i, k;
+ pTable = (unsigned short **)Extra_ArrayAlloc( 256, 16, 2 );
+ for ( i = 0; i < 256; i++ )
+ {
+ uTruth = (i << 8) | i;
+ for ( k = 0; k < 16; k++ )
+ pTable[i][k] = Extra_TruthPerm4One( uTruth, k );
+ }
+ return pTable;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocated lookup table for truth table permutation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned ** Extra_TruthPerm53()
+{
+ unsigned ** pTable;
+ unsigned uTruth;
+ int i, k;
+ pTable = (unsigned **)Extra_ArrayAlloc( 256, 32, 4 );
+ for ( i = 0; i < 256; i++ )
+ {
+ uTruth = (i << 24) | (i << 16) | (i << 8) | i;
+ for ( k = 0; k < 32; k++ )
+ pTable[i][k] = Extra_TruthPerm5One( uTruth, k );
+ }
+ return pTable;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocated lookup table for truth table permutation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned ** Extra_TruthPerm54()
+{
+ unsigned ** pTable;
+ unsigned uTruth;
+ int i;
+ pTable = (unsigned **)Extra_ArrayAlloc( 256*256, 4, 4 );
+ for ( i = 0; i < 256*256; i++ )
+ {
+ uTruth = (i << 16) | i;
+ pTable[i][0] = Extra_TruthPerm5One( uTruth, 31-8 );
+ pTable[i][1] = Extra_TruthPerm5One( uTruth, 31-4 );
+ pTable[i][2] = Extra_TruthPerm5One( uTruth, 31-2 );
+ pTable[i][3] = Extra_TruthPerm5One( uTruth, 31-1 );
+ }
+ return pTable;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocated lookup table for truth table permutation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned ** Extra_TruthPerm63()
+{
+ unsigned ** pTable;
+ unsigned uTruth[2];
+ int i, k;
+ pTable = (unsigned **)Extra_ArrayAlloc( 256, 64, 8 );
+ for ( i = 0; i < 256; i++ )
+ {
+ uTruth[0] = (i << 24) | (i << 16) | (i << 8) | i;
+ uTruth[1] = uTruth[0];
+ for ( k = 0; k < 64; k++ )
+ Extra_TruthPerm6One( uTruth, k, &pTable[i][k] );
+ }
+ return pTable;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the elementary truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned ** Extra_Truths8()
+{
+ static unsigned uTruths[8][8] = {
+ { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+ { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+ { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+ { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+ { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
+ { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
+ };
+ static unsigned * puResult[8] = {
+ uTruths[0], uTruths[1], uTruths[2], uTruths[3], uTruths[4], uTruths[5], uTruths[6], uTruths[7]
+ };
+ return (unsigned **)puResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Bubble-sorts components by scores in increasing order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing )
+{
+ int i, Temp, fChanges;
+ assert( nSize < 1000 );
+ for ( i = 0; i < nSize; i++ )
+ Order[i] = i;
+ if ( fIncreasing )
+ {
+ do {
+ fChanges = 0;
+ for ( i = 0; i < nSize - 1; i++ )
+ {
+ if ( Costs[Order[i]] <= Costs[Order[i+1]] )
+ continue;
+ Temp = Order[i];
+ Order[i] = Order[i+1];
+ Order[i+1] = Temp;
+ fChanges = 1;
+ }
+ } while ( fChanges );
+ }
+ else
+ {
+ do {
+ fChanges = 0;
+ for ( i = 0; i < nSize - 1; i++ )
+ {
+ if ( Costs[Order[i]] >= Costs[Order[i+1]] )
+ continue;
+ Temp = Order[i];
+ Order[i] = Order[i+1];
+ Order[i+1] = Temp;
+ fChanges = 1;
+ }
+ } while ( fChanges );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the smallest prime larger than the number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned int Cudd_PrimeCopy( 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 */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the permutation table for 8 variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthExpandGeneratePermTable()
+{
+ int i, k, nOnes, Last1, First0;
+ int iOne, iZero;
+
+ printf( "\nstatic char Cases[256] = {\n" );
+ for ( i = 0; i < 256; i++ )
+ {
+ nOnes = 0;
+ Last1 = First0 = -1;
+ for ( k = 0; k < 8; k++ )
+ {
+ if ( i & (1 << k) )
+ {
+ nOnes++;
+ Last1 = k;
+ }
+ else if ( First0 == -1 )
+ First0 = k;
+ }
+ if ( Last1 + 1 == First0 || i == 255 )
+ printf( " %d%s", 0, (i==255? " ":",") );
+ else if ( nOnes == 1 )
+ printf( " %d,", Last1 );
+ else
+ printf( " -%d,", 1 );
+ printf( " // " );
+ Extra_PrintBinary( stdout, (unsigned*)&i, 8 );
+ printf( "\n" );
+ }
+ printf( "};\n" );
+
+ printf( "\nstatic char Perms[256][8] = {\n" );
+ for ( i = 0; i < 256; i++ )
+ {
+ printf( " {" );
+ nOnes = 0;
+ for ( k = 0; k < 8; k++ )
+ if ( i & (1 << k) )
+ nOnes++;
+ iOne = 0;
+ iZero = nOnes;
+ for ( k = 0; k < 8; k++ )
+ if ( i & (1 << k) )
+ printf( "%s %d", (k==0? "":","), iOne++ );
+ else
+ printf( "%s %d", (k==0? "":","), iZero++ );
+ assert( iOne + iZero == 8 );
+ printf( " }%s // ", (i==255? " ":",") );
+ Extra_PrintBinary( stdout, (unsigned*)&i, 8 );
+ printf( "\n" );
+ }
+ printf( "};\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilProgress.c b/src/misc/extra/extraUtilProgress.c
new file mode 100644
index 00000000..6b6d5132
--- /dev/null
+++ b/src/misc/extra/extraUtilProgress.c
@@ -0,0 +1,176 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilProgress.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Progress bar.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilProgress.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct ProgressBarStruct
+{
+ int nItemsNext; // the number of items for the next update of the progress bar
+ int nItemsTotal; // the total number of items
+ int posTotal; // the total number of positions
+ int posCur; // the current position
+ FILE * pFile; // the output stream
+};
+
+static void Extra_ProgressBarShow( ProgressBar * p, char * pString );
+static void Extra_ProgressBarClean( ProgressBar * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the progress bar.]
+
+ Description [The first parameter is the output stream (pFile), where
+ the progress is printed. The current printing position should be the
+ first one on the given line. The second parameters is the total
+ number of items that correspond to 100% position of the progress bar.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal )
+{
+ ProgressBar * p;
+ extern int Abc_FrameShowProgress( void * p );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL;
+ p = ALLOC( ProgressBar, 1 );
+ memset( p, 0, sizeof(ProgressBar) );
+ p->pFile = pFile;
+ p->nItemsTotal = nItemsTotal;
+ p->posTotal = 78;
+ p->posCur = 1;
+ p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+ Extra_ProgressBarShow( p, NULL );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the progress bar.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString )
+{
+ if ( p == NULL ) return;
+ if ( nItemsCur < p->nItemsNext )
+ return;
+ if ( nItemsCur >= p->nItemsTotal )
+ {
+ p->posCur = 78;
+ p->nItemsNext = 0x7FFFFFFF;
+ }
+ else
+ {
+ p->posCur += 7;
+ p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+ }
+ Extra_ProgressBarShow( p, pString );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Stops the progress bar.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_ProgressBarStop( ProgressBar * p )
+{
+ if ( p == NULL ) return;
+ Extra_ProgressBarClean( p );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the progress bar of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_ProgressBarShow( ProgressBar * p, char * pString )
+{
+ int i;
+ if ( p == NULL ) return;
+ if ( pString )
+ fprintf( p->pFile, "%s ", pString );
+ for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ )
+ fprintf( p->pFile, "-" );
+ if ( i == p->posCur )
+ fprintf( p->pFile, ">" );
+ for ( i++ ; i <= p->posTotal; i++ )
+ fprintf( p->pFile, " " );
+ fprintf( p->pFile, "\r" );
+ fflush( stdout );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the progress bar before quitting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_ProgressBarClean( ProgressBar * p )
+{
+ int i;
+ if ( p == NULL ) return;
+ for ( i = 0; i <= p->posTotal; i++ )
+ fprintf( p->pFile, " " );
+ fprintf( p->pFile, "\r" );
+ fflush( stdout );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilReader.c b/src/misc/extra/extraUtilReader.c
new file mode 100644
index 00000000..c165b989
--- /dev/null
+++ b/src/misc/extra/extraUtilReader.c
@@ -0,0 +1,383 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilReader.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [File reading utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilReader.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "extra.h"
+#include "vec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory
+#define EXTRA_OFFSET_SIZE 4096 // 4K - load new data when less than this is left
+
+#define EXTRA_MINIMUM(a,b) (((a) < (b))? (a) : (b))
+
+struct Extra_FileReader_t_
+{
+ // the input file
+ char * pFileName; // the input file name
+ FILE * pFile; // the input file pointer
+ int nFileSize; // the total number of bytes in the file
+ int nFileRead; // the number of bytes currently read from file
+ // info about processing different types of input chars
+ char pCharMap[256]; // the character map
+ // temporary storage for data
+ char * pBuffer; // the buffer
+ int nBufferSize; // the size of the buffer
+ char * pBufferCur; // the current reading position
+ char * pBufferEnd; // the first position not used by currently loaded data
+ char * pBufferStop; // the position where loading new data will be done
+ // tokens given to the user
+ Vec_Ptr_t * vTokens; // the vector of tokens returned to the user
+ Vec_Int_t * vLines; // the vector of line numbers for each token
+ int nLineCounter; // the counter of lines processed
+ // status of the parser
+ int fStop; // this flag goes high when the end of file is reached
+};
+
+// character types
+typedef enum {
+ EXTRA_CHAR_COMMENT, // a character that begins the comment
+ EXTRA_CHAR_NORMAL, // a regular character
+ EXTRA_CHAR_STOP, // a character that delimits a series of tokens
+ EXTRA_CHAR_CLEAN // a character that should be cleaned
+} Extra_CharType_t;
+
+// the static functions
+static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p );
+static void Extra_FileReaderReload( Extra_FileReader_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the file reader.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName,
+ char * pCharsComment, char * pCharsStop, char * pCharsClean )
+{
+ Extra_FileReader_t * p;
+ FILE * pFile;
+ char * pChar;
+ int nCharsToRead;
+ // check if the file can be opened
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName );
+ return NULL;
+ }
+ // start the file reader
+ p = ALLOC( Extra_FileReader_t, 1 );
+ memset( p, 0, sizeof(Extra_FileReader_t) );
+ p->pFileName = pFileName;
+ p->pFile = pFile;
+ // set the character map
+ memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 );
+ for ( pChar = pCharsComment; *pChar; pChar++ )
+ p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT;
+ for ( pChar = pCharsStop; *pChar; pChar++ )
+ p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP;
+ for ( pChar = pCharsClean; *pChar; pChar++ )
+ p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN;
+ // get the file size, in bytes
+ fseek( pFile, 0, SEEK_END );
+ p->nFileSize = ftell( pFile );
+ rewind( pFile );
+ // allocate the buffer
+ p->pBuffer = ALLOC( char, EXTRA_BUFFER_SIZE+1 );
+ p->nBufferSize = EXTRA_BUFFER_SIZE;
+ p->pBufferCur = p->pBuffer;
+ // determine how many chars to read
+ nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE);
+ // load the first part into the buffer
+ fread( p->pBuffer, nCharsToRead, 1, p->pFile );
+ p->nFileRead = nCharsToRead;
+ // set the ponters to the end and the stopping point
+ p->pBufferEnd = p->pBuffer + nCharsToRead;
+ p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
+ // start the arrays
+ p->vTokens = Vec_PtrAlloc( 100 );
+ p->vLines = Vec_IntAlloc( 100 );
+ p->nLineCounter = 1; // 1-based line counting
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the file reader.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_FileReaderFree( Extra_FileReader_t * p )
+{
+ if ( p->pFile )
+ fclose( p->pFile );
+ FREE( p->pBuffer );
+ Vec_PtrFree( p->vTokens );
+ Vec_IntFree( p->vLines );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the file size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_FileReaderGetFileName( Extra_FileReader_t * p )
+{
+ return p->pFileName;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the file size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_FileReaderGetFileSize( Extra_FileReader_t * p )
+{
+ return p->nFileSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the current reading position.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p )
+{
+ return p->nFileRead - (p->pBufferEnd - p->pBufferCur);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the line number for the given token.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken )
+{
+ assert( iToken >= 0 && iToken < p->vTokens->nSize );
+ return p->vLines->pArray[iToken];
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the next set of tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Extra_FileReaderGetTokens( Extra_FileReader_t * p )
+{
+ Vec_Ptr_t * vTokens;
+ while ( vTokens = Extra_FileReaderGetTokens_int( p ) )
+ if ( vTokens->nSize > 0 )
+ break;
+ return vTokens;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the next set of tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p )
+{
+ char * pChar;
+ int fTokenStarted, MapValue;
+ if ( p->fStop )
+ return NULL;
+ // reset the token info
+ p->vTokens->nSize = 0;
+ p->vLines->nSize = 0;
+ fTokenStarted = 0;
+ // check if the new data should to be loaded
+ if ( p->pBufferCur > p->pBufferStop )
+ Extra_FileReaderReload( p );
+
+// printf( "%d\n", p->pBufferEnd - p->pBufferCur );
+
+ // process the string starting from the current position
+ for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+ {
+ // count the lines
+ if ( *pChar == '\n' )
+ p->nLineCounter++;
+ // switch depending on the character
+ MapValue = p->pCharMap[*pChar];
+
+// printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue );
+
+
+ switch ( MapValue )
+ {
+ case EXTRA_CHAR_COMMENT:
+ if ( *pChar != '/' || *(pChar+1) == '/' )
+ { // dealing with the need to have // as a comment
+ // if the token was being written, stop it
+ if ( fTokenStarted )
+ fTokenStarted = 0;
+ // eraze the comment till the end of line
+ while ( *pChar != '\n' )
+ {
+ *pChar++ = 0;
+ if ( pChar == p->pBufferEnd )
+ { // this failure is due to the fact the comment continued
+ // through EXTRA_OFFSET_SIZE chars till the end of the buffer
+ printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
+ return NULL;
+ }
+ }
+ pChar--;
+ break;
+ }
+ // otherwise it is a normal character
+ case EXTRA_CHAR_NORMAL:
+ if ( !fTokenStarted )
+ {
+ Vec_PtrPush( p->vTokens, pChar );
+ Vec_IntPush( p->vLines, p->nLineCounter );
+ fTokenStarted = 1;
+ }
+ break;
+ case EXTRA_CHAR_STOP:
+ if ( fTokenStarted )
+ fTokenStarted = 0;
+ *pChar = 0;
+ // prepare before leaving
+ p->pBufferCur = pChar + 1;
+ return p->vTokens;
+ case EXTRA_CHAR_CLEAN:
+ if ( fTokenStarted )
+ fTokenStarted = 0;
+ *pChar = 0;
+ break;
+ default:
+ assert( 0 );
+ }
+ }
+ // the file is finished or the last part continued
+ // through EXTRA_OFFSET_SIZE chars till the end of the buffer
+ if ( p->pBufferStop == p->pBufferEnd ) // end of file
+ {
+ *pChar = 0;
+ p->fStop = 1;
+ return p->vTokens;
+ }
+ printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
+/*
+ {
+ int i;
+ for ( i = 0; i < p->vTokens->nSize; i++ )
+ printf( "%s ", p->vTokens->pArray[i] );
+ printf( "\n" );
+ }
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads new data into the file reader.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_FileReaderReload( Extra_FileReader_t * p )
+{
+ int nCharsUsed, nCharsToRead;
+ assert( !p->fStop );
+ assert( p->pBufferCur > p->pBufferStop );
+ assert( p->pBufferCur < p->pBufferEnd );
+ // figure out how many chars are still not processed
+ nCharsUsed = p->pBufferEnd - p->pBufferCur;
+ // move the remaining data to the beginning of the buffer
+ memmove( p->pBuffer, p->pBufferCur, nCharsUsed );
+ p->pBufferCur = p->pBuffer;
+ // determine how many chars we will read
+ nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead );
+ // read the chars
+ fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile );
+ p->nFileRead += nCharsToRead;
+ // set the ponters to the end and the stopping point
+ p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead;
+ p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilTruth.c b/src/misc/extra/extraUtilTruth.c
new file mode 100644
index 00000000..3b0b16eb
--- /dev/null
+++ b/src/misc/extra/extraUtilTruth.c
@@ -0,0 +1,1148 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilMisc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Various procedures for truth table manipulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+static unsigned s_VarMasks[5][2] = {
+ { 0x33333333, 0xAAAAAAAA },
+ { 0x55555555, 0xCCCCCCCC },
+ { 0x0F0F0F0F, 0xF0F0F0F0 },
+ { 0x00FF00FF, 0xFF00FF00 },
+ { 0x0000FFFF, 0xFFFF0000 }
+};
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Derive elementary truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned ** Extra_TruthElementary( int nVars )
+{
+ unsigned ** pRes;
+ int i, k, nWords;
+ nWords = Extra_TruthWordNum(nVars);
+ pRes = (unsigned **)Extra_ArrayAlloc( nVars, nWords, 4 );
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( i < 5 )
+ {
+ for ( k = 0; k < nWords; k++ )
+ pRes[i][k] = s_VarMasks[i][1];
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( k & (1 << (i-5)) )
+ pRes[i][k] = ~(unsigned)0;
+ else
+ pRes[i][k] = 0;
+ }
+ }
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Swaps two adjacent variables in the truth table.]
+
+ Description [Swaps var number Start and var number Start+1 (0-based numbers).
+ The input truth table is pIn. The output truth table is pOut.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar )
+{
+ static unsigned PMasks[4][3] = {
+ { 0x99999999, 0x22222222, 0x44444444 },
+ { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 },
+ { 0xF00FF00F, 0x00F000F0, 0x0F000F00 },
+ { 0xFF0000FF, 0x0000FF00, 0x00FF0000 }
+ };
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step, Shift;
+
+ assert( iVar < nVars - 1 );
+ if ( iVar < 4 )
+ {
+ Shift = (1 << iVar);
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+ }
+ else if ( iVar > 4 )
+ {
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 4*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pOut[i] = pIn[i];
+ for ( i = 0; i < Step; i++ )
+ pOut[Step+i] = pIn[2*Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[2*Step+i] = pIn[Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[3*Step+i] = pIn[3*Step+i];
+ pIn += 4*Step;
+ pOut += 4*Step;
+ }
+ }
+ else // if ( iVar == 4 )
+ {
+ for ( i = 0; i < nWords; i += 2 )
+ {
+ pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+ pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16);
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Swaps two adjacent variables in the truth table.]
+
+ Description [Swaps var number Start and var number Start+1 (0-based numbers).
+ The input truth table is pIn. The output truth table is pOut.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start )
+{
+ int nWords = (nVars <= 5)? 1 : (1 << (nVars-5));
+ int i, k, Step;
+
+ assert( Start < nVars - 1 );
+ switch ( Start )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i += 2 )
+ {
+ pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+ pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16);
+ }
+ return;
+ default:
+ Step = (1 << (Start - 5));
+ for ( k = 0; k < nWords; k += 4*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pOut[i] = pIn[i];
+ for ( i = 0; i < Step; i++ )
+ pOut[Step+i] = pIn[2*Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[2*Step+i] = pIn[Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[3*Step+i] = pIn[3*Step+i];
+ pIn += 4*Step;
+ pOut += 4*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expands the truth table according to the phase.]
+
+ Description [The input and output truth tables are in pIn/pOut. The current number
+ of variables is nVars. The total number of variables in nVarsAll. The last argument
+ (Phase) contains shows where the variables should go.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase )
+{
+ unsigned * pTemp;
+ int i, k, Var = nVars - 1, Counter = 0;
+ for ( i = nVarsAll - 1; i >= 0; i-- )
+ if ( Phase & (1 << i) )
+ {
+ for ( k = Var; k < i; k++ )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ Counter++;
+ }
+ Var--;
+ }
+ assert( Var == -1 );
+ // swap if it was moved an even number of times
+ if ( !(Counter & 1) )
+ Extra_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Shrinks the truth table according to the phase.]
+
+ Description [The input and output truth tables are in pIn/pOut. The current number
+ of variables is nVars. The total number of variables in nVarsAll. The last argument
+ (Phase) contains shows what variables should remain.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase )
+{
+ unsigned * pTemp;
+ int i, k, Var = 0, Counter = 0;
+ for ( i = 0; i < nVarsAll; i++ )
+ if ( Phase & (1 << i) )
+ {
+ for ( k = i-1; k >= Var; k-- )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ Counter++;
+ }
+ Var++;
+ }
+ assert( Var == nVars );
+ // swap if it was moved an even number of times
+ if ( !(Counter & 1) )
+ Extra_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if TT depends on the given variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) )
+ return 1;
+ return 0;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) )
+ return 1;
+ return 0;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) )
+ return 1;
+ return 0;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) )
+ return 1;
+ return 0;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) )
+ return 1;
+ return 0;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ if ( pTruth[i] != pTruth[Step+i] )
+ return 1;
+ pTruth += 2*Step;
+ }
+ return 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of support vars.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthSupportSize( unsigned * pTruth, int nVars )
+{
+ int i, Counter = 0;
+ for ( i = 0; i < nVars; i++ )
+ Counter += Extra_TruthVarInSupport( pTruth, nVars, i );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns support of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthSupport( unsigned * pTruth, int nVars )
+{
+ int i, Support = 0;
+ for ( i = 0; i < nVars; i++ )
+ if ( Extra_TruthVarInSupport( pTruth, nVars, i ) )
+ Support |= (1 << i);
+ return Support;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes positive cofactor of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pTruth[i] = pTruth[Step+i];
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes negative cofactor of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pTruth[Step+i] = pTruth[i];
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Existentially quantifies the variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ pTruth[i] |= pTruth[Step+i];
+ pTruth[Step+i] = pTruth[i];
+ }
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Existentially quantifies the variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ pTruth[i] &= pTruth[Step+i];
+ pTruth[Step+i] = pTruth[i];
+ }
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes negative cofactor of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ pOut[i] = pCof0[i];
+ pOut[Step+i] = pCof1[Step+i];
+ }
+ pOut += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks symmetry of two variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 )
+{
+ static unsigned uTemp0[16], uTemp1[16];
+ assert( nVars <= 9 );
+ // compute Cof01
+ Extra_TruthCopy( uTemp0, pTruth, nVars );
+ Extra_TruthCofactor0( uTemp0, nVars, iVar0 );
+ Extra_TruthCofactor1( uTemp0, nVars, iVar1 );
+ // compute Cof10
+ Extra_TruthCopy( uTemp1, pTruth, nVars );
+ Extra_TruthCofactor1( uTemp1, nVars, iVar0 );
+ Extra_TruthCofactor0( uTemp1, nVars, iVar1 );
+ // compare
+ return Extra_TruthIsEqual( uTemp0, uTemp1, nVars );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks antisymmetry of two variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 )
+{
+ static unsigned uTemp0[16], uTemp1[16];
+ assert( nVars <= 9 );
+ // compute Cof00
+ Extra_TruthCopy( uTemp0, pTruth, nVars );
+ Extra_TruthCofactor0( uTemp0, nVars, iVar0 );
+ Extra_TruthCofactor0( uTemp0, nVars, iVar1 );
+ // compute Cof11
+ Extra_TruthCopy( uTemp1, pTruth, nVars );
+ Extra_TruthCofactor1( uTemp1, nVars, iVar0 );
+ Extra_TruthCofactor1( uTemp1, nVars, iVar1 );
+ // compare
+ return Extra_TruthIsEqual( uTemp0, uTemp1, nVars );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Changes phase of the function w.r.t. one variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+ unsigned Temp;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ Temp = pTruth[i];
+ pTruth[i] = pTruth[Step+i];
+ pTruth[Step+i] = Temp;
+ }
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes minimum overlap in supports of cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin )
+{
+ static unsigned uCofactor[16];
+ int i, ValueCur, ValueMin, VarMin;
+ unsigned uSupp0, uSupp1;
+ int nVars0, nVars1;
+ assert( nVars <= 9 );
+ ValueMin = 32;
+ VarMin = -1;
+ for ( i = 0; i < nVars; i++ )
+ {
+ // get negative cofactor
+ Extra_TruthCopy( uCofactor, pTruth, nVars );
+ Extra_TruthCofactor0( uCofactor, nVars, i );
+ uSupp0 = Extra_TruthSupport( uCofactor, nVars );
+ nVars0 = Extra_WordCountOnes( uSupp0 );
+//Extra_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" );
+ // get positive cofactor
+ Extra_TruthCopy( uCofactor, pTruth, nVars );
+ Extra_TruthCofactor1( uCofactor, nVars, i );
+ uSupp1 = Extra_TruthSupport( uCofactor, nVars );
+ nVars1 = Extra_WordCountOnes( uSupp1 );
+//Extra_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" );
+ // get the number of common vars
+ ValueCur = Extra_WordCountOnes( uSupp0 & uSupp1 );
+ if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 )
+ {
+ ValueMin = ValueCur;
+ VarMin = i;
+ }
+ if ( ValueMin == 0 )
+ break;
+ }
+ if ( pVarMin )
+ *pVarMin = VarMin;
+ return ValueMin;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1's in each cofactor.]
+
+ Description [The resulting numbers are stored in the array of shorts,
+ whose length is 2*nVars. The number of 1's is counted in a different
+ space than the original function. For example, if the function depends
+ on k variables, the cofactors are assumed to depend on k-1 variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Counter;
+ memset( pStore, 0, sizeof(short) * 2 * nVars );
+ if ( nVars <= 5 )
+ {
+ if ( nVars > 0 )
+ {
+ pStore[2*0+0] = Extra_WordCountOnes( pTruth[0] & 0x55555555 );
+ pStore[2*0+1] = Extra_WordCountOnes( pTruth[0] & 0xAAAAAAAA );
+ }
+ if ( nVars > 1 )
+ {
+ pStore[2*1+0] = Extra_WordCountOnes( pTruth[0] & 0x33333333 );
+ pStore[2*1+1] = Extra_WordCountOnes( pTruth[0] & 0xCCCCCCCC );
+ }
+ if ( nVars > 2 )
+ {
+ pStore[2*2+0] = Extra_WordCountOnes( pTruth[0] & 0x0F0F0F0F );
+ pStore[2*2+1] = Extra_WordCountOnes( pTruth[0] & 0xF0F0F0F0 );
+ }
+ if ( nVars > 3 )
+ {
+ pStore[2*3+0] = Extra_WordCountOnes( pTruth[0] & 0x00FF00FF );
+ pStore[2*3+1] = Extra_WordCountOnes( pTruth[0] & 0xFF00FF00 );
+ }
+ if ( nVars > 4 )
+ {
+ pStore[2*4+0] = Extra_WordCountOnes( pTruth[0] & 0x0000FFFF );
+ pStore[2*4+1] = Extra_WordCountOnes( pTruth[0] & 0xFFFF0000 );
+ }
+ return;
+ }
+ // nVars >= 6
+ // count 1's for all other variables
+ for ( k = 0; k < nWords; k++ )
+ {
+ Counter = Extra_WordCountOnes( pTruth[k] );
+ for ( i = 5; i < nVars; i++ )
+ if ( k & (1 << (i-5)) )
+ pStore[2*i+1] += Counter;
+ else
+ pStore[2*i+0] += Counter;
+ }
+ // count 1's for the first five variables
+ for ( k = 0; k < nWords/2; k++ )
+ {
+ pStore[2*0+0] += Extra_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) );
+ pStore[2*0+1] += Extra_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) );
+ pStore[2*1+0] += Extra_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) );
+ pStore[2*1+1] += Extra_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) );
+ pStore[2*2+0] += Extra_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) );
+ pStore[2*2+1] += Extra_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) );
+ pStore[2*3+0] += Extra_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) );
+ pStore[2*3+1] += Extra_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) );
+ pStore[2*4+0] += Extra_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) );
+ pStore[2*4+1] += Extra_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) );
+ pTruth += 2;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Canonicize the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthHash( unsigned * pIn, int nWords )
+{
+ // The 1,024 smallest prime numbers used to compute the hash value
+ // http://www.math.utah.edu/~alfeld/math/primelist.html
+ static int HashPrimes[1024] = { 2, 3, 5,
+ 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191,
+ 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+ 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401,
+ 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
+ 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
+ 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877,
+ 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
+ 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
+ 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193,
+ 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
+ 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
+ 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
+ 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
+ 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699,
+ 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
+ 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
+ 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029,
+ 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137,
+ 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
+ 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
+ 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459,
+ 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593,
+ 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
+ 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
+ 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
+ 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023,
+ 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
+ 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
+ 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373,
+ 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
+ 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
+ 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
+ 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833,
+ 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931,
+ 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
+ 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
+ 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283,
+ 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
+ 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
+ 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
+ 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789,
+ 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931,
+ 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
+ 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147,
+ 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
+ 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413,
+ 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507,
+ 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647,
+ 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
+ 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
+ 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
+ 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121,
+ 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247,
+ 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343,
+ 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
+ 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607,
+ 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733,
+ 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857,
+ 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971,
+ 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
+ 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
+ 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369,
+ 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517,
+ 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603,
+ 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+ 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873,
+ 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
+ 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123,
+ 8147, 8161 };
+ int i;
+ unsigned uHashKey;
+ assert( nWords <= 1024 );
+ uHashKey = 0;
+ for ( i = 0; i < nWords; i++ )
+ uHashKey ^= HashPrimes[i] * pIn[i];
+ return uHashKey;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Canonicize the truth table.]
+
+ Description [Returns the phase. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore )
+{
+ unsigned * pIn = pInOut, * pOut = pAux, * pTemp;
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit;
+ unsigned uCanonPhase;
+
+ // canonicize output
+ uCanonPhase = 0;
+ nOnes = Extra_TruthCountOnes(pIn, nVars);
+ if ( (nOnes > nWords * 16) || ((nOnes == nWords * 16) && (pIn[0] & 1)) )
+ {
+ uCanonPhase |= (1 << nVars);
+ Extra_TruthNot( pIn, pIn, nVars );
+ }
+
+ // collect the minterm counts
+ Extra_TruthCountOnesInCofs( pIn, nVars, pStore );
+
+ // canonicize phase
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pStore[2*i+0] <= pStore[2*i+1] )
+ continue;
+ uCanonPhase |= (1 << i);
+ Temp = pStore[2*i+0];
+ pStore[2*i+0] = pStore[2*i+1];
+ pStore[2*i+1] = Temp;
+ Extra_TruthChangePhase( pIn, nVars, i );
+ }
+
+// Extra_PrintHexadecimal( stdout, pIn, nVars );
+// printf( "\n" );
+
+ // permute
+ Counter = 0;
+ do {
+ fChange = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( pStore[2*i] <= pStore[2*(i+1)] )
+ continue;
+ Counter++;
+ fChange = 1;
+
+ Temp = pCanonPerm[i];
+ pCanonPerm[i] = pCanonPerm[i+1];
+ pCanonPerm[i+1] = Temp;
+
+ Temp = pStore[2*i];
+ pStore[2*i] = pStore[2*(i+1)];
+ pStore[2*(i+1)] = Temp;
+
+ Temp = pStore[2*i+1];
+ pStore[2*i+1] = pStore[2*(i+1)+1];
+ pStore[2*(i+1)+1] = Temp;
+
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ } while ( fChange );
+
+/*
+ Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " );
+ for ( i = 0; i < nVars; i++ )
+ printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] );
+ printf( " C = %d\n", Counter );
+ Extra_PrintHexadecimal( stdout, pIn, nVars );
+ printf( "\n" );
+*/
+
+/*
+ // process symmetric variable groups
+ uSymms = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ if ( pStore[2*i] != pStore[2*i+1] )
+ continue;
+ if ( Extra_TruthVarsSymm( pIn, nVars, i, i+1 ) )
+ continue;
+ if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) )
+ Extra_TruthChangePhase( pIn, nVars, i+1 );
+ }
+*/
+
+/*
+ // process symmetric variable groups
+ uSymms = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ // i and i+1 can be symmetric
+ // find the end of this group
+ for ( k = i+1; k < nVars; k++ )
+ if ( pStore[2*i] != pStore[2*k] )
+ break;
+ Limit = k;
+ assert( i < Limit-1 );
+ // go through the variables in this group
+ for ( j = i + 1; j < Limit; j++ )
+ {
+ // check symmetry
+ if ( Extra_TruthVarsSymm( pIn, nVars, i, j ) )
+ {
+ uSymms |= (1 << j);
+ continue;
+ }
+ // they are phase-unknown
+ if ( pStore[2*i] == pStore[2*i+1] )
+ {
+ if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, j ) )
+ {
+ Extra_TruthChangePhase( pIn, nVars, j );
+ uCanonPhase ^= (1 << j);
+ uSymms |= (1 << j);
+ continue;
+ }
+ }
+
+ // they are not symmetric - move j as far as it goes in the group
+ for ( k = j; k < Limit-1; k++ )
+ {
+ Counter++;
+
+ Temp = pCanonPerm[k];
+ pCanonPerm[k] = pCanonPerm[k+1];
+ pCanonPerm[k+1] = Temp;
+
+ assert( pStore[2*k] == pStore[2*(k+1)] );
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ Limit--;
+ j--;
+ }
+ i = Limit - 1;
+ }
+*/
+
+ // swap if it was moved an even number of times
+ if ( Counter & 1 )
+ Extra_TruthCopy( pOut, pIn, nVars );
+ return uCanonPhase;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c
new file mode 100644
index 00000000..ee0c400a
--- /dev/null
+++ b/src/misc/extra/extraUtilUtil.c
@@ -0,0 +1,330 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Old SIS utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilUtil.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define EXTRA_RLIMIT_DATA_DEFAULT 67108864 // assume 64MB by default
+
+/* 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 * globalUtilOptarg; // Global argument pointer (util_optarg)
+int globalUtilOptind = 0; // Global argv index (util_optind)
+
+static char *pScanStr;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [util_cpu_time()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+long Extra_CpuTime()
+{
+ return clock();
+}
+
+/**Function*************************************************************
+
+ Synopsis [getSoftDataLimit()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_GetSoftDataLimit()
+{
+ return EXTRA_RLIMIT_DATA_DEFAULT;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_getopt_reset()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_UtilGetoptReset()
+{
+ globalUtilOptarg = 0;
+ globalUtilOptind = 0;
+ pScanStr = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_getopt()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_UtilGetopt( int argc, char *argv[], char *optstring )
+{
+ register int c;
+ register char *place;
+
+ globalUtilOptarg = NULL;
+
+ if (pScanStr == NULL || *pScanStr == '\0') {
+ if (globalUtilOptind == 0) globalUtilOptind++;
+ if (globalUtilOptind >= argc) return EOF;
+ place = argv[globalUtilOptind];
+ if (place[0] != '-' || place[1] == '\0') return EOF;
+ globalUtilOptind++;
+ if (place[1] == '-' && place[2] == '\0') return EOF;
+ pScanStr = place+1;
+ }
+
+ c = *pScanStr++;
+ place = strchr(optstring, c);
+ if (place == NULL || c == ':') {
+ (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+ return '?';
+ }
+ if (*++place == ':') {
+ if (*pScanStr != '\0') {
+ globalUtilOptarg = pScanStr;
+ pScanStr = NULL;
+ } else {
+ if (globalUtilOptind >= argc) {
+ (void) fprintf(stderr, "%s: %c requires an argument\n",
+ argv[0], c);
+ return '?';
+ }
+ globalUtilOptarg = argv[globalUtilOptind];
+ globalUtilOptind++;
+ }
+ }
+ return c;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_print_time()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilPrintTime( long t )
+{
+ static char s[40];
+
+ (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10);
+ return s;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Extra_UtilStrsav()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilStrsav( char *s )
+{
+ if(s == NULL) { /* added 7/95, for robustness */
+ return s;
+ }
+ else {
+ return strcpy(ALLOC(char, strlen(s)+1), s);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_tilde_expand()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilTildeExpand( char *fname )
+{
+ return Extra_UtilStrsav( fname );
+}
+
+/**Function*************************************************************
+
+ Synopsis [check_file()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_UtilCheckFile(char *filename, char *mode)
+{
+ 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;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_file_search()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilFileSearch(char *file, char *path, char *mode)
+//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 = Extra_UtilStrsav(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 = Extra_UtilStrsav(file);
+ } else {
+ buffer = ALLOC(char, strlen(path) + strlen(file) + 4);
+ (void) sprintf(buffer, "%s/%s", path, file);
+ }
+ filename = Extra_UtilTildeExpand(buffer);
+ FREE(buffer);
+
+ /* see if we can access it */
+ if (Extra_UtilCheckFile(filename, mode)) {
+ FREE(save_path);
+ return filename;
+ }
+ FREE(filename);
+ path = ++cp;
+ } while (! quit);
+
+ FREE(save_path);
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [MMout_of_memory()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+/* MMout_of_memory -- out of memory for lazy people, flush and exit */
+void Extra_UtilMMout_Of_Memory( long size )
+{
+ (void) fflush(stdout);
+ (void) fprintf(stderr, "\nout of memory allocating %u bytes\n",
+ (unsigned) size);
+ assert( 0 );
+ exit(1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [MMoutOfMemory()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void (*Extra_UtilMMoutOfMemory)() = Extra_UtilMMout_Of_Memory;
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/module.make b/src/misc/extra/module.make
new file mode 100644
index 00000000..ec8bca4d
--- /dev/null
+++ b/src/misc/extra/module.make
@@ -0,0 +1,15 @@
+SRC += src/misc/extra/extraBddAuto.c \
+ src/misc/extra/extraBddCas.c \
+ src/misc/extra/extraBddKmap.c \
+ src/misc/extra/extraBddMisc.c \
+ src/misc/extra/extraBddSymm.c \
+ src/misc/extra/extraBddUnate.c \
+ src/misc/extra/extraUtilBitMatrix.c \
+ src/misc/extra/extraUtilCanon.c \
+ src/misc/extra/extraUtilFile.c \
+ src/misc/extra/extraUtilMemory.c \
+ src/misc/extra/extraUtilMisc.c \
+ src/misc/extra/extraUtilProgress.c \
+ src/misc/extra/extraUtilReader.c \
+ src/misc/extra/extraUtilTruth.c \
+ src/misc/extra/extraUtilUtil.c
diff --git a/src/misc/hash/hash.h b/src/misc/hash/hash.h
new file mode 100644
index 00000000..90e72868
--- /dev/null
+++ b/src/misc/hash/hash.h
@@ -0,0 +1,65 @@
+/**CFile****************************************************************
+
+ FileName [hash.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash map.]
+
+ Synopsis [External declarations.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2005.]
+
+ Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+#include "hashInt.h"
+#include "hashFlt.h"
+#include "hashPtr.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef ABS
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+int Hash_DefaultHashFunc(int key, int nBins) {
+ return ABS( ( (key+11)*(key)*7+3 ) % nBins );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/src/misc/hash/hashFlt.h b/src/misc/hash/hashFlt.h
new file mode 100644
index 00000000..da20ee28
--- /dev/null
+++ b/src/misc/hash/hashFlt.h
@@ -0,0 +1,330 @@
+/**CFile****************************************************************
+
+ FileName [hashFlt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash maps.]
+
+ Synopsis [Hash maps.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2006.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_FLT_H__
+#define __HASH_FLT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Flt_t_ Hash_Flt_t;
+typedef struct Hash_Flt_Entry_t_ Hash_Flt_Entry_t;
+
+struct Hash_Flt_Entry_t_
+{
+ int key;
+ float data;
+ struct Hash_Flt_Entry_t_ * pNext;
+};
+
+struct Hash_Flt_t_
+{
+ int nSize;
+ int nBins;
+ int (* fHash)(int key, int nBins);
+ Hash_Flt_Entry_t ** pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_FltForEachEntry( pHash, pEntry, bin) \
+ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+ if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a hash map with the given number of bins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hash_Flt_t * Hash_FltAlloc( int nBins )
+{
+ Hash_Flt_t * p;
+ int i;
+ assert(nBins > 0);
+ p = ALLOC( Hash_Flt_t, 1);
+ p->nBins = nBins;
+ p->fHash = Hash_DefaultHashFunc;
+ p->nSize = 0;
+ p->pArray = ALLOC( Hash_Flt_Entry_t *, nBins );
+ for(i=0; i<nBins; i++)
+ p->pArray[i] = NULL;
+
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if a key already exists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_FltExists( Hash_Flt_t *p, int key )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ return 1;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and writes value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_FltWriteEntry( Hash_Flt_t *p, int key, float data )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ pEntry->data = data;
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = data;
+
+ return;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key.]
+
+ Description [fCreate specifies whether new entries should be created.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Hash_FltEntry( Hash_Flt_t *p, int key, int fCreate )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return pEntry->data;
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ if (fCreate) {
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0.0;
+ return pEntry->data;
+ }
+
+ return 0.0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and returns the pointer to it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float* Hash_FltEntryPtr( Hash_Flt_t *p, int key )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return &(pEntry->data);
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0.0;
+
+ return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes an entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_FltRemove( Hash_Flt_t *p, int key )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ p->nSize--;
+ *pLast = pEntry->pNext;
+ FREE( pEntry );
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // could not find key
+ return;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the hash.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_FltFree( Hash_Flt_t *p ) {
+ int bin;
+ Hash_Flt_Entry_t *pEntry;
+
+ // free bins
+ for(bin = 0; bin < p->nBins; bin++) {
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ pEntry = pEntry->pNext;
+ FREE( pEntry );
+ }
+ }
+
+ // free hash
+ FREE( p->pArray );
+ FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/misc/hash/hashInt.h b/src/misc/hash/hashInt.h
new file mode 100644
index 00000000..3b91f5df
--- /dev/null
+++ b/src/misc/hash/hashInt.h
@@ -0,0 +1,293 @@
+/**CFile****************************************************************
+
+ FileName [hashInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash maps.]
+
+ Synopsis [Hash maps.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2006.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_INT_H__
+#define __HASH_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Int_t_ Hash_Int_t;
+typedef struct Hash_Int_Entry_t_ Hash_Int_Entry_t;
+
+struct Hash_Int_Entry_t_
+{
+ int key;
+ int data;
+ struct Hash_Int_Entry_t_ * pNext;
+};
+
+struct Hash_Int_t_
+{
+ int nSize;
+ int nBins;
+ int (* fHash)(int key, int nBins);
+ Hash_Int_Entry_t ** pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_IntForEachEntry( pHash, pEntry, bin) \
+ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+ if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a hash map with the given number of bins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hash_Int_t * Hash_IntAlloc( int nBins )
+{
+ Hash_Int_t * p;
+ int i;
+ assert(nBins > 0);
+ p = ALLOC( Hash_Int_t, 1);
+ p->nBins = nBins;
+ p->fHash = Hash_DefaultHashFunc;
+ p->nSize = 0;
+ p->pArray = ALLOC( Hash_Int_Entry_t *, nBins );
+ for(i=0; i<nBins; i++)
+ p->pArray[i] = NULL;
+
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if a key already exists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_IntExists( Hash_Int_t *p, int key)
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ return 1;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and writes value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_IntWriteEntry( Hash_Int_t *p, int key, int data )
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ pEntry->data = data;
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = data;
+
+ return;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key.]
+
+ Description [fCreate specifies whether new entries will be created.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_IntEntry( Hash_Int_t *p, int key, int fCreate )
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return pEntry->data;
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ if (fCreate) {
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0;
+ return pEntry->data;
+ }
+
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and returns the pointer to it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int* Hash_IntEntryPtr( Hash_Int_t *p, int key )
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return &(pEntry->data);
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0;
+
+ return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the hash.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_IntFree( Hash_Int_t *p ) {
+ int bin;
+ Hash_Int_Entry_t *pEntry;
+
+ // free bins
+ for(bin = 0; bin < p->nBins; bin++) {
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ pEntry = pEntry->pNext;
+ FREE( pEntry );
+ }
+ }
+
+ // free hash
+ FREE( p->pArray );
+ FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/misc/hash/hashPtr.h b/src/misc/hash/hashPtr.h
new file mode 100644
index 00000000..15398a8a
--- /dev/null
+++ b/src/misc/hash/hashPtr.h
@@ -0,0 +1,331 @@
+/**CFile****************************************************************
+
+ FileName [hashFlt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash maps.]
+
+ Synopsis [Hash maps.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2006.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_PTR_H__
+#define __HASH_PTR_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Ptr_t_ Hash_Ptr_t;
+typedef struct Hash_Ptr_Entry_t_ Hash_Ptr_Entry_t;
+
+struct Hash_Ptr_Entry_t_
+{
+ int key;
+ void * data;
+ struct Hash_Ptr_Entry_t_ * pNext;
+};
+
+struct Hash_Ptr_t_
+{
+ int nSize;
+ int nBins;
+ int (* fHash)(int key, int nBins);
+ Hash_Ptr_Entry_t ** pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_PtrForEachEntry( pHash, pEntry, bin ) \
+ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+ if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a hash map with the given number of bins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hash_Ptr_t * Hash_PtrAlloc( int nBins )
+{
+ Hash_Ptr_t * p;
+ int i;
+ assert(nBins > 0);
+ p = ALLOC( Hash_Ptr_t, 1);
+ p->nBins = nBins;
+ p->fHash = Hash_DefaultHashFunc;
+ p->nSize = 0;
+ p->pArray = ALLOC( Hash_Ptr_Entry_t *, nBins );
+ for(i=0; i<nBins; i++)
+ p->pArray[i] = NULL;
+
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if a key already exists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_PtrExists( Hash_Ptr_t *p, int key )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ return 1;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and writes value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_PtrWriteEntry( Hash_Ptr_t *p, int key, void * data )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ pEntry->data = data;
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = data;
+
+ return;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key.]
+
+ Description [fCreate specifies whether a new entry should be created.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Hash_PtrEntry( Hash_Ptr_t *p, int key, int fCreate )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return pEntry->data;
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ if (fCreate) {
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = NULL;
+ return pEntry->data;
+ }
+
+ return NULL;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and returns the pointer to it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void** Hash_PtrEntryPtr( Hash_Ptr_t *p, int key )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return &(pEntry->data);
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = NULL;
+
+ return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes an entry.]
+
+ Description [Returns data, if there was any.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void* Hash_PtrRemove( Hash_Ptr_t *p, int key )
+{
+ int bin;
+ void * data;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ p->nSize--;
+ data = pEntry->data;
+ *pLast = pEntry->pNext;
+ return data;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // could not find key
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the hash.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_PtrFree( Hash_Ptr_t *p ) {
+ int bin;
+ Hash_Ptr_Entry_t *pEntry;
+
+ // free bins
+ for(bin = 0; bin < p->nBins; bin++) {
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ pEntry = pEntry->pNext;
+ FREE( pEntry );
+ }
+ }
+
+ // free hash
+ FREE( p->pArray );
+ FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/misc/hash/module.make b/src/misc/hash/module.make
new file mode 100644
index 00000000..d6d908e7
--- /dev/null
+++ b/src/misc/hash/module.make
@@ -0,0 +1 @@
+SRC +=
diff --git a/src/misc/mvc/module.make b/src/misc/mvc/module.make
new file mode 100644
index 00000000..23735ca2
--- /dev/null
+++ b/src/misc/mvc/module.make
@@ -0,0 +1,16 @@
+SRC += src/misc/mvc/mvc.c \
+ src/misc/mvc/mvcApi.c \
+ src/misc/mvc/mvcCompare.c \
+ src/misc/mvc/mvcContain.c \
+ src/misc/mvc/mvcCover.c \
+ src/misc/mvc/mvcCube.c \
+ src/misc/mvc/mvcDivide.c \
+ src/misc/mvc/mvcDivisor.c \
+ src/misc/mvc/mvcList.c \
+ src/misc/mvc/mvcLits.c \
+ src/misc/mvc/mvcMan.c \
+ src/misc/mvc/mvcOpAlg.c \
+ src/misc/mvc/mvcOpBool.c \
+ src/misc/mvc/mvcPrint.c \
+ src/misc/mvc/mvcSort.c \
+ src/misc/mvc/mvcUtils.c
diff --git a/src/misc/mvc/mvc.c b/src/misc/mvc/mvc.c
new file mode 100644
index 00000000..001b1c63
--- /dev/null
+++ b/src/misc/mvc/mvc.c
@@ -0,0 +1,46 @@
+/**CFile****************************************************************
+
+ FileName [mvc.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis []
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvc.c,v 1.3 2003/03/19 19:50:26 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvc.h b/src/misc/mvc/mvc.h
new file mode 100644
index 00000000..70834e0a
--- /dev/null
+++ b/src/misc/mvc/mvc.h
@@ -0,0 +1,732 @@
+/**CFile****************************************************************
+
+ FileName [mvc.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Data structure for MV cube/cover manipulation.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvc.h,v 1.10 2003/05/02 23:23:59 wjiang Exp $]
+
+***********************************************************************/
+
+#ifndef __MVC_H__
+#define __MVC_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+// this is the only part of Mvc package, which should be modified
+// when compiling the package for other platforms
+
+// these parameters can be computed but setting them manually makes it faster
+#define BITS_PER_WORD 32 // sizeof(Mvc_CubeWord_t) * 8
+#define BITS_PER_WORD_MINUS 31 // the same minus 1
+#define BITS_PER_WORD_LOG 5 // log2(sizeof(Mvc_CubeWord_t) * 8)
+#define BITS_DISJOINT ((Mvc_CubeWord_t)0x55555555) // the mask of the type "01010101"
+#define BITS_FULL ((Mvc_CubeWord_t)0xffffffff) // the mask of the type "11111111"
+
+// uncomment this macro to switch to standard memory management
+//#define USE_SYSTEM_MEMORY_MANAGEMENT
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// cube/list/cover/data
+typedef unsigned int Mvc_CubeWord_t;
+typedef struct MvcCubeStruct Mvc_Cube_t;
+typedef struct MvcListStruct Mvc_List_t;
+typedef struct MvcCoverStruct Mvc_Cover_t;
+typedef struct MvcDataStruct Mvc_Data_t;
+typedef struct MvcManagerStruct Mvc_Manager_t;
+
+// the cube data structure
+struct MvcCubeStruct
+{
+ Mvc_Cube_t * pNext; // the next cube in the linked list
+ unsigned iLast : 8; // the index of the last word
+ unsigned nUnused : 6; // the number of unused bits in the last word
+ unsigned fPrime : 1; // marks the prime cube
+ unsigned fEssen : 1; // marks the essential cube
+ unsigned nOnes : 16; // the number of 1's in the bit data
+ Mvc_CubeWord_t pData[1]; // the first Mvc_CubeWord_t filled with bit data
+};
+
+// the single-linked list of cubes in the cover
+struct MvcListStruct
+{
+ Mvc_Cube_t * pHead; // the first cube in the list
+ Mvc_Cube_t * pTail; // the last cube in the list
+ int nItems; // the number of cubes in the list
+};
+
+// the cover data structure
+struct MvcCoverStruct
+{
+ char nWords; // the number of machine words
+ char nUnused; // the number of unused bits in the last word
+ short nBits; // the number of used data bits in the cube
+ Mvc_List_t lCubes; // the single-linked list of cubes
+ Mvc_Cube_t ** pCubes; // the array of cubes (for sorting)
+ int nCubesAlloc; // the size of allocated storage
+ int * pLits; // the counter of lit occurrances in cubes
+ Mvc_Cube_t * pMask; // the multipurpose mask
+ Mvc_Manager_t * pMem; // the memory manager
+};
+
+// data structure to store information about MV variables
+struct MvcDataStruct
+{
+ Mvc_Manager_t * pMan; // the memory manager
+// Vm_VarMap_t * pVm; // the MV variable data
+ int nBinVars; // the number of binary variables
+ Mvc_Cube_t * pMaskBin; // the mask to select the binary bits only
+ Mvc_Cube_t ** ppMasks; // the mask to select each MV variable
+ Mvc_Cube_t * ppTemp[3]; // the temporary cubes
+};
+
+// the manager of covers and cubes (as of today, only managing memory)
+struct MvcManagerStruct
+{
+ Extra_MmFixed_t * pManC; // the manager for covers
+ Extra_MmFixed_t * pMan1; // the manager for 1-word cubes
+ Extra_MmFixed_t * pMan2; // the manager for 2-word cubes
+ Extra_MmFixed_t * pMan4; // the manager for 3-word cubes
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// reading data from the header of the cube
+#define Mvc_CubeReadNext(Cube) ((Cube)->pNext)
+#define Mvc_CubeReadNextP(Cube) (&(Cube)->pNext)
+#define Mvc_CubeReadLast(Cube) ((Cube)->iLast)
+#define Mvc_CubeReadSize(Cube) ((Cube)->nOnes)
+// setting data to the header of the cube
+#define Mvc_CubeSetNext(Cube,Next) ((Cube)->pNext = (Next))
+#define Mvc_CubeSetLast(Cube,Last) ((Cube)->iLast = (Last))
+#define Mvc_CubeSetSize(Cube,Size) ((Cube)->nOnes = (Size))
+// checking the number of words
+
+#define Mvc_Cube1Words(Cube) ((Cube)->iLast == 0)
+#define Mvc_Cube2Words(Cube) ((Cube)->iLast == 1)
+#define Mvc_CubeNWords(Cube) ((Cube)->iLast > 1)
+// getting one data bit
+#define Mvc_CubeWhichWord(Bit) ((Bit) >> BITS_PER_WORD_LOG)
+#define Mvc_CubeWhichBit(Bit) ((Bit) & BITS_PER_WORD_MINUS)
+// accessing individual bits
+#define Mvc_CubeBitValue(Cube, Bit) (((Cube)->pData[Mvc_CubeWhichWord(Bit)] & (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) > 0)
+#define Mvc_CubeBitInsert(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] |= (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit))))
+#define Mvc_CubeBitRemove(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] &= ~(((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit))))
+// accessing values of the binary variables
+#define Mvc_CubeVarValue(Cube, Var) (((Cube)->pData[Mvc_CubeWhichWord(2*(Var))] >> (Mvc_CubeWhichBit(2*(Var)))) & ((Mvc_CubeWord_t)3))
+
+// various macros
+
+// cleaning the data bits of the cube
+#define Mvc_Cube1BitClean( Cube )\
+ ((Cube)->pData[0] = 0)
+#define Mvc_Cube2BitClean( Cube )\
+ (((Cube)->pData[0] = 0),\
+ ((Cube)->pData[1] = 0))
+#define Mvc_CubeNBitClean( Cube )\
+{\
+ int _i_;\
+ for( _i_ = (Cube)->iLast; _i_ >= 0; _i_--)\
+ (Cube)->pData[_i_] = 0;\
+}
+
+// cleaning the unused part of the lat word
+#define Mvc_CubeBitCleanUnused( Cube )\
+ ((Cube)->pData[(Cube)->iLast] &= (BITS_FULL >> (Cube)->nUnused))
+
+// filling the used data bits with 1's
+#define Mvc_Cube1BitFill( Cube )\
+ (Cube)->pData[0] = (BITS_FULL >> (Cube)->nUnused);
+#define Mvc_Cube2BitFill( Cube )\
+ (((Cube)->pData[0] = BITS_FULL),\
+ ((Cube)->pData[1] = (BITS_FULL >> (Cube)->nUnused)))
+#define Mvc_CubeNBitFill( Cube )\
+{\
+ int _i_;\
+ (Cube)->pData[(Cube)->iLast] = (BITS_FULL >> (Cube)->nUnused);\
+ for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\
+ (Cube)->pData[_i_] = BITS_FULL;\
+}
+
+// complementing the data bits
+#define Mvc_Cube1BitNot( Cube )\
+ ((Cube)->pData[0] ^= (BITS_FULL >> (Cube)->nUnused))
+#define Mvc_Cube2BitNot( Cube )\
+ (((Cube)->pData[0] ^= BITS_FULL),\
+ ((Cube)->pData[1] ^= (BITS_FULL >> (Cube)->nUnused)))
+#define Mvc_CubeNBitNot( Cube )\
+{\
+ int _i_;\
+ (Cube)->pData[(Cube)->iLast] ^= (BITS_FULL >> (Cube)->nUnused);\
+ for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\
+ (Cube)->pData[_i_] ^= BITS_FULL;\
+}
+
+#define Mvc_Cube1BitCopy( Cube1, Cube2 )\
+ (((Cube1)->pData[0]) = ((Cube2)->pData[0]))
+#define Mvc_Cube2BitCopy( Cube1, Cube2 )\
+ ((((Cube1)->pData[0]) = ((Cube2)->pData[0])),\
+ (((Cube1)->pData[1])= ((Cube2)->pData[1])))
+#define Mvc_CubeNBitCopy( Cube1, Cube2 )\
+{\
+ int _i_;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ ((Cube1)->pData[_i_]) = ((Cube2)->pData[_i_]);\
+}
+
+#define Mvc_Cube1BitOr( CubeR, Cube1, Cube2 )\
+ (((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0]))
+#define Mvc_Cube2BitOr( CubeR, Cube1, Cube2 )\
+ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])),\
+ (((CubeR)->pData[1]) = ((Cube1)->pData[1] | (Cube2)->pData[1])))
+#define Mvc_CubeNBitOr( CubeR, Cube1, Cube2 )\
+{\
+ int _i_;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] | (Cube2)->pData[_i_]));\
+}
+
+#define Mvc_Cube1BitExor( CubeR, Cube1, Cube2 )\
+ (((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0]))
+#define Mvc_Cube2BitExor( CubeR, Cube1, Cube2 )\
+ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])),\
+ (((CubeR)->pData[1]) = ((Cube1)->pData[1] ^ (Cube2)->pData[1])))
+#define Mvc_CubeNBitExor( CubeR, Cube1, Cube2 )\
+{\
+ int _i_;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] ^ (Cube2)->pData[_i_]));\
+}
+
+#define Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 )\
+ (((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0]))
+#define Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 )\
+ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])),\
+ (((CubeR)->pData[1]) = ((Cube1)->pData[1] & (Cube2)->pData[1])))
+#define Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 )\
+{\
+ int _i_;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & (Cube2)->pData[_i_]));\
+}
+
+#define Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 )\
+ (((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0])))
+#define Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 )\
+ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))),\
+ (((CubeR)->pData[1]) = ((Cube1)->pData[1] & ~((Cube2)->pData[1]))))
+#define Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 )\
+{\
+ int _i_;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & ~(Cube2)->pData[_i_]));\
+}
+
+#define Mvc_Cube1BitEmpty( Res, Cube )\
+ (Res = ((Cube)->pData[0] == 0))
+#define Mvc_Cube2BitEmpty( Res, Cube )\
+ (Res = ((Cube)->pData[0] == 0 && (Cube)->pData[1] == 0))
+#define Mvc_CubeNBitEmpty( Res, Cube )\
+{\
+ int _i_; Res = 1;\
+ for (_i_ = (Cube)->iLast; _i_ >= 0; _i_--)\
+ if ( (Cube)->pData[_i_] )\
+ { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitEqual( Res, Cube1, Cube2 )\
+ (Res = (((Cube1)->pData[0]) == ((Cube2)->pData[0])))
+#define Mvc_Cube2BitEqual( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) &&\
+ (((Cube1)->pData[1]) == ((Cube2)->pData[1]))))
+#define Mvc_CubeNBitEqual( Res, Cube1, Cube2 )\
+{\
+ int _i_; Res = 1;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if (((Cube1)->pData[_i_]) != ((Cube2)->pData[_i_]))\
+ { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitLess( Res, Cube1, Cube2 )\
+ (Res = (((Cube1)->pData[0]) < ((Cube2)->pData[0])))
+#define Mvc_Cube2BitLess( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) < ((Cube2)->pData[0])) ||\
+ ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) < ((Cube2)->pData[1])))))
+#define Mvc_CubeNBitLess( Res, Cube1, Cube2 )\
+{\
+ int _i_; Res = 1;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if (((Cube1)->pData[_i_]) >= ((Cube2)->pData[_i_]))\
+ { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitMore( Res, Cube1, Cube2 )\
+ (Res = (((Cube1)->pData[0]) > ((Cube2)->pData[0])))
+#define Mvc_Cube2BitMore( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) > ((Cube2)->pData[0])) ||\
+ ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) > ((Cube2)->pData[1])))))
+#define Mvc_CubeNBitMore( Res, Cube1, Cube2 )\
+{\
+ int _i_; Res = 1;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if (((Cube1)->pData[_i_]) <= ((Cube2)->pData[_i_]))\
+ { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 )\
+ (Res = (((Cube1)->pData[0]) & ~((Cube2)->pData[0])))
+#define Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\
+ (((Cube1)->pData[1]) & ~((Cube2)->pData[1]))))
+#define Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 )\
+{\
+ int _i_; Res = 0;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if (((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\
+ { Res = 1; break; }\
+}
+
+#define Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 )\
+ (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 ))
+#define Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 )\
+ (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 ) &&\
+ ((((Cube1)->pData[1]) & ((Cube2)->pData[1])) == 0 )))
+#define Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 )\
+{\
+ int _i_; Res = 1;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]))\
+ { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+ (Res = ((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0]))))
+#define Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+ (Res = (((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0]))) &&\
+ ((((Cube1)->pData[1]) & ((Mask)->pData[1])) == (((Cube2)->pData[1]) & ((Mask)->pData[1])))))
+#define Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+{\
+ int _i_; Res = 1;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if ((((Cube1)->pData[_i_]) & ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) & ((Mask)->pData[_i_])))\
+ { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+ (Res = ((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0]))))
+#define Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+ (Res = (((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0]))) &&\
+ ((((Cube1)->pData[1]) | ((Mask)->pData[1])) == (((Cube2)->pData[1]) | ((Mask)->pData[1])))))
+#define Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+{\
+ int _i_; Res = 1;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if ((((Cube1)->pData[_i_]) | ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) | ((Mask)->pData[_i_])))\
+ { Res = 0; break; }\
+}
+
+#define Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\
+ (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0))
+#define Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\
+ (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0) ||\
+ ((((Cube1)->pData[1]) & ((Cube2)->pData[1]) & ((Mask)->pData[1])) > 0)))
+#define Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask)\
+{\
+ int _i_; Res = 0;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]) & ((Mask)->pData[_i_]))\
+ { Res = 1; break; }\
+}
+
+#define Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+ (Res = (((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0])))
+#define Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+ (Res = ((((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\
+ (((Mask)->pData[1]) & ((Cube1)->pData[1]) & ~((Cube2)->pData[1]))))
+#define Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+{\
+ int _i_; Res = 0;\
+ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\
+ if (((Mask)->pData[_i_]) & ((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\
+ { Res = 1; break; }\
+}
+
+// the following macros make no assumption about the cube's bitset size
+#define Mvc_CubeBitClean( Cube )\
+ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitClean( Cube ); }\
+ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitClean( Cube ); }\
+ else { Mvc_CubeNBitClean( Cube ); }
+#define Mvc_CubeBitFill( Cube )\
+ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitFill( Cube ); }\
+ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitFill( Cube ); }\
+ else { Mvc_CubeNBitFill( Cube ); }
+#define Mvc_CubeBitNot( Cube )\
+ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitNot( Cube ); }\
+ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitNot( Cube ); }\
+ else { Mvc_CubeNBitNot( Cube ); }
+#define Mvc_CubeBitCopy( Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitCopy( Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitCopy( Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitCopy( Cube1, Cube2 ); }
+#define Mvc_CubeBitOr( CubeR, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitOr( CubeR, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitOr( CubeR, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitOr( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitExor( CubeR, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitExor( CubeR, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitExor( CubeR, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitExor( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitAnd( CubeR, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitSharp( CubeR, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 ); }
+#define Mvc_CubeBitEmpty( Res, Cube )\
+ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitEmpty( Res, Cube ); }\
+ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitEmpty( Res, Cube ); }\
+ else { Mvc_CubeNBitEmpty( Res, Cube ); }
+#define Mvc_CubeBitEqual( Res, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqual( Res, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqual( Res, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitEqual( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitLess( Res, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitLess( Res, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitLess( Res, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitLess( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitMore( Res, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitMore( Res, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitMore( Res, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitMore( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitNotImpl( Res, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitDisjoint( Res, Cube1, Cube2 )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 ); }\
+ else { Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 ); }
+#define Mvc_CubeBitEqualUnderMask( Res, Cube1, Cube2, Mask )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\
+ else { Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask ); }
+#define Mvc_CubeBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\
+ else { Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }
+#define Mvc_CubeBitIntersectUnderMask( Res, Cube1, Cube2, Mask )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\
+ else { Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }
+#define Mvc_CubeBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\
+ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\
+ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\
+ else { Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }
+
+
+// managing linked lists
+#define Mvc_ListAddCubeHead( pList, pCube )\
+ {\
+ if ( pList->pHead == NULL )\
+ {\
+ Mvc_CubeSetNext( pCube, NULL );\
+ pList->pHead = pCube;\
+ pList->pTail = pCube;\
+ }\
+ else\
+ {\
+ Mvc_CubeSetNext( pCube, pList->pHead );\
+ pList->pHead = pCube;\
+ }\
+ pList->nItems++;\
+ }
+#define Mvc_ListAddCubeTail( pList, pCube )\
+ {\
+ if ( pList->pHead == NULL )\
+ pList->pHead = pCube;\
+ else\
+ Mvc_CubeSetNext( pList->pTail, pCube );\
+ pList->pTail = pCube;\
+ Mvc_CubeSetNext( pCube, NULL );\
+ pList->nItems++;\
+ }
+#define Mvc_ListDeleteCube( pList, pPrev, pCube )\
+{\
+ if ( pPrev == NULL )\
+ pList->pHead = pCube->pNext;\
+ else\
+ pPrev->pNext = pCube->pNext;\
+ if ( pList->pTail == pCube )\
+ {\
+ assert( pCube->pNext == NULL );\
+ pList->pTail = pPrev;\
+ }\
+ pList->nItems--;\
+}
+
+// managing linked lists inside the cover
+#define Mvc_CoverAddCubeHead( pCover, pCube )\
+{\
+ Mvc_List_t * pList = &pCover->lCubes;\
+ Mvc_ListAddCubeHead( pList, pCube );\
+}
+#define Mvc_CoverAddCubeTail( pCover, pCube )\
+{\
+ Mvc_List_t * pList = &pCover->lCubes;\
+ Mvc_ListAddCubeTail( pList, pCube );\
+}
+#define Mvc_CoverDeleteCube( pCover, pPrev, pCube )\
+{\
+ Mvc_List_t * pList = &pCover->lCubes;\
+ Mvc_ListDeleteCube( pList, pPrev, pCube );\
+}
+
+
+
+
+
+
+// iterator through the cubes in the cube list
+#define Mvc_ListForEachCube( List, Cube )\
+ for ( Cube = List->pHead;\
+ Cube;\
+ Cube = Cube->pNext )
+#define Mvc_ListForEachCubeSafe( List, Cube, Cube2 )\
+ for ( Cube = List->pHead, Cube2 = (Cube? Cube->pNext: NULL);\
+ Cube;\
+ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+// iterator through cubes in the cover
+#define Mvc_CoverForEachCube( Cover, Cube )\
+ for ( Cube = (Cover)->lCubes.pHead;\
+ Cube;\
+ Cube = Cube->pNext )
+#define Mvc_CoverForEachCubeWithIndex( Cover, Cube, Index )\
+ for ( Index = 0, Cube = (Cover)->lCubes.pHead;\
+ Cube;\
+ Index++, Cube = Cube->pNext )
+#define Mvc_CoverForEachCubeSafe( Cover, Cube, Cube2 )\
+ for ( Cube = (Cover)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\
+ Cube;\
+ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+// iterator which starts from the given cube
+#define Mvc_CoverForEachCubeStart( Start, Cube )\
+ for ( Cube = Start;\
+ Cube;\
+ Cube = Cube->pNext )
+#define Mvc_CoverForEachCubeStartSafe( Start, Cube, Cube2 )\
+ for ( Cube = Start, Cube2 = (Cube? Cube->pNext: NULL);\
+ Cube;\
+ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+
+// iterator through literals of the cube
+#define Mvc_CubeForEachBit( Cover, Cube, iBit, Value )\
+ for ( iBit = 0;\
+ iBit < Cover->nBits && ((Value = Mvc_CubeBitValue(Cube,iBit))>=0);\
+ iBit++ )
+// iterator through values of binary variables
+#define Mvc_CubeForEachVarValue( Cover, Cube, iVar, Value )\
+ for ( iVar = 0;\
+ iVar < Cover->nBits/2 && (Value = Mvc_CubeVarValue(Cube,iVar));\
+ iVar++ )
+
+
+// macros which work with memory
+// MEM_ALLOC: allocate the given number (Size) of items of type (Type)
+// MEM_FREE: deallocate the pointer (Pointer) to the given number (Size) of items of type (Type)
+#define MEM_ALLOC( Manager, Type, Size ) ((Type *)malloc( (Size) * sizeof(Type) ))
+#define MEM_FREE( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mvcApi.c ====================================================*/
+extern int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover );
+extern int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover );
+extern int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover );
+extern Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover );
+extern int Mvc_ListReadCubeNum( Mvc_List_t * pList );
+extern Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList );
+extern Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList );
+extern void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems );
+extern void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList );
+extern int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover );
+extern int Mvc_CoverIsTautology( Mvc_Cover_t * pCover );
+extern int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover );
+extern void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover );
+extern void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover );
+/*=== mvcCover.c ====================================================*/
+extern Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits );
+extern Mvc_Cover_t * Mvc_CoverCreateConst( Mvc_Manager_t * pMem, int nBits, int Phase );
+extern Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * pCover );
+extern void Mvc_CoverFree( Mvc_Cover_t * pCover );
+extern void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover );
+extern void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover );
+extern void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover );
+extern void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover );
+extern void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover );
+/*=== mvcCube.c ====================================================*/
+extern Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube );
+/*=== mvcCompare.c ====================================================*/
+extern int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+extern int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask );
+/*=== mvcDd.c ====================================================*/
+/*
+extern DdNode * Mvc_CoverConvertToBdd( DdManager * dd, Mvc_Cover_t * pCover );
+extern DdNode * Mvc_CoverConvertToZdd( DdManager * dd, Mvc_Cover_t * pCover );
+extern DdNode * Mvc_CoverConvertToZdd2( DdManager * dd, Mvc_Cover_t * pCover );
+extern DdNode * Mvc_CubeConvertToBdd( DdManager * dd, Mvc_Cube_t * pCube );
+extern DdNode * Mvc_CubeConvertToZdd( DdManager * dd, Mvc_Cube_t * pCube );
+extern DdNode * Mvc_CubeConvertToZdd2( DdManager * dd, Mvc_Cube_t * pCube );
+*/
+/*=== mvcDivisor.c ====================================================*/
+extern Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover );
+/*=== mvcDivide.c ====================================================*/
+extern void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem );
+extern void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit );
+/*=== mvcList.c ====================================================*/
+// these functions are available as macros
+extern void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube );
+extern void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube );
+extern void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube );
+extern void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube );
+extern void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+// other functions
+extern void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverList2Array( Mvc_Cover_t * pCover );
+extern void Mvc_CoverArray2List( Mvc_Cover_t * pCover );
+extern Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead );
+/*=== mvcPrint.c ====================================================*/
+extern void Mvc_CoverPrint( Mvc_Cover_t * pCover );
+extern void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+extern void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover );
+extern void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+/*=== mvcSort.c ====================================================*/
+extern void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) );
+/*=== mvcUtils.c ====================================================*/
+extern void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp );
+extern int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover );
+extern int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar );
+extern void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube );
+extern int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover );
+extern void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover );
+extern int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover );
+extern int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube );
+extern int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] );
+extern Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * pCover, int * pVarsRem, int nVarsRem );
+extern void Mvc_CoverInverse( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t * Mvc_CoverRemoveDontCareLits( Mvc_Cover_t * pCover );
+extern Mvc_Cover_t * Mvc_CoverCofactor( Mvc_Cover_t * pCover, int iValue, int iValueOther );
+extern Mvc_Cover_t * Mvc_CoverFlipVar( Mvc_Cover_t * pCover, int iValue0, int iValue1 );
+extern Mvc_Cover_t * Mvc_CoverUnivQuantify( Mvc_Cover_t * p, int iValueA0, int iValueA1, int iValueB0, int iValueB1 );
+extern Mvc_Cover_t ** Mvc_CoverCofactors( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar );
+extern int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue );
+//extern Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew );
+extern Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover );
+extern int Mvc_UtilsCheckUnusedZeros( Mvc_Cover_t * pCover );
+/*=== mvcLits.c ====================================================*/
+extern int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask );
+extern int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask );
+extern int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask );
+extern Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple );
+extern int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover );
+extern int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover );
+extern int Mvc_CoverIsOneLiteral( Mvc_Cover_t * pCover );
+/*=== mvcOpAlg.c ====================================================*/
+extern Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+/*=== mvcOpBool.c ====================================================*/
+extern Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+extern int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 );
+
+/*=== mvcContain.c ====================================================*/
+extern int Mvc_CoverContain( Mvc_Cover_t * pCover );
+/*=== mvcTau.c ====================================================*/
+extern int Mvc_CoverTautology( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+/*=== mvcCompl.c ====================================================*/
+extern Mvc_Cover_t * Mvc_CoverComplement( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+/*=== mvcSharp.c ====================================================*/
+extern Mvc_Cover_t * Mvc_CoverSharp( Mvc_Data_t * p, Mvc_Cover_t * pA, Mvc_Cover_t * pB );
+extern int Mvc_CoverDist0Cubes( Mvc_Data_t * pData, Mvc_Cube_t * pA, Mvc_Cube_t * pB );
+extern void Mvc_CoverIntersectCubes( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern int Mvc_CoverIsIntersecting( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern void Mvc_CoverAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern void Mvc_CoverCopyAndAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 );
+extern void Mvc_CoverRemoveCubes( Mvc_Cover_t * pC );
+
+/*=== mvcReshape.c ====================================================*/
+extern void Mvc_CoverMinimizeByReshape( Mvc_Data_t * pData, Mvc_Cover_t * pCover );
+
+/*=== mvcMerge.c ====================================================*/
+extern void Mvc_CoverDist1Merge( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+
+/*=== mvcData.c ====================================================*/
+//extern Mvc_Data_t * Mvc_CoverDataAlloc( Vm_VarMap_t * pVm, Mvc_Cover_t * pCover );
+//extern void Mvc_CoverDataFree( Mvc_Data_t * p, Mvc_Cover_t * pCover );
+
+/*=== mvcMan.c ====================================================*/
+extern void Mvc_ManagerFree( Mvc_Manager_t * p );
+extern Mvc_Manager_t * Mvc_ManagerStart();
+extern Mvc_Manager_t * Mvc_ManagerAllocCover();
+extern Mvc_Manager_t * Mvc_ManagerAllocCube( int nWords );
+extern Mvc_Manager_t * Mvc_ManagerFreeCover( Mvc_Cover_t * pCover );
+extern Mvc_Manager_t * Mvc_ManagerFreeCube( Mvc_Cover_t * pCube, int nWords );
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/mvc/mvcApi.c b/src/misc/mvc/mvcApi.c
new file mode 100644
index 00000000..eb942f93
--- /dev/null
+++ b/src/misc/mvc/mvcApi.c
@@ -0,0 +1,233 @@
+/**CFile****************************************************************
+
+ FileName [mvcApi.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis []
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcApi.c,v 1.4 2003/04/03 06:31:48 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover ) { return pCover->nWords; }
+int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover ) { return pCover->nBits; }
+int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover ) { return pCover->lCubes.nItems; }
+Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover ) { return pCover->lCubes.pHead; }
+Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover ) { return pCover->lCubes.pTail; }
+Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover ) { return &pCover->lCubes; }
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_ListReadCubeNum( Mvc_List_t * pList ) { return pList->nItems; }
+Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList ) { return pList->pHead; }
+Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList ) { return pList->pTail; }
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems ) { pCover->lCubes.nItems = nItems; }
+void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pHead = pCube; }
+void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pTail = pCube; }
+void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ) { pCover->lCubes = *pList; }
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover )
+{
+ return Mvc_CoverReadCubeNum(pCover) == 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverIsTautology( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int iBit, Value;
+
+ if ( Mvc_CoverReadCubeNum(pCover) != 1 )
+ return 0;
+
+ pCube = Mvc_CoverReadCubeHead( pCover );
+ Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+ if ( Value == 0 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cover is a binary buffer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ if ( pCover->nBits != 2 )
+ return 0;
+ if ( Mvc_CoverReadCubeNum(pCover) != 1 )
+ return 0;
+ pCube = pCover->lCubes.pHead;
+ if ( Mvc_CubeBitValue(pCube, 0) == 0 && Mvc_CubeBitValue(pCube, 1) == 1 )
+ return 1;
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube, * pCube2;
+ Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 )
+ Mvc_CubeFree( pCover, pCube );
+ pCover->lCubes.nItems = 0;
+ pCover->lCubes.pHead = NULL;
+ pCover->lCubes.pTail = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCubeNew;
+ Mvc_CoverMakeEmpty( pCover );
+ pCubeNew = Mvc_CubeAlloc( pCover );
+ Mvc_CubeBitFill( pCubeNew );
+ Mvc_CoverAddCubeTail( pCover, pCubeNew );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover )
+{
+ Mvc_Cover_t * pCoverNew;
+ pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+ return pCoverNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCubeNew;
+ Mvc_Cover_t * pCoverNew;
+ pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+ pCubeNew = Mvc_CubeAlloc( pCoverNew );
+ Mvc_CubeBitFill( pCubeNew );
+ Mvc_CoverAddCubeTail( pCoverNew, pCubeNew );
+ return pCoverNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcCompare.c b/src/misc/mvc/mvcCompare.c
new file mode 100644
index 00000000..9cff99cd
--- /dev/null
+++ b/src/misc/mvc/mvcCompare.c
@@ -0,0 +1,369 @@
+/**CFile****************************************************************
+
+ FileName [mvcCompare.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Various cube comparison functions.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcCompare.c,v 1.5 2003/04/03 23:25:41 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Compares two cubes according to their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+ if ( Mvc_Cube1Words(pC1) )
+ {
+ if ( pC1->pData[0] < pC2->pData[0] )
+ return -1;
+ if ( pC1->pData[0] > pC2->pData[0] )
+ return 1;
+ return 0;
+ }
+ else if ( Mvc_Cube2Words(pC1) )
+ {
+ if ( pC1->pData[1] < pC2->pData[1] )
+ return -1;
+ if ( pC1->pData[1] > pC2->pData[1] )
+ return 1;
+ if ( pC1->pData[0] < pC2->pData[0] )
+ return -1;
+ if ( pC1->pData[0] > pC2->pData[0] )
+ return 1;
+ return 0;
+ }
+ else
+ {
+ int i = Mvc_CubeReadLast(pC1);
+ for(; i >= 0; i--)
+ {
+ if ( pC1->pData[i] < pC2->pData[i] )
+ return -1;
+ if ( pC1->pData[i] > pC2->pData[i] )
+ return 1;
+ }
+ return 0;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares the cubes (1) by size, (2) by integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+ // compare the cubes by size
+ if ( Mvc_CubeReadSize( pC1 ) < Mvc_CubeReadSize( pC2 ) )
+ return 1;
+ if ( Mvc_CubeReadSize( pC1 ) > Mvc_CubeReadSize( pC2 ) )
+ return -1;
+ // the cubes have the same size
+
+ // compare the cubes as integers
+ if ( Mvc_Cube1Words( pC1 ) )
+ {
+ if ( pC1->pData[0] < pC2->pData[0] )
+ return -1;
+ if ( pC1->pData[0] > pC2->pData[0] )
+ return 1;
+ return 0;
+ }
+ else if ( Mvc_Cube2Words( pC1 ) )
+ {
+ if ( pC1->pData[1] < pC2->pData[1] )
+ return -1;
+ if ( pC1->pData[1] > pC2->pData[1] )
+ return 1;
+ if ( pC1->pData[0] < pC2->pData[0] )
+ return -1;
+ if ( pC1->pData[0] > pC2->pData[0] )
+ return 1;
+ return 0;
+ }
+ else
+ {
+ int i = Mvc_CubeReadLast( pC1 );
+ for(; i >= 0; i--)
+ {
+ if ( pC1->pData[i] < pC2->pData[i] )
+ return -1;
+ if ( pC1->pData[i] > pC2->pData[i] )
+ return 1;
+ }
+ return 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two cubes under the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+ unsigned uBits1, uBits2;
+
+ // compare the cubes under the mask
+ if ( Mvc_Cube1Words(pC1) )
+ {
+ uBits1 = pC1->pData[0] & pMask->pData[0];
+ uBits2 = pC2->pData[0] & pMask->pData[0];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ // cubes are equal
+ return 0;
+ }
+ else if ( Mvc_Cube2Words(pC1) )
+ {
+ uBits1 = pC1->pData[1] & pMask->pData[1];
+ uBits2 = pC2->pData[1] & pMask->pData[1];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ uBits1 = pC1->pData[0] & pMask->pData[0];
+ uBits2 = pC2->pData[0] & pMask->pData[0];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ return 0;
+ }
+ else
+ {
+ int i = Mvc_CubeReadLast(pC1);
+ for(; i >= 0; i--)
+ {
+ uBits1 = pC1->pData[i] & pMask->pData[i];
+ uBits2 = pC2->pData[i] & pMask->pData[i];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ }
+ return 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two cubes under the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+ unsigned uBits1, uBits2;
+
+ // compare the cubes under the mask
+ if ( Mvc_Cube1Words(pC1) )
+ {
+ uBits1 = pC1->pData[0] | pMask->pData[0];
+ uBits2 = pC2->pData[0] | pMask->pData[0];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ // cubes are equal
+ return 0;
+ }
+ else if ( Mvc_Cube2Words(pC1) )
+ {
+ uBits1 = pC1->pData[1] | pMask->pData[1];
+ uBits2 = pC2->pData[1] | pMask->pData[1];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ uBits1 = pC1->pData[0] | pMask->pData[0];
+ uBits2 = pC2->pData[0] | pMask->pData[0];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ return 0;
+ }
+ else
+ {
+ int i = Mvc_CubeReadLast(pC1);
+ for(; i >= 0; i--)
+ {
+ uBits1 = pC1->pData[i] | pMask->pData[i];
+ uBits2 = pC2->pData[i] | pMask->pData[i];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ }
+ return 0;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares the cubes (1) outside the mask, (2) under the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask )
+{
+ unsigned uBits1, uBits2;
+
+ if ( Mvc_Cube1Words(pC1) )
+ {
+ // compare the cubes outside the mask
+ uBits1 = pC1->pData[0] & ~(pMask->pData[0]);
+ uBits2 = pC2->pData[0] & ~(pMask->pData[0]);
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+
+ // compare the cubes under the mask
+ uBits1 = pC1->pData[0] & pMask->pData[0];
+ uBits2 = pC2->pData[0] & pMask->pData[0];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ // cubes are equal
+ // should never happen
+ assert( 0 );
+ return 0;
+ }
+ else if ( Mvc_Cube2Words(pC1) )
+ {
+ // compare the cubes outside the mask
+ uBits1 = pC1->pData[1] & ~(pMask->pData[1]);
+ uBits2 = pC2->pData[1] & ~(pMask->pData[1]);
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+
+ uBits1 = pC1->pData[0] & ~(pMask->pData[0]);
+ uBits2 = pC2->pData[0] & ~(pMask->pData[0]);
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+
+ // compare the cubes under the mask
+ uBits1 = pC1->pData[1] & pMask->pData[1];
+ uBits2 = pC2->pData[1] & pMask->pData[1];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+
+ uBits1 = pC1->pData[0] & pMask->pData[0];
+ uBits2 = pC2->pData[0] & pMask->pData[0];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+
+ // cubes are equal
+ // should never happen
+ assert( 0 );
+ return 0;
+ }
+ else
+ {
+ int i;
+
+ // compare the cubes outside the mask
+ for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- )
+ {
+ uBits1 = pC1->pData[i] & ~(pMask->pData[i]);
+ uBits2 = pC2->pData[i] & ~(pMask->pData[i]);
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ }
+ // compare the cubes under the mask
+ for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- )
+ {
+ uBits1 = pC1->pData[i] & pMask->pData[i];
+ uBits2 = pC2->pData[i] & pMask->pData[i];
+ if ( uBits1 < uBits2 )
+ return -1;
+ if ( uBits1 > uBits2 )
+ return 1;
+ }
+/*
+ {
+ Mvc_Cover_t * pCover;
+ pCover = Mvc_CoverAlloc( NULL, 96 );
+ Mvc_CubePrint( pCover, pC1 );
+ Mvc_CubePrint( pCover, pC2 );
+ Mvc_CubePrint( pCover, pMask );
+ }
+*/
+ // cubes are equal
+ // should never happen
+ assert( 0 );
+ return 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcContain.c b/src/misc/mvc/mvcContain.c
new file mode 100644
index 00000000..a9eae06e
--- /dev/null
+++ b/src/misc/mvc/mvcContain.c
@@ -0,0 +1,173 @@
+/**CFile****************************************************************
+
+ FileName [mvcContain.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Making the cover single-cube containment free.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcContain.c,v 1.4 2003/04/03 23:25:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover );
+static void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Removes the contained cubes.]
+
+ Description [Returns 1 if the cover has been changed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverContain( Mvc_Cover_t * pCover )
+{
+ int nCubes;
+ nCubes = Mvc_CoverReadCubeNum( pCover );
+ if ( nCubes < 2 )
+ return 0;
+ Mvc_CoverSetCubeSizes(pCover);
+ Mvc_CoverSort( pCover, NULL, Mvc_CubeCompareSizeAndInt );
+ Mvc_CoverRemoveDuplicates( pCover );
+ if ( nCubes > 1 )
+ Mvc_CoverRemoveContained( pCover );
+ return (nCubes != Mvc_CoverReadCubeNum(pCover));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes adjacent duplicated cubes from the cube list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pPrev, * pCube, * pCube2;
+ int fEqual;
+
+ // set the first cube of the cover
+ pPrev = Mvc_CoverReadCubeHead(pCover);
+ // go through all the cubes after this one
+ Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pPrev), pCube, pCube2 )
+ {
+ // compare the current cube with the prev cube
+ Mvc_CubeBitEqual( fEqual, pPrev, pCube );
+ if ( fEqual )
+ { // they are equal - remove the current cube
+ Mvc_CoverDeleteCube( pCover, pPrev, pCube );
+ Mvc_CubeFree( pCover, pCube );
+ // don't change the previous cube cube
+ }
+ else
+ { // they are not equal - update the previous cube
+ pPrev = pCube;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes contained cubes from the sorted cube list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCubeBeg, * pCubeEnd, * pCubeLarge;
+ Mvc_Cube_t * pCube, * pCube2, * pPrev;
+ unsigned sizeCur;
+ int Result;
+
+ // since the cubes are sorted by size, it is sufficient
+ // to compare each cube with other cubes that have larger sizes
+ // if the given cube implies a larger cube, the larger cube is removed
+ pCubeBeg = Mvc_CoverReadCubeHead(pCover);
+ do
+ {
+ // get the current cube size
+ sizeCur = Mvc_CubeReadSize(pCubeBeg);
+
+ // initialize the end of the given size group
+ pCubeEnd = pCubeBeg;
+ // find the beginning of the next size group
+ Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCubeBeg), pCube )
+ {
+ if ( sizeCur == Mvc_CubeReadSize(pCube) )
+ pCubeEnd = pCube;
+ else // pCube is the first cube in the new size group
+ break;
+ }
+ // if we could not find the next size group
+ // the containment check is finished
+ if ( pCube == NULL )
+ break;
+ // otherwise, pCubeBeg/pCubeEnd are the first/last cubes of the group
+
+ // go through all the cubes between pCubeBeg and pCubeEnd, inclusive,
+ // and for each of them, try removing cubes after pCubeEnd
+ Mvc_CoverForEachCubeStart( pCubeBeg, pCubeLarge )
+ {
+ pPrev = pCubeEnd;
+ Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pCubeEnd), pCube, pCube2 )
+ {
+ // check containment
+ Mvc_CubeBitNotImpl( Result, pCube, pCubeLarge );
+ if ( !Result )
+ { // pCubeLarge implies pCube - remove pCube
+ Mvc_CoverDeleteCube( pCover, pPrev, pCube );
+ Mvc_CubeFree( pCover, pCube );
+ // don't update the previous cube
+ }
+ else
+ { // update the previous cube
+ pPrev = pCube;
+ }
+ }
+ // quit, if the main cube was the last one of this size
+ if ( pCubeLarge == pCubeEnd )
+ break;
+ }
+
+ // set the beginning of the next group
+ pCubeBeg = Mvc_CubeReadNext(pCubeEnd);
+ }
+ while ( pCubeBeg );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcCover.c b/src/misc/mvc/mvcCover.c
new file mode 100644
index 00000000..d8584446
--- /dev/null
+++ b/src/misc/mvc/mvcCover.c
@@ -0,0 +1,251 @@
+/**CFile****************************************************************
+
+ FileName [mvcCover.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Basic procedures to manipulate unate cube covers.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcCover.c,v 1.5 2003/04/09 18:02:05 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits )
+{
+ Mvc_Cover_t * p;
+ int nBitsInUnsigned;
+
+ nBitsInUnsigned = 8 * sizeof(Mvc_CubeWord_t);
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+ p = (Mvc_Cover_t *)malloc( sizeof(Mvc_Cover_t) );
+#else
+ p = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( pMem->pManC );
+#endif
+ p->pMem = pMem;
+ p->nBits = nBits;
+ p->nWords = nBits / nBitsInUnsigned + (int)(nBits % nBitsInUnsigned > 0);
+ p->nUnused = p->nWords * nBitsInUnsigned - p->nBits;
+ p->lCubes.nItems = 0;
+ p->lCubes.pHead = NULL;
+ p->lCubes.pTail = NULL;
+ p->nCubesAlloc = 0;
+ p->pCubes = NULL;
+ p->pMask = NULL;
+ p->pLits = NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * p )
+{
+ Mvc_Cover_t * pCover;
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+ pCover = (Mvc_Cover_t *)malloc( sizeof(Mvc_Cover_t) );
+#else
+ pCover = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( p->pMem->pManC );
+#endif
+ pCover->pMem = p->pMem;
+ pCover->nBits = p->nBits;
+ pCover->nWords = p->nWords;
+ pCover->nUnused = p->nUnused;
+ pCover->lCubes.nItems = 0;
+ pCover->lCubes.pHead = NULL;
+ pCover->lCubes.pTail = NULL;
+ pCover->nCubesAlloc = 0;
+ pCover->pCubes = NULL;
+ pCover->pMask = NULL;
+ pCover->pLits = NULL;
+ return pCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * p )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube, * pCubeCopy;
+ // clone the cover
+ pCover = Mvc_CoverClone( p );
+ // copy the cube list
+ Mvc_CoverForEachCube( p, pCube )
+ {
+ pCubeCopy = Mvc_CubeDup( p, pCube );
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+ }
+ return pCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverFree( Mvc_Cover_t * p )
+{
+ Mvc_Cube_t * pCube, * pCube2;
+ // recycle cube list
+ Mvc_CoverForEachCubeSafe( p, pCube, pCube2 )
+ Mvc_CubeFree( p, pCube );
+ // recycle other pointers
+ Mvc_CubeFree( p, p->pMask );
+ MEM_FREE( p->pMem, Mvc_Cube_t *, p->nCubesAlloc, p->pCubes );
+ MEM_FREE( p->pMem, int, p->nBits, p->pLits );
+
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+ free( p );
+#else
+ Extra_MmFixedEntryRecycle( p->pMem->pManC, (char *)p );
+#endif
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover )
+{
+ if ( pCover->pMask == NULL )
+ pCover->pMask = Mvc_CubeAlloc( pCover );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover )
+{
+ if ( pCover->pLits == NULL )
+ pCover->pLits = MEM_ALLOC( pCover->pMem, int, pCover->nBits );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover )
+{
+ if ( pCover->nCubesAlloc < pCover->lCubes.nItems )
+ {
+ if ( pCover->nCubesAlloc > 0 )
+ MEM_FREE( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc, pCover->pCubes );
+ pCover->nCubesAlloc = pCover->lCubes.nItems;
+ pCover->pCubes = MEM_ALLOC( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover )
+{
+ Mvc_CubeFree( pCover, pCover->pMask );
+ pCover->pMask = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover )
+{
+ if ( pCover->pLits )
+ {
+ MEM_FREE( pCover->pMem, int, pCover->nBits, pCover->pLits );
+ pCover->pLits = NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcCube.c b/src/misc/mvc/mvcCube.c
new file mode 100644
index 00000000..e157879f
--- /dev/null
+++ b/src/misc/mvc/mvcCube.c
@@ -0,0 +1,175 @@
+/**CFile****************************************************************
+
+ FileName [mvcCube.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Manipulating unate cubes.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcCube.c,v 1.4 2003/04/03 06:31:49 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+
+ assert( pCover->nWords >= 0 );
+ // allocate the cube
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+ if ( pCover->nWords == 0 )
+ pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) );
+ else
+ pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) );
+#else
+ switch( pCover->nWords )
+ {
+ case 0:
+ case 1:
+ pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan1 );
+ break;
+ case 2:
+ pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan2 );
+ break;
+ case 3:
+ case 4:
+ pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan4 );
+ break;
+ default:
+ pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) );
+ break;
+ }
+#endif
+ // set the parameters charactering this cube
+ if ( pCover->nWords == 0 )
+ pCube->iLast = pCover->nWords;
+ else
+ pCube->iLast = pCover->nWords - 1;
+ pCube->nUnused = pCover->nUnused;
+ return pCube;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ Mvc_Cube_t * pCubeCopy;
+ pCubeCopy = Mvc_CubeAlloc( pCover );
+ Mvc_CubeBitCopy( pCubeCopy, pCube );
+ return pCubeCopy;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ if ( pCube == NULL )
+ return;
+
+ // verify the parameters charactering this cube
+ assert( pCube->iLast == 0 || ((int)pCube->iLast) == pCover->nWords - 1 );
+ assert( ((int)pCube->nUnused) == pCover->nUnused );
+
+ // deallocate the cube
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+ free( pCube );
+#else
+ switch( pCover->nWords )
+ {
+ case 0:
+ case 1:
+ Extra_MmFixedEntryRecycle( pCover->pMem->pMan1, (char *)pCube );
+ break;
+ case 2:
+ Extra_MmFixedEntryRecycle( pCover->pMem->pMan2, (char *)pCube );
+ break;
+ case 3:
+ case 4:
+ Extra_MmFixedEntryRecycle( pCover->pMem->pMan4, (char *)pCube );
+ break;
+ default:
+ free( pCube );
+ break;
+ }
+#endif
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Removes the don't-care variable from the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube )
+{
+ unsigned Mask;
+ int i;
+ for ( i = Mvc_CubeReadLast(pCube); i >= 0; i-- )
+ {
+ // detect those variables that are different (not DCs)
+ Mask = (pCube->pData[i] ^ (pCube->pData[i] >> 1)) & BITS_DISJOINT;
+ // create the mask of all that are different
+ Mask |= (Mask << 1);
+ // remove other bits from the set
+ pCube->pData[i] &= Mask;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcDivide.c b/src/misc/mvc/mvcDivide.c
new file mode 100644
index 00000000..03643dcf
--- /dev/null
+++ b/src/misc/mvc/mvcDivide.c
@@ -0,0 +1,436 @@
+/**CFile****************************************************************
+
+ FileName [mvcDivide.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Procedures for algebraic division.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcDivide.c,v 1.5 2003/04/26 20:41:36 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem );
+
+int s_fVerbose = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+ // check the number of cubes
+ if ( Mvc_CoverReadCubeNum( pCover ) < Mvc_CoverReadCubeNum( pDiv ) )
+ {
+ *ppQuo = NULL;
+ *ppRem = NULL;
+ return;
+ }
+
+ // make sure that support of pCover contains that of pDiv
+ if ( !Mvc_CoverCheckSuppContainment( pCover, pDiv ) )
+ {
+ *ppQuo = NULL;
+ *ppRem = NULL;
+ return;
+ }
+
+ // perform the general division
+ Mvc_CoverDivideInternal( pCover, pDiv, ppQuo, ppRem );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Merge the cubes inside the groups.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+ Mvc_Cover_t * pQuo, * pRem;
+ Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy;
+ Mvc_Cube_t * pCube1, * pCube2;
+ int * pGroups, nGroups; // the cube groups
+ int nCubesC, nCubesD, nMerges, iCubeC, iCubeD, iMerge;
+ int fSkipG, GroupSize, g, c, RetValue;
+ int nCubes;
+
+ // get cover sizes
+ nCubesD = Mvc_CoverReadCubeNum( pDiv );
+ nCubesC = Mvc_CoverReadCubeNum( pCover );
+
+ // check trivial cases
+ if ( nCubesD == 1 )
+ {
+ if ( Mvc_CoverIsOneLiteral( pDiv ) )
+ Mvc_CoverDivideByLiteral( pCover, pDiv, ppQuo, ppRem );
+ else
+ Mvc_CoverDivideByCube( pCover, pDiv, ppQuo, ppRem );
+ return;
+ }
+
+ // create the divisor and the remainder
+ pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+ pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+
+ // get the support of the divisor
+ Mvc_CoverAllocateMask( pDiv );
+ Mvc_CoverSupport( pDiv, pDiv->pMask );
+
+ // sort the cubes of the divisor
+ Mvc_CoverSort( pDiv, NULL, Mvc_CubeCompareInt );
+ // sort the cubes of the cover
+ Mvc_CoverSort( pCover, pDiv->pMask, Mvc_CubeCompareIntOutsideAndUnderMask );
+
+ // allocate storage for cube groups
+ pGroups = MEM_ALLOC( pCover->pMem, int, nCubesC + 1 );
+
+ // mask contains variables in the support of Div
+ // split the cubes into groups using the mask
+ Mvc_CoverList2Array( pCover );
+ Mvc_CoverList2Array( pDiv );
+ pGroups[0] = 0;
+ nGroups = 1;
+ for ( c = 1; c < nCubesC; c++ )
+ {
+ // get the cubes
+ pCube1 = pCover->pCubes[c-1];
+ pCube2 = pCover->pCubes[c ];
+ // compare the cubes
+ Mvc_CubeBitEqualOutsideMask( RetValue, pCube1, pCube2, pDiv->pMask );
+ if ( !RetValue )
+ pGroups[nGroups++] = c;
+ }
+ // finish off the last group
+ pGroups[nGroups] = nCubesC;
+
+ // consider each group separately and decide
+ // whether it can produce a quotient cube
+ nCubes = 0;
+ for ( g = 0; g < nGroups; g++ )
+ {
+ // if the group has less than nCubesD cubes,
+ // there is no way it can produce the quotient cube
+ // copy the cubes to the remainder
+ GroupSize = pGroups[g+1] - pGroups[g];
+ if ( GroupSize < nCubesD )
+ {
+ for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+ {
+ pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] );
+ Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+ nCubes++;
+ }
+ continue;
+ }
+
+ // mark the cubes as those that should be added to the remainder
+ for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+ Mvc_CubeSetSize( pCover->pCubes[c], 1 );
+
+ // go through the cubes in the group and at the same time
+ // go through the cubes in the divisor
+ iCubeD = 0;
+ iCubeC = 0;
+ pCubeD = pDiv->pCubes[iCubeD++];
+ pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
+ fSkipG = 0;
+ nMerges = 0;
+
+ while ( 1 )
+ {
+ // compare the topmost cubes in F and in D
+ RetValue = Mvc_CubeCompareIntUnderMask( pCubeC, pCubeD, pDiv->pMask );
+ // cube are ordered in increasing order of their int value
+ if ( RetValue == -1 ) // pCubeC is above pCubeD
+ { // cube in C should be added to the remainder
+ // check that there is enough cubes in the group
+ if ( GroupSize - iCubeC < nCubesD - nMerges )
+ {
+ fSkipG = 1;
+ break;
+ }
+ // get the next cube in the cover
+ pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
+ continue;
+ }
+ if ( RetValue == 1 ) // pCubeD is above pCubeC
+ { // given cube in D does not have a corresponding cube in the cover
+ fSkipG = 1;
+ break;
+ }
+ // mark the cube as the one that should NOT be added to the remainder
+ Mvc_CubeSetSize( pCubeC, 0 );
+ // remember this merged cube
+ iMerge = iCubeC-1;
+ nMerges++;
+
+ // stop if we considered the last cube of the group
+ if ( iCubeD == nCubesD )
+ break;
+
+ // advance the cube of the divisor
+ assert( iCubeD < nCubesD );
+ pCubeD = pDiv->pCubes[iCubeD++];
+
+ // advance the cube of the group
+ assert( pGroups[g]+iCubeC < nCubesC );
+ pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
+ }
+
+ if ( fSkipG )
+ {
+ // the group has failed, add all the cubes to the remainder
+ for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+ {
+ pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] );
+ Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+ nCubes++;
+ }
+ continue;
+ }
+
+ // the group has worked, add left-over cubes to the remainder
+ for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
+ {
+ pCubeC = pCover->pCubes[c];
+ if ( Mvc_CubeReadSize(pCubeC) )
+ {
+ pCubeCopy = Mvc_CubeDup( pRem, pCubeC );
+ Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+ nCubes++;
+ }
+ }
+
+ // create the quotient cube
+ pCube1 = Mvc_CubeAlloc( pQuo );
+ Mvc_CubeBitSharp( pCube1, pCover->pCubes[pGroups[g]+iMerge], pDiv->pMask );
+ // add the cube to the quotient
+ Mvc_CoverAddCubeTail( pQuo, pCube1 );
+ nCubes += nCubesD;
+ }
+ assert( nCubes == nCubesC );
+
+ // deallocate the memory
+ MEM_FREE( pCover->pMem, int, nCubesC + 1, pGroups );
+
+ // return the results
+ *ppRem = pRem;
+ *ppQuo = pQuo;
+// Mvc_CoverVerifyDivision( pCover, pDiv, pQuo, pRem );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Divides the cover by a cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+ Mvc_Cover_t * pQuo, * pRem;
+ Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy;
+ int CompResult;
+
+ // get the only cube of D
+ assert( Mvc_CoverReadCubeNum(pDiv) == 1 );
+
+ // start the quotient and the remainder
+ pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+ pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+
+ // get the first and only cube of the divisor
+ pCubeD = Mvc_CoverReadCubeHead( pDiv );
+
+ // iterate through the cubes in the cover
+ Mvc_CoverForEachCube( pCover, pCubeC )
+ {
+ // check the containment of literals from pCubeD in pCube
+ Mvc_Cube2BitNotImpl( CompResult, pCubeD, pCubeC );
+ if ( !CompResult )
+ { // this cube belongs to the quotient
+ // alloc the cube
+ pCubeCopy = Mvc_CubeAlloc( pQuo );
+ // clean the support of D
+ Mvc_CubeBitSharp( pCubeCopy, pCubeC, pCubeD );
+ // add the cube to the quotient
+ Mvc_CoverAddCubeTail( pQuo, pCubeCopy );
+ }
+ else
+ {
+ // copy the cube
+ pCubeCopy = Mvc_CubeDup( pRem, pCubeC );
+ // add the cube to the remainder
+ Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+ }
+ }
+ // return the results
+ *ppRem = pRem;
+ *ppQuo = pQuo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Divides the cover by a literal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
+{
+ Mvc_Cover_t * pQuo, * pRem;
+ Mvc_Cube_t * pCubeC, * pCubeCopy;
+ int iLit;
+
+ // get the only cube of D
+ assert( Mvc_CoverReadCubeNum(pDiv) == 1 );
+
+ // start the quotient and the remainder
+ pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+ pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
+
+ // get the first and only literal in the divisor cube
+ iLit = Mvc_CoverFirstCubeFirstLit( pDiv );
+
+ // iterate through the cubes in the cover
+ Mvc_CoverForEachCube( pCover, pCubeC )
+ {
+ // copy the cube
+ pCubeCopy = Mvc_CubeDup( pCover, pCubeC );
+ // add the cube to the quotient or to the remainder depending on the literal
+ if ( Mvc_CubeBitValue( pCubeCopy, iLit ) )
+ { // remove the literal
+ Mvc_CubeBitRemove( pCubeCopy, iLit );
+ // add the cube ot the quotient
+ Mvc_CoverAddCubeTail( pQuo, pCubeCopy );
+ }
+ else
+ { // add the cube ot the remainder
+ Mvc_CoverAddCubeTail( pRem, pCubeCopy );
+ }
+ }
+ // return the results
+ *ppRem = pRem;
+ *ppQuo = pQuo;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the quotient of division by literal.]
+
+ Description [Reduces the cover to be the equal to the result of
+ division of the given cover by the literal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit )
+{
+ Mvc_Cube_t * pCube, * pCube2, * pPrev;
+ // delete those cubes that do not have this literal
+ // remove this literal from other cubes
+ pPrev = NULL;
+ Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 )
+ {
+ if ( Mvc_CubeBitValue( pCube, iLit ) == 0 )
+ { // delete the cube from the cover
+ Mvc_CoverDeleteCube( pCover, pPrev, pCube );
+ Mvc_CubeFree( pCover, pCube );
+ // don't update the previous cube
+ }
+ else
+ { // delete this literal from the cube
+ Mvc_CubeBitRemove( pCube, iLit );
+ // update the previous cube
+ pPrev = pCube;
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Verifies that the result of algebraic division is correct.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem )
+{
+ Mvc_Cover_t * pProd;
+ Mvc_Cover_t * pDiff;
+
+ pProd = Mvc_CoverAlgebraicMultiply( pDiv, pQuo );
+ pDiff = Mvc_CoverAlgebraicSubtract( pCover, pProd );
+
+ if ( Mvc_CoverAlgebraicEqual( pDiff, pRem ) )
+ printf( "Verification OKAY!\n" );
+ else
+ {
+ printf( "Verification FAILED!\n" );
+ printf( "pCover:\n" );
+ Mvc_CoverPrint( pCover );
+ printf( "pDiv:\n" );
+ Mvc_CoverPrint( pDiv );
+ printf( "pRem:\n" );
+ Mvc_CoverPrint( pRem );
+ printf( "pQuo:\n" );
+ Mvc_CoverPrint( pQuo );
+ }
+
+ Mvc_CoverFree( pProd );
+ Mvc_CoverFree( pDiff );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcDivisor.c b/src/misc/mvc/mvcDivisor.c
new file mode 100644
index 00000000..ecdea75b
--- /dev/null
+++ b/src/misc/mvc/mvcDivisor.c
@@ -0,0 +1,90 @@
+/**CFile****************************************************************
+
+ FileName [mvcDivisor.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Procedures for compute the quick divisor.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcDivisor.c,v 1.1 2003/04/03 15:34:08 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the quick divisor of the cover.]
+
+ Description [Returns NULL, if there is not divisor other than
+ trivial.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover )
+{
+ Mvc_Cover_t * pKernel;
+ if ( Mvc_CoverReadCubeNum(pCover) <= 1 )
+ return NULL;
+ // allocate the literal array and count literals
+ if ( Mvc_CoverAnyLiteral( pCover, NULL ) == -1 )
+ return NULL;
+ // duplicate the cover
+ pKernel = Mvc_CoverDup(pCover);
+ // perform the kerneling
+ Mvc_CoverDivisorZeroKernel( pKernel );
+ assert( Mvc_CoverReadCubeNum(pKernel) );
+ return pKernel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes a level-zero kernel.]
+
+ Description [Modifies the cover to contain one level-zero kernel.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover )
+{
+ int iLit;
+ // find any literal that occurs at least two times
+// iLit = Mvc_CoverAnyLiteral( pCover, NULL );
+ iLit = Mvc_CoverWorstLiteral( pCover, NULL );
+// iLit = Mvc_CoverBestLiteral( pCover, NULL );
+ if ( iLit == -1 )
+ return;
+ // derive the cube-free quotient
+ Mvc_CoverDivideByLiteralQuo( pCover, iLit ); // the same cover
+ Mvc_CoverMakeCubeFree( pCover ); // the same cover
+ // call recursively
+ Mvc_CoverDivisorZeroKernel( pCover ); // the same cover
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcList.c b/src/misc/mvc/mvcList.c
new file mode 100644
index 00000000..8a82f911
--- /dev/null
+++ b/src/misc/mvc/mvcList.c
@@ -0,0 +1,362 @@
+/**CFile****************************************************************
+
+ FileName [mvcList.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Manipulating list of cubes in the cover.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcList.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube )
+{
+ if ( pList->pHead == NULL )
+ {
+ Mvc_CubeSetNext( pCube, NULL );
+ pList->pHead = pCube;
+ pList->pTail = pCube;
+ }
+ else
+ {
+ Mvc_CubeSetNext( pCube, pList->pHead );
+ pList->pHead = pCube;
+ }
+ pList->nItems++;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube )
+{
+ if ( pList->pHead == NULL )
+ pList->pHead = pCube;
+ else
+ Mvc_CubeSetNext( pList->pTail, pCube );
+ pList->pTail = pCube;
+ Mvc_CubeSetNext( pCube, NULL );
+ pList->nItems++;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube )
+{
+ if ( pPrev == NULL ) // deleting the head cube
+ pList->pHead = Mvc_CubeReadNext(pCube);
+ else
+ pPrev->pNext = pCube->pNext;
+ if ( pList->pTail == pCube ) // deleting the tail cube
+ {
+ assert( Mvc_CubeReadNext(pCube) == NULL );
+ pList->pTail = pPrev;
+ }
+ pList->nItems--;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ Mvc_List_t * pList = &pCover->lCubes;
+ if ( pList->pHead == NULL )
+ {
+ Mvc_CubeSetNext( pCube, NULL );
+ pList->pHead = pCube;
+ pList->pTail = pCube;
+ }
+ else
+ {
+ Mvc_CubeSetNext( pCube, pList->pHead );
+ pList->pHead = pCube;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ Mvc_List_t * pList = &pCover->lCubes;
+
+ if ( pList->pHead == NULL )
+ pList->pHead = pCube;
+ else
+ Mvc_CubeSetNext( pList->pTail, pCube );
+ pList->pTail = pCube;
+ Mvc_CubeSetNext( pCube, NULL );
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube )
+{
+ Mvc_List_t * pList = &pCover->lCubes;
+
+ if ( pPrev == NULL ) // deleting the head cube
+ pList->pHead = Mvc_CubeReadNext(pCube);
+ else
+ pPrev->pNext = pCube->pNext;
+ if ( pList->pTail == pCube ) // deleting the tail cube
+ {
+ assert( Mvc_CubeReadNext(pCube) == NULL );
+ pList->pTail = pPrev;
+ }
+ pList->nItems--;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ Mvc_Cube_t * pCubeNew;
+ pCubeNew = Mvc_CubeAlloc( pCover );
+ Mvc_CubeBitCopy( pCubeNew, pCube );
+ Mvc_CoverAddCubeHead( pCover, pCubeNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ Mvc_Cube_t * pCubeNew;
+ // copy the cube as part of this cover
+ pCubeNew = Mvc_CubeAlloc( pCover );
+ Mvc_CubeBitCopy( pCubeNew, pCube );
+ // clean the last bits of the new cube
+// pCubeNew->pData[pCubeNew->iLast] &= (BITS_FULL >> pCubeNew->nUnused);
+ // add the cube at the end
+ Mvc_CoverAddCubeTail( pCover, pCubeNew );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+// int iBit, Value;
+// assert( pCover->pLits );
+// Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+// if ( Value )
+// pCover->pLits[iBit] += Value;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+// int iBit, Value;
+// assert( pCover->pLits );
+// Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+// if ( Value )
+// pCover->pLits[iBit] -= Value;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the cubes from the list into the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverList2Array( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int Counter;
+ // resize storage if necessary
+ Mvc_CoverAllocateArrayCubes( pCover );
+ // iterate through the cubes
+ Counter = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ pCover->pCubes[ Counter++ ] = pCube;
+ assert( Counter == Mvc_CoverReadCubeNum(pCover) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the cubes from the array into list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverArray2List( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int nCubes, i;
+
+ assert( pCover->pCubes );
+
+ nCubes = Mvc_CoverReadCubeNum(pCover);
+ if ( nCubes == 0 )
+ return;
+ if ( nCubes == 1 )
+ {
+ pCube = pCover->pCubes[0];
+ pCube->pNext = NULL;
+ pCover->lCubes.pHead = pCover->lCubes.pTail = pCube;
+ return;
+ }
+ // set up the first cube
+ pCube = pCover->pCubes[0];
+ pCover->lCubes.pHead = pCube;
+ // set up the last cube
+ pCube = pCover->pCubes[nCubes-1];
+ pCube->pNext = NULL;
+ pCover->lCubes.pTail = pCube;
+
+ // link all cubes starting from the first one
+ for ( i = 0; i < nCubes - 1; i++ )
+ pCover->pCubes[i]->pNext = pCover->pCubes[i+1];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the tail of the linked list given by the head.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead )
+{
+ Mvc_Cube_t * pCube, * pTail;
+ for ( pTail = pCube = pHead;
+ pCube;
+ pTail = pCube, pCube = Mvc_CubeReadNext(pCube) );
+ return pTail;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcLits.c b/src/misc/mvc/mvcLits.c
new file mode 100644
index 00000000..910158e9
--- /dev/null
+++ b/src/misc/mvc/mvcLits.c
@@ -0,0 +1,345 @@
+/**CFile****************************************************************
+
+ FileName [mvcLits.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Literal counting/updating procedures.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcLits.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find the any literal that occurs more than once.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask )
+{
+ Mvc_Cube_t * pCube;
+ int nWord, nBit, i;
+ int nLitsCur;
+ int fUseFirst = 0;
+
+ // go through each literal
+ if ( fUseFirst )
+ {
+ for ( i = 0; i < pCover->nBits; i++ )
+ if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+ {
+ // get the word and bit of this literal
+ nWord = Mvc_CubeWhichWord(i);
+ nBit = Mvc_CubeWhichBit(i);
+ // go through all the cubes
+ nLitsCur = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ if ( pCube->pData[nWord] & (1<<nBit) )
+ {
+ nLitsCur++;
+ if ( nLitsCur > 1 )
+ return i;
+ }
+ }
+ }
+ else
+ {
+ for ( i = pCover->nBits - 1; i >=0; i-- )
+ if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+ {
+ // get the word and bit of this literal
+ nWord = Mvc_CubeWhichWord(i);
+ nBit = Mvc_CubeWhichBit(i);
+ // go through all the cubes
+ nLitsCur = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ if ( pCube->pData[nWord] & (1<<nBit) )
+ {
+ nLitsCur++;
+ if ( nLitsCur > 1 )
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the most often occurring literal.]
+
+ Description [Find the most often occurring literal among those
+ that occur more than once.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask )
+{
+ Mvc_Cube_t * pCube;
+ int nWord, nBit;
+ int i, iMax, nLitsMax, nLitsCur;
+ int fUseFirst = 1;
+
+ // go through each literal
+ iMax = -1;
+ nLitsMax = -1;
+ for ( i = 0; i < pCover->nBits; i++ )
+ if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+ {
+ // get the word and bit of this literal
+ nWord = Mvc_CubeWhichWord(i);
+ nBit = Mvc_CubeWhichBit(i);
+ // go through all the cubes
+ nLitsCur = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ if ( pCube->pData[nWord] & (1<<nBit) )
+ nLitsCur++;
+
+ // check if this is the best literal
+ if ( fUseFirst )
+ {
+ if ( nLitsMax < nLitsCur )
+ {
+ nLitsMax = nLitsCur;
+ iMax = i;
+ }
+ }
+ else
+ {
+ if ( nLitsMax <= nLitsCur )
+ {
+ nLitsMax = nLitsCur;
+ iMax = i;
+ }
+ }
+ }
+
+ if ( nLitsMax > 1 )
+ return iMax;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the most often occurring literal.]
+
+ Description [Find the most often occurring literal among those
+ that occur more than once.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask )
+{
+ Mvc_Cube_t * pCube;
+ int nWord, nBit;
+ int i, iMin, nLitsMin, nLitsCur;
+ int fUseFirst = 1;
+
+ // go through each literal
+ iMin = -1;
+ nLitsMin = 1000000;
+ for ( i = 0; i < pCover->nBits; i++ )
+ if ( !pMask || Mvc_CubeBitValue(pMask,i) )
+ {
+ // get the word and bit of this literal
+ nWord = Mvc_CubeWhichWord(i);
+ nBit = Mvc_CubeWhichBit(i);
+ // go through all the cubes
+ nLitsCur = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ if ( pCube->pData[nWord] & (1<<nBit) )
+ nLitsCur++;
+
+ // skip the literal that does not occur or occurs once
+ if ( nLitsCur < 2 )
+ continue;
+
+ // check if this is the best literal
+ if ( fUseFirst )
+ {
+ if ( nLitsMin > nLitsCur )
+ {
+ nLitsMin = nLitsCur;
+ iMin = i;
+ }
+ }
+ else
+ {
+ if ( nLitsMin >= nLitsCur )
+ {
+ nLitsMin = nLitsCur;
+ iMin = i;
+ }
+ }
+ }
+
+ if ( nLitsMin < 1000000 )
+ return iMin;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple )
+{
+ Mvc_Cover_t * pCoverNew;
+ Mvc_Cube_t * pCubeNew;
+ Mvc_Cube_t * pCubeS;
+ int iLitBest;
+
+ // create the new cover
+ pCoverNew = Mvc_CoverClone( pCover );
+ // get the new cube
+ pCubeNew = Mvc_CubeAlloc( pCoverNew );
+ // clean the cube
+ Mvc_CubeBitClean( pCubeNew );
+
+ // get the first cube of pSimple
+ assert( Mvc_CoverReadCubeNum(pSimple) == 1 );
+ pCubeS = Mvc_CoverReadCubeHead( pSimple );
+ // find the best literal among those of pCubeS
+ iLitBest = Mvc_CoverBestLiteral( pCover, pCubeS );
+
+ // insert this literal into the cube
+ Mvc_CubeBitInsert( pCubeNew, iLitBest );
+ // add the cube to the cover
+ Mvc_CoverAddCubeTail( pCoverNew, pCubeNew );
+ return pCoverNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int iBit, Value;
+
+ // get the first cube
+ pCube = Mvc_CoverReadCubeHead( pCover );
+ // get the first literal
+ Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+ if ( Value )
+ return iBit;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of literals in the cover.]
+
+ Description [Allocates storage for literal counters and fills it up
+ using the current information.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int nWord, nBit;
+ int i, CounterTot, CounterCur;
+
+ // allocate/clean the storage for literals
+// Mvc_CoverAllocateArrayLits( pCover );
+// memset( pCover->pLits, 0, pCover->nBits * sizeof(int) );
+ // go through each literal
+ CounterTot = 0;
+ for ( i = 0; i < pCover->nBits; i++ )
+ {
+ // get the word and bit of this literal
+ nWord = Mvc_CubeWhichWord(i);
+ nBit = Mvc_CubeWhichBit(i);
+ // go through all the cubes
+ CounterCur = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ if ( pCube->pData[nWord] & (1<<nBit) )
+ CounterCur++;
+ CounterTot += CounterCur;
+ }
+ return CounterTot;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of literals in the cover.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverIsOneLiteral( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int iBit, Counter, Value;
+ if ( Mvc_CoverReadCubeNum(pCover) != 1 )
+ return 0;
+ pCube = Mvc_CoverReadCubeHead(pCover);
+ // count literals
+ Counter = 0;
+ Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+ {
+ if ( Value )
+ {
+ if ( Counter++ )
+ return 0;
+ }
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcMan.c b/src/misc/mvc/mvcMan.c
new file mode 100644
index 00000000..7b4ef2af
--- /dev/null
+++ b/src/misc/mvc/mvcMan.c
@@ -0,0 +1,77 @@
+/**CFile****************************************************************
+
+ FileName [mvcMan.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Procedures working with the MVC memory manager.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcMan.c,v 1.3 2003/03/19 19:50:26 alanmi Exp $]
+
+***********************************************************************/
+
+#include <string.h>
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Manager_t * Mvc_ManagerStart()
+{
+ Mvc_Manager_t * p;
+ p = ALLOC( Mvc_Manager_t, 1 );
+ memset( p, 0, sizeof(Mvc_Manager_t) );
+ p->pMan1 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) );
+ p->pMan2 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) );
+ p->pMan4 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + 3 * sizeof(Mvc_CubeWord_t) );
+ p->pManC = Extra_MmFixedStart( sizeof(Mvc_Cover_t) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_ManagerFree( Mvc_Manager_t * p )
+{
+ Extra_MmFixedStop( p->pMan1 );
+ Extra_MmFixedStop( p->pMan2 );
+ Extra_MmFixedStop( p->pMan4 );
+ Extra_MmFixedStop( p->pManC );
+ free( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcOpAlg.c b/src/misc/mvc/mvcOpAlg.c
new file mode 100644
index 00000000..65c02fa5
--- /dev/null
+++ b/src/misc/mvc/mvcOpAlg.c
@@ -0,0 +1,163 @@
+/**CFile****************************************************************
+
+ FileName [mvcOperAlg.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Miscellaneous operations on covers.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcOpAlg.c,v 1.4 2003/04/26 20:41:36 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Multiplies two disjoint-support covers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube1, * pCube2, * pCube;
+ int CompResult;
+
+ // covers should be the same base
+ assert( pCover1->nBits == pCover2->nBits );
+ // make sure that supports do not overlap
+ Mvc_CoverAllocateMask( pCover1 );
+ Mvc_CoverAllocateMask( pCover2 );
+ Mvc_CoverSupport( pCover1, pCover1->pMask );
+ Mvc_CoverSupport( pCover2, pCover2->pMask );
+ // check if the cubes are bit-wise disjoint
+ Mvc_CubeBitDisjoint( CompResult, pCover1->pMask, pCover2->pMask );
+ if ( !CompResult )
+ printf( "Mvc_CoverMultiply(): Cover supports are not disjoint!\n" );
+
+ // iterate through the cubes
+ pCover = Mvc_CoverClone( pCover1 );
+ Mvc_CoverForEachCube( pCover1, pCube1 )
+ Mvc_CoverForEachCube( pCover2, pCube2 )
+ {
+ // create the product cube
+ pCube = Mvc_CubeAlloc( pCover );
+ // set the product cube equal to the product of the two cubes
+ Mvc_CubeBitOr( pCube, pCube1, pCube2 );
+ // add the cube to the cover
+ Mvc_CoverAddCubeTail( pCover, pCube );
+ }
+ return pCover;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Subtracts the second cover from the first.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube1, * pCube2, * pCube;
+ int fFound;
+ int CompResult;
+
+ // covers should be the same base
+ assert( pCover1->nBits == pCover2->nBits );
+
+ // iterate through the cubes
+ pCover = Mvc_CoverClone( pCover1 );
+ Mvc_CoverForEachCube( pCover1, pCube1 )
+ {
+ fFound = 0;
+ Mvc_CoverForEachCube( pCover2, pCube2 )
+ {
+ Mvc_CubeBitEqual( CompResult, pCube1, pCube2 );
+ if ( CompResult )
+ {
+ fFound = 1;
+ break;
+ }
+ }
+ if ( !fFound )
+ {
+ // create the copy of the cube
+ pCube = Mvc_CubeDup( pCover, pCube1 );
+ // add the cube copy to the cover
+ Mvc_CoverAddCubeTail( pCover, pCube );
+ }
+ }
+ return pCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+ Mvc_Cube_t * pCube1, * pCube2;
+ int fFound;
+ int CompResult;
+
+ // covers should be the same base
+ assert( pCover1->nBits == pCover2->nBits );
+ // iterate through the cubes
+ Mvc_CoverForEachCube( pCover1, pCube1 )
+ {
+ fFound = 0;
+ Mvc_CoverForEachCube( pCover2, pCube2 )
+ {
+ Mvc_CubeBitEqual( CompResult, pCube1, pCube2 );
+ if ( CompResult )
+ {
+ fFound = 1;
+ break;
+ }
+ }
+ if ( !fFound )
+ return 0;
+ }
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcOpBool.c b/src/misc/mvc/mvcOpBool.c
new file mode 100644
index 00000000..0b34f1de
--- /dev/null
+++ b/src/misc/mvc/mvcOpBool.c
@@ -0,0 +1,151 @@
+/**CFile****************************************************************
+
+ FileName [mvcProc.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Various boolean procedures working with covers.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcOpBool.c,v 1.4 2003/04/16 01:55:37 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube, * pCubeCopy;
+ // make sure the covers are compatible
+ assert( pCover1->nBits == pCover2->nBits );
+ // clone the cover
+ pCover = Mvc_CoverClone( pCover1 );
+ // create the cubes by making pair-wise products
+ // of cubes in pCover1 and pCover2
+ Mvc_CoverForEachCube( pCover1, pCube )
+ {
+ pCubeCopy = Mvc_CubeDup( pCover, pCube );
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+ }
+ Mvc_CoverForEachCube( pCover2, pCube )
+ {
+ pCubeCopy = Mvc_CubeDup( pCover, pCube );
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+ }
+ return pCover;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube1, * pCube2, * pCubeCopy;
+ // make sure the covers are compatible
+ assert( pCover1->nBits == pCover2->nBits );
+ // clone the cover
+ pCover = Mvc_CoverClone( pCover1 );
+ // create the cubes by making pair-wise products
+ // of cubes in pCover1 and pCover2
+ Mvc_CoverForEachCube( pCover1, pCube1 )
+ {
+ Mvc_CoverForEachCube( pCover2, pCube2 )
+ {
+ if ( Mvc_CoverDist0Cubes( p, pCube1, pCube2 ) )
+ {
+ pCubeCopy = Mvc_CubeAlloc( pCover );
+ Mvc_CubeBitAnd( pCubeCopy, pCube1, pCube2 );
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+ }
+ }
+ // if the number of cubes in the new cover is too large
+ // try compressing them
+ if ( Mvc_CoverReadCubeNum( pCover ) > 500 )
+ Mvc_CoverContain( pCover );
+ }
+ return pCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the two covers are equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+ Mvc_Cover_t * pSharp;
+
+ pSharp = Mvc_CoverSharp( p, pCover1, pCover2 );
+ if ( Mvc_CoverReadCubeNum( pSharp ) )
+ {
+Mvc_CoverContain( pSharp );
+printf( "Sharp \n" );
+Mvc_CoverPrint( pSharp );
+ Mvc_CoverFree( pSharp );
+ return 0;
+ }
+ Mvc_CoverFree( pSharp );
+
+ pSharp = Mvc_CoverSharp( p, pCover2, pCover1 );
+ if ( Mvc_CoverReadCubeNum( pSharp ) )
+ {
+Mvc_CoverContain( pSharp );
+printf( "Sharp \n" );
+Mvc_CoverPrint( pSharp );
+ Mvc_CoverFree( pSharp );
+ return 0;
+ }
+ Mvc_CoverFree( pSharp );
+
+ return 1;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcPrint.c b/src/misc/mvc/mvcPrint.c
new file mode 100644
index 00000000..52ac76b3
--- /dev/null
+++ b/src/misc/mvc/mvcPrint.c
@@ -0,0 +1,220 @@
+/**CFile****************************************************************
+
+ FileName [mvcPrint.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Printing cubes and covers.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcPrint.c,v 1.6 2003/04/09 18:02:06 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+//#include "vm.h"
+//#include "vmInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverPrint( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int i;
+ // print general statistics
+ printf( "The cover contains %d cubes (%d bits and %d words)\n",
+ pCover->lCubes.nItems, pCover->nBits, pCover->nWords );
+ // iterate through the cubes
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubePrint( pCover, pCube );
+
+ if ( pCover->pLits )
+ {
+ for ( i = 0; i < pCover->nBits; i++ )
+ printf( " %d", pCover->pLits[i] );
+ printf( "\n" );
+ }
+ printf( "End of cover printout\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ int iBit, Value;
+ // iterate through the literals
+// printf( "Size = %2d ", Mvc_CubeReadSize(pCube) );
+ Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
+ printf( "%c", '0' + Value );
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverPrintBinary( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int i;
+ // print general statistics
+ printf( "The cover contains %d cubes (%d bits and %d words)\n",
+ pCover->lCubes.nItems, pCover->nBits, pCover->nWords );
+ // iterate through the cubes
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubePrintBinary( pCover, pCube );
+
+ if ( pCover->pLits )
+ {
+ for ( i = 0; i < pCover->nBits; i++ )
+ printf( " %d", pCover->pLits[i] );
+ printf( "\n" );
+ }
+ printf( "End of cover printout\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ int iVar, Value;
+ // iterate through the literals
+// printf( "Size = %2d ", Mvc_CubeReadSize(pCube) );
+ Mvc_CubeForEachVarValue( pCover, pCube, iVar, Value )
+ {
+ assert( Value != 0 );
+ if ( Value == 3 )
+ printf( "-" );
+ else if ( Value == 1 )
+ printf( "0" );
+ else
+ printf( "1" );
+ }
+ printf( "\n" );
+}
+
+#if 0
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ int i;
+ // print general statistics
+ printf( "The cover contains %d cubes (%d bits and %d words)\n",
+ pCover->lCubes.nItems, pCover->nBits, pCover->nWords );
+ // iterate through the cubes
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubePrintMv( pData, pCover, pCube );
+
+ if ( pCover->pLits )
+ {
+ for ( i = 0; i < pCover->nBits; i++ )
+ printf( " %d", pCover->pLits[i] );
+ printf( "\n" );
+ }
+ printf( "End of cover printout\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube )
+{
+ int iLit, iVar;
+ // iterate through the literals
+ printf( "Size = %2d ", Mvc_CubeReadSize(pCube) );
+ iVar = 0;
+ for ( iLit = 0; iLit < pData->pVm->nValuesIn; iLit++ )
+ {
+ if ( iLit == pData->pVm->pValuesFirst[iVar+1] )
+ {
+ printf( " " );
+ iVar++;
+ }
+ if ( Mvc_CubeBitValue( pCube, iLit ) )
+ printf( "%c", '0' + iLit - pData->pVm->pValuesFirst[iVar] );
+ else
+ printf( "-" );
+ }
+ printf( "\n" );
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcSort.c b/src/misc/mvc/mvcSort.c
new file mode 100644
index 00000000..3c975cb3
--- /dev/null
+++ b/src/misc/mvc/mvcSort.c
@@ -0,0 +1,141 @@
+/**CFile****************************************************************
+
+ FileName [mvcSort.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Sorting cubes in the cover with the mask.]
+
+ Author [MVSIS Group]
+
+ Affiliation [uC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcSort.c,v 1.5 2003/04/27 01:03:45 wjiang Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) );
+Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) );
+
+////////////////////////////////////////////////////////////////////////
+/// FuNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sorts cubes using the given cost function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) )
+{
+ Mvc_Cube_t * pHead;
+ int nCubes;
+ // one cube does not need sorting
+ nCubes = Mvc_CoverReadCubeNum(pCover);
+ if ( nCubes <= 1 )
+ return;
+ // sort the cubes
+ pHead = Mvc_CoverSort_rec( Mvc_CoverReadCubeHead(pCover), nCubes, pMask, pCompareFunc );
+ // insert the sorted list into the cover
+ Mvc_CoverSetCubeHead( pCover, pHead );
+ Mvc_CoverSetCubeTail( pCover, Mvc_ListGetTailFromHead(pHead) );
+ // make sure that the list is sorted in the increasing order
+ assert( pCompareFunc( Mvc_CoverReadCubeHead(pCover), Mvc_CoverReadCubeTail(pCover), pMask ) <= 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursive part of Mvc_CoverSort()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) )
+{
+ Mvc_Cube_t * pList1, * pList2;
+ int nItems1, nItems2, i;
+
+ // trivial case
+ if ( nItems == 1 )
+ {
+ Mvc_CubeSetNext( pList, NULL );
+ return pList;
+ }
+
+ // select the new sizes
+ nItems1 = nItems/2;
+ nItems2 = nItems - nItems1;
+
+ // set the new beginnings
+ pList1 = pList2 = pList;
+ for ( i = 0; i < nItems1; i++ )
+ pList2 = Mvc_CubeReadNext( pList2 );
+
+ // solve recursively
+ pList1 = Mvc_CoverSort_rec( pList1, nItems1, pMask, pCompareFunc );
+ pList2 = Mvc_CoverSort_rec( pList2, nItems2, pMask, pCompareFunc );
+
+ // merge
+ return Mvc_CoverSortMerge( pList1, pList2, pMask, pCompareFunc );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Merges two NULL-terminated linked lists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) )
+{
+ Mvc_Cube_t * pList = NULL, ** ppTail = &pList;
+ Mvc_Cube_t * pCube;
+ while ( pList1 && pList2 )
+ {
+ if ( pCompareFunc( pList1, pList2, pMask ) < 0 )
+ {
+ pCube = pList1;
+ pList1 = Mvc_CubeReadNext(pList1);
+ }
+ else
+ {
+ pCube = pList2;
+ pList2 = Mvc_CubeReadNext(pList2);
+ }
+ *ppTail = pCube;
+ ppTail = Mvc_CubeReadNextP(pCube);
+ }
+ *ppTail = pList1? pList1: pList2;
+ return pList;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/mvc/mvcUtils.c b/src/misc/mvc/mvcUtils.c
new file mode 100644
index 00000000..4b13b23d
--- /dev/null
+++ b/src/misc/mvc/mvcUtils.c
@@ -0,0 +1,868 @@
+/**CFile****************************************************************
+
+ FileName [mvcUtils.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Various cover handling utilities.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: mvcUtils.c,v 1.7 2003/04/26 20:41:36 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mvc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+
+static void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, int iColOld, int iColNew );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp )
+{
+ Mvc_Cube_t * pCube;
+ // clean the support
+ Mvc_CubeBitClean( pSupp );
+ // collect the support
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubeBitOr( pSupp, pSupp, pCube );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverSupportAnd( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp )
+{
+ Mvc_Cube_t * pCube;
+ // clean the support
+ Mvc_CubeBitFill( pSupp );
+ // collect the support
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubeBitAnd( pSupp, pSupp, pCube );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pSupp;
+ int Counter, i, v0, v1;
+ // compute the support
+ pSupp = Mvc_CubeAlloc( pCover );
+ Mvc_CoverSupportAnd( pCover, pSupp );
+ Counter = pCover->nBits/2;
+ for ( i = 0; i < pCover->nBits/2; i++ )
+ {
+ v0 = Mvc_CubeBitValue( pSupp, 2*i );
+ v1 = Mvc_CubeBitValue( pSupp, 2*i+1 );
+ if ( v0 && v1 )
+ Counter--;
+ }
+ Mvc_CubeFree( pCover, pSupp );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar )
+{
+ Mvc_Cube_t * pSupp;
+ int RetValue, v0, v1;
+ // compute the support
+ pSupp = Mvc_CubeAlloc( pCover );
+ Mvc_CoverSupportAnd( pCover, pSupp );
+ v0 = Mvc_CubeBitValue( pSupp, 2*iVar );
+ v1 = Mvc_CubeBitValue( pSupp, 2*iVar+1 );
+ RetValue = (int)( !v0 || !v1 );
+ Mvc_CubeFree( pCover, pSupp );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube )
+{
+ Mvc_Cube_t * pCube;
+ // clean the support
+ Mvc_CubeBitFill( pComCube );
+ // collect the support
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubeBitAnd( pComCube, pComCube, pCube );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover )
+{
+ int Result;
+ // get the common cube
+ Mvc_CoverAllocateMask( pCover );
+ Mvc_CoverCommonCube( pCover, pCover->pMask );
+ // check whether the common cube is empty
+ Mvc_CubeBitEmpty( Result, pCover->pMask );
+ return Result;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ // get the common cube
+ Mvc_CoverAllocateMask( pCover );
+ Mvc_CoverCommonCube( pCover, pCover->pMask );
+ // remove this cube from the cubes in the cover
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubeBitSharp( pCube, pCube, pCover->pMask );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover )
+{
+ Mvc_Cover_t * pRes;
+ Mvc_Cube_t * pCube;
+ // create the new cover
+ pRes = Mvc_CoverClone( pCover );
+ // get the new cube
+ pCube = Mvc_CubeAlloc( pRes );
+ // get the common cube
+ Mvc_CoverCommonCube( pCover, pCube );
+ // add the cube to the cover
+ Mvc_CoverAddCubeTail( pRes, pCube );
+ return pRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the support of cover2 is contained in the support of cover1.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 )
+{
+ int Result;
+ assert( pCover1->nBits == pCover2->nBits );
+ // set the supports
+ Mvc_CoverAllocateMask( pCover1 );
+ Mvc_CoverSupport( pCover1, pCover1->pMask );
+ Mvc_CoverAllocateMask( pCover2 );
+ Mvc_CoverSupport( pCover2, pCover2->pMask );
+ // check the containment
+ Mvc_CubeBitNotImpl( Result, pCover2->pMask, pCover1->pMask );
+ return !Result;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the cube sizes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ unsigned char * pByte, * pByteStart, * pByteStop;
+ int nBytes, nOnes;
+
+ // get the number of unsigned chars in the cube's bit strings
+ nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0);
+ // iterate through the cubes
+ Mvc_CoverForEachCube( pCover, pCube )
+ {
+ // clean the counter of ones
+ nOnes = 0;
+ // set the starting and stopping positions
+ pByteStart = (unsigned char *)pCube->pData;
+ pByteStop = pByteStart + nBytes;
+ // iterate through the positions
+ for ( pByte = pByteStart; pByte < pByteStop; pByte++ )
+ nOnes += bit_count[*pByte];
+ // set the nOnes
+ Mvc_CubeSetSize( pCube, nOnes );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the cube sizes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube )
+{
+ unsigned char * pByte, * pByteStart, * pByteStop;
+ int nOnes, nBytes, nBits;
+ // get the number of unsigned chars in the cube's bit strings
+ nBits = (pCube->iLast + 1) * sizeof(Mvc_CubeWord_t) * 8 - pCube->nUnused;
+ nBytes = nBits / (8 * sizeof(unsigned char)) + (int)(nBits % (8 * sizeof(unsigned char)) > 0);
+ // clean the counter of ones
+ nOnes = 0;
+ // set the starting and stopping positions
+ pByteStart = (unsigned char *)pCube->pData;
+ pByteStop = pByteStart + nBytes;
+ // iterate through the positions
+ for ( pByte = pByteStart; pByte < pByteStop; pByte++ )
+ nOnes += bit_count[*pByte];
+ return nOnes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the differences in each cube pair in the cover.]
+
+ Description [Takes the cover (pCover) and the array where the
+ diff counters go (pDiffs). The array pDiffs should have as many
+ entries as there are different pairs of cubes in the cover: n(n-1)/2.
+ Fills out the array pDiffs with the following info: For each cube
+ pair, included in the array is the number of literals in both cubes
+ after they are made cube free.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] )
+{
+ Mvc_Cube_t * pCube1;
+ Mvc_Cube_t * pCube2;
+ Mvc_Cube_t * pMask;
+ unsigned char * pByte, * pByteStart, * pByteStop;
+ int nBytes, nOnes;
+ int nCubePairs;
+
+ // allocate a temporary mask
+ pMask = Mvc_CubeAlloc( pCover );
+ // get the number of unsigned chars in the cube's bit strings
+ nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0);
+ // iterate through the cubes
+ nCubePairs = 0;
+ Mvc_CoverForEachCube( pCover, pCube1 )
+ {
+ Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCube1), pCube2 )
+ {
+ // find the bit-wise exor of cubes
+ Mvc_CubeBitExor( pMask, pCube1, pCube2 );
+ // set the starting and stopping positions
+ pByteStart = (unsigned char *)pMask->pData;
+ pByteStop = pByteStart + nBytes;
+ // clean the counter of ones
+ nOnes = 0;
+ // iterate through the positions
+ for ( pByte = pByteStart; pByte < pByteStop; pByte++ )
+ nOnes += bit_count[*pByte];
+ // set the nOnes
+ pDiffs[nCubePairs++] = nOnes;
+ }
+ }
+ // deallocate the mask
+ Mvc_CubeFree( pCover, pMask );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new cover containing some literals of the old cover.]
+
+ Description [Creates the new cover containing the given number (nVarsRem)
+ literals of the old cover. All the bits of the new cover are initialized
+ to "1". The selected bits from the old cover are copied on top. The numbers
+ of the selected bits to copy are given in the array pVarsRem. The i-set
+ entry in this array is the index of the bit in the old cover which goes
+ to the i-th place in the new cover. If the i-th entry in pVarsRem is -1,
+ it means that the i-th bit does not change (remains composed of all 1's).
+ This is a useful feature to speed up remapping covers, which are known
+ to depend only on a subset of input variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * p, int * pVarsRem, int nVarsRem )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube, * pCubeCopy;
+ int i;
+ // clone the cover
+ pCover = Mvc_CoverAlloc( p->pMem, nVarsRem );
+ // copy the cube list
+ Mvc_CoverForEachCube( p, pCube )
+ {
+ pCubeCopy = Mvc_CubeAlloc( pCover );
+ //Mvc_CubeBitClean( pCubeCopy ); //changed by wjiang
+ Mvc_CubeBitFill( pCubeCopy ); //changed by wjiang
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+ }
+ // copy the corresponding columns
+ for ( i = 0; i < nVarsRem; i++ )
+ {
+ if (pVarsRem[i] < 0)
+ continue; //added by wjiang
+ assert( pVarsRem[i] >= 0 && pVarsRem[i] < p->nBits );
+ Mvc_CoverCopyColumn( p, pCover, pVarsRem[i], i );
+ }
+ return pCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copies a column from the old cover to the new cover.]
+
+ Description [Copies the column (iColOld) of the old cover (pCoverOld)
+ into the column (iColNew) of the new cover (pCoverNew). Assumes that
+ the number of cubes is the same in both covers. Makes no assuptions
+ about the current contents of the column in the new cover.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew,
+ int iColOld, int iColNew )
+{
+ Mvc_Cube_t * pCubeOld, * pCubeNew;
+ int iWordOld, iWordNew, iBitOld, iBitNew;
+
+ assert( Mvc_CoverReadCubeNum(pCoverOld) == Mvc_CoverReadCubeNum(pCoverNew) );
+
+ // get the place of the old and new columns
+ iWordOld = Mvc_CubeWhichWord(iColOld);
+ iBitOld = Mvc_CubeWhichBit(iColOld);
+ iWordNew = Mvc_CubeWhichWord(iColNew);
+ iBitNew = Mvc_CubeWhichBit(iColNew);
+
+ // go through the cubes of both covers
+ pCubeNew = Mvc_CoverReadCubeHead(pCoverNew);
+ Mvc_CoverForEachCube( pCoverOld, pCubeOld )
+ {
+ if ( pCubeOld->pData[iWordOld] & (1<<iBitOld) )
+ pCubeNew->pData[iWordNew] |= (1<<iBitNew);
+ else
+ pCubeNew->pData[iWordNew] &= ~(1<<iBitNew); // added by wjiang
+ pCubeNew = Mvc_CubeReadNext( pCubeNew );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mvc_CoverInverse( Mvc_Cover_t * pCover )
+{
+ Mvc_Cube_t * pCube;
+ // complement the cubes
+ Mvc_CoverForEachCube( pCover, pCube )
+ Mvc_CubeBitNot( pCube );
+}
+
+/**Function*************************************************************
+
+ Synopsis [This function dups the cover and removes DC literals from cubes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverRemoveDontCareLits( Mvc_Cover_t * pCover )
+{
+ Mvc_Cover_t * pCoverNew;
+ Mvc_Cube_t * pCube;
+
+ pCoverNew = Mvc_CoverDup( pCover );
+ Mvc_CoverForEachCube( pCoverNew, pCube )
+ Mvc_CubeBitRemoveDcs( pCube );
+ return pCoverNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the cofactor w.r.t. to a binary var.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCofactor( Mvc_Cover_t * p, int iValue, int iValueOther )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube, * pCubeCopy;
+ // clone the cover
+ pCover = Mvc_CoverClone( p );
+ // copy the cube list
+ Mvc_CoverForEachCube( p, pCube )
+ if ( Mvc_CubeBitValue( pCube, iValue ) )
+ {
+ pCubeCopy = Mvc_CubeDup( pCover, pCube );
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+ Mvc_CubeBitInsert( pCubeCopy, iValueOther );
+ }
+ return pCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the cover, in which the binary var is complemented.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverFlipVar( Mvc_Cover_t * p, int iValue0, int iValue1 )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube, * pCubeCopy;
+ int Value0, Value1, Temp;
+
+ assert( iValue0 + 1 == iValue1 ); // should be adjacent
+
+ // clone the cover
+ pCover = Mvc_CoverClone( p );
+ // copy the cube list
+ Mvc_CoverForEachCube( p, pCube )
+ {
+ pCubeCopy = Mvc_CubeDup( pCover, pCube );
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+
+ // get the bits
+ Value0 = Mvc_CubeBitValue( pCubeCopy, iValue0 );
+ Value1 = Mvc_CubeBitValue( pCubeCopy, iValue1 );
+
+ // if both bits are one, nothing to swap
+ if ( Value0 && Value1 )
+ continue;
+ // cannot be both zero because they belong to the same var
+ assert( Value0 || Value1 );
+
+ // swap the bits
+ Temp = Value0;
+ Value0 = Value1;
+ Value1 = Temp;
+
+ // set the bits after the swap
+ if ( Value0 )
+ Mvc_CubeBitInsert( pCubeCopy, iValue0 );
+ else
+ Mvc_CubeBitRemove( pCubeCopy, iValue0 );
+
+ if ( Value1 )
+ Mvc_CubeBitInsert( pCubeCopy, iValue1 );
+ else
+ Mvc_CubeBitRemove( pCubeCopy, iValue1 );
+ }
+ return pCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the cover derived by universal quantification.]
+
+ Description [Returns the cover computed by universal quantification
+ as follows: CoverNew = Univ(B) [Cover & (A==B)]. Removes the second
+ binary var from the support (given by values iValueB0 and iValueB1).
+ Leaves the first binary variable (given by values iValueA0 and iValueA1)
+ in the support.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverUnivQuantify( Mvc_Cover_t * p,
+ int iValueA0, int iValueA1, int iValueB0, int iValueB1 )
+{
+ Mvc_Cover_t * pCover;
+ Mvc_Cube_t * pCube, * pCubeCopy;
+ int ValueA0, ValueA1, ValueB0, ValueB1;
+
+ // clone the cover
+ pCover = Mvc_CoverClone( p );
+ // copy the cube list
+ Mvc_CoverForEachCube( p, pCube )
+ {
+ // get the bits
+ ValueA0 = Mvc_CubeBitValue( pCube, iValueA0 );
+ ValueA1 = Mvc_CubeBitValue( pCube, iValueA1 );
+ ValueB0 = Mvc_CubeBitValue( pCube, iValueB0 );
+ ValueB1 = Mvc_CubeBitValue( pCube, iValueB1 );
+
+ // cannot be both zero because they belong to the same var
+ assert( ValueA0 || ValueA1 );
+ assert( ValueB0 || ValueB1 );
+
+ // if the values of this var are different, do not add the cube
+ if ( ValueA0 != ValueB0 && ValueA1 != ValueB1 )
+ continue;
+
+ // create the cube
+ pCubeCopy = Mvc_CubeDup( pCover, pCube );
+ Mvc_CoverAddCubeTail( pCover, pCubeCopy );
+
+ // insert 1's into for the first var, if both have this value
+ if ( ValueA0 && ValueB0 )
+ Mvc_CubeBitInsert( pCubeCopy, iValueA0 );
+ else
+ Mvc_CubeBitRemove( pCubeCopy, iValueA0 );
+
+ if ( ValueA1 && ValueB1 )
+ Mvc_CubeBitInsert( pCubeCopy, iValueA1 );
+ else
+ Mvc_CubeBitRemove( pCubeCopy, iValueA1 );
+
+ // insert 1's into for the second var (the cover does not depend on it)
+ Mvc_CubeBitInsert( pCubeCopy, iValueB0 );
+ Mvc_CubeBitInsert( pCubeCopy, iValueB1 );
+ }
+ return pCover;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+ Synopsis [Derives the cofactors of the cover.]
+
+ Description [Derives the cofactors w.r.t. a variable and also cubes
+ that do not depend on this variable.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t ** Mvc_CoverCofactors( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar )
+{
+ Mvc_Cover_t ** ppCofs;
+ Mvc_Cube_t * pCube, * pCubeNew;
+ int i, nValues, iValueFirst, Res;
+
+ // start the covers for cofactors
+ iValueFirst = Vm_VarMapReadValuesFirst(pData->pVm, iVar);
+ nValues = Vm_VarMapReadValues(pData->pVm, iVar);
+ ppCofs = ALLOC( Mvc_Cover_t *, nValues + 1 );
+ for ( i = 0; i <= nValues; i++ )
+ ppCofs[i] = Mvc_CoverClone( pCover );
+
+ // go through the cubes
+ Mvc_CoverForEachCube( pCover, pCube )
+ {
+ // if the literal if a full literal, add it to last "cofactor"
+ Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] );
+ if ( Res )
+ {
+ pCubeNew = Mvc_CubeDup(pCover, pCube);
+ Mvc_CoverAddCubeTail( ppCofs[nValues], pCubeNew );
+ continue;
+ }
+
+ // otherwise, add it to separate values
+ for ( i = 0; i < nValues; i++ )
+ if ( Mvc_CubeBitValue( pCube, iValueFirst + i ) )
+ {
+ pCubeNew = Mvc_CubeDup(pCover, pCube);
+ Mvc_CubeBitOr( pCubeNew, pCubeNew, pData->ppMasks[iVar] );
+ Mvc_CoverAddCubeTail( ppCofs[i], pCubeNew );
+ }
+ }
+ return ppCofs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the cubes with non-trivial literals with the given value.]
+
+ Description [The data and the cover are given (pData, pCover). Also given
+ are the variable number and the number of a value of this variable.
+ This procedure returns the number of cubes having a non-trivial literal
+ of this variable that have the given value present.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue )
+{
+ Mvc_Cube_t * pCube;
+ int iValueFirst, Res, Counter;
+
+ Counter = 0;
+ iValueFirst = Vm_VarMapReadValuesFirst( pData->pVm, iVar );
+ Mvc_CoverForEachCube( pCover, pCube )
+ {
+ // check if the given literal is the full literal
+ Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] );
+ if ( Res )
+ continue;
+ // this literal is not a full literal; check if it has this value
+ Counter += Mvc_CubeBitValue( pCube, iValueFirst + iValue );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the expanded cover.]
+
+ Description [The original cover is expanded by adding some variables.
+ These variables are the additional variables in pVmNew, compared to
+ pCvr->pVm. The resulting cover is the same as the original one, except
+ that it contains the additional variables present as full literals
+ in every cube.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew )
+{
+ Mvc_Cover_t * pCoverNew;
+ Mvc_Cube_t * pCube, * pCubeNew;
+ int i, iLast, iLastNew;
+
+ // create the new cover
+ pCoverNew = Mvc_CoverAlloc( pCover->pMem, Vm_VarMapReadValuesInNum(pVmNew) );
+
+ // get the cube composed of extra bits
+ Mvc_CoverAllocateMask( pCoverNew );
+ Mvc_CubeBitClean( pCoverNew->pMask );
+ for ( i = pCover->nBits; i < pCoverNew->nBits; i++ )
+ Mvc_CubeBitInsert( pCoverNew->pMask, i );
+
+ // get the indexes of the last words in both covers
+ iLast = pCover->nWords? pCover->nWords - 1: 0;
+ iLastNew = pCoverNew->nWords? pCoverNew->nWords - 1: 0;
+
+ // create the cubes of the new cover
+ Mvc_CoverForEachCube( pCover, pCube )
+ {
+ pCubeNew = Mvc_CubeAlloc( pCoverNew );
+ Mvc_CubeBitClean( pCubeNew );
+ // copy the bits (cannot immediately use Mvc_CubeBitCopy,
+ // because covers have different numbers of bits)
+ Mvc_CubeSetLast( pCubeNew, iLast );
+ Mvc_CubeBitCopy( pCubeNew, pCube );
+ Mvc_CubeSetLast( pCubeNew, iLastNew );
+ // add the extra bits
+ Mvc_CubeBitOr( pCubeNew, pCubeNew, pCoverNew->pMask );
+ // add the cube to the new cover
+ Mvc_CoverAddCubeTail( pCoverNew, pCubeNew );
+ }
+ return pCoverNew;
+}
+
+#endif
+
+/**Function*************************************************************
+
+ Synopsis [Transposes the cube cover.]
+
+ Description [Returns the cube cover that looks like a transposed
+ matrix, compared to the matrix derived from the original cover.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover )
+{
+ Mvc_Cover_t * pRes;
+ Mvc_Cube_t * pCubeRes, * pCube;
+ int nWord, nBit, i, iCube;
+
+ pRes = Mvc_CoverAlloc( pCover->pMem, Mvc_CoverReadCubeNum(pCover) );
+ for ( i = 0; i < pCover->nBits; i++ )
+ {
+ // get the word and bit of this literal
+ nWord = Mvc_CubeWhichWord(i);
+ nBit = Mvc_CubeWhichBit(i);
+ // get the transposed cube
+ pCubeRes = Mvc_CubeAlloc( pRes );
+ Mvc_CubeBitClean( pCubeRes );
+ iCube = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ {
+ if ( pCube->pData[nWord] & (1<<nBit) )
+ Mvc_CubeBitInsert( pCubeRes, iCube );
+ iCube++;
+ }
+ Mvc_CoverAddCubeTail( pRes, pCubeRes );
+ }
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks that the cubes of the cover have 0's in unused bits.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mvc_UtilsCheckUnusedZeros( Mvc_Cover_t * pCover )
+{
+ unsigned Unsigned;
+ Mvc_Cube_t * pCube;
+ int nCubes;
+
+ nCubes = 0;
+ Mvc_CoverForEachCube( pCover, pCube )
+ {
+ if ( pCube->nUnused == 0 )
+ continue;
+
+ Unsigned = ( pCube->pData[pCube->iLast] &
+ (BITS_FULL << (32-pCube->nUnused)) );
+ if( Unsigned )
+ {
+ printf( "Cube %2d out of %2d contains dirty bits.\n", nCubes,
+ Mvc_CoverReadCubeNum(pCover) );
+ }
+ nCubes++;
+ }
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/nm/module.make b/src/misc/nm/module.make
new file mode 100644
index 00000000..2a3820c7
--- /dev/null
+++ b/src/misc/nm/module.make
@@ -0,0 +1,2 @@
+SRC += src/misc/nm/nmApi.c \
+ src/misc/nm/nmTable.c
diff --git a/src/misc/nm/nm.h b/src/misc/nm/nm.h
new file mode 100644
index 00000000..c6344bbf
--- /dev/null
+++ b/src/misc/nm/nm.h
@@ -0,0 +1,92 @@
+/**CFilextern e****************************************************************
+
+ FileName [nm.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __NM_H__
+#define __NM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ This manager is designed to store ID-to-name and name-to-ID mapping
+ for Boolean networks and And-Inverter Graphs.
+
+ In a netlist, net names are unique. In this case, there is a one-to-one
+ mapping between IDs and names.
+
+ In a logic network, which do not have nets, several objects may have
+ the same name. For example, a latch output and a primary output.
+ Another example, a primary input and an input to a black box.
+ In this case, for each ID on an object there is only one name,
+ but for each name may be several IDs of objects having this name.
+
+ The name manager maps ID-to-name uniquely but it allows one name to
+ be mapped into several IDs. When a query to find an ID of the object
+ by its name is submitted, it is possible to specify the object type,
+ which will help select one of several IDs. If the type is -1, and
+ there is more than one object with the given name, any object with
+ the given name is returned.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Nm_Man_t_ Nm_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nmApi.c ==========================================================*/
+extern Nm_Man_t * Nm_ManCreate( int nSize );
+extern void Nm_ManFree( Nm_Man_t * p );
+extern int Nm_ManNumEntries( Nm_Man_t * p );
+extern char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix );
+extern void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId );
+extern char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId );
+extern char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId );
+extern int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type );
+extern int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 );
+extern Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/nm/nmApi.c b/src/misc/nm/nmApi.c
new file mode 100644
index 00000000..9165922f
--- /dev/null
+++ b/src/misc/nm/nmApi.c
@@ -0,0 +1,272 @@
+/**CFile****************************************************************
+
+ FileName [nmApi.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [APIs of the name manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nmApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nmInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the name manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Nm_Man_t * Nm_ManCreate( int nSize )
+{
+ Nm_Man_t * p;
+ // allocate the table
+ p = ALLOC( Nm_Man_t, 1 );
+ memset( p, 0, sizeof(Nm_Man_t) );
+ // set the parameters
+ p->nSizeFactor = 2; // determined the limit on the grow of data before the table resizes
+ p->nGrowthFactor = 3; // determined how much the table grows after resizing
+ // allocate and clean the bins
+ p->nBins = Cudd_PrimeNm(nSize);
+ p->pBinsI2N = ALLOC( Nm_Entry_t *, p->nBins );
+ p->pBinsN2I = ALLOC( Nm_Entry_t *, p->nBins );
+ memset( p->pBinsI2N, 0, sizeof(Nm_Entry_t *) * p->nBins );
+ memset( p->pBinsN2I, 0, sizeof(Nm_Entry_t *) * p->nBins );
+ // start the memory manager
+ p->pMem = Extra_MmFlexStart();
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the name manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManFree( Nm_Man_t * p )
+{
+ Extra_MmFlexStop( p->pMem );
+ FREE( p->pBinsI2N );
+ FREE( p->pBinsN2I );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of objects with names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManNumEntries( Nm_Man_t * p )
+{
+ return p->nEntries;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new entry in the name manager.]
+
+ Description [Returns 1 if the entry with the given object ID
+ already exists in the name manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix )
+{
+ Nm_Entry_t * pEntry;
+ int RetValue, nEntrySize;
+ // check if the object with this ID is already stored
+ if ( pEntry = Nm_ManTableLookupId(p, ObjId) )
+ {
+ printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" );
+ return NULL;
+ }
+ // create a new entry
+ nEntrySize = sizeof(Nm_Entry_t) + strlen(pName) + (pSuffix?strlen(pSuffix):0) + 1;
+ nEntrySize = (nEntrySize / 4 + ((nEntrySize % 4) > 0)) * 4;
+ pEntry = (Nm_Entry_t *)Extra_MmFlexEntryFetch( p->pMem, nEntrySize );
+ pEntry->pNextI2N = pEntry->pNextN2I = pEntry->pNameSake = NULL;
+ pEntry->ObjId = ObjId;
+ pEntry->Type = Type;
+ sprintf( pEntry->Name, "%s%s", pName, pSuffix? pSuffix : "" );
+ // add the entry to the hash table
+ RetValue = Nm_ManTableAdd( p, pEntry );
+ assert( RetValue == 1 );
+ return pEntry->Name;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new entry in the name manager.]
+
+ Description [Returns 1 if the entry with the given object ID
+ already exists in the name manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t * pEntry;
+ pEntry = Nm_ManTableLookupId(p, ObjId);
+ if ( pEntry == NULL )
+ {
+ printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" );
+ return;
+ }
+ // remove entry from the table
+ Nm_ManTableDelete( p, ObjId );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds a unique name for the node.]
+
+ Description [If the name exists, tries appending numbers to it until
+ it becomes unique. The name is not added to the table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId )
+{
+ static char NameStr[1000];
+ Nm_Entry_t * pEntry;
+ int i;
+ if ( pEntry = Nm_ManTableLookupId(p, ObjId) )
+ return pEntry->Name;
+ sprintf( NameStr, "n%d", ObjId );
+ for ( i = 1; Nm_ManTableLookupName(p, NameStr, -1); i++ )
+ sprintf( NameStr, "n%d_%d", ObjId, i );
+ return NameStr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns name of the object if the ID is known.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t * pEntry;
+ if ( pEntry = Nm_ManTableLookupId(p, ObjId) )
+ return pEntry->Name;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns ID of the object if its name is known.]
+
+ Description [This procedure may return two IDs because POs and latches
+ may have the same name (the only allowed case of name duplication).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type )
+{
+ Nm_Entry_t * pEntry;
+ if ( pEntry = Nm_ManTableLookupName(p, pName, Type) )
+ return pEntry->ObjId;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns ID of the object if its name is known.]
+
+ Description [This procedure may return two IDs because POs and latches
+ may have the same name (the only allowed case of name duplication).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 )
+{
+ int iNodeId;
+ iNodeId = Nm_ManFindIdByName( p, pName, Type1 );
+ if ( iNodeId == -1 )
+ iNodeId = Nm_ManFindIdByName( p, pName, Type2 );
+ if ( iNodeId == -1 )
+ return -1;
+ return iNodeId;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return the IDs of objects with names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p )
+{
+ Vec_Int_t * vNameIds;
+ int i;
+ vNameIds = Vec_IntAlloc( p->nEntries );
+ for ( i = 0; i < p->nBins; i++ )
+ if ( p->pBinsI2N[i] )
+ Vec_IntPush( vNameIds, p->pBinsI2N[i]->ObjId );
+ return vNameIds;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/nm/nmInt.h b/src/misc/nm/nmInt.h
new file mode 100644
index 00000000..028316e1
--- /dev/null
+++ b/src/misc/nm/nmInt.h
@@ -0,0 +1,91 @@
+/**CFile****************************************************************
+
+ FileName [nmInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nmInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __NM_INT_H__
+#define __NM_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "extra.h"
+#include "vec.h"
+#include "nm.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Nm_Entry_t_ Nm_Entry_t;
+struct Nm_Entry_t_
+{
+ unsigned Type : 4; // object type
+ unsigned ObjId : 28; // object ID
+ Nm_Entry_t * pNextI2N; // the next entry in the ID hash table
+ Nm_Entry_t * pNextN2I; // the next entry in the name hash table
+ Nm_Entry_t * pNameSake; // the next entry with the same name
+ char Name[0]; // name of the object
+};
+
+struct Nm_Man_t_
+{
+ Nm_Entry_t ** pBinsI2N; // mapping IDs into names
+ Nm_Entry_t ** pBinsN2I; // mapping names into IDs
+ int nBins; // the number of bins in tables
+ int nEntries; // the number of entries
+ int nSizeFactor; // determined how much larger the table should be
+ int nGrowthFactor; // determined how much the table grows after resizing
+ Extra_MmFlex_t * pMem; // memory manager for entries (and names)
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nmTable.c ==========================================================*/
+extern int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry );
+extern int Nm_ManTableDelete( Nm_Man_t * p, int ObjId );
+extern Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId );
+extern Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type );
+extern unsigned int Cudd_PrimeNm( unsigned int p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/nm/nmTable.c b/src/misc/nm/nmTable.c
new file mode 100644
index 00000000..f97a2f0b
--- /dev/null
+++ b/src/misc/nm/nmTable.c
@@ -0,0 +1,340 @@
+/**CFile****************************************************************
+
+ FileName [nmTable.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [Hash table for the name manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nmTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nmInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing for integers
+static unsigned Nm_HashNumber( int Num, int TableSize )
+{
+ unsigned Key = 0;
+ Key ^= ( Num & 0xFF) * 7937;
+ Key ^= ((Num >> 8) & 0xFF) * 2971;
+ Key ^= ((Num >> 16) & 0xFF) * 911;
+ Key ^= ((Num >> 24) & 0xFF) * 353;
+ return Key % TableSize;
+}
+
+// hashing for strings
+static unsigned Nm_HashString( char * pName, int TableSize )
+{
+ static int s_Primes[10] = {
+ 1291, 1699, 2357, 4177, 5147,
+ 5647, 6343, 7103, 7873, 8147
+ };
+ unsigned i, Key = 0;
+ for ( i = 0; pName[i] != '\0'; i++ )
+ Key ^= s_Primes[i%10]*pName[i]*pName[i];
+ return Key % TableSize;
+}
+
+static void Nm_ManResize( Nm_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds an entry to two hash tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry )
+{
+ Nm_Entry_t ** ppSpot, * pOther;
+ // resize the tables if needed
+ if ( p->nEntries > p->nBins * p->nSizeFactor )
+ Nm_ManResize( p );
+ // add the entry to the table Id->Name
+ assert( Nm_ManTableLookupId(p, pEntry->ObjId) == NULL );
+ ppSpot = p->pBinsI2N + Nm_HashNumber(pEntry->ObjId, p->nBins);
+ pEntry->pNextI2N = *ppSpot;
+ *ppSpot = pEntry;
+ // check if an entry with the same name already exists
+ if ( pOther = Nm_ManTableLookupName(p, pEntry->Name, -1) )
+ {
+ // entry with the same name already exists - add it to the ring
+ pEntry->pNameSake = pOther->pNameSake? pOther->pNameSake : pOther;
+ pOther->pNameSake = pEntry;
+ }
+ else
+ {
+ // entry with the same name does not exist - add it to the table
+ ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins);
+ pEntry->pNextN2I = *ppSpot;
+ *ppSpot = pEntry;
+ }
+ // report successfully added entry
+ p->nEntries++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the entry from two hash tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManTableDelete( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t ** ppSpot, * pEntry, * pPrev;
+ int fRemoved;
+ p->nEntries--;
+ // remove the entry from the table Id->Name
+ assert( Nm_ManTableLookupId(p, ObjId) != NULL );
+ ppSpot = p->pBinsI2N + Nm_HashNumber(ObjId, p->nBins);
+ while ( (*ppSpot)->ObjId != (unsigned)ObjId )
+ ppSpot = &(*ppSpot)->pNextI2N;
+ pEntry = *ppSpot;
+ *ppSpot = (*ppSpot)->pNextI2N;
+ // remove the entry from the table Name->Id
+ ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins);
+ while ( *ppSpot && *ppSpot != pEntry )
+ ppSpot = &(*ppSpot)->pNextN2I;
+ // remember if we found this one in the list
+ fRemoved = (*ppSpot != NULL);
+ if ( *ppSpot )
+ {
+ assert( *ppSpot == pEntry );
+ *ppSpot = (*ppSpot)->pNextN2I;
+ }
+ // quit if this entry has no namesakes
+ if ( pEntry->pNameSake == NULL )
+ {
+ assert( fRemoved );
+ return 1;
+ }
+ // remove entry from the ring of namesakes
+ assert( pEntry->pNameSake != pEntry );
+ for ( pPrev = pEntry; pPrev->pNameSake != pEntry; pPrev = pPrev->pNameSake );
+ assert( !strcmp(pPrev->Name, pEntry->Name) );
+ assert( pPrev->pNameSake == pEntry );
+ if ( pEntry->pNameSake == pPrev ) // two entries in the ring
+ pPrev->pNameSake = NULL;
+ else
+ pPrev->pNameSake = pEntry->pNameSake;
+ // reinsert the ring back if we removed its connection with the list in the table
+ if ( fRemoved )
+ {
+ assert( pPrev->pNextN2I == NULL );
+ pPrev->pNextN2I = *ppSpot;
+ *ppSpot = pPrev;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the entry by ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t * pEntry;
+ for ( pEntry = p->pBinsI2N[ Nm_HashNumber(ObjId, p->nBins) ]; pEntry; pEntry = pEntry->pNextI2N )
+ if ( pEntry->ObjId == (unsigned)ObjId )
+ return pEntry;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the entry by name and type.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type )
+{
+ Nm_Entry_t * pEntry, * pTemp;
+ int Counter = 0;
+ for ( pEntry = p->pBinsN2I[ Nm_HashString(pName, p->nBins) ]; pEntry; pEntry = pEntry->pNextN2I )
+ {
+ // check the entry itself
+ if ( !strcmp(pEntry->Name, pName) && (Type == -1 || pEntry->Type == (unsigned)Type) )
+ return pEntry;
+ // if there is no namesakes, continue
+ if ( pEntry->pNameSake == NULL )
+ continue;
+ // check the list of namesakes
+ for ( pTemp = pEntry->pNameSake; pTemp != pEntry; pTemp = pTemp->pNameSake )
+ if ( !strcmp(pTemp->Name, pName) && (Type == -1 || pTemp->Type == (unsigned)Type) )
+ return pTemp;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Profiles hash tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManProfile( Nm_Man_t * p )
+{
+ Nm_Entry_t * pEntry;
+ int Counter, e;
+ printf( "I2N table: " );
+ for ( e = 0; e < p->nBins; e++ )
+ {
+ Counter = 0;
+ for ( pEntry = p->pBinsI2N[e]; pEntry; pEntry = pEntry->pNextI2N )
+ Counter++;
+ printf( "%d ", Counter );
+ }
+ printf( "\n" );
+ printf( "N2I table: " );
+ for ( e = 0; e < p->nBins; e++ )
+ {
+ Counter = 0;
+ for ( pEntry = p->pBinsN2I[e]; pEntry; pEntry = pEntry->pNextN2I )
+ Counter++;
+ printf( "%d ", Counter );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManResize( Nm_Man_t * p )
+{
+ Nm_Entry_t ** pBinsNewI2N, ** pBinsNewN2I, * pEntry, * pEntry2, ** ppSpot;
+ int nBinsNew, Counter, e, clk;
+
+clk = clock();
+ // get the new table size
+ nBinsNew = Cudd_PrimeCopy( p->nGrowthFactor * p->nBins );
+ // allocate a new array
+ pBinsNewI2N = ALLOC( Nm_Entry_t *, nBinsNew );
+ pBinsNewN2I = ALLOC( Nm_Entry_t *, nBinsNew );
+ memset( pBinsNewI2N, 0, sizeof(Nm_Entry_t *) * nBinsNew );
+ memset( pBinsNewN2I, 0, sizeof(Nm_Entry_t *) * nBinsNew );
+ // rehash entries in Id->Name table
+ Counter = 0;
+ for ( e = 0; e < p->nBins; e++ )
+ for ( pEntry = p->pBinsI2N[e], pEntry2 = pEntry? pEntry->pNextI2N : NULL;
+ pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextI2N : NULL )
+ {
+ ppSpot = pBinsNewI2N + Nm_HashNumber(pEntry->ObjId, nBinsNew);
+ pEntry->pNextI2N = *ppSpot;
+ *ppSpot = pEntry;
+ Counter++;
+ }
+ // rehash entries in Name->Id table
+ for ( e = 0; e < p->nBins; e++ )
+ for ( pEntry = p->pBinsN2I[e], pEntry2 = pEntry? pEntry->pNextN2I : NULL;
+ pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextN2I : NULL )
+ {
+ ppSpot = pBinsNewN2I + Nm_HashString(pEntry->Name, nBinsNew);
+ pEntry->pNextN2I = *ppSpot;
+ *ppSpot = pEntry;
+ }
+ assert( Counter == p->nEntries );
+// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew );
+// PRT( "Time", clock() - clk );
+ // replace the table and the parameters
+ free( p->pBinsI2N );
+ free( p->pBinsN2I );
+ p->pBinsI2N = pBinsNewI2N;
+ p->pBinsN2I = pBinsNewN2I;
+ p->nBins = nBinsNew;
+// Nm_ManProfile( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the smallest prime larger than the number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned int Cudd_PrimeNm( 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 */
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/st/module.make b/src/misc/st/module.make
new file mode 100644
index 00000000..33e442c0
--- /dev/null
+++ b/src/misc/st/module.make
@@ -0,0 +1,2 @@
+SRC += src/misc/st/st.c \
+ src/misc/st/stmm.c
diff --git a/src/misc/st/st.c b/src/misc/st/st.c
new file mode 100644
index 00000000..872fe51b
--- /dev/null
+++ b/src/misc/st/st.c
@@ -0,0 +1,625 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.c,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:13
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "st.h"
+
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef ALLOC
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#endif
+
+#ifndef FREE
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#endif
+
+#ifndef REALLOC
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+#endif
+
+#define ST_NUMCMP(x,y) ((x) != (y))
+#define ST_NUMHASH(x,size) (ABS((long)x)%(size))
+//#define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007
+#define ST_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%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)\
+ ((table->hash == st_ptrhash) ? ST_PTRHASH((key),(table)->num_bins) :\
+ (table->hash == st_numhash) ? ST_NUMHASH((key), (table)->num_bins) :\
+ (*table->hash)((key), (table)->num_bins))
+
+static int rehash();
+int st_numhash(), st_ptrhash(), st_numcmp(), st_ptrcmp();
+
+st_table *
+st_init_table_with_params(compare, hash, size, density, grow_factor,
+ reorder_flag)
+int (*compare)();
+int (*hash)();
+int size;
+int density;
+double grow_factor;
+int reorder_flag;
+{
+ int i;
+ st_table *new;
+
+ new = ALLOC(st_table, 1);
+ if (new == NULL) {
+ return NULL;
+ }
+ new->compare = compare;
+ new->hash = hash;
+ new->num_entries = 0;
+ new->max_density = density;
+ new->grow_factor = grow_factor;
+ new->reorder_flag = reorder_flag;
+ if (size <= 0) {
+ size = 1;
+ }
+ new->num_bins = size;
+ new->bins = ALLOC(st_table_entry *, size);
+ if (new->bins == NULL) {
+ FREE(new);
+ return NULL;
+ }
+ for(i = 0; i < size; i++) {
+ new->bins[i] = 0;
+ }
+ return new;
+}
+
+st_table *
+st_init_table(compare, hash)
+int (*compare)();
+int (*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);
+}
+
+void
+st_free_table(table)
+st_table *table;
+{
+ register st_table_entry *ptr, *next;
+ int i;
+
+ for(i = 0; i < table->num_bins ; i++) {
+ ptr = table->bins[i];
+ while (ptr != NULL) {
+ next = ptr->next;
+ FREE(ptr);
+ ptr = next;
+ }
+ }
+ FREE(table->bins);
+ FREE(table);
+}
+
+#define PTR_NOT_EQUAL(table, ptr, user_key)\
+(ptr != NULL && !EQUAL(table->compare, 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) != NULL && (table)->reorder_flag) {\
+ *(last) = (ptr)->next;\
+ (ptr)->next = (table)->bins[hash_val];\
+ (table)->bins[hash_val] = (ptr);\
+ }
+
+int
+st_lookup(table, key, value)
+st_table *table;
+register char *key;
+char **value;
+{
+ int hash_val;
+ register st_table_entry *ptr, **last;
+
+ hash_val = do_hash(key, table);
+
+ FIND_ENTRY(table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ return 0;
+ } else {
+ if (value != NULL) {
+ *value = ptr->record;
+ }
+ return 1;
+ }
+}
+
+int
+st_lookup_int(table, key, value)
+st_table *table;
+register char *key;
+int *value;
+{
+ int hash_val;
+ register st_table_entry *ptr, **last;
+
+ hash_val = do_hash(key, table);
+
+ FIND_ENTRY(table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ return 0;
+ } else {
+ if (value != 0) {
+ *value = (long) ptr->record;
+ }
+ return 1;
+ }
+}
+
+/* This macro does not check if memory allocation fails. Use at you own risk */
+#define ADD_DIRECT(table, key, value, hash_val, new)\
+{\
+ if (table->num_entries/table->num_bins >= table->max_density) {\
+ rehash(table);\
+ hash_val = do_hash(key,table);\
+ }\
+ \
+ new = ALLOC(st_table_entry, 1);\
+ \
+ new->key = key;\
+ new->record = value;\
+ new->next = table->bins[hash_val];\
+ table->bins[hash_val] = new;\
+ table->num_entries++;\
+}
+
+int
+st_insert(table, key, value)
+register st_table *table;
+register char *key;
+char *value;
+{
+ int hash_val;
+ st_table_entry *new;
+ register st_table_entry *ptr, **last;
+
+ hash_val = do_hash(key, table);
+
+ FIND_ENTRY(table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ 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);
+ }
+ new = ALLOC(st_table_entry, 1);
+ if (new == NULL) {
+ return ST_OUT_OF_MEM;
+ }
+ new->key = key;
+ new->record = value;
+ new->next = table->bins[hash_val];
+ table->bins[hash_val] = new;
+ table->num_entries++;
+ return 0;
+ } else {
+ ptr->record = value;
+ return 1;
+ }
+}
+
+int
+st_add_direct(table, key, value)
+st_table *table;
+char *key;
+char *value;
+{
+ int hash_val;
+ st_table_entry *new;
+
+ 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);
+ new = ALLOC(st_table_entry, 1);
+ if (new == NULL) {
+ return ST_OUT_OF_MEM;
+ }
+ new->key = key;
+ new->record = value;
+ new->next = table->bins[hash_val];
+ table->bins[hash_val] = new;
+ table->num_entries++;
+ return 1;
+}
+
+int
+st_find_or_add(table, key, slot)
+st_table *table;
+char *key;
+char ***slot;
+{
+ int hash_val;
+ st_table_entry *new, *ptr, **last;
+
+ hash_val = do_hash(key, table);
+
+ FIND_ENTRY(table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ 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);
+ }
+ new = ALLOC(st_table_entry, 1);
+ if (new == NULL) {
+ return ST_OUT_OF_MEM;
+ }
+ new->key = key;
+ new->record = (char *) 0;
+ new->next = table->bins[hash_val];
+ table->bins[hash_val] = new;
+ table->num_entries++;
+ if (slot != NULL) *slot = &new->record;
+ return 0;
+ } else {
+ if (slot != NULL) *slot = &ptr->record;
+ return 1;
+ }
+}
+
+int
+st_find(table, key, slot)
+st_table *table;
+char *key;
+char ***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 == NULL) {
+ return 0;
+ } else {
+ if (slot != NULL) {
+ *slot = &ptr->record;
+ }
+ return 1;
+ }
+}
+
+static int
+rehash(table)
+register st_table *table;
+{
+ register 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 == NULL) {
+ 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 != NULL) {
+ 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;
+}
+
+st_table *
+st_copy(old_table)
+st_table *old_table;
+{
+ st_table *new_table;
+ st_table_entry *ptr, *newptr, *next, *new;
+ int i, j, num_bins = old_table->num_bins;
+
+ new_table = ALLOC(st_table, 1);
+ if (new_table == NULL) {
+ return NULL;
+ }
+
+ *new_table = *old_table;
+ new_table->bins = ALLOC(st_table_entry *, num_bins);
+ if (new_table->bins == NULL) {
+ FREE(new_table);
+ return NULL;
+ }
+ for(i = 0; i < num_bins ; i++) {
+ new_table->bins[i] = NULL;
+ ptr = old_table->bins[i];
+ while (ptr != NULL) {
+ new = ALLOC(st_table_entry, 1);
+ if (new == NULL) {
+ for (j = 0; j <= i; j++) {
+ newptr = new_table->bins[j];
+ while (newptr != NULL) {
+ next = newptr->next;
+ FREE(newptr);
+ newptr = next;
+ }
+ }
+ FREE(new_table->bins);
+ FREE(new_table);
+ return NULL;
+ }
+ *new = *ptr;
+ new->next = new_table->bins[i];
+ new_table->bins[i] = new;
+ ptr = ptr->next;
+ }
+ }
+ return new_table;
+}
+
+int
+st_delete(table, keyp, value)
+register st_table *table;
+register char **keyp;
+char **value;
+{
+ int hash_val;
+ char *key = *keyp;
+ register st_table_entry *ptr, **last;
+
+ hash_val = do_hash(key, table);
+
+ FIND_ENTRY(table, hash_val, key, ptr ,last);
+
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ *last = ptr->next;
+ if (value != NULL) *value = ptr->record;
+ *keyp = ptr->key;
+ FREE(ptr);
+ table->num_entries--;
+ return 1;
+}
+
+int
+st_delete_int(table, keyp, value)
+register st_table *table;
+register long *keyp;
+char **value;
+{
+ int hash_val;
+ char *key = (char *) *keyp;
+ register st_table_entry *ptr, **last;
+
+ hash_val = do_hash(key, table);
+
+ FIND_ENTRY(table, hash_val, key, ptr ,last);
+
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ *last = ptr->next;
+ if (value != NULL) *value = ptr->record;
+ *keyp = (long) ptr->key;
+ FREE(ptr);
+ table->num_entries--;
+ return 1;
+}
+
+int
+st_foreach(table, func, arg)
+st_table *table;
+enum st_retval (*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 != NULL) {
+ 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;
+}
+
+int
+st_strhash(string, modulus)
+register char *string;
+int modulus;
+{
+ register int val = 0;
+ register int c;
+
+ while ((c = *string++) != '\0') {
+ val = val*997 + c;
+ }
+
+ return ((val < 0) ? -val : val)%modulus;
+}
+
+int
+st_numhash(x, size)
+char *x;
+int size;
+{
+ return ST_NUMHASH(x, size);
+}
+
+int
+st_ptrhash(x, size)
+char *x;
+int size;
+{
+ return ST_PTRHASH(x, size);
+}
+
+int
+st_numcmp(x, y)
+char *x;
+char *y;
+{
+ return ST_NUMCMP(x, y);
+}
+
+int
+st_ptrcmp(x, y)
+char *x;
+char *y;
+{
+ return ST_NUMCMP(x, y);
+}
+
+st_generator *
+st_init_gen(table)
+st_table *table;
+{
+ st_generator *gen;
+
+ gen = ALLOC(st_generator, 1);
+ if (gen == NULL) {
+ return NULL;
+ }
+ gen->table = table;
+ gen->entry = NULL;
+ gen->index = 0;
+ return gen;
+}
+
+
+int
+st_gen(gen, key_p, value_p)
+st_generator *gen;
+char **key_p;
+char **value_p;
+{
+ register int i;
+
+ if (gen->entry == NULL) {
+ /* try to find next entry */
+ for(i = gen->index; i < gen->table->num_bins; i++) {
+ if (gen->table->bins[i] != NULL) {
+ gen->index = i+1;
+ gen->entry = gen->table->bins[i];
+ break;
+ }
+ }
+ if (gen->entry == NULL) {
+ return 0; /* that's all folks ! */
+ }
+ }
+ *key_p = gen->entry->key;
+ if (value_p != 0) {
+ *value_p = gen->entry->record;
+ }
+ gen->entry = gen->entry->next;
+ return 1;
+}
+
+
+int
+st_gen_int(gen, key_p, value_p)
+st_generator *gen;
+char **key_p;
+long *value_p;
+{
+ register int i;
+
+ if (gen->entry == NULL) {
+ /* try to find next entry */
+ for(i = gen->index; i < gen->table->num_bins; i++) {
+ if (gen->table->bins[i] != NULL) {
+ gen->index = i+1;
+ gen->entry = gen->table->bins[i];
+ break;
+ }
+ }
+ if (gen->entry == NULL) {
+ return 0; /* that's all folks ! */
+ }
+ }
+ *key_p = gen->entry->key;
+ if (value_p != 0) {
+ *value_p = (long) gen->entry->record;
+ }
+ gen->entry = gen->entry->next;
+ return 1;
+}
+
+
+void
+st_free_gen(gen)
+st_generator *gen;
+{
+ FREE(gen);
+}
diff --git a/src/misc/st/st.h b/src/misc/st/st.h
new file mode 100644
index 00000000..b15f3c83
--- /dev/null
+++ b/src/misc/st/st.h
@@ -0,0 +1,96 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.h,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:21
+ *
+ */
+/* LINTLIBRARY */
+
+/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */
+
+#ifndef ST_INCLUDED
+#define ST_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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)();
+ int (*hash)();
+ 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;
+};
+
+#define st_is_member(table,key) st_lookup(table,key,(char **) 0)
+#define st_count(table) ((table)->num_entries)
+
+enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
+
+typedef enum st_retval (*ST_PFSR)();
+typedef int (*ST_PFI)();
+
+extern st_table *st_init_table_with_params (ST_PFI, ST_PFI, int, int, double, int);
+extern st_table *st_init_table (ST_PFI, ST_PFI);
+extern void st_free_table (st_table *);
+extern int st_lookup (st_table *, char *, char **);
+extern int st_lookup_int (st_table *, char *, int *);
+extern int st_insert (st_table *, char *, char *);
+extern int st_add_direct (st_table *, char *, char *);
+extern int st_find_or_add (st_table *, char *, char ***);
+extern int st_find (st_table *, char *, char ***);
+extern st_table *st_copy (st_table *);
+extern int st_delete (st_table *, char **, char **);
+extern int st_delete_int (st_table *, long *, char **);
+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 (char *, char *);
+extern int st_ptrcmp (char *, char *);
+extern st_generator *st_init_gen (st_table *);
+extern int st_gen (st_generator *, char **, char **);
+extern int st_gen_int (st_generator *, char **, long *);
+extern void st_free_gen (st_generator *);
+
+
+#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_foreach_item(table, gen, key, value) \
+ for(gen=st_init_gen(table); st_gen(gen,key,value) || (st_free_gen(gen),0);)
+
+#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);)
+
+#define ST_OUT_OF_MEM -10000
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ST_INCLUDED */
diff --git a/src/misc/st/stmm.c b/src/misc/st/stmm.c
new file mode 100644
index 00000000..8dfacfe4
--- /dev/null
+++ b/src/misc/st/stmm.c
@@ -0,0 +1,688 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.c,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:13
+ *
+ */
+#include <stdio.h>
+#include "extra.h"
+#include "stmm.h"
+
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+#define STMM_NUMCMP(x,y) ((x) != (y))
+#define STMM_NUMHASH(x,size) (ABS((long)x)%(size))
+//#define STMM_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007
+#define STMM_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%size))
+#define EQUAL(func, x, y) \
+ ((((func) == stmm_numcmp) || ((func) == stmm_ptrcmp)) ?\
+ (STMM_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0))
+
+
+#define do_hash(key, table)\
+ ((table->hash == stmm_ptrhash) ? STMM_PTRHASH((key),(table)->num_bins) :\
+ (table->hash == stmm_numhash) ? STMM_NUMHASH((key), (table)->num_bins) :\
+ (*table->hash)((key), (table)->num_bins))
+
+static int rehash ();
+int stmm_numhash (), stmm_ptrhash (), stmm_numcmp (), stmm_ptrcmp ();
+
+stmm_table *
+stmm_init_table_with_params (compare, hash, size, density, grow_factor,
+ reorder_flag)
+ int (*compare) ();
+ int (*hash) ();
+ int size;
+ int density;
+ double grow_factor;
+ int reorder_flag;
+{
+ int i;
+ stmm_table *new;
+
+ new = ALLOC (stmm_table, 1);
+ if (new == NULL) {
+ return NULL;
+ }
+ new->compare = compare;
+ new->hash = hash;
+ new->num_entries = 0;
+ new->max_density = density;
+ new->grow_factor = grow_factor;
+ new->reorder_flag = reorder_flag;
+ if (size <= 0) {
+ size = 1;
+ }
+ new->num_bins = size;
+ new->bins = ALLOC (stmm_table_entry *, size);
+ if (new->bins == NULL) {
+ FREE (new);
+ return NULL;
+ }
+ for (i = 0; i < size; i++) {
+ new->bins[i] = 0;
+ }
+
+ // added by alanmi
+ new->pMemMan = Extra_MmFixedStart(sizeof (stmm_table_entry));
+ return new;
+}
+
+stmm_table *
+stmm_init_table (compare, hash)
+ int (*compare) ();
+ int (*hash) ();
+{
+ return stmm_init_table_with_params (compare, hash,
+ STMM_DEFAULT_INIT_TABLE_SIZE,
+ STMM_DEFAULT_MAX_DENSITY,
+ STMM_DEFAULT_GROW_FACTOR,
+ STMM_DEFAULT_REORDER_FLAG);
+}
+
+void
+stmm_free_table (table)
+ stmm_table *table;
+{
+/*
+ register stmm_table_entry *ptr, *next;
+ int i;
+ for ( i = 0; i < table->num_bins; i++ )
+ {
+ ptr = table->bins[i];
+ while ( ptr != NULL )
+ {
+ next = ptr->next;
+ FREE( ptr );
+ ptr = next;
+ }
+ }
+*/
+ // no need to deallocate entries because they are in the memory manager now
+ // added by alanmi
+ if ( table->pMemMan )
+ Extra_MmFixedStop (table->pMemMan);
+ FREE (table->bins);
+ FREE (table);
+}
+
+// this function recycles all the bins
+void
+stmm_clean (table)
+ stmm_table *table;
+{
+ int i;
+ // clean the bins
+ for (i = 0; i < table->num_bins; i++)
+ table->bins[i] = NULL;
+ // reset the parameters
+ table->num_entries = 0;
+ // restart the memory manager
+ Extra_MmFixedRestart (table->pMemMan);
+}
+
+
+#define PTR_NOT_EQUAL(table, ptr, user_key)\
+(ptr != NULL && !EQUAL(table->compare, 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) != NULL && (table)->reorder_flag) {\
+ *(last) = (ptr)->next;\
+ (ptr)->next = (table)->bins[hash_val];\
+ (table)->bins[hash_val] = (ptr);\
+ }
+
+int
+stmm_lookup (table, key, value)
+ stmm_table *table;
+ register char *key;
+ char **value;
+{
+ int hash_val;
+ register stmm_table_entry *ptr, **last;
+
+ hash_val = do_hash (key, table);
+
+ FIND_ENTRY (table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ return 0;
+ }
+ else {
+ if (value != NULL)
+ {
+ *value = ptr->record;
+ }
+ return 1;
+ }
+}
+
+int
+stmm_lookup_int (table, key, value)
+ stmm_table *table;
+ register char *key;
+ int *value;
+{
+ int hash_val;
+ register stmm_table_entry *ptr, **last;
+
+ hash_val = do_hash (key, table);
+
+ FIND_ENTRY (table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ return 0;
+ }
+ else {
+ if (value != 0)
+ {
+ *value = (long) ptr->record;
+ }
+ return 1;
+ }
+}
+
+// This macro contained a line
+// new = ALLOC(stmm_table_entry, 1);
+// which was modified by alanmi
+
+
+/* This macro does not check if memory allocation fails. Use at you own risk */
+#define ADD_DIRECT(table, key, value, hash_val, new)\
+{\
+ if (table->num_entries/table->num_bins >= table->max_density) {\
+ rehash(table);\
+ hash_val = do_hash(key,table);\
+ }\
+ \
+ new = (stmm_table_entry *)Extra_MmFixedEntryFetch( table->pMemMan );\
+ \
+ new->key = key;\
+ new->record = value;\
+ new->next = table->bins[hash_val];\
+ table->bins[hash_val] = new;\
+ table->num_entries++;\
+}
+
+int
+stmm_insert (table, key, value)
+ register stmm_table *table;
+ register char *key;
+ char *value;
+{
+ int hash_val;
+ stmm_table_entry *new;
+ register stmm_table_entry *ptr, **last;
+
+ hash_val = do_hash (key, table);
+
+ FIND_ENTRY (table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ if (table->num_entries / table->num_bins >= table->max_density) {
+ if (rehash (table) == STMM_OUT_OF_MEM) {
+ return STMM_OUT_OF_MEM;
+ }
+ hash_val = do_hash (key, table);
+ }
+
+// new = ALLOC( stmm_table_entry, 1 );
+ new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
+ if (new == NULL) {
+ return STMM_OUT_OF_MEM;
+ }
+
+ new->key = key;
+ new->record = value;
+ new->next = table->bins[hash_val];
+ table->bins[hash_val] = new;
+ table->num_entries++;
+ return 0;
+ }
+ else {
+ ptr->record = value;
+ return 1;
+ }
+}
+
+int
+stmm_add_direct (table, key, value)
+ stmm_table *table;
+ char *key;
+ char *value;
+{
+ int hash_val;
+ stmm_table_entry *new;
+
+ hash_val = do_hash (key, table);
+ if (table->num_entries / table->num_bins >= table->max_density) {
+ if (rehash (table) == STMM_OUT_OF_MEM) {
+ return STMM_OUT_OF_MEM;
+ }
+ }
+ hash_val = do_hash (key, table);
+
+// new = ALLOC( stmm_table_entry, 1 );
+ new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
+ if (new == NULL) {
+ return STMM_OUT_OF_MEM;
+ }
+
+ new->key = key;
+ new->record = value;
+ new->next = table->bins[hash_val];
+ table->bins[hash_val] = new;
+ table->num_entries++;
+ return 1;
+}
+
+int
+stmm_find_or_add (table, key, slot)
+ stmm_table *table;
+ char *key;
+ char ***slot;
+{
+ int hash_val;
+ stmm_table_entry *new, *ptr, **last;
+
+ hash_val = do_hash (key, table);
+
+ FIND_ENTRY (table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ if (table->num_entries / table->num_bins >= table->max_density) {
+ if (rehash (table) == STMM_OUT_OF_MEM) {
+ return STMM_OUT_OF_MEM;
+ }
+ hash_val = do_hash (key, table);
+ }
+
+ // new = ALLOC( stmm_table_entry, 1 );
+ new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
+ if (new == NULL) {
+ return STMM_OUT_OF_MEM;
+ }
+
+ new->key = key;
+ new->record = (char *) 0;
+ new->next = table->bins[hash_val];
+ table->bins[hash_val] = new;
+ table->num_entries++;
+ if (slot != NULL)
+ *slot = &new->record;
+ return 0;
+ }
+ else {
+ if (slot != NULL)
+ *slot = &ptr->record;
+ return 1;
+ }
+}
+
+int
+stmm_find (table, key, slot)
+ stmm_table *table;
+ char *key;
+ char ***slot;
+{
+ int hash_val;
+ stmm_table_entry *ptr, **last;
+
+ hash_val = do_hash (key, table);
+
+ FIND_ENTRY (table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ return 0;
+ }
+ else {
+ if (slot != NULL)
+ {
+ *slot = &ptr->record;
+ }
+ return 1;
+ }
+}
+
+static int
+rehash (table)
+ register stmm_table *table;
+{
+ register stmm_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 (stmm_table_entry *, table->num_bins);
+ if (table->bins == NULL) {
+ table->bins = old_bins;
+ table->num_bins = old_num_bins;
+ table->num_entries = old_num_entries;
+ return STMM_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 != NULL) {
+ 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;
+}
+
+stmm_table *
+stmm_copy (old_table)
+ stmm_table *old_table;
+{
+ stmm_table *new_table;
+ stmm_table_entry *ptr, /* *newptr, *next, */ *new;
+ int i, /*j, */ num_bins = old_table->num_bins;
+
+ new_table = ALLOC (stmm_table, 1);
+ if (new_table == NULL) {
+ return NULL;
+ }
+
+ *new_table = *old_table;
+ new_table->bins = ALLOC (stmm_table_entry *, num_bins);
+ if (new_table->bins == NULL) {
+ FREE (new_table);
+ return NULL;
+ }
+
+ // allocate the memory manager for the new table
+ new_table->pMemMan =
+ Extra_MmFixedStart (sizeof (stmm_table_entry));
+
+ for (i = 0; i < num_bins; i++) {
+ new_table->bins[i] = NULL;
+ ptr = old_table->bins[i];
+ while (ptr != NULL) {
+// new = ALLOC( stmm_table_entry, 1 );
+ new =
+ (stmm_table_entry *) Extra_MmFixedEntryFetch (new_table->
+ pMemMan);
+
+ if (new == NULL) {
+/*
+ for ( j = 0; j <= i; j++ )
+ {
+ newptr = new_table->bins[j];
+ while ( newptr != NULL )
+ {
+ next = newptr->next;
+ FREE( newptr );
+ newptr = next;
+ }
+ }
+*/
+ Extra_MmFixedStop (new_table->pMemMan);
+
+ FREE (new_table->bins);
+ FREE (new_table);
+ return NULL;
+ }
+ *new = *ptr;
+ new->next = new_table->bins[i];
+ new_table->bins[i] = new;
+ ptr = ptr->next;
+ }
+ }
+ return new_table;
+}
+
+int
+stmm_delete (table, keyp, value)
+ register stmm_table *table;
+ register char **keyp;
+ char **value;
+{
+ int hash_val;
+ char *key = *keyp;
+ register stmm_table_entry *ptr, **last;
+
+ hash_val = do_hash (key, table);
+
+ FIND_ENTRY (table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ *last = ptr->next;
+ if (value != NULL)
+ *value = ptr->record;
+ *keyp = ptr->key;
+// FREE( ptr );
+ Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr);
+
+ table->num_entries--;
+ return 1;
+}
+
+int
+stmm_delete_int (table, keyp, value)
+ register stmm_table *table;
+ register long *keyp;
+ char **value;
+{
+ int hash_val;
+ char *key = (char *) *keyp;
+ register stmm_table_entry *ptr, **last;
+
+ hash_val = do_hash (key, table);
+
+ FIND_ENTRY (table, hash_val, key, ptr, last);
+
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ *last = ptr->next;
+ if (value != NULL)
+ *value = ptr->record;
+ *keyp = (long) ptr->key;
+// FREE( ptr );
+ Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr);
+
+ table->num_entries--;
+ return 1;
+}
+
+int
+stmm_foreach (table, func, arg)
+ stmm_table *table;
+ enum stmm_retval (*func) ();
+ char *arg;
+{
+ stmm_table_entry *ptr, **last;
+ enum stmm_retval retval;
+ int i;
+
+ for (i = 0; i < table->num_bins; i++) {
+ last = &table->bins[i];
+ ptr = *last;
+ while (ptr != NULL) {
+ retval = (*func) (ptr->key, ptr->record, arg);
+ switch (retval) {
+ case STMM_CONTINUE:
+ last = &ptr->next;
+ ptr = *last;
+ break;
+ case STMM_STOP:
+ return 0;
+ case STMM_DELETE:
+ *last = ptr->next;
+ table->num_entries--; /* cstevens@ic */
+// FREE( ptr );
+ Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr);
+
+ ptr = *last;
+ }
+ }
+ }
+ return 1;
+}
+
+int
+stmm_strhash (string, modulus)
+ register char *string;
+ int modulus;
+{
+ register int val = 0;
+ register int c;
+
+ while ((c = *string++) != '\0') {
+ val = val * 997 + c;
+ }
+
+ return ((val < 0) ? -val : val) % modulus;
+}
+
+int
+stmm_numhash (x, size)
+ char *x;
+ int size;
+{
+ return STMM_NUMHASH (x, size);
+}
+
+int
+stmm_ptrhash (x, size)
+ char *x;
+ int size;
+{
+ return STMM_PTRHASH (x, size);
+}
+
+int
+stmm_numcmp (x, y)
+ char *x;
+ char *y;
+{
+ return STMM_NUMCMP (x, y);
+}
+
+int
+stmm_ptrcmp (x, y)
+ char *x;
+ char *y;
+{
+ return STMM_NUMCMP (x, y);
+}
+
+stmm_generator *
+stmm_init_gen (table)
+ stmm_table *table;
+{
+ stmm_generator *gen;
+
+ gen = ALLOC (stmm_generator, 1);
+ if (gen == NULL) {
+ return NULL;
+ }
+ gen->table = table;
+ gen->entry = NULL;
+ gen->index = 0;
+ return gen;
+}
+
+
+int
+stmm_gen (gen, key_p, value_p)
+ stmm_generator *gen;
+ char **key_p;
+ char **value_p;
+{
+ register int i;
+
+ if (gen->entry == NULL) {
+ /* try to find next entry */
+ for (i = gen->index; i < gen->table->num_bins; i++) {
+ if (gen->table->bins[i] != NULL) {
+ gen->index = i + 1;
+ gen->entry = gen->table->bins[i];
+ break;
+ }
+ }
+ if (gen->entry == NULL) {
+ return 0; /* that's all folks ! */
+ }
+ }
+ *key_p = gen->entry->key;
+ if (value_p != 0) {
+ *value_p = gen->entry->record;
+ }
+ gen->entry = gen->entry->next;
+ return 1;
+}
+
+
+int
+stmm_gen_int (gen, key_p, value_p)
+ stmm_generator *gen;
+ char **key_p;
+ long *value_p;
+{
+ register int i;
+
+ if (gen->entry == NULL) {
+ /* try to find next entry */
+ for (i = gen->index; i < gen->table->num_bins; i++) {
+ if (gen->table->bins[i] != NULL) {
+ gen->index = i + 1;
+ gen->entry = gen->table->bins[i];
+ break;
+ }
+ }
+ if (gen->entry == NULL) {
+ return 0; /* that's all folks ! */
+ }
+ }
+ *key_p = gen->entry->key;
+ if (value_p != 0)
+ {
+ *value_p = (long) gen->entry->record;
+ }
+ gen->entry = gen->entry->next;
+ return 1;
+}
+
+
+void
+stmm_free_gen (gen)
+ stmm_generator *gen;
+{
+ FREE (gen);
+}
diff --git a/src/misc/st/stmm.h b/src/misc/st/stmm.h
new file mode 100644
index 00000000..4330416e
--- /dev/null
+++ b/src/misc/st/stmm.h
@@ -0,0 +1,127 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/st/st.h,v
+ * serdar
+ * 1.1
+ * 1993/07/29 01:00:21
+ *
+ */
+/* LINTLIBRARY */
+
+/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */
+
+#ifndef STMM_INCLUDED
+#define STMM_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "extra.h"
+
+typedef struct stmm_table_entry stmm_table_entry;
+typedef struct stmm_table stmm_table;
+typedef struct stmm_generator stmm_generator;
+
+struct stmm_table_entry
+{
+ char *key;
+ char *record;
+ stmm_table_entry *next;
+};
+
+struct stmm_table
+{
+ int (*compare) ();
+ int (*hash) ();
+ int num_bins;
+ int num_entries;
+ int max_density;
+ int reorder_flag;
+ double grow_factor;
+ stmm_table_entry **bins;
+ // memory manager to improve runtime and prevent memory fragmentation
+ // added by alanmi - January 16, 2003
+ Extra_MmFixed_t *pMemMan;
+};
+
+struct stmm_generator
+{
+ stmm_table *table;
+ stmm_table_entry *entry;
+ int index;
+};
+
+#define stmm_is_member(table,key) stmm_lookup(table,key,(char **) 0)
+#define stmm_count(table) ((table)->num_entries)
+
+enum stmm_retval
+{ STMM_CONTINUE, STMM_STOP, STMM_DELETE };
+
+typedef enum stmm_retval (*STMM_PFSR) ();
+typedef int (*STMM_PFI) ();
+
+EXTERN stmm_table *stmm_init_table_with_params
+ARGS ((STMM_PFI, STMM_PFI, int, int, double, int));
+EXTERN stmm_table *stmm_init_table ARGS ((STMM_PFI, STMM_PFI));
+EXTERN void stmm_free_table ARGS ((stmm_table *));
+EXTERN int stmm_lookup ARGS ((stmm_table *, char *, char **));
+EXTERN int stmm_lookup_int ARGS ((stmm_table *, char *, int *));
+EXTERN int stmm_insert ARGS ((stmm_table *, char *, char *));
+EXTERN int stmm_add_direct ARGS ((stmm_table *, char *, char *));
+EXTERN int stmm_find_or_add ARGS ((stmm_table *, char *, char ***));
+EXTERN int stmm_find ARGS ((stmm_table *, char *, char ***));
+EXTERN stmm_table *stmm_copy ARGS ((stmm_table *));
+EXTERN int stmm_delete ARGS ((stmm_table *, char **, char **));
+EXTERN int stmm_delete_int ARGS ((stmm_table *, long *, char **));
+EXTERN int stmm_foreach ARGS ((stmm_table *, STMM_PFSR, char *));
+EXTERN int stmm_strhash ARGS ((char *, int));
+EXTERN int stmm_numhash ARGS ((char *, int));
+EXTERN int stmm_ptrhash ARGS ((char *, int));
+EXTERN int stmm_numcmp ARGS ((char *, char *));
+EXTERN int stmm_ptrcmp ARGS ((char *, char *));
+EXTERN stmm_generator *stmm_init_gen ARGS ((stmm_table *));
+EXTERN int stmm_gen ARGS ((stmm_generator *, char **, char **));
+EXTERN int stmm_gen_int ARGS ((stmm_generator *, char **, long *));
+EXTERN void stmm_free_gen ARGS ((stmm_generator *));
+// additional functions
+EXTERN void stmm_clean ARGS ((stmm_table *));
+
+
+
+#define STMM_DEFAULT_MAX_DENSITY 5
+#define STMM_DEFAULT_INIT_TABLE_SIZE 11
+#define STMM_DEFAULT_GROW_FACTOR 2.0
+#define STMM_DEFAULT_REORDER_FLAG 0
+
+// added by Zhihong: no need for memory allocation
+#define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \
+ for(gen.table=(tb), gen.entry=NULL, gen.index=0; \
+ stmm_gen(&(gen),key,value);)
+
+#define stmm_foreach_item(table, gen, key, value) \
+ for(gen=stmm_init_gen(table); stmm_gen(gen,key,value) || (stmm_free_gen(gen),0);)
+
+#define stmm_foreach_item_int(table, gen, key, value) \
+ for(gen=stmm_init_gen(table); stmm_gen_int(gen,key,value) || (stmm_free_gen(gen),0);)
+
+#define STMM_OUT_OF_MEM -10000
+
+/*
+
+// consider adding these other other similar definitions
+#define st_table stmm_table
+#define st_insert stmm_insert
+#define st_delete stmm_delete
+#define st_lookup stmm_lookup
+#define st_init_table stmm_init_table
+#define st_free_table stmm_free_table
+
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STMM_INCLUDED */
diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h
new file mode 100644
index 00000000..1a32062a
--- /dev/null
+++ b/src/misc/util/leaks.h
@@ -0,0 +1,30 @@
+//////////////////////////////////////////////////////////////////////////
+// This file is used to detect memory leaks using Visual Studio 6.0
+// The idea comes from this page: http://www.michaelmoser.org/memory.htm
+// In addition to this file, it required the presence of "stdlib_hack.h"
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef __LEAKS_H__
+#define __LEAKS_H__
+
+#ifdef _DEBUG
+#define _CRTDBG_MAP_ALLOC // include Microsoft memory leak detection procedures
+//#define _INC_MALLOC // exclude standard memory alloc procedures
+
+#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
+#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
+#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
+//#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
+//#define free(p) _free_dbg(p, _NORMAL_BLOCK)
+//#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK)
+
+//#include <stdlib.h>
+#include <stdlib_hack.h>
+#include <crtdbg.h>
+#endif
+
+#endif
+
+//////////////////////////////////////
+
+
diff --git a/src/misc/util/module.make b/src/misc/util/module.make
new file mode 100644
index 00000000..d6d908e7
--- /dev/null
+++ b/src/misc/util/module.make
@@ -0,0 +1 @@
+SRC +=
diff --git a/src/misc/util/stdlib_hack.h b/src/misc/util/stdlib_hack.h
new file mode 100644
index 00000000..2ddf73d1
--- /dev/null
+++ b/src/misc/util/stdlib_hack.h
@@ -0,0 +1,4 @@
+
+#include <stdlib.h>
+
+
diff --git a/src/misc/util/util_hack.h b/src/misc/util/util_hack.h
new file mode 100644
index 00000000..71c77321
--- /dev/null
+++ b/src/misc/util/util_hack.h
@@ -0,0 +1,95 @@
+/**CFile****************************************************************
+
+ FileName [util_hack.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [This file is used to simulate the presence of "util.h".]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: util_hack.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __UTIL_HACK_H__
+#define __UTIL_HACK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <math.h>
+
+#define EXTERN extern
+#define NIL(type) ((type *) 0)
+#define random rand
+#define srandom srand
+
+#define util_cpu_time Extra_CpuTime
+#define getSoftDataLimit Extra_GetSoftDataLimit
+#define util_getopt_reset Extra_UtilGetoptReset
+#define util_getopt Extra_UtilGetopt
+#define util_print_time Extra_UtilPrintTime
+#define util_strsav Extra_UtilStrsav
+#define util_tilde_expand Extra_UtilTildeExpand
+#define util_file_search Extra_UtilFileSearch
+#define MMoutOfMemory Extra_UtilMMoutOfMemory
+
+#define util_optarg globalUtilOptarg
+#define util_optind globalUtilOptind
+
+#ifndef ARGS
+# ifdef __STDC__
+# define ARGS(args) args
+# else
+# define ARGS(args) ()
+# endif
+#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 ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+
+extern long Extra_CpuTime();
+extern int Extra_GetSoftDataLimit();
+extern void Extra_UtilGetoptReset();
+extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring );
+extern char * Extra_UtilPrintTime( long t );
+extern char * Extra_UtilStrsav( char *s );
+extern char * Extra_UtilTildeExpand( char *fname );
+extern char * Extra_UtilFileSearch( char *file, char *path, char *mode );
+
+extern char * globalUtilOptarg;
+extern int globalUtilOptind;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/misc/vec/module.make b/src/misc/vec/module.make
new file mode 100644
index 00000000..d6d908e7
--- /dev/null
+++ b/src/misc/vec/module.make
@@ -0,0 +1 @@
+SRC +=
diff --git a/src/misc/vec/vec.h b/src/misc/vec/vec.h
new file mode 100644
index 00000000..a4bd4771
--- /dev/null
+++ b/src/misc/vec/vec.h
@@ -0,0 +1,121 @@
+/**CFile****************************************************************
+
+ FileName [vec.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resizable arrays.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __VEC_H__
+#define __VEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#pragma warning(disable : 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression
+#pragma warning(disable : 4244) // warning C4244: '+=' : conversion from 'int ' to 'unsigned short ', possible loss of data
+#pragma warning(disable : 4514) // warning C4514: 'Vec_StrPop' : unreferenced inline function has been removed
+#pragma warning(disable : 4710) // warning C4710: function 'Vec_PtrGrow' not inlined
+#endif
+
+#ifndef SINT64
+#define SINT64
+
+#ifdef _WIN32
+typedef signed __int64 sint64; // compatible with MS VS 6.0
+#else
+typedef long long sint64;
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+// this include should be the first one in the list
+// it is used to catch memory leaks on Windows
+#include "leaks.h"
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#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
+
+#ifndef ALLOC
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#endif
+
+#ifndef FREE
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#endif
+
+#ifndef REALLOC
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+#endif
+
+#ifndef PRT
+#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
+#endif
+
+#ifndef PRTP
+#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0)
+#endif
+
+#include "vecInt.h"
+#include "vecFlt.h"
+#include "vecStr.h"
+#include "vecPtr.h"
+#include "vecVec.h"
+#include "vecAtt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/vec/vecAtt.h b/src/misc/vec/vecAtt.h
new file mode 100644
index 00000000..da7a8445
--- /dev/null
+++ b/src/misc/vec/vecAtt.h
@@ -0,0 +1,391 @@
+/**CFile****************************************************************
+
+ FileName [vecAtt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resizable arrays.]
+
+ Synopsis [Array of user-specified attiributes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: vecAtt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __Vec_Att_H__
+#define __Vec_Att_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+// various attributes
+typedef enum {
+ VEC_ATTR_NONE = 0, // 0
+ VEC_ATTR_COPY, // 1
+ VEC_ATTR_LOCAL_AIG, // 2
+ VEC_ATTR_LOCAL_SOP, // 3
+ VEC_ATTR_LOCAL_BDD, // 4
+ VEC_ATTR_GLOBAL_AIG, // 5
+ VEC_ATTR_GLOBAL_SOP, // 6
+ VEC_ATTR_GLOBAL_BDD, // 7
+ VEC_ATTR_LEVEL, // 8
+ VEC_ATTR_LEVEL_REV, // 9
+ VEC_ATTR_RETIME_LAG, // 10
+ VEC_ATTR_FRAIG, // 11
+ VEC_ATTR_MVVAR, // 12
+ VEC_ATTR_DATA1, // 13
+ VEC_ATTR_DATA2, // 14
+ VEC_ATTR_TOTAL_NUM // 15
+} Vec_AttrType_t;
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Att_t_ Vec_Att_t;
+struct Vec_Att_t_
+{
+ // storage for attributes
+ int nCap; // the size of array allocated
+ int * pArrayInt; // the integer attribute array
+ void ** pArrayPtr; // the pointer attribute array
+ // attribute specific info
+ void * pMan; // the manager for this attribute
+ void (*pFuncFreeMan) (void *); // the procedure to free the manager
+ void*(*pFuncStartObj)(void *); // the procedure to start one attribute
+ void (*pFuncFreeObj) (void *, void *); // the procedure to free one attribute
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Att_t * Vec_AttAlloc(
+ int fInteger, int nSize, void * pMan,
+ void (*pFuncFreeMan) (void *),
+ void*(*pFuncStartObj)(void *),
+ void (*pFuncFreeObj) (void *, void *) )
+{
+ Vec_Att_t * p;
+ p = ALLOC( Vec_Att_t, 1 );
+ memset( p, 0, sizeof(Vec_Att_t) );
+ p->pMan = pMan;
+ p->pFuncFreeMan = pFuncFreeMan;
+ p->pFuncStartObj = pFuncStartObj;
+ p->pFuncFreeObj = pFuncFreeObj;
+ p->nCap = nSize? nSize : 16;
+ if ( fInteger )
+ {
+ p->pArrayInt = ALLOC( int, p->nCap );
+ memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap );
+ }
+ else
+ {
+ p->pArrayPtr = ALLOC( void *, p->nCap );
+ memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_AttFree( Vec_Att_t * p, int fFreeMan )
+{
+ void * pMan;
+ if ( p == NULL )
+ return NULL;
+ // free the attributes of objects
+ if ( p->pFuncFreeObj )
+ {
+ int i;
+ if ( p->pArrayInt )
+ {
+ for ( i = 0; i < p->nCap; i++ )
+ if ( p->pArrayInt[i] )
+ p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] );
+ }
+ else
+ {
+ for ( i = 0; i < p->nCap; i++ )
+ if ( p->pArrayPtr[i] )
+ p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] );
+ }
+ }
+ // free the memory manager
+ pMan = fFreeMan? NULL : p->pMan;
+ if ( p->pMan && fFreeMan )
+ p->pFuncFreeMan( p->pMan );
+ FREE( p->pArrayInt );
+ FREE( p->pArrayPtr );
+ FREE( p );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears the vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_AttClear( Vec_Att_t * p )
+{
+ // free the attributes of objects
+ if ( p->pFuncFreeObj )
+ {
+ int i;
+ if ( p->pArrayInt )
+ {
+ if ( p->pFuncFreeObj )
+ for ( i = 0; i < p->nCap; i++ )
+ if ( p->pArrayInt[i] )
+ p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] );
+ }
+ else
+ {
+ if ( p->pFuncFreeObj )
+ for ( i = 0; i < p->nCap; i++ )
+ if ( p->pArrayPtr[i] )
+ p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] );
+ }
+ }
+ if ( p->pArrayInt )
+ memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap );
+ else
+ memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes one entry from the attribute manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_AttFreeEntry( Vec_Att_t * p, int i )
+{
+ if ( i >= p->nCap )
+ return;
+ if ( p->pMan )
+ {
+ if ( p->pArrayInt[i] && p->pFuncFreeObj )
+ p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] );
+ if ( p->pArrayPtr[i] && p->pFuncFreeObj )
+ p->pFuncFreeObj( p->pMan, (void *)p->pArrayPtr[i] );
+ }
+ if ( p->pArrayInt )
+ p->pArrayInt[i] = ~(unsigned)0;
+ else
+ p->pArrayPtr[i] = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_AttGrow( Vec_Att_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ if ( p->pArrayInt )
+ {
+ p->pArrayInt = REALLOC( int, p->pArrayInt, nCapMin );
+ memset( p->pArrayInt + p->nCap, 0xff, sizeof(int) * (nCapMin - p->nCap) );
+ }
+ else
+ {
+ p->pArrayPtr = REALLOC( void *, p->pArrayPtr, nCapMin );
+ memset( p->pArrayPtr + p->nCap, 0, sizeof(void *) * (nCapMin - p->nCap) );
+ }
+ p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the entry into its place.]
+
+ Description [Only works if the manager is not defined.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_AttWriteEntry( Vec_Att_t * p, int i, void * pEntry )
+{
+ assert( p->pArrayPtr );
+ assert( p->pFuncStartObj == NULL );
+ if ( i >= p->nCap )
+ Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 );
+ p->pArrayPtr[i] = pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the entry into its place.]
+
+ Description [Only works if the manager is not defined.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_AttWriteEntryInt( Vec_Att_t * p, int i, int Entry )
+{
+ assert( p->pArrayInt );
+ assert( p->pFuncStartObj == NULL );
+ if ( i >= p->nCap )
+ Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 );
+ p->pArrayInt[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_AttEntry( Vec_Att_t * p, int i )
+{
+ assert( p->pArrayPtr );
+ if ( i >= p->nCap )
+ Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 );
+ if ( p->pArrayPtr[i] == NULL && p->pFuncStartObj )
+ p->pArrayPtr[i] = p->pFuncStartObj( p->pMan );
+ return p->pArrayPtr[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_AttEntryInt( Vec_Att_t * p, int i )
+{
+ assert( p->pArrayInt );
+ assert( p->pMan == NULL );
+ if ( i >= p->nCap )
+ Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 );
+ return p->pArrayInt[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_AttMan( Vec_Att_t * p )
+{
+ return p->pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of attributes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void ** Vec_AttArray( Vec_Att_t * p )
+{
+ return p->pArrayPtr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of attributes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int * Vec_AttArrayInt( Vec_Att_t * p )
+{
+ return p->pArrayInt;
+}
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/vec/vecFlt.h b/src/misc/vec/vecFlt.h
new file mode 100644
index 00000000..6b36ce84
--- /dev/null
+++ b/src/misc/vec/vecFlt.h
@@ -0,0 +1,630 @@
+/**CFile****************************************************************
+
+ FileName [vecFlt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resizable arrays.]
+
+ Synopsis [Resizable arrays of floats.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __VEC_FLT_H__
+#define __VEC_FLT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Flt_t_ Vec_Flt_t;
+struct Vec_Flt_t_
+{
+ int nCap;
+ int nSize;
+ float * pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_FltForEachEntry( vVec, Entry, i ) \
+ for ( i = 0; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ )
+#define Vec_FltForEachEntryStart( vVec, Entry, i, Start ) \
+ for ( i = Start; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ )
+#define Vec_FltForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \
+ for ( i = Start; (i < Stop) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ )
+#define Vec_FltForEachEntryReverse( vVec, pEntry, i ) \
+ for ( i = Vec_FltSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_FltEntry(vVec, i)), 1); i-- )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltAlloc( int nCap )
+{
+ Vec_Flt_t * p;
+ p = ALLOC( Vec_Flt_t, 1 );
+ if ( nCap > 0 && nCap < 16 )
+ nCap = 16;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given size and cleans it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltStart( int nSize )
+{
+ Vec_Flt_t * p;
+ p = Vec_FltAlloc( nSize );
+ p->nSize = nSize;
+ memset( p->pArray, 0, sizeof(float) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from a float array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltAllocArray( float * pArray, int nSize )
+{
+ Vec_Flt_t * p;
+ p = ALLOC( Vec_Flt_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = pArray;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from a float array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltAllocArrayCopy( float * pArray, int nSize )
+{
+ Vec_Flt_t * p;
+ p = ALLOC( Vec_Flt_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = ALLOC( float, nSize );
+ memcpy( p->pArray, pArray, sizeof(float) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the float array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltDup( Vec_Flt_t * pVec )
+{
+ Vec_Flt_t * p;
+ p = ALLOC( Vec_Flt_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL;
+ memcpy( p->pArray, pVec->pArray, sizeof(float) * pVec->nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the array into another vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Flt_t * Vec_FltDupArray( Vec_Flt_t * pVec )
+{
+ Vec_Flt_t * p;
+ p = ALLOC( Vec_Flt_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = pVec->pArray;
+ pVec->nSize = 0;
+ pVec->nCap = 0;
+ pVec->pArray = NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltFree( Vec_Flt_t * p )
+{
+ FREE( p->pArray );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float * Vec_FltReleaseArray( Vec_Flt_t * p )
+{
+ float * pArray = p->pArray;
+ p->nCap = 0;
+ p->nSize = 0;
+ p->pArray = NULL;
+ return pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float * Vec_FltArray( Vec_Flt_t * p )
+{
+ return p->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_FltSize( Vec_Flt_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Vec_FltEntry( Vec_Flt_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltWriteEntry( Vec_Flt_t * p, int i, float Entry )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltAddToEntry( Vec_Flt_t * p, int i, float Addition )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] += Addition;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Vec_FltEntryLast( Vec_Flt_t * p )
+{
+ return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltGrow( Vec_Flt_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ p->pArray = REALLOC( float, p->pArray, nCapMin );
+ p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills the vector with given number of entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltFill( Vec_Flt_t * p, int nSize, float Entry )
+{
+ int i;
+ Vec_FltGrow( p, nSize );
+ for ( i = 0; i < nSize; i++ )
+ p->pArray[i] = Entry;
+ p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills the vector with given number of entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltFillExtra( Vec_Flt_t * p, int nSize, float Entry )
+{
+ int i;
+ if ( p->nSize >= nSize )
+ return;
+ Vec_FltGrow( p, nSize );
+ for ( i = p->nSize; i < nSize; i++ )
+ p->pArray[i] = Entry;
+ p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltShrink( Vec_Flt_t * p, int nSizeNew )
+{
+ assert( p->nSize >= nSizeNew );
+ p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltClear( Vec_Flt_t * p )
+{
+ p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltPush( Vec_Flt_t * p, float Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_FltGrow( p, 16 );
+ else
+ Vec_FltGrow( p, 2 * p->nCap );
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltPushOrder( Vec_Flt_t * p, float Entry )
+{
+ int i;
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_FltGrow( p, 16 );
+ else
+ Vec_FltGrow( p, 2 * p->nCap );
+ }
+ p->nSize++;
+ for ( i = p->nSize-2; i >= 0; i-- )
+ if ( p->pArray[i] > Entry )
+ p->pArray[i+1] = p->pArray[i];
+ else
+ break;
+ p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_FltPushUnique( Vec_Flt_t * p, float Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Vec_FltPush( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the last entry and removes it from the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Vec_FltPop( Vec_Flt_t * p )
+{
+ assert( p->nSize > 0 );
+ return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_FltFind( Vec_Flt_t * p, float Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_FltRemove( Vec_Flt_t * p, float Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ break;
+ if ( i == p->nSize )
+ return 0;
+ assert( i < p->nSize );
+ for ( i++; i < p->nSize; i++ )
+ p->pArray[i-1] = p->pArray[i];
+ p->nSize--;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two floats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_FltSortCompare1( float * pp1, float * pp2 )
+{
+ // for some reason commenting out lines (as shown) led to crashing of the release version
+ if ( *pp1 < *pp2 )
+ return -1;
+ if ( *pp1 > *pp2 ) //
+ return 1;
+ return 0; //
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two floats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_FltSortCompare2( float * pp1, float * pp2 )
+{
+ // for some reason commenting out lines (as shown) led to crashing of the release version
+ if ( *pp1 > *pp2 )
+ return -1;
+ if ( *pp1 < *pp2 ) //
+ return 1;
+ return 0; //
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_FltSort( Vec_Flt_t * p, int fReverse )
+{
+ if ( fReverse )
+ qsort( (void *)p->pArray, p->nSize, sizeof(float),
+ (int (*)(const void *, const void *)) Vec_FltSortCompare2 );
+ else
+ qsort( (void *)p->pArray, p->nSize, sizeof(float),
+ (int (*)(const void *, const void *)) Vec_FltSortCompare1 );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h
new file mode 100644
index 00000000..082ebe70
--- /dev/null
+++ b/src/misc/vec/vecInt.h
@@ -0,0 +1,834 @@
+/**CFile****************************************************************
+
+ FileName [vecInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resizable arrays.]
+
+ Synopsis [Resizable arrays of integers.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __VEC_INT_H__
+#define __VEC_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Int_t_ Vec_Int_t;
+struct Vec_Int_t_
+{
+ int nCap;
+ int nSize;
+ int * pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_IntForEachEntry( vVec, Entry, i ) \
+ for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \
+ for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \
+ for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \
+ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAlloc( int nCap )
+{
+ Vec_Int_t * p;
+ p = ALLOC( Vec_Int_t, 1 );
+ if ( nCap > 0 && nCap < 16 )
+ nCap = 16;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given size and cleans it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntStart( int nSize )
+{
+ Vec_Int_t * p;
+ p = Vec_IntAlloc( nSize );
+ p->nSize = nSize;
+ memset( p->pArray, 0, sizeof(int) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given size and cleans it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntStartNatural( int nSize )
+{
+ Vec_Int_t * p;
+ int i;
+ p = Vec_IntAlloc( nSize );
+ p->nSize = nSize;
+ for ( i = 0; i < nSize; i++ )
+ p->pArray[i] = i;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from an integer array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize )
+{
+ Vec_Int_t * p;
+ p = ALLOC( Vec_Int_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = pArray;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from an integer array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize )
+{
+ Vec_Int_t * p;
+ p = ALLOC( Vec_Int_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = ALLOC( int, nSize );
+ memcpy( p->pArray, pArray, sizeof(int) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the integer array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec )
+{
+ Vec_Int_t * p;
+ p = ALLOC( Vec_Int_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nSize;
+ p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL;
+ memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the array into another vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec )
+{
+ Vec_Int_t * p;
+ p = ALLOC( Vec_Int_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = pVec->pArray;
+ pVec->nSize = 0;
+ pVec->nCap = 0;
+ pVec->pArray = NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntFree( Vec_Int_t * p )
+{
+ FREE( p->pArray );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int * Vec_IntReleaseArray( Vec_Int_t * p )
+{
+ int * pArray = p->pArray;
+ p->nCap = 0;
+ p->nSize = 0;
+ p->pArray = NULL;
+ return pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int * Vec_IntArray( Vec_Int_t * p )
+{
+ return p->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntSize( Vec_Int_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntEntry( Vec_Int_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] += Addition;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntEntryLast( Vec_Int_t * p )
+{
+ assert( p->nSize > 0 );
+ return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ p->pArray = REALLOC( int, p->pArray, nCapMin );
+ assert( p->pArray );
+ p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills the vector with given number of entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Entry )
+{
+ int i;
+ Vec_IntGrow( p, nSize );
+ for ( i = 0; i < nSize; i++ )
+ p->pArray[i] = Entry;
+ p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills the vector with given number of entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Entry )
+{
+ int i;
+ if ( p->nSize >= nSize )
+ return;
+ Vec_IntGrow( p, nSize );
+ for ( i = p->nSize; i < nSize; i++ )
+ p->pArray[i] = Entry;
+ p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew )
+{
+ assert( p->nSize >= nSizeNew );
+ p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntClear( Vec_Int_t * p )
+{
+ p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_IntGrow( p, 16 );
+ else
+ Vec_IntGrow( p, 2 * p->nCap );
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry )
+{
+ int i;
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_IntGrow( p, 16 );
+ else
+ Vec_IntGrow( p, 2 * p->nCap );
+ }
+ p->nSize++;
+ for ( i = p->nSize - 1; i >= 1; i-- )
+ p->pArray[i] = p->pArray[i-1];
+ p->pArray[0] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the entry while preserving the increasing order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry )
+{
+ int i;
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_IntGrow( p, 16 );
+ else
+ Vec_IntGrow( p, 2 * p->nCap );
+ }
+ p->nSize++;
+ for ( i = p->nSize-2; i >= 0; i-- )
+ if ( p->pArray[i] > Entry )
+ p->pArray[i+1] = p->pArray[i];
+ else
+ break;
+ p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the entry while preserving the increasing order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Vec_IntPushOrder( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Vec_IntPush( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the next nWords entries in the vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords )
+{
+ if ( nWords == 0 )
+ return NULL;
+ assert( nWords > 0 );
+ p->nSize += nWords;
+ if ( p->nSize > p->nCap )
+ {
+// Vec_IntGrow( p, 2 * p->nSize );
+ return NULL;
+ }
+ return ((unsigned *)p->pArray) + p->nSize - nWords;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the last entry and removes it from the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntPop( Vec_Int_t * p )
+{
+ assert( p->nSize > 0 );
+ return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntFind( Vec_Int_t * p, int Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntRemove( Vec_Int_t * p, int Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ break;
+ if ( i == p->nSize )
+ return 0;
+ assert( i < p->nSize );
+ for ( i++; i < p->nSize; i++ )
+ p->pArray[i-1] = p->pArray[i];
+ p->nSize--;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two integers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntSortCompare1( int * pp1, int * pp2 )
+{
+ // for some reason commenting out lines (as shown) led to crashing of the release version
+ if ( *pp1 < *pp2 )
+ return -1;
+ if ( *pp1 > *pp2 ) //
+ return 1;
+ return 0; //
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two integers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntSortCompare2( int * pp1, int * pp2 )
+{
+ // for some reason commenting out lines (as shown) led to crashing of the release version
+ if ( *pp1 > *pp2 )
+ return -1;
+ if ( *pp1 < *pp2 ) //
+ return 1;
+ return 0; //
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntSort( Vec_Int_t * p, int fReverse )
+{
+ if ( fReverse )
+ qsort( (void *)p->pArray, p->nSize, sizeof(int),
+ (int (*)(const void *, const void *)) Vec_IntSortCompare2 );
+ else
+ qsort( (void *)p->pArray, p->nSize, sizeof(int),
+ (int (*)(const void *, const void *)) Vec_IntSortCompare1 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two integers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 )
+{
+ if ( *pp1 < *pp2 )
+ return -1;
+ if ( *pp1 > *pp2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntSortUnsigned( Vec_Int_t * p )
+{
+ qsort( (void *)p->pArray, p->nSize, sizeof(int),
+ (int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of common entries.]
+
+ Description [Assumes that the vectors are sorted in the increasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+{
+ int * pBeg1 = vArr1->pArray;
+ int * pBeg2 = vArr2->pArray;
+ int * pEnd1 = vArr1->pArray + vArr1->nSize;
+ int * pEnd2 = vArr2->pArray + vArr2->nSize;
+ int Counter = 0;
+ while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+ {
+ if ( *pBeg1 == *pBeg2 )
+ pBeg1++, pBeg2++, Counter++;
+ else if ( *pBeg1 < *pBeg2 )
+ pBeg1++;
+ else
+ pBeg2++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the result of merging the two vectors.]
+
+ Description [Assumes that the vectors are sorted in the increasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+{
+ Vec_Int_t * vArr = Vec_IntAlloc( vArr1->nSize + vArr2->nSize );
+ int * pBeg = vArr->pArray;
+ int * pBeg1 = vArr1->pArray;
+ int * pBeg2 = vArr2->pArray;
+ int * pEnd1 = vArr1->pArray + vArr1->nSize;
+ int * pEnd2 = vArr2->pArray + vArr2->nSize;
+ while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+ {
+ if ( *pBeg1 == *pBeg2 )
+ *pBeg++ = *pBeg1++, pBeg2++;
+ else if ( *pBeg1 < *pBeg2 )
+ *pBeg++ = *pBeg1++;
+ else
+ *pBeg++ = *pBeg2++;
+ }
+ while ( pBeg1 < pEnd1 )
+ *pBeg++ = *pBeg1++;
+ while ( pBeg2 < pEnd2 )
+ *pBeg++ = *pBeg2++;
+ vArr->nSize = pBeg - vArr->pArray;
+ assert( vArr->nSize <= vArr->nCap );
+ assert( vArr->nSize >= vArr1->nSize );
+ assert( vArr->nSize >= vArr2->nSize );
+ return vArr;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/vec/vecPtr.h b/src/misc/vec/vecPtr.h
new file mode 100644
index 00000000..1862bc7c
--- /dev/null
+++ b/src/misc/vec/vecPtr.h
@@ -0,0 +1,762 @@
+/**CFile****************************************************************
+
+ FileName [vecPtr.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resizable arrays.]
+
+ Synopsis [Resizable arrays of generic pointers.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __VEC_PTR_H__
+#define __VEC_PTR_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Ptr_t_ Vec_Ptr_t;
+struct Vec_Ptr_t_
+{
+ int nCap;
+ int nSize;
+ void ** pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// iterators through entries
+#define Vec_PtrForEachEntry( vVec, pEntry, i ) \
+ for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \
+ for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \
+ for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStartStop( vVec, pEntry, i, Start, Stop ) \
+ for ( i = Start; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryReverse( vVec, pEntry, i ) \
+ for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i-- )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap )
+{
+ Vec_Ptr_t * p;
+ p = ALLOC( Vec_Ptr_t, 1 );
+ if ( nCap > 0 && nCap < 8 )
+ nCap = 8;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given size and cleans it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrStart( int nSize )
+{
+ Vec_Ptr_t * p;
+ p = Vec_PtrAlloc( nSize );
+ p->nSize = nSize;
+ memset( p->pArray, 0, sizeof(void *) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from an integer array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize )
+{
+ Vec_Ptr_t * p;
+ p = ALLOC( Vec_Ptr_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = pArray;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from an integer array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize )
+{
+ Vec_Ptr_t * p;
+ p = ALLOC( Vec_Ptr_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = ALLOC( void *, nSize );
+ memcpy( p->pArray, pArray, sizeof(void *) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the array of simulation info.]
+
+ Description [Allocates the array containing given number of entries,
+ each of which contains given number of unsigned words of simulation data.
+ The resulting array can be freed using regular procedure Vec_PtrFree().
+ It is the responsibility of the user to ensure this array is never grown.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocSimInfo( int nEntries, int nWords )
+{
+ void ** pMemory;
+ unsigned * pInfo;
+ int i;
+ pMemory = (void **)ALLOC( char, (sizeof(void *) + sizeof(unsigned) * nWords) * nEntries );
+ pInfo = (unsigned *)(pMemory + nEntries);
+ for ( i = 0; i < nEntries; i++ )
+ pMemory[i] = pInfo + i * nWords;
+ return Vec_PtrAllocArray( pMemory, nEntries );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the array of truth tables for the given number of vars.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocTruthTables( int nVars )
+{
+ Vec_Ptr_t * p;
+ unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+ unsigned * pTruth;
+ int i, k, nWords;
+ nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5)));
+ p = Vec_PtrAllocSimInfo( nVars, nWords );
+ for ( i = 0; i < nVars; i++ )
+ {
+ pTruth = (unsigned *)p->pArray[i];
+ if ( i < 5 )
+ {
+ for ( k = 0; k < nWords; k++ )
+ pTruth[k] = Masks[i];
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( k & (1 << (i-5)) )
+ pTruth[k] = ~(unsigned)0;
+ else
+ pTruth[k] = 0;
+ }
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the integer array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec )
+{
+ Vec_Ptr_t * p;
+ p = ALLOC( Vec_Ptr_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
+ memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the array into another vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec )
+{
+ Vec_Ptr_t * p;
+ p = ALLOC( Vec_Ptr_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = pVec->pArray;
+ pVec->nSize = 0;
+ pVec->nCap = 0;
+ pVec->pArray = NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrFree( Vec_Ptr_t * p )
+{
+ FREE( p->pArray );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p )
+{
+ void ** pArray = p->pArray;
+ p->nCap = 0;
+ p->nSize = 0;
+ p->pArray = NULL;
+ return pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void ** Vec_PtrArray( Vec_Ptr_t * p )
+{
+ return p->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_PtrSize( Vec_Ptr_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the array of simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo )
+{
+ Vec_Ptr_t * vInfoNew;
+ int nWords;
+ assert( Vec_PtrSize(vInfo) > 2 );
+ // get the new array
+ nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0);
+ vInfoNew = Vec_PtrAllocSimInfo( 2*Vec_PtrSize(vInfo), nWords );
+ // copy the simulation info
+ memcpy( Vec_PtrEntry(vInfoNew,0), Vec_PtrEntry(vInfo,0), Vec_PtrSize(vInfo) * nWords * 4 );
+ // replace the array
+ free( vInfo->pArray );
+ vInfo->pArray = vInfoNew->pArray;
+ vInfo->nSize *= 2;
+ vInfo->nCap *= 2;
+ // free the old array
+ vInfoNew->pArray = NULL;
+ free( vInfoNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray + i;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p )
+{
+ assert( p->nSize > 0 );
+ return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ p->pArray = REALLOC( void *, p->pArray, nCapMin );
+ p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills the vector with given number of entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry )
+{
+ int i;
+ Vec_PtrGrow( p, nSize );
+ for ( i = 0; i < nSize; i++ )
+ p->pArray[i] = Entry;
+ p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills the vector with given number of entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry )
+{
+ int i;
+ if ( p->nSize >= nSize )
+ return;
+ assert( p->nSize < nSize );
+ if ( 2 * p->nSize > nSize )
+ Vec_PtrGrow( p, 2 * nSize );
+ else
+ Vec_PtrGrow( p, nSize );
+ for ( i = p->nSize; i < nSize; i++ )
+ p->pArray[i] = Entry;
+ p->nSize = nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the entry even if the place not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_PtrGetEntry( Vec_Ptr_t * p, int i )
+{
+ Vec_PtrFillExtra( p, i + 1, NULL );
+ return Vec_PtrEntry( p, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the entry even if the place does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrSetEntry( Vec_Ptr_t * p, int i, void * Entry )
+{
+ Vec_PtrFillExtra( p, i + 1, NULL );
+ Vec_PtrWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew )
+{
+ assert( p->nSize >= nSizeNew );
+ p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrClear( Vec_Ptr_t * p )
+{
+ p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copies the interger array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour )
+{
+ pDest->nSize = 0;
+ Vec_PtrGrow( pDest, pSour->nSize );
+ memcpy( pDest->pArray, pSour->pArray, sizeof(void *) * pSour->nSize );
+ pDest->nSize = pSour->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_PtrGrow( p, 16 );
+ else
+ Vec_PtrGrow( p, 2 * p->nCap );
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Vec_PtrPush( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the last entry and removes it from the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_PtrPop( Vec_Ptr_t * p )
+{
+ assert( p->nSize > 0 );
+ return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry )
+{
+ int i;
+ // delete assuming that it is closer to the end
+ for ( i = p->nSize - 1; i >= 0; i-- )
+ if ( p->pArray[i] == Entry )
+ break;
+ assert( i >= 0 );
+/*
+ // delete assuming that it is closer to the beginning
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ break;
+ assert( i < p->nSize );
+*/
+ for ( i++; i < p->nSize; i++ )
+ p->pArray[i-1] = p->pArray[i];
+ p->nSize--;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves the first nItems to the end.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems )
+{
+ assert( nItems < p->nSize );
+ Vec_PtrGrow( p, nItems + p->nSize );
+ memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) );
+ memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
+{
+ if ( p->nSize < 2 )
+ return;
+ qsort( (void *)p->pArray, p->nSize, sizeof(void *),
+ (int (*)(const void *, const void *)) Vec_PtrSortCompare );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
+{
+ int i, k;
+ if ( p->nSize < 2 )
+ return;
+ qsort( (void *)p->pArray, p->nSize, sizeof(void *),
+ (int (*)(const void *, const void *)) Vec_PtrSortCompare );
+ for ( i = k = 1; i < p->nSize; i++ )
+ if ( p->pArray[i] != p->pArray[i-1] )
+ p->pArray[k++] = p->pArray[i];
+ p->nSize = k;
+}
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/vec/vecStr.h b/src/misc/vec/vecStr.h
new file mode 100644
index 00000000..47367bc6
--- /dev/null
+++ b/src/misc/vec/vecStr.h
@@ -0,0 +1,583 @@
+/**CFile****************************************************************
+
+ FileName [vecStr.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resizable arrays.]
+
+ Synopsis [Resizable arrays of characters.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __VEC_STR_H__
+#define __VEC_STR_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Str_t_ Vec_Str_t;
+struct Vec_Str_t_
+{
+ int nCap;
+ int nSize;
+ char * pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Vec_StrForEachEntry( vVec, Entry, i ) \
+ for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAlloc( int nCap )
+{
+ Vec_Str_t * p;
+ p = ALLOC( Vec_Str_t, 1 );
+ if ( nCap > 0 && nCap < 16 )
+ nCap = 16;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given size and cleans it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrStart( int nSize )
+{
+ Vec_Str_t * p;
+ p = Vec_StrAlloc( nSize );
+ p->nSize = nSize;
+ memset( p->pArray, 0, sizeof(char) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from an integer array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize )
+{
+ Vec_Str_t * p;
+ p = ALLOC( Vec_Str_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = pArray;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the vector from an integer array of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize )
+{
+ Vec_Str_t * p;
+ p = ALLOC( Vec_Str_t, 1 );
+ p->nSize = nSize;
+ p->nCap = nSize;
+ p->pArray = ALLOC( char, nSize );
+ memcpy( p->pArray, pArray, sizeof(char) * nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the integer array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec )
+{
+ Vec_Str_t * p;
+ p = ALLOC( Vec_Str_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL;
+ memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the array into another vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec )
+{
+ Vec_Str_t * p;
+ p = ALLOC( Vec_Str_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = pVec->pArray;
+ pVec->nSize = 0;
+ pVec->nCap = 0;
+ pVec->pArray = NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrFree( Vec_Str_t * p )
+{
+ FREE( p->pArray );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline char * Vec_StrReleaseArray( Vec_Str_t * p )
+{
+ char * pArray = p->pArray;
+ p->nCap = 0;
+ p->nSize = 0;
+ p->pArray = NULL;
+ return pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline char * Vec_StrArray( Vec_Str_t * p )
+{
+ return p->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_StrSize( Vec_Str_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline char Vec_StrEntry( Vec_Str_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline char Vec_StrEntryLast( Vec_Str_t * p )
+{
+ assert( p->nSize > 0 );
+ return p->pArray[p->nSize-1];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ p->pArray = REALLOC( char, p->pArray, 2 * nCapMin );
+ p->nCap = 2 * nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills the vector with given number of entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Entry )
+{
+ int i;
+ Vec_StrGrow( p, nSize );
+ p->nSize = nSize;
+ for ( i = 0; i < p->nSize; i++ )
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew )
+{
+ assert( p->nSize >= nSizeNew );
+ p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrClear( Vec_Str_t * p )
+{
+ p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrPush( Vec_Str_t * p, char Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_StrGrow( p, 16 );
+ else
+ Vec_StrGrow( p, 2 * p->nCap );
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Finds the smallest integer larger of equal than the logarithm.]
+
+ Description [Returns [Log10(Num)].]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+static inline int Vec_StrBase10Log( unsigned Num )
+{
+ int Res;
+ assert( Num >= 0 );
+ if ( Num == 0 ) return 0;
+ if ( Num == 1 ) return 1;
+ for ( Res = 0, Num--; Num; Num /= 10, Res++ );
+ return Res;
+} /* end of Extra_Base2Log */
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num )
+{
+ int i, nDigits;
+ if ( Num < 0 )
+ {
+ Vec_StrPush( p, '-' );
+ Num = -Num;
+ }
+ if ( Num < 10 )
+ {
+ Vec_StrPush( p, (char)('0' + Num) );
+ return;
+ }
+ nDigits = Vec_StrBase10Log( Num );
+ Vec_StrGrow( p, p->nSize + nDigits );
+ for ( i = nDigits - 1; i >= 0; i-- )
+ {
+ Vec_StrWriteEntry( p, p->nSize + i, (char)('0' + Num % 10) );
+ Num /= 10;
+ }
+ assert( Num == 0 );
+ p->nSize += nDigits;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrPrintStr( Vec_Str_t * p, char * pStr )
+{
+ int i, Length = strlen(pStr);
+ for ( i = 0; i < Length; i++ )
+ Vec_StrPush( p, pStr[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Appends the string to the char vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrAppend( Vec_Str_t * p, char * pString )
+{
+ int i, nLength = strlen(pString);
+ Vec_StrGrow( p, p->nSize + nLength );
+ for ( i = 0; i < nLength; i++ )
+ p->pArray[p->nSize + i] = pString[i];
+ p->nSize += nLength;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the last entry and removes it from the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline char Vec_StrPop( Vec_Str_t * p )
+{
+ assert( p->nSize > 0 );
+ return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_StrSortCompare1( char * pp1, char * pp2 )
+{
+ // for some reason commenting out lines (as shown) led to crashing of the release version
+ if ( *pp1 < *pp2 )
+ return -1;
+ if ( *pp1 > *pp2 ) //
+ return 1;
+ return 0; //
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_StrSortCompare2( char * pp1, char * pp2 )
+{
+ // for some reason commenting out lines (as shown) led to crashing of the release version
+ if ( *pp1 > *pp2 )
+ return -1;
+ if ( *pp1 < *pp2 ) //
+ return 1;
+ return 0; //
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrSort( Vec_Str_t * p, int fReverse )
+{
+ if ( fReverse )
+ qsort( (void *)p->pArray, p->nSize, sizeof(char),
+ (int (*)(const void *, const void *)) Vec_StrSortCompare2 );
+ else
+ qsort( (void *)p->pArray, p->nSize, sizeof(char),
+ (int (*)(const void *, const void *)) Vec_StrSortCompare1 );
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/vec/vecVec.h b/src/misc/vec/vecVec.h
new file mode 100644
index 00000000..55ffdf4f
--- /dev/null
+++ b/src/misc/vec/vecVec.h
@@ -0,0 +1,356 @@
+/**CFile****************************************************************
+
+ FileName [vecVec.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resizable arrays.]
+
+ Synopsis [Resizable vector of resizable vectors.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __VEC_VEC_H__
+#define __VEC_VEC_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Vec_Vec_t_ Vec_Vec_t;
+struct Vec_Vec_t_
+{
+ int nCap;
+ int nSize;
+ void ** pArray;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// iterators through levels
+#define Vec_VecForEachLevel( vGlob, vVec, i ) \
+ for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \
+ for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
+ for ( i = LevelStart; (i <= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
+#define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \
+ for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- )
+#define Vec_VecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
+ for ( i = LevelStart; (i >= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- )
+
+// iteratores through entries
+#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \
+ for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
+ Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryLevel( vGlob, pEntry, i, Level ) \
+ Vec_PtrForEachEntry( Vec_VecEntry(vGlob, Level), pEntry, i )
+#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \
+ for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \
+ Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryStartStop( vGlob, pEntry, i, k, LevelStart, LevelStop ) \
+ for ( i = LevelStart; i <= LevelStop; i++ ) \
+ Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \
+ for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
+ Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \
+ for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \
+ Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryReverseStart( vGlob, pEntry, i, k, LevelStart ) \
+ for ( i = LevelStart; i >= 0; i-- ) \
+ Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Vec_t * Vec_VecAlloc( int nCap )
+{
+ Vec_Vec_t * p;
+ p = ALLOC( Vec_Vec_t, 1 );
+ if ( nCap > 0 && nCap < 8 )
+ nCap = 8;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Vec_t * Vec_VecStart( int nSize )
+{
+ Vec_Vec_t * p;
+ int i;
+ p = Vec_VecAlloc( nSize );
+ for ( i = 0; i < nSize; i++ )
+ p->pArray[i] = Vec_PtrAlloc( 0 );
+ p->nSize = nSize;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecExpand( Vec_Vec_t * p, int Level )
+{
+ int i;
+ if ( p->nSize >= Level + 1 )
+ return;
+ Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
+ for ( i = p->nSize; i <= Level; i++ )
+ p->pArray[i] = Vec_PtrAlloc( 0 );
+ p->nSize = Level + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_VecSize( Vec_Vec_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_VecEntry( Vec_Vec_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecFree( Vec_Vec_t * p )
+{
+ Vec_Ptr_t * vVec;
+ int i;
+ Vec_VecForEachLevel( p, vVec, i )
+ Vec_PtrFree( vVec );
+ Vec_PtrFree( (Vec_Ptr_t *)p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the vector of vectors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_VecSizeSize( Vec_Vec_t * p )
+{
+ Vec_Ptr_t * vVec;
+ int i, Counter = 0;
+ Vec_VecForEachLevel( p, vVec, i )
+ Counter += vVec->nSize;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecClear( Vec_Vec_t * p )
+{
+ Vec_Ptr_t * vVec;
+ int i;
+ Vec_VecForEachLevel( p, vVec, i )
+ Vec_PtrClear( vVec );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry )
+{
+ if ( p->nSize < Level + 1 )
+ {
+ int i;
+ Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
+ for ( i = p->nSize; i < Level + 1; i++ )
+ p->pArray[i] = Vec_PtrAlloc( 0 );
+ p->nSize = Level + 1;
+ }
+ Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry )
+{
+ if ( p->nSize < Level + 1 )
+ Vec_VecPush( p, Level, Entry );
+ else
+ Vec_PtrPushUnique( (Vec_Ptr_t*)p->pArray[Level], Entry );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two arrays.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+{
+ if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
+ return -1;
+ if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two integers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+{
+ if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
+ return -1;
+ if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
+{
+ if ( fReverse )
+ qsort( (void *)p->pArray, p->nSize, sizeof(void *),
+ (int (*)(const void *, const void *)) Vec_VecSortCompare2 );
+ else
+ qsort( (void *)p->pArray, p->nSize, sizeof(void *),
+ (int (*)(const void *, const void *)) Vec_VecSortCompare1 );
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+