summaryrefslogtreecommitdiffstats
path: root/src/opt/fxu
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2005-08-06 08:01:00 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2005-08-06 08:01:00 -0700
commitd0e834d1a615f8e0e9d04c2ac97811f63562bd0b (patch)
tree0973181bfb5ee7d556cc95bd640de16fee771e89 /src/opt/fxu
parent888e5bed5d7f56a5d86d91a6e8e88f3e5a3454dc (diff)
downloadabc-d0e834d1a615f8e0e9d04c2ac97811f63562bd0b.tar.gz
abc-d0e834d1a615f8e0e9d04c2ac97811f63562bd0b.tar.bz2
abc-d0e834d1a615f8e0e9d04c2ac97811f63562bd0b.zip
Version abc50806
Diffstat (limited to 'src/opt/fxu')
-rw-r--r--src/opt/fxu/fxu.c260
-rw-r--r--src/opt/fxu/fxu.h108
-rw-r--r--src/opt/fxu/fxuCreate.c425
-rw-r--r--src/opt/fxu/fxuHeapD.c445
-rw-r--r--src/opt/fxu/fxuHeapS.c444
-rw-r--r--src/opt/fxu/fxuInt.h541
-rw-r--r--src/opt/fxu/fxuList.c522
-rw-r--r--src/opt/fxu/fxuMatrix.c382
-rw-r--r--src/opt/fxu/fxuPair.c555
-rw-r--r--src/opt/fxu/fxuPrint.c195
-rw-r--r--src/opt/fxu/fxuReduce.c194
-rw-r--r--src/opt/fxu/fxuSelect.c603
-rw-r--r--src/opt/fxu/fxuSingle.c166
-rw-r--r--src/opt/fxu/fxuUpdate.c802
-rw-r--r--src/opt/fxu/module.make12
15 files changed, 5654 insertions, 0 deletions
diff --git a/src/opt/fxu/fxu.c b/src/opt/fxu/fxu.c
new file mode 100644
index 00000000..4b95b5a5
--- /dev/null
+++ b/src/opt/fxu/fxu.c
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+ FileName [fxu.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [The entrance into the fast extract module.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxu.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+//#include "mvc.h"
+#include "fxu.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*===== fxuCreate.c ====================================================*/
+extern Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData );
+extern void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData );
+
+static int s_MemoryTotal;
+static int s_MemoryPeak;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast_extract on a set of covers.]
+
+ Description [All the covers are given in the array p->ppCovers.
+ The resulting covers are returned in the array p->ppCoversNew.
+ The number of entries in both cover arrays is equal to the number
+ of all values in the current nodes plus the max expected number
+ of extracted nodes (p->nValuesCi + p->nValuesInt + p->nValuesExtMax).
+ The first p->nValuesCi entries, corresponding to the CI nodes, are NULL.
+ The next p->nValuesInt entries, corresponding to the int nodes, are covers
+ from which the divisors are extracted. The last p->nValuesExtMax entries
+ are reserved for the new covers to be extracted. The number of extracted
+ covers is returned. This number does not exceed the given number (p->nNodesExt).
+ Two other things are important for the correct operation of this procedure:
+ (1) The input covers should be SCC-free. (2) The literal array (pCover->pLits)
+ is allocated in each cover. The i-th entry in the literal array of a cover
+ is the number of the cover in the array p->ppCovers, which represents this
+ literal (variable value) in the given cover.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_FastExtract( Fxu_Data_t * pData )
+{
+ Fxu_Matrix * p;
+ Fxu_Single * pSingle;
+ Fxu_Double * pDouble;
+ int Weight1, Weight2, Weight3;
+
+ s_MemoryTotal = 0;
+ s_MemoryPeak = 0;
+
+ // create the matrix
+ p = Fxu_CreateMatrix( pData );
+ if ( p == NULL )
+ return -1;
+// if ( pData->fVerbose )
+// printf( "Memory usage after construction: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
+//Fxu_MatrixPrint( NULL, p );
+
+ if ( pData->fOnlyS )
+ {
+ pData->nNodesNew = 0;
+ do
+ {
+ Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
+ if ( pData->fVerbose )
+ printf( "Best single = %3d.\n", Weight1 );
+ if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 )
+ Fxu_UpdateSingle( p );
+ else
+ break;
+ }
+ while ( ++pData->nNodesNew < pData->nNodesExt );
+ }
+ else if ( pData->fOnlyD )
+ {
+ pData->nNodesNew = 0;
+ do
+ {
+ Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+ if ( pData->fVerbose )
+ printf( "Best double = %3d.\n", Weight2 );
+ if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 )
+ Fxu_UpdateDouble( p );
+ else
+ break;
+ }
+ while ( ++pData->nNodesNew < pData->nNodesExt );
+ }
+ else if ( !pData->fUseCompl )
+ {
+ pData->nNodesNew = 0;
+ do
+ {
+ Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
+ Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+
+ if ( pData->fVerbose )
+ printf( "Best double = %3d. Best single = %3d.\n", Weight2, Weight1 );
+//Fxu_Select( p, &pSingle, &pDouble );
+
+ if ( Weight1 >= Weight2 )
+ {
+ if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 )
+ Fxu_UpdateSingle( p );
+ else
+ break;
+ }
+ else
+ {
+ if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 )
+ Fxu_UpdateDouble( p );
+ else
+ break;
+ }
+ }
+ while ( ++pData->nNodesNew < pData->nNodesExt );
+ }
+ else
+ { // use the complement
+ pData->nNodesNew = 0;
+ do
+ {
+ Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
+ Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+
+ // select the best single and double
+ Weight3 = Fxu_Select( p, &pSingle, &pDouble );
+ if ( pData->fVerbose )
+ printf( "Best double = %3d. Best single = %3d. Best complement = %3d.\n",
+ Weight2, Weight1, Weight3 );
+
+ if ( Weight3 > 0 || Weight3 == 0 && pData->fUse0 )
+ Fxu_Update( p, pSingle, pDouble );
+ else
+ break;
+ }
+ while ( ++pData->nNodesNew < pData->nNodesExt );
+ }
+
+ if ( pData->fVerbose )
+ printf( "Total single = %3d. Total double = %3d. Total compl = %3d.\n", p->nDivs1, p->nDivs2, p->nDivs3 );
+
+ // create the new covers
+ if ( pData->nNodesNew )
+ Fxu_CreateCovers( p, pData );
+ Fxu_MatrixDelete( p );
+// printf( "Memory usage after delocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
+ if ( pData->nNodesNew == pData->nNodesExt )
+ printf( "Warning: The limit on the number of extracted divisors has been reached.\n" );
+ return pData->nNodesNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the cubes in the ring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p )
+{
+ Fxu_Cube * pCube, * pCube2;
+ // unmark the cubes
+ Fxu_MatrixForEachCubeInRingSafe( p, pCube, pCube2 )
+ pCube->pOrder = NULL;
+ Fxu_MatrixRingCubesReset( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the vars in the ring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p )
+{
+ Fxu_Var * pVar, * pVar2;
+ // unmark the vars
+ Fxu_MatrixForEachVarInRingSafe( p, pVar, pVar2 )
+ pVar->pOrder = NULL;
+ Fxu_MatrixRingVarsReset( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes )
+{
+ s_MemoryTotal += nBytes;
+ if ( s_MemoryPeak < s_MemoryTotal )
+ s_MemoryPeak = s_MemoryTotal;
+// return malloc( nBytes );
+ return Extra_MmFixedEntryFetch( p->pMemMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes )
+{
+ s_MemoryTotal -= nBytes;
+// free( pItem );
+ Extra_MmFixedEntryRecycle( p->pMemMan, pItem );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxu.h b/src/opt/fxu/fxu.h
new file mode 100644
index 00000000..5bc1e75f
--- /dev/null
+++ b/src/opt/fxu/fxu.h
@@ -0,0 +1,108 @@
+/**CFile****************************************************************
+
+ FileName [fxu.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [External declarations of fast extract for unate covers.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxu.h,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __FXU_H__
+#define __FXU_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "vec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef bool
+#define bool int
+#endif
+
+typedef struct FxuDataStruct Fxu_Data_t;
+
+// structure for the FX input/output data
+struct FxuDataStruct
+{
+ // user specified parameters
+ bool fOnlyS; // set to 1 to have only single-cube divs
+ bool fOnlyD; // set to 1 to have only double-cube divs
+ bool fUse0; // set to 1 to have 0-weight also extracted
+ bool fUseCompl; // set to 1 to have complement taken into account
+ bool fVerbose; // set to 1 to have verbose output
+ int nPairsMax; // the maximum number of cube pairs to consider
+/*
+ // parameters of the network
+ int fMvNetwork; // the network has some MV nodes
+ // the information about nodes
+ int nNodesCi; // the number of CI nodes of the network
+ int nNodesInt; // the number of internal nodes of the network
+ int nNodesOld; // the number of CI and int nodes
+ int nNodesNew; // the number of added nodes
+ int nNodesExt; // the max number of (binary) nodes to be added by FX
+ int nNodesAlloc; // the total number of all nodes
+ int * pNode2Value; // for each node, the number of its first value
+ // the information about values
+ int nValuesCi; // the total number of values of CI nodes
+ int nValuesInt; // the total number of values of int nodes
+ int nValuesOld; // the number of CI and int values
+ int nValuesNew; // the number of values added nodes
+ int nValuesExt; // the total number of values of the added nodes
+ int nValuesAlloc; // the total number of all values of all nodes
+ int * pValue2Node; // for each value, the number of its node
+ // the information about covers
+ Mvc_Cover_t ** ppCovers; // for each value, the corresponding cover
+ Mvc_Cover_t ** ppCoversNew; // for each value, the corresponding cover after FX
+ // the MVC manager
+ Mvc_Manager_t * pManMvc;
+*/
+ // statistics
+ int nNodesOld; // the old number of nodes
+ int nNodesExt; // the number of divisors to extract
+ int nNodesNew; // the number of divisors extracted
+
+ // the input information
+ Vec_Ptr_t * vSops; // the SOPs for each node in the network
+ Vec_Ptr_t * vFanins; // the fanins of each node in the network
+ // output information
+ Vec_Ptr_t * vSopsNew; // the SOPs for each node in the network after extraction
+ Vec_Ptr_t * vFaninsNew; // the fanins of each node in the network after extraction
+ // the SOP manager
+ Extra_MmFlex_t * pManSop;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*===== fxu.c ==========================================================*/
+extern int Fxu_FastExtract( Fxu_Data_t * pData );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/src/opt/fxu/fxuCreate.c b/src/opt/fxu/fxuCreate.c
new file mode 100644
index 00000000..04b23fce
--- /dev/null
+++ b/src/opt/fxu/fxuCreate.c
@@ -0,0 +1,425 @@
+/**CFile****************************************************************
+
+ FileName [fxuCreate.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Create matrix from covers and covers from matrix.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuCreate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fxuInt.h"
+#include "fxu.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax );
+
+static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder );
+static int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY );
+static void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext );
+static Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode );
+static Abc_Fan_t * s_pLits;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the sparse matrix from the array of Sop covers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
+{
+ Fxu_Matrix * p;
+ Fxu_Var * pVar;
+ Fxu_Cube * pCubeFirst, * pCubeNew;
+ Fxu_Cube * pCube1, * pCube2;
+ char * pSopCover;
+ char * pSopCube;
+ int * pOrder, nBitsMax;
+ int i, v, c;
+ int nCubesTotal;
+ int nPairsTotal;
+ int nPairsStore;
+ int nCubes;
+ int iCube, iPair;
+ int nFanins;
+ Vec_Fan_t * vFanins;
+
+ // collect all sorts of statistics
+ nCubesTotal = 0;
+ nPairsTotal = 0;
+ nPairsStore = 0;
+ nBitsMax = -1;
+ for ( i = 0; i < pData->nNodesOld; i++ )
+ if ( pSopCover = pData->vSops->pArray[i] )
+ {
+ nCubes = Abc_SopGetCubeNum( pSopCover );
+ nFanins = Abc_SopGetVarNum( pSopCover );
+ assert( nFanins > 1 && nCubes > 0 );
+
+ nCubesTotal += nCubes;
+ nPairsTotal += nCubes * (nCubes - 1) / 2;
+ nPairsStore += nCubes * nCubes;
+ if ( nBitsMax < nFanins )
+ nBitsMax = nFanins;
+ }
+ if ( nBitsMax <= 0 )
+ {
+ printf( "The current network does not have SOPs to perform extraction.\n" );
+ return NULL;
+ }
+
+ if ( nPairsStore > 10000000 )
+ {
+ printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore );
+ return NULL;
+ }
+
+ // start the matrix
+ p = Fxu_MatrixAllocate();
+ // create the column labels
+ p->ppVars = ALLOC( Fxu_Var *, 2 * (pData->nNodesOld + pData->nNodesExt) );
+ for ( i = 0; i < 2 * pData->nNodesOld; i++ )
+ p->ppVars[i] = Fxu_MatrixAddVar( p );
+
+ // allocate storage for all cube pairs at once
+ p->pppPairs = ALLOC( Fxu_Pair **, nCubesTotal + 100 );
+ p->ppPairs = ALLOC( Fxu_Pair *, nPairsStore + 100 );
+ memset( p->ppPairs, 0, sizeof(Fxu_Pair *) * nPairsStore );
+ iCube = 0;
+ iPair = 0;
+ for ( i = 0; i < pData->nNodesOld; i++ )
+ if ( pSopCover = pData->vSops->pArray[i] )
+ {
+ // get the number of cubes
+ nCubes = Abc_SopGetCubeNum( pSopCover );
+ // get the new var in the matrix
+ pVar = p->ppVars[2*i+1];
+ // assign the pair storage
+ pVar->nCubes = nCubes;
+ if ( nCubes > 0 )
+ {
+ pVar->ppPairs = p->pppPairs + iCube;
+ pVar->ppPairs[0] = p->ppPairs + iPair;
+ for ( v = 1; v < nCubes; v++ )
+ pVar->ppPairs[v] = pVar->ppPairs[v-1] + nCubes;
+ }
+ // update
+ iCube += nCubes;
+ iPair += nCubes * nCubes;
+ }
+ assert( iCube == nCubesTotal );
+ assert( iPair == nPairsStore );
+
+
+ // allocate room for the reordered literals
+ pOrder = ALLOC( int, nBitsMax );
+ // create the rows
+ for ( i = 0; i < pData->nNodesOld; i++ )
+ if ( pSopCover = pData->vSops->pArray[i] )
+ {
+ // get the new var in the matrix
+ pVar = p->ppVars[2*i+1];
+ // here we sort the literals of the cover
+ // in the increasing order of the numbers of the corresponding nodes
+ // because literals should be added to the matrix in this order
+ vFanins = pData->vFanins->pArray[i];
+ s_pLits = vFanins->pArray;
+ // start the variable order
+ nFanins = Abc_SopGetVarNum( pSopCover );
+ for ( v = 0; v < nFanins; v++ )
+ pOrder[v] = v;
+ // reorder the fanins
+ qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare);
+ assert( s_pLits[ pOrder[0] ].iFan < s_pLits[ pOrder[nFanins-1] ].iFan );
+ // create the corresponding cubes in the matrix
+ pCubeFirst = NULL;
+ c = 0;
+ Abc_SopForEachCube( pSopCover, nFanins, pSopCube )
+ {
+ // create the cube
+ pCubeNew = Fxu_MatrixAddCube( p, pVar, c );
+ Fxu_CreateMatrixAddCube( p, pCubeNew, pSopCube, vFanins, pOrder );
+ if ( pCubeFirst == NULL )
+ pCubeFirst = pCubeNew;
+ pCubeNew->pFirst = pCubeFirst;
+ c++;
+ }
+ // set the first cube of this var
+ pVar->pFirst = pCubeFirst;
+ // create the divisors without preprocessing
+ if ( nPairsTotal <= pData->nPairsMax )
+ {
+ for ( pCube1 = pCubeFirst; pCube1; pCube1 = pCube1->pNext )
+ for ( pCube2 = pCube1? pCube1->pNext: NULL; pCube2; pCube2 = pCube2->pNext )
+ Fxu_MatrixAddDivisor( p, pCube1, pCube2 );
+ }
+ }
+ FREE( pOrder );
+
+ // consider the case when cube pairs should be preprocessed
+ // before adding them to the set of divisors
+ if ( nPairsTotal > pData->nPairsMax )
+ Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax );
+
+ // add the var pairs to the heap
+ Fxu_MatrixComputeSingles( p );
+
+ // allocate temporary storage for pairs
+ if ( pData->nPairsMax < 1000 )
+ pData->nPairsMax = 1000;
+ p->pPairsTemp = ALLOC( Fxu_Pair *, pData->nPairsMax * 10 + 100 );
+ if ( pData->fVerbose )
+ {
+ double Density;
+ Density = ((double)p->nEntries) / p->lVars.nItems / p->lCubes.nItems;
+ fprintf( stdout, "Matrix: [vars x cubes] = [%d x %d] ",
+ p->lVars.nItems, p->lCubes.nItems );
+ fprintf( stdout, "Lits = %d Density = %.5f%%\n",
+ p->nEntries, Density );
+ fprintf( stdout, "1-cube divisors = %6d. ", p->lSingles.nItems );
+ fprintf( stdout, "2-cube divisors = %6d. ", p->nDivsTotal );
+ fprintf( stdout, "Cube pairs = %6d.", nPairsTotal );
+ fprintf( stdout, "\n" );
+ }
+// Fxu_MatrixPrint( stdout, p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one cube with literals to the matrix.]
+
+ Description [Create the cube and literals in the matrix corresponding
+ to the given cube in the SOP cover. Co-singleton transform is performed here.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder )
+{
+ Fxu_Var * pVar;
+ int Value, i;
+ // add literals to the matrix
+ Abc_CubeForEachVar( pSopCube, Value, i )
+ {
+ Value = pSopCube[pOrder[i]];
+ if ( Value == '0' )
+ {
+ pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan + 1 ]; // CST
+ Fxu_MatrixAddLiteral( p, pCube, pVar );
+ }
+ else if ( Value == '1' )
+ {
+ pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan ]; // CST
+ Fxu_MatrixAddLiteral( p, pCube, pVar );
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates the new array of Sop covers from the sparse matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData )
+{
+ Fxu_Cube * pCube, * pCubeFirst, * pCubeNext;
+ int iNode, n;
+ char * pSopCover;
+
+ // get the first cube of the first internal node
+ pCubeFirst = Fxu_CreateCoversFirstCube( p, pData, 0 );
+
+ // go through the internal nodes
+ for ( n = 0; n < pData->nNodesOld; n++ )
+ if ( pSopCover = pData->vSops->pArray[n] )
+ {
+ // get the number of this node
+ iNode = n;
+ // get the next first cube
+ pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 );
+ // check if there any new variables in these cubes
+ for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+ if ( pCube->lLits.pTail && pCube->lLits.pTail->iVar >= 2 * pData->nNodesOld )
+ break;
+ if ( pCube != pCubeNext )
+ Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext );
+ // update the first cube
+ pCubeFirst = pCubeNext;
+ }
+
+ // add the covers for the extracted nodes
+ for ( n = 0; n < pData->nNodesNew; n++ )
+ {
+ // get the number of this node
+ iNode = pData->nNodesOld + n;
+ // get the next first cube
+ pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 );
+ // the node should be added
+ Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext );
+ // update the first cube
+ pCubeFirst = pCubeNext;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create Sop covers for one node that has changed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext )
+{
+ Vec_Int_t * vInputsNew;
+ char * pSopCover;
+ char * pSopCube;
+ Fxu_Var * pVar;
+ Fxu_Cube * pCube;
+ Fxu_Lit * pLit;
+ int iNum, nCubes, v;
+ int fEmptyCube;
+
+ // collect positive polarity variable in the cubes between pCubeFirst and pCubeNext
+ Fxu_MatrixRingVarsStart( p );
+ for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+ for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext )
+ {
+ pVar = p->ppVars[ 2 * (pLit->pVar->iVar/2) + 1 ];
+ if ( pVar->pOrder == NULL )
+ Fxu_MatrixRingVarsAdd( p, pVar );
+ }
+ Fxu_MatrixRingVarsStop( p );
+
+ // collect the variable numbers
+ vInputsNew = Vec_IntAlloc( 4 );
+ Fxu_MatrixForEachVarInRing( p, pVar )
+ Vec_IntPush( vInputsNew, pVar->iVar / 2 );
+ Fxu_MatrixRingVarsUnmark( p );
+
+ // sort the vars by their number
+ Vec_IntSort( vInputsNew, 0 );
+
+ // mark the vars with their numbers in the sorted array
+ for ( v = 0; v < vInputsNew->nSize; v++ )
+ {
+ p->ppVars[ 2 * vInputsNew->pArray[v] + 0 ]->lLits.nItems = v; // hack - reuse lLits.nItems
+ p->ppVars[ 2 * vInputsNew->pArray[v] + 1 ]->lLits.nItems = v; // hack - reuse lLits.nItems
+ }
+
+ // count the number of cubes
+ nCubes = 0;
+ for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+ if ( pCube->lLits.nItems )
+ nCubes++;
+
+ // allocate room for the new cover
+ pSopCover = Abc_SopStart( pData->pManSop, nCubes, vInputsNew->nSize );
+ // set the correct polarity of the cover
+ if ( iNode < pData->nNodesOld && Abc_SopGetPhase( pData->vSops->pArray[iNode] ) == 0 )
+ Abc_SopComplement( pSopCover );
+
+ // add the cubes
+ nCubes = 0;
+ for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext )
+ {
+ if ( pCube->lLits.nItems == 0 )
+ continue;
+ // get hold of the SOP cube
+ pSopCube = pSopCover + nCubes * (vInputsNew->nSize + 3);
+ // insert literals
+ fEmptyCube = 1;
+ for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext )
+ {
+ iNum = pLit->pVar->lLits.nItems; // hack - reuse lLits.nItems
+ assert( iNum < vInputsNew->nSize );
+ if ( pLit->pVar->iVar / 2 < pData->nNodesOld )
+ pSopCube[iNum] = (pLit->pVar->iVar & 1)? '0' : '1'; // reverse CST
+ else
+ pSopCube[iNum] = (pLit->pVar->iVar & 1)? '1' : '0'; // no CST
+ fEmptyCube = 0;
+ }
+ assert( !fEmptyCube );
+ // count the cube
+ nCubes++;
+ }
+ assert( nCubes == Abc_SopGetCubeNum(pSopCover) );
+
+ pData->vSopsNew->pArray[iNode] = pSopCover;
+ pData->vFaninsNew->pArray[iNode] = vInputsNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds the var to storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iVar )
+{
+ int v;
+ for ( v = iVar; v < pData->nNodesOld + pData->nNodesNew; v++ )
+ if ( p->ppVars[ 2*v + 1 ]->pFirst )
+ return p->ppVars[ 2*v + 1 ]->pFirst;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the vars by their number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY )
+{
+ return s_pLits[*ptrX].iFan - s_pLits[*ptrY].iFan;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/fxu/fxuHeapD.c b/src/opt/fxu/fxuHeapD.c
new file mode 100644
index 00000000..7c123249
--- /dev/null
+++ b/src/opt/fxu/fxuHeapD.c
@@ -0,0 +1,445 @@
+/**CFile****************************************************************
+
+ FileName [fxuHeapD.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [The priority queue for double cube divisors.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuHeapD.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define FXU_HEAP_DOUBLE_WEIGHT(pDiv) ((pDiv)->Weight)
+#define FXU_HEAP_DOUBLE_CURRENT(p, pDiv) ((p)->pTree[(pDiv)->HNum])
+#define FXU_HEAP_DOUBLE_PARENT_EXISTS(p, pDiv) ((pDiv)->HNum > 1)
+#define FXU_HEAP_DOUBLE_CHILD1_EXISTS(p, pDiv) (((pDiv)->HNum << 1) <= p->nItems)
+#define FXU_HEAP_DOUBLE_CHILD2_EXISTS(p, pDiv) ((((pDiv)->HNum << 1)+1) <= p->nItems)
+#define FXU_HEAP_DOUBLE_PARENT(p, pDiv) ((p)->pTree[(pDiv)->HNum >> 1])
+#define FXU_HEAP_DOUBLE_CHILD1(p, pDiv) ((p)->pTree[(pDiv)->HNum << 1])
+#define FXU_HEAP_DOUBLE_CHILD2(p, pDiv) ((p)->pTree[((pDiv)->HNum << 1)+1])
+#define FXU_HEAP_DOUBLE_ASSERT(p, pDiv) assert( (pDiv)->HNum >= 1 && (pDiv)->HNum <= p->nItemsAlloc )
+
+static void Fxu_HeapDoubleResize( Fxu_HeapDouble * p );
+static void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 );
+static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv );
+static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_HeapDouble * Fxu_HeapDoubleStart()
+{
+ Fxu_HeapDouble * p;
+ p = ALLOC( Fxu_HeapDouble, 1 );
+ memset( p, 0, sizeof(Fxu_HeapDouble) );
+ p->nItems = 0;
+ p->nItemsAlloc = 10000;
+ p->pTree = ALLOC( Fxu_Double *, p->nItemsAlloc + 1 );
+ p->pTree[0] = NULL;
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleResize( Fxu_HeapDouble * p )
+{
+ p->nItemsAlloc *= 2;
+ p->pTree = REALLOC( Fxu_Double *, p->pTree, p->nItemsAlloc + 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleStop( Fxu_HeapDouble * p )
+{
+ free( p->pTree );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p )
+{
+ Fxu_Double * pDiv;
+ int Counter = 1;
+ int Degree = 1;
+
+ Fxu_HeapDoubleCheck( p );
+ fprintf( pFile, "The contents of the heap:\n" );
+ fprintf( pFile, "Level %d: ", Degree );
+ Fxu_HeapDoubleForEachItem( p, pDiv )
+ {
+ assert( Counter == p->pTree[Counter]->HNum );
+ fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_DOUBLE_WEIGHT(p->pTree[Counter]) );
+ if ( ++Counter == (1 << Degree) )
+ {
+ fprintf( pFile, "\n" );
+ Degree++;
+ fprintf( pFile, "Level %d: ", Degree );
+ }
+ }
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "End of the heap printout.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p )
+{
+ Fxu_Double * pDiv;
+ Fxu_HeapDoubleForEachItem( p, pDiv )
+ {
+ assert( pDiv->HNum == p->i );
+ Fxu_HeapDoubleCheckOne( p, pDiv );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+ int Weight1, Weight2;
+ if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) )
+ {
+ Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv);
+ Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) );
+ assert( Weight1 >= Weight2 );
+ }
+ if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) )
+ {
+ Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv);
+ Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) );
+ assert( Weight1 >= Weight2 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+ if ( p->nItems == p->nItemsAlloc )
+ Fxu_HeapDoubleResize( p );
+ // put the last entry to the last place and move up
+ p->pTree[++p->nItems] = pDiv;
+ pDiv->HNum = p->nItems;
+ // move the last entry up if necessary
+ Fxu_HeapDoubleMoveUp( p, pDiv );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+//printf( "Updating divisor %d.\n", pDiv->Num );
+
+ FXU_HEAP_DOUBLE_ASSERT(p,pDiv);
+ if ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,pDiv) &&
+ FXU_HEAP_DOUBLE_WEIGHT(pDiv) > FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_PARENT(p,pDiv) ) )
+ Fxu_HeapDoubleMoveUp( p, pDiv );
+ else if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) &&
+ FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ) )
+ Fxu_HeapDoubleMoveDn( p, pDiv );
+ else if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) &&
+ FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ) )
+ Fxu_HeapDoubleMoveDn( p, pDiv );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+ FXU_HEAP_DOUBLE_ASSERT(p,pDiv);
+ // put the last entry to the deleted place
+ // decrement the number of entries
+ p->pTree[pDiv->HNum] = p->pTree[p->nItems--];
+ p->pTree[pDiv->HNum]->HNum = pDiv->HNum;
+ // move the top entry down if necessary
+ Fxu_HeapDoubleUpdate( p, p->pTree[pDiv->HNum] );
+ pDiv->HNum = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p )
+{
+ if ( p->nItems == 0 )
+ return NULL;
+ return p->pTree[1];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p )
+{
+ Fxu_Double * pDiv;
+ if ( p->nItems == 0 )
+ return NULL;
+ // prepare the return value
+ pDiv = p->pTree[1];
+ pDiv->HNum = 0;
+ // put the last entry on top
+ // decrement the number of entries
+ p->pTree[1] = p->pTree[p->nItems--];
+ p->pTree[1]->HNum = 1;
+ // move the top entry down if necessary
+ Fxu_HeapDoubleMoveDn( p, p->pTree[1] );
+ return pDiv;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p )
+{
+ if ( p->nItems == 0 )
+ return -1;
+ else
+ return FXU_HEAP_DOUBLE_WEIGHT(p->pTree[1]);
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 )
+{
+ Fxu_Double * pDiv;
+ int Temp;
+ pDiv = *pDiv1;
+ *pDiv1 = *pDiv2;
+ *pDiv2 = pDiv;
+ Temp = (*pDiv1)->HNum;
+ (*pDiv1)->HNum = (*pDiv2)->HNum;
+ (*pDiv2)->HNum = Temp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+ Fxu_Double ** ppDiv, ** ppPar;
+ ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv);
+ while ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,*ppDiv) )
+ {
+ ppPar = &FXU_HEAP_DOUBLE_PARENT(p,*ppDiv);
+ if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) > FXU_HEAP_DOUBLE_WEIGHT(*ppPar) )
+ {
+ Fxu_HeapDoubleSwap( ppDiv, ppPar );
+ ppDiv = ppPar;
+ }
+ else
+ break;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv )
+{
+ Fxu_Double ** ppChild1, ** ppChild2, ** ppDiv;
+ ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv);
+ while ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,*ppDiv) )
+ { // if Child1 does not exist, Child2 also does not exists
+
+ // get the children
+ ppChild1 = &FXU_HEAP_DOUBLE_CHILD1(p,*ppDiv);
+ if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,*ppDiv) )
+ {
+ ppChild2 = &FXU_HEAP_DOUBLE_CHILD2(p,*ppDiv);
+
+ // consider two cases
+ if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) &&
+ FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) )
+ { // Div is larger than both, skip
+ break;
+ }
+ else
+ { // Div is smaller than one of them, then swap it with larger
+ if ( FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) )
+ {
+ Fxu_HeapDoubleSwap( ppDiv, ppChild1 );
+ // update the pointer
+ ppDiv = ppChild1;
+ }
+ else
+ {
+ Fxu_HeapDoubleSwap( ppDiv, ppChild2 );
+ // update the pointer
+ ppDiv = ppChild2;
+ }
+ }
+ }
+ else // Child2 does not exist
+ {
+ // consider two cases
+ if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) )
+ { // Div is larger than Child1, skip
+ break;
+ }
+ else
+ { // Div is smaller than Child1, then swap them
+ Fxu_HeapDoubleSwap( ppDiv, ppChild1 );
+ // update the pointer
+ ppDiv = ppChild1;
+ }
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuHeapS.c b/src/opt/fxu/fxuHeapS.c
new file mode 100644
index 00000000..dbd66055
--- /dev/null
+++ b/src/opt/fxu/fxuHeapS.c
@@ -0,0 +1,444 @@
+/**CFile****************************************************************
+
+ FileName [fxuHeapS.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [The priority queue for variables.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuHeapS.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define FXU_HEAP_SINGLE_WEIGHT(pSingle) ((pSingle)->Weight)
+#define FXU_HEAP_SINGLE_CURRENT(p, pSingle) ((p)->pTree[(pSingle)->HNum])
+#define FXU_HEAP_SINGLE_PARENT_EXISTS(p, pSingle) ((pSingle)->HNum > 1)
+#define FXU_HEAP_SINGLE_CHILD1_EXISTS(p, pSingle) (((pSingle)->HNum << 1) <= p->nItems)
+#define FXU_HEAP_SINGLE_CHILD2_EXISTS(p, pSingle) ((((pSingle)->HNum << 1)+1) <= p->nItems)
+#define FXU_HEAP_SINGLE_PARENT(p, pSingle) ((p)->pTree[(pSingle)->HNum >> 1])
+#define FXU_HEAP_SINGLE_CHILD1(p, pSingle) ((p)->pTree[(pSingle)->HNum << 1])
+#define FXU_HEAP_SINGLE_CHILD2(p, pSingle) ((p)->pTree[((pSingle)->HNum << 1)+1])
+#define FXU_HEAP_SINGLE_ASSERT(p, pSingle) assert( (pSingle)->HNum >= 1 && (pSingle)->HNum <= p->nItemsAlloc )
+
+static void Fxu_HeapSingleResize( Fxu_HeapSingle * p );
+static void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 );
+static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle );
+static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_HeapSingle * Fxu_HeapSingleStart()
+{
+ Fxu_HeapSingle * p;
+ p = ALLOC( Fxu_HeapSingle, 1 );
+ memset( p, 0, sizeof(Fxu_HeapSingle) );
+ p->nItems = 0;
+ p->nItemsAlloc = 2000;
+ p->pTree = ALLOC( Fxu_Single *, p->nItemsAlloc + 10 );
+ p->pTree[0] = NULL;
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleResize( Fxu_HeapSingle * p )
+{
+ p->nItemsAlloc *= 2;
+ p->pTree = REALLOC( Fxu_Single *, p->pTree, p->nItemsAlloc + 10 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleStop( Fxu_HeapSingle * p )
+{
+ int i;
+ i = 0;
+ free( p->pTree );
+ i = 1;
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p )
+{
+ Fxu_Single * pSingle;
+ int Counter = 1;
+ int Degree = 1;
+
+ Fxu_HeapSingleCheck( p );
+ fprintf( pFile, "The contents of the heap:\n" );
+ fprintf( pFile, "Level %d: ", Degree );
+ Fxu_HeapSingleForEachItem( p, pSingle )
+ {
+ assert( Counter == p->pTree[Counter]->HNum );
+ fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_SINGLE_WEIGHT(p->pTree[Counter]) );
+ if ( ++Counter == (1 << Degree) )
+ {
+ fprintf( pFile, "\n" );
+ Degree++;
+ fprintf( pFile, "Level %d: ", Degree );
+ }
+ }
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "End of the heap printout.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleCheck( Fxu_HeapSingle * p )
+{
+ Fxu_Single * pSingle;
+ Fxu_HeapSingleForEachItem( p, pSingle )
+ {
+ assert( pSingle->HNum == p->i );
+ Fxu_HeapSingleCheckOne( p, pSingle );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+ int Weight1, Weight2;
+ if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) )
+ {
+ Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle);
+ Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) );
+ assert( Weight1 >= Weight2 );
+ }
+ if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) )
+ {
+ Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle);
+ Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) );
+ assert( Weight1 >= Weight2 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+ if ( p->nItems == p->nItemsAlloc )
+ Fxu_HeapSingleResize( p );
+ // put the last entry to the last place and move up
+ p->pTree[++p->nItems] = pSingle;
+ pSingle->HNum = p->nItems;
+ // move the last entry up if necessary
+ Fxu_HeapSingleMoveUp( p, pSingle );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+ FXU_HEAP_SINGLE_ASSERT(p,pSingle);
+ if ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,pSingle) &&
+ FXU_HEAP_SINGLE_WEIGHT(pSingle) > FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_PARENT(p,pSingle) ) )
+ Fxu_HeapSingleMoveUp( p, pSingle );
+ else if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) &&
+ FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ) )
+ Fxu_HeapSingleMoveDn( p, pSingle );
+ else if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) &&
+ FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ) )
+ Fxu_HeapSingleMoveDn( p, pSingle );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+ int Place = pSingle->HNum;
+ FXU_HEAP_SINGLE_ASSERT(p,pSingle);
+ // put the last entry to the deleted place
+ // decrement the number of entries
+ p->pTree[Place] = p->pTree[p->nItems--];
+ p->pTree[Place]->HNum = Place;
+ // move the top entry down if necessary
+ Fxu_HeapSingleUpdate( p, p->pTree[Place] );
+ pSingle->HNum = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p )
+{
+ if ( p->nItems == 0 )
+ return NULL;
+ return p->pTree[1];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p )
+{
+ Fxu_Single * pSingle;
+ if ( p->nItems == 0 )
+ return NULL;
+ // prepare the return value
+ pSingle = p->pTree[1];
+ pSingle->HNum = 0;
+ // put the last entry on top
+ // decrement the number of entries
+ p->pTree[1] = p->pTree[p->nItems--];
+ p->pTree[1]->HNum = 1;
+ // move the top entry down if necessary
+ Fxu_HeapSingleMoveDn( p, p->pTree[1] );
+ return pSingle;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p )
+{
+ if ( p->nItems == 0 )
+ return -1;
+ return FXU_HEAP_SINGLE_WEIGHT(p->pTree[1]);
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 )
+{
+ Fxu_Single * pSingle;
+ int Temp;
+ pSingle = *pSingle1;
+ *pSingle1 = *pSingle2;
+ *pSingle2 = pSingle;
+ Temp = (*pSingle1)->HNum;
+ (*pSingle1)->HNum = (*pSingle2)->HNum;
+ (*pSingle2)->HNum = Temp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+ Fxu_Single ** ppSingle, ** ppPar;
+ ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle);
+ while ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,*ppSingle) )
+ {
+ ppPar = &FXU_HEAP_SINGLE_PARENT(p,*ppSingle);
+ if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) > FXU_HEAP_SINGLE_WEIGHT(*ppPar) )
+ {
+ Fxu_HeapSingleSwap( ppSingle, ppPar );
+ ppSingle = ppPar;
+ }
+ else
+ break;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle )
+{
+ Fxu_Single ** ppChild1, ** ppChild2, ** ppSingle;
+ ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle);
+ while ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,*ppSingle) )
+ { // if Child1 does not exist, Child2 also does not exists
+
+ // get the children
+ ppChild1 = &FXU_HEAP_SINGLE_CHILD1(p,*ppSingle);
+ if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,*ppSingle) )
+ {
+ ppChild2 = &FXU_HEAP_SINGLE_CHILD2(p,*ppSingle);
+
+ // consider two cases
+ if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) &&
+ FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) )
+ { // Var is larger than both, skip
+ break;
+ }
+ else
+ { // Var is smaller than one of them, then swap it with larger
+ if ( FXU_HEAP_SINGLE_WEIGHT(*ppChild1) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) )
+ {
+ Fxu_HeapSingleSwap( ppSingle, ppChild1 );
+ // update the pointer
+ ppSingle = ppChild1;
+ }
+ else
+ {
+ Fxu_HeapSingleSwap( ppSingle, ppChild2 );
+ // update the pointer
+ ppSingle = ppChild2;
+ }
+ }
+ }
+ else // Child2 does not exist
+ {
+ // consider two cases
+ if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) )
+ { // Var is larger than Child1, skip
+ break;
+ }
+ else
+ { // Var is smaller than Child1, then swap them
+ Fxu_HeapSingleSwap( ppSingle, ppChild1 );
+ // update the pointer
+ ppSingle = ppChild1;
+ }
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h
new file mode 100644
index 00000000..1f5a19b8
--- /dev/null
+++ b/src/opt/fxu/fxuInt.h
@@ -0,0 +1,541 @@
+/**CFile****************************************************************
+
+ FileName [fxuInt.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Internal declarations of fast extract for unate covers.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuInt.h,v 1.3 2003/04/10 05:42:44 donald Exp $]
+
+***********************************************************************/
+
+#ifndef __FXU_INT_H__
+#define __FXU_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "util.h"
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+// uncomment this macro to switch to standard memory management
+//#define USE_SYSTEM_MEMORY_MANAGEMENT
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+ Here is an informal description of the FX data structure.
+ (1) The sparse matrix is filled with literals, associated with
+ cubes (row) and variables (columns). The matrix contains
+ all the cubes of all the nodes in the network.
+ (2) A cube is associated with
+ (a) its literals in the matrix,
+ (b) the output variable of the node, to which this cube belongs,
+ (3) A variable is associated with
+ (a) its literals in the matrix and
+ (b) the list of cube pairs in the cover, for which it is the output
+ (4) A cube pair is associated with two cubes and contains the counters
+ of literals in the base and in the cubes without the base
+ (5) A double-cube divisor is associated with list of all cube pairs
+ that produce it and its current weight (which is updated automatically
+ each time a new pair is added or an old pair is removed).
+ (6) A single-cube divisor is associated the pair of variables.
+*/
+
+// sparse matrix
+typedef struct FxuMatrix Fxu_Matrix; // the sparse matrix
+
+// sparse matrix contents: cubes (rows), vars (columns), literals (entries)
+typedef struct FxuCube Fxu_Cube; // one cube in the sparse matrix
+typedef struct FxuVar Fxu_Var; // one literal in the sparse matrix
+typedef struct FxuLit Fxu_Lit; // one entry in the sparse matrix
+
+// double cube divisors
+typedef struct FxuPair Fxu_Pair; // the pair of cubes
+typedef struct FxuDouble Fxu_Double; // the double-cube divisor
+typedef struct FxuSingle Fxu_Single; // the two-literal single-cube divisor
+
+// various lists
+typedef struct FxuListCube Fxu_ListCube; // the list of cubes
+typedef struct FxuListVar Fxu_ListVar; // the list of literals
+typedef struct FxuListLit Fxu_ListLit; // the list of entries
+typedef struct FxuListPair Fxu_ListPair; // the list of pairs
+typedef struct FxuListDouble Fxu_ListDouble; // the list of divisors
+typedef struct FxuListSingle Fxu_ListSingle; // the list of single-cube divisors
+
+// various heaps
+typedef struct FxuHeapDouble Fxu_HeapDouble; // the heap of divisors
+typedef struct FxuHeapSingle Fxu_HeapSingle; // the heap of variables
+
+
+// various lists
+
+// the list of cubes in the sparse matrix
+struct FxuListCube
+{
+ Fxu_Cube * pHead;
+ Fxu_Cube * pTail;
+ int nItems;
+};
+
+// the list of literals in the sparse matrix
+struct FxuListVar
+{
+ Fxu_Var * pHead;
+ Fxu_Var * pTail;
+ int nItems;
+};
+
+// the list of entries in the sparse matrix
+struct FxuListLit
+{
+ Fxu_Lit * pHead;
+ Fxu_Lit * pTail;
+ int nItems;
+};
+
+// the list of cube pair in the sparse matrix
+struct FxuListPair
+{
+ Fxu_Pair * pHead;
+ Fxu_Pair * pTail;
+ int nItems;
+};
+
+// the list of divisors in the sparse matrix
+struct FxuListDouble
+{
+ Fxu_Double * pHead;
+ Fxu_Double * pTail;
+ int nItems;
+};
+
+// the list of divisors in the sparse matrix
+struct FxuListSingle
+{
+ Fxu_Single * pHead;
+ Fxu_Single * pTail;
+ int nItems;
+};
+
+
+// various heaps
+
+// the heap of double cube divisors by weight
+struct FxuHeapDouble
+{
+ Fxu_Double ** pTree;
+ int nItems;
+ int nItemsAlloc;
+ int i;
+};
+
+// the heap of variable by their occurrence in the cubes
+struct FxuHeapSingle
+{
+ Fxu_Single ** pTree;
+ int nItems;
+ int nItemsAlloc;
+ int i;
+};
+
+
+
+// sparse matrix
+struct FxuMatrix // ~ 30 words
+{
+ // information about the network
+// int fMvNetwork; // set to 1 if the network has MV nodes
+// int * pValue2Node; // the mapping of values into nodes
+ // the cubes
+ Fxu_ListCube lCubes; // the double linked list of cubes
+ // the values (binary literals)
+ Fxu_ListVar lVars; // the double linked list of variables
+ Fxu_Var ** ppVars; // the array of variables
+ // the double cube divisors
+ Fxu_ListDouble * pTable; // the hash table of divisors
+ int nTableSize; // the hash table size
+ int nDivs; // the number of divisors in the table
+ int nDivsTotal; // the number of divisors in the table
+ Fxu_HeapDouble * pHeapDouble; // the heap of divisors by weight
+ // the single cube divisors
+ Fxu_ListSingle lSingles; // the linked list of single cube divisors
+ Fxu_HeapSingle * pHeapSingle; // the heap of variables by the number of literals in the matrix
+ // storage for cube pairs
+ Fxu_Pair *** pppPairs;
+ Fxu_Pair ** ppPairs;
+ // temporary storage for cubes
+ Fxu_Cube * pOrderCubes;
+ Fxu_Cube ** ppTailCubes;
+ // temporary storage for variables
+ Fxu_Var * pOrderVars;
+ Fxu_Var ** ppTailVars;
+ // temporary storage for pairs
+ Fxu_Pair ** pPairsTemp;
+ int nPairsTemp;
+// int nPairsMax;
+ // statistics
+ int nEntries; // the total number of entries in the sparse matrix
+ int nDivs1; // the single cube divisors taken
+ int nDivs2; // the double cube divisors taken
+ int nDivs3; // the double cube divisors with complement
+ // memory manager
+ Extra_MmFixed_t * pMemMan; // the memory manager for all small sized entries
+};
+
+// the cube in the sparse matrix
+struct FxuCube // 9 words
+{
+ int iCube; // the number of this cube in the cover
+ Fxu_Cube * pFirst; // the pointer to the first cube of this cover
+ Fxu_Var * pVar; // the variable representing the output of the cover
+ Fxu_ListLit lLits; // the row in the table
+ Fxu_Cube * pPrev; // the previous cube
+ Fxu_Cube * pNext; // the next cube
+ Fxu_Cube * pOrder; // the specialized linked list of cubes
+};
+
+// the variable in the sparse matrix
+struct FxuVar // 10 words
+{
+ int iVar; // the number of this variable
+ int nCubes; // the number of cubes assoc with this var
+ Fxu_Cube * pFirst; // the first cube assoc with this var
+ Fxu_Pair *** ppPairs; // the pairs of cubes assoc with this var
+ Fxu_ListLit lLits; // the column in the table
+ Fxu_Var * pPrev; // the previous variable
+ Fxu_Var * pNext; // the next variable
+ Fxu_Var * pOrder; // the specialized linked list of variables
+};
+
+// the literal entry in the sparse matrix
+struct FxuLit // 8 words
+{
+ int iVar; // the number of this variable
+ int iCube; // the number of this cube
+ Fxu_Cube * pCube; // the cube of this literal
+ Fxu_Var * pVar; // the variable of this literal
+ Fxu_Lit * pHPrev; // prev lit in the cube
+ Fxu_Lit * pHNext; // next lit in the cube
+ Fxu_Lit * pVPrev; // prev lit of the var
+ Fxu_Lit * pVNext; // next lit of the var
+};
+
+// the cube pair
+struct FxuPair // 10 words
+{
+ int nLits1; // the number of literals in the two cubes
+ int nLits2; // the number of literals in the two cubes
+ int nBase; // the number of literals in the base
+ Fxu_Double * pDiv; // the divisor of this pair
+ Fxu_Cube * pCube1; // the first cube of the pair
+ Fxu_Cube * pCube2; // the second cube of the pair
+ int iCube1; // the first cube of the pair
+ int iCube2; // the second cube of the pair
+ Fxu_Pair * pDPrev; // the previous pair in the divisor
+ Fxu_Pair * pDNext; // the next pair in the divisor
+};
+
+// the double cube divisor
+struct FxuDouble // 10 words
+{
+ int Num; // the unique number of this divisor
+ int HNum; // the heap number of this divisor
+ int Weight; // the weight of this divisor
+ unsigned Key; // the hash key of this divisor
+ Fxu_ListPair lPairs; // the pairs of cubes, which produce this divisor
+ Fxu_Double * pPrev; // the previous divisor in the table
+ Fxu_Double * pNext; // the next divisor in the table
+ Fxu_Double * pOrder; // the specialized linked list of divisors
+};
+
+// the single cube divisor
+struct FxuSingle // 7 words
+{
+ int Num; // the unique number of this divisor
+ int HNum; // the heap number of this divisor
+ int Weight; // the weight of this divisor
+ Fxu_Var * pVar1; // the first variable of the single-cube divisor
+ Fxu_Var * pVar2; // the second variable of the single-cube divisor
+ Fxu_Single * pPrev; // the previous divisor in the list
+ Fxu_Single * pNext; // the next divisor in the list
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// minimum/maximum
+#define Fxu_Min( a, b ) ( ((a)<(b))? (a):(b) )
+#define Fxu_Max( a, b ) ( ((a)>(b))? (a):(b) )
+
+// selection of the minimum/maximum cube in the pair
+#define Fxu_PairMinCube( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2)
+#define Fxu_PairMaxCube( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2)
+#define Fxu_PairMinCubeInt( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2)
+#define Fxu_PairMaxCubeInt( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2)
+
+// iterators
+
+#define Fxu_MatrixForEachCube( Matrix, Cube )\
+ for ( Cube = (Matrix)->lCubes.pHead;\
+ Cube;\
+ Cube = Cube->pNext )
+#define Fxu_MatrixForEachCubeSafe( Matrix, Cube, Cube2 )\
+ for ( Cube = (Matrix)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\
+ Cube;\
+ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) )
+
+#define Fxu_MatrixForEachVariable( Matrix, Var )\
+ for ( Var = (Matrix)->lVars.pHead;\
+ Var;\
+ Var = Var->pNext )
+#define Fxu_MatrixForEachVariableSafe( Matrix, Var, Var2 )\
+ for ( Var = (Matrix)->lVars.pHead, Var2 = (Var? Var->pNext: NULL);\
+ Var;\
+ Var = Var2, Var2 = (Var? Var->pNext: NULL) )
+
+#define Fxu_MatrixForEachSingle( Matrix, Single )\
+ for ( Single = (Matrix)->lSingles.pHead;\
+ Single;\
+ Single = Single->pNext )
+#define Fxu_MatrixForEachSingleSafe( Matrix, Single, Single2 )\
+ for ( Single = (Matrix)->lSingles.pHead, Single2 = (Single? Single->pNext: NULL);\
+ Single;\
+ Single = Single2, Single2 = (Single? Single->pNext: NULL) )
+
+#define Fxu_TableForEachDouble( Matrix, Key, Div )\
+ for ( Div = (Matrix)->pTable[Key].pHead;\
+ Div;\
+ Div = Div->pNext )
+#define Fxu_TableForEachDoubleSafe( Matrix, Key, Div, Div2 )\
+ for ( Div = (Matrix)->pTable[Key].pHead, Div2 = (Div? Div->pNext: NULL);\
+ Div;\
+ Div = Div2, Div2 = (Div? Div->pNext: NULL) )
+
+#define Fxu_MatrixForEachDouble( Matrix, Div, Index )\
+ for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\
+ Fxu_TableForEachDouble( Matrix, Index, Div )
+#define Fxu_MatrixForEachDoubleSafe( Matrix, Div, Div2, Index )\
+ for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\
+ Fxu_TableForEachDoubleSafe( Matrix, Index, Div, Div2 )
+
+
+#define Fxu_CubeForEachLiteral( Cube, Lit )\
+ for ( Lit = (Cube)->lLits.pHead;\
+ Lit;\
+ Lit = Lit->pHNext )
+#define Fxu_CubeForEachLiteralSafe( Cube, Lit, Lit2 )\
+ for ( Lit = (Cube)->lLits.pHead, Lit2 = (Lit? Lit->pHNext: NULL);\
+ Lit;\
+ Lit = Lit2, Lit2 = (Lit? Lit->pHNext: NULL) )
+
+#define Fxu_VarForEachLiteral( Var, Lit )\
+ for ( Lit = (Var)->lLits.pHead;\
+ Lit;\
+ Lit = Lit->pVNext )
+
+#define Fxu_CubeForEachDivisor( Cube, Div )\
+ for ( Div = (Cube)->lDivs.pHead;\
+ Div;\
+ Div = Div->pCNext )
+
+#define Fxu_DoubleForEachPair( Div, Pair )\
+ for ( Pair = (Div)->lPairs.pHead;\
+ Pair;\
+ Pair = Pair->pDNext )
+#define Fxu_DoubleForEachPairSafe( Div, Pair, Pair2 )\
+ for ( Pair = (Div)->lPairs.pHead, Pair2 = (Pair? Pair->pDNext: NULL);\
+ Pair;\
+ Pair = Pair2, Pair2 = (Pair? Pair->pDNext: NULL) )
+
+
+// iterator through the cube pairs belonging to the given cube
+#define Fxu_CubeForEachPair( pCube, pPair, i )\
+ for ( i = 0;\
+ i < pCube->pVar->nCubes &&\
+ (((unsigned)(pPair = pCube->pVar->ppPairs[pCube->iCube][i])) >= 0);\
+ i++ )\
+ if ( pPair )
+
+// iterator through all the items in the heap
+#define Fxu_HeapDoubleForEachItem( Heap, Div )\
+ for ( Heap->i = 1;\
+ Heap->i <= Heap->nItems && (Div = Heap->pTree[Heap->i]);\
+ Heap->i++ )
+#define Fxu_HeapSingleForEachItem( Heap, Single )\
+ for ( Heap->i = 1;\
+ Heap->i <= Heap->nItems && (Single = Heap->pTree[Heap->i]);\
+ Heap->i++ )
+
+// starting the rings
+#define Fxu_MatrixRingCubesStart( Matrix ) (((Matrix)->ppTailCubes = &((Matrix)->pOrderCubes)), ((Matrix)->pOrderCubes = NULL))
+#define Fxu_MatrixRingVarsStart( Matrix ) (((Matrix)->ppTailVars = &((Matrix)->pOrderVars)), ((Matrix)->pOrderVars = NULL))
+// stopping the rings
+#define Fxu_MatrixRingCubesStop( Matrix )
+#define Fxu_MatrixRingVarsStop( Matrix )
+// resetting the rings
+#define Fxu_MatrixRingCubesReset( Matrix ) (((Matrix)->pOrderCubes = NULL), ((Matrix)->ppTailCubes = NULL))
+#define Fxu_MatrixRingVarsReset( Matrix ) (((Matrix)->pOrderVars = NULL), ((Matrix)->ppTailVars = NULL))
+// adding to the rings
+#define Fxu_MatrixRingCubesAdd( Matrix, Cube) ((*((Matrix)->ppTailCubes) = Cube), ((Matrix)->ppTailCubes = &(Cube)->pOrder), ((Cube)->pOrder = (Fxu_Cube *)1))
+#define Fxu_MatrixRingVarsAdd( Matrix, Var ) ((*((Matrix)->ppTailVars ) = Var ), ((Matrix)->ppTailVars = &(Var)->pOrder ), ((Var)->pOrder = (Fxu_Var *)1))
+// iterating through the rings
+#define Fxu_MatrixForEachCubeInRing( Matrix, Cube )\
+ if ( (Matrix)->pOrderCubes )\
+ for ( Cube = (Matrix)->pOrderCubes;\
+ Cube != (Fxu_Cube *)1;\
+ Cube = Cube->pOrder )
+#define Fxu_MatrixForEachCubeInRingSafe( Matrix, Cube, Cube2 )\
+ if ( (Matrix)->pOrderCubes )\
+ for ( Cube = (Matrix)->pOrderCubes, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1);\
+ Cube != (Fxu_Cube *)1;\
+ Cube = Cube2, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1) )
+#define Fxu_MatrixForEachVarInRing( Matrix, Var )\
+ if ( (Matrix)->pOrderVars )\
+ for ( Var = (Matrix)->pOrderVars;\
+ Var != (Fxu_Var *)1;\
+ Var = Var->pOrder )
+#define Fxu_MatrixForEachVarInRingSafe( Matrix, Var, Var2 )\
+ if ( (Matrix)->pOrderVars )\
+ for ( Var = (Matrix)->pOrderVars, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1);\
+ Var != (Fxu_Var *)1;\
+ Var = Var2, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1) )
+// the procedures are related to the above macros
+extern void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p );
+extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p );
+
+
+// macros working 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)
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+#define MEM_ALLOC_FXU( Manager, Type, Size ) ((Type *)malloc( (Size) * sizeof(Type) ))
+#define MEM_FREE_FXU( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; }
+#else
+#define MEM_ALLOC_FXU( Manager, Type, Size )\
+ ((Type *)Fxu_MemFetch( Manager, (Size) * sizeof(Type) ))
+#define MEM_FREE_FXU( Manager, Type, Size, Pointer )\
+ if ( Pointer ) { Fxu_MemRecycle( Manager, (char *)(Pointer), (Size) * sizeof(Type) ); Pointer = NULL; }
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*===== fxu.c ====================================================*/
+extern char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes );
+extern void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes );
+/*===== fxuCreate.c ====================================================*/
+/*===== fxuReduce.c ====================================================*/
+/*===== fxuPrint.c ====================================================*/
+extern void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p );
+extern void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p );
+/*===== fxuSelect.c ====================================================*/
+extern int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble );
+extern int Fxu_SelectSCD( Fxu_Matrix * p, int Weight, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 );
+/*===== fxuUpdate.c ====================================================*/
+extern void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble );
+extern void Fxu_UpdateDouble( Fxu_Matrix * p );
+extern void Fxu_UpdateSingle( Fxu_Matrix * p );
+/*===== fxuPair.c ====================================================*/
+extern void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 );
+extern unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 );
+extern unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 );
+extern unsigned Fxu_PairHashKeyMv( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 );
+extern int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 );
+extern void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes );
+extern void Fxu_PairFreeStorage( Fxu_Var * pVar );
+extern void Fxu_PairClearStorage( Fxu_Cube * pCube );
+extern Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 );
+extern void Fxu_PairAdd( Fxu_Pair * pPair );
+/*===== fxuSingle.c ====================================================*/
+extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p );
+extern void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar );
+extern int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 );
+/*===== fxuMatrix.c ====================================================*/
+// matrix
+extern Fxu_Matrix * Fxu_MatrixAllocate();
+extern void Fxu_MatrixDelete( Fxu_Matrix * p );
+// double-cube divisor
+extern void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 );
+extern void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv );
+// single-cube divisor
+extern void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight );
+// variable
+extern Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p );
+// cube
+extern Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube );
+// literal
+extern void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar );
+extern void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit );
+/*===== fxuList.c ====================================================*/
+// matrix -> variable
+extern void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pVar );
+extern void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pVar );
+// matrix -> cube
+extern void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube );
+extern void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pCube );
+// matrix -> single
+extern void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pSingle );
+extern void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pSingle );
+// table -> divisor
+extern void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pDiv );
+extern void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv );
+// cube -> literal
+extern void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit );
+extern void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit );
+// var -> literal
+extern void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLit );
+extern void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLit );
+// divisor -> pair
+extern void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink );
+extern void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink );
+extern void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink );
+extern void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pPair );
+/*===== fxuHeapDouble.c ====================================================*/
+extern Fxu_HeapDouble * Fxu_HeapDoubleStart();
+extern void Fxu_HeapDoubleStop( Fxu_HeapDouble * p );
+extern void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p );
+extern void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p );
+extern void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv );
+
+extern void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv );
+extern void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv );
+extern void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv );
+extern int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p );
+extern Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p );
+extern Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p );
+/*===== fxuHeapSingle.c ====================================================*/
+extern Fxu_HeapSingle * Fxu_HeapSingleStart();
+extern void Fxu_HeapSingleStop( Fxu_HeapSingle * p );
+extern void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p );
+extern void Fxu_HeapSingleCheck( Fxu_HeapSingle * p );
+extern void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle );
+
+extern void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle );
+extern void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle );
+extern void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle );
+extern int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p );
+extern Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p );
+extern Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+#endif
+
diff --git a/src/opt/fxu/fxuList.c b/src/opt/fxu/fxuList.c
new file mode 100644
index 00000000..bb081d80
--- /dev/null
+++ b/src/opt/fxu/fxuList.c
@@ -0,0 +1,522 @@
+/**CFile****************************************************************
+
+ FileName [fxuList.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Operations on lists.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuList.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// matrix -> var
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pLink )
+{
+ Fxu_ListVar * pList = &p->lVars;
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pPrev = NULL;
+ pLink->pNext = NULL;
+ }
+ else
+ {
+ pLink->pNext = NULL;
+ pList->pTail->pNext = pLink;
+ pLink->pPrev = pList->pTail;
+ pList->pTail = pLink;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pLink )
+{
+ Fxu_ListVar * pList = &p->lVars;
+ if ( pList->pHead == pLink )
+ pList->pHead = pLink->pNext;
+ if ( pList->pTail == pLink )
+ pList->pTail = pLink->pPrev;
+ if ( pLink->pPrev )
+ pLink->pPrev->pNext = pLink->pNext;
+ if ( pLink->pNext )
+ pLink->pNext->pPrev = pLink->pPrev;
+ pList->nItems--;
+}
+
+
+// matrix -> cube
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pLink )
+{
+ Fxu_ListCube * pList = &p->lCubes;
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pPrev = NULL;
+ pLink->pNext = NULL;
+ }
+ else
+ {
+ pLink->pNext = NULL;
+ pList->pTail->pNext = pLink;
+ pLink->pPrev = pList->pTail;
+ pList->pTail = pLink;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pLink )
+{
+ Fxu_ListCube * pList = &p->lCubes;
+ if ( pList->pHead == pLink )
+ pList->pHead = pLink->pNext;
+ if ( pList->pTail == pLink )
+ pList->pTail = pLink->pPrev;
+ if ( pLink->pPrev )
+ pLink->pPrev->pNext = pLink->pNext;
+ if ( pLink->pNext )
+ pLink->pNext->pPrev = pLink->pPrev;
+ pList->nItems--;
+}
+
+
+// matrix -> single
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pLink )
+{
+ Fxu_ListSingle * pList = &p->lSingles;
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pPrev = NULL;
+ pLink->pNext = NULL;
+ }
+ else
+ {
+ pLink->pNext = NULL;
+ pList->pTail->pNext = pLink;
+ pLink->pPrev = pList->pTail;
+ pList->pTail = pLink;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pLink )
+{
+ Fxu_ListSingle * pList = &p->lSingles;
+ if ( pList->pHead == pLink )
+ pList->pHead = pLink->pNext;
+ if ( pList->pTail == pLink )
+ pList->pTail = pLink->pPrev;
+ if ( pLink->pPrev )
+ pLink->pPrev->pNext = pLink->pNext;
+ if ( pLink->pNext )
+ pLink->pNext->pPrev = pLink->pPrev;
+ pList->nItems--;
+}
+
+
+// table -> divisor
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pLink )
+{
+ Fxu_ListDouble * pList = &(p->pTable[pLink->Key]);
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pPrev = NULL;
+ pLink->pNext = NULL;
+ }
+ else
+ {
+ pLink->pNext = NULL;
+ pList->pTail->pNext = pLink;
+ pLink->pPrev = pList->pTail;
+ pList->pTail = pLink;
+ }
+ pList->nItems++;
+ p->nDivs++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pLink )
+{
+ Fxu_ListDouble * pList = &(p->pTable[pLink->Key]);
+ if ( pList->pHead == pLink )
+ pList->pHead = pLink->pNext;
+ if ( pList->pTail == pLink )
+ pList->pTail = pLink->pPrev;
+ if ( pLink->pPrev )
+ pLink->pPrev->pNext = pLink->pNext;
+ if ( pLink->pNext )
+ pLink->pNext->pPrev = pLink->pPrev;
+ pList->nItems--;
+ p->nDivs--;
+}
+
+
+// cube -> literal
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink )
+{
+ Fxu_ListLit * pList = &(pCube->lLits);
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pHPrev = NULL;
+ pLink->pHNext = NULL;
+ }
+ else
+ {
+ pLink->pHNext = NULL;
+ pList->pTail->pHNext = pLink;
+ pLink->pHPrev = pList->pTail;
+ pList->pTail = pLink;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink )
+{
+ Fxu_ListLit * pList = &(pCube->lLits);
+ if ( pList->pHead == pLink )
+ pList->pHead = pLink->pHNext;
+ if ( pList->pTail == pLink )
+ pList->pTail = pLink->pHPrev;
+ if ( pLink->pHPrev )
+ pLink->pHPrev->pHNext = pLink->pHNext;
+ if ( pLink->pHNext )
+ pLink->pHNext->pHPrev = pLink->pHPrev;
+ pList->nItems--;
+}
+
+
+// var -> literal
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLink )
+{
+ Fxu_ListLit * pList = &(pVar->lLits);
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pVPrev = NULL;
+ pLink->pVNext = NULL;
+ }
+ else
+ {
+ pLink->pVNext = NULL;
+ pList->pTail->pVNext = pLink;
+ pLink->pVPrev = pList->pTail;
+ pList->pTail = pLink;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLink )
+{
+ Fxu_ListLit * pList = &(pVar->lLits);
+ if ( pList->pHead == pLink )
+ pList->pHead = pLink->pVNext;
+ if ( pList->pTail == pLink )
+ pList->pTail = pLink->pVPrev;
+ if ( pLink->pVPrev )
+ pLink->pVPrev->pVNext = pLink->pVNext;
+ if ( pLink->pVNext )
+ pLink->pVNext->pVPrev = pLink->pVPrev;
+ pList->nItems--;
+}
+
+
+
+// divisor -> pair
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink )
+{
+ Fxu_ListPair * pList = &pDiv->lPairs;
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pDPrev = NULL;
+ pLink->pDNext = NULL;
+ }
+ else
+ {
+ pLink->pDNext = NULL;
+ pList->pTail->pDNext = pLink;
+ pLink->pDPrev = pList->pTail;
+ pList->pTail = pLink;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink )
+{
+ Fxu_ListPair * pList = &pDiv->lPairs;
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pLink;
+ pList->pTail = pLink;
+ pLink->pDPrev = NULL;
+ pLink->pDNext = NULL;
+ }
+ else
+ {
+ pLink->pDPrev = NULL;
+ pList->pHead->pDPrev = pLink;
+ pLink->pDNext = pList->pHead;
+ pList->pHead = pLink;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the entry in the middle of the list after the spot.]
+
+ Description [Assumes that spot points to the link, after which the given
+ link should be added. Spot cannot be NULL or the tail of the list.
+ Therefore, the head and the tail of the list are not changed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink )
+{
+ Fxu_ListPair * pList = &pDiv->lPairs;
+ assert( pSpot );
+ assert( pSpot != pList->pTail );
+ pLink->pDPrev = pSpot;
+ pLink->pDNext = pSpot->pDNext;
+ pLink->pDPrev->pDNext = pLink;
+ pLink->pDNext->pDPrev = pLink;
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pLink )
+{
+ Fxu_ListPair * pList = &pDiv->lPairs;
+ if ( pList->pHead == pLink )
+ pList->pHead = pLink->pDNext;
+ if ( pList->pTail == pLink )
+ pList->pTail = pLink->pDPrev;
+ if ( pLink->pDPrev )
+ pLink->pDPrev->pDNext = pLink->pDNext;
+ if ( pLink->pDNext )
+ pLink->pDNext->pDPrev = pLink->pDPrev;
+ pList->nItems--;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_ListDoubleAddPairPlace( Fxu_Double * pDiv, Fxu_Pair * pPair, Fxu_Pair * pPairSpot )
+{
+ printf( "Fxu_ListDoubleAddPairPlace() is called!\n" );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuMatrix.c b/src/opt/fxu/fxuMatrix.c
new file mode 100644
index 00000000..0b732aef
--- /dev/null
+++ b/src/opt/fxu/fxuMatrix.c
@@ -0,0 +1,382 @@
+/**CFile****************************************************************
+
+ FileName [fxuMatrix.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Procedures to manipulate the sparse matrix.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuMatrix.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern unsigned int Cudd_Prime( unsigned int p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Matrix * Fxu_MatrixAllocate()
+{
+ Fxu_Matrix * p;
+ p = ALLOC( Fxu_Matrix, 1 );
+ memset( p, 0, sizeof(Fxu_Matrix) );
+ p->nTableSize = Cudd_Prime(10000);
+ p->pTable = ALLOC( Fxu_ListDouble, p->nTableSize );
+ memset( p->pTable, 0, sizeof(Fxu_ListDouble) * p->nTableSize );
+#ifndef USE_SYSTEM_MEMORY_MANAGEMENT
+ {
+ // get the largest size in bytes for the following structures:
+ // Fxu_Cube, Fxu_Var, Fxu_Lit, Fxu_Pair, Fxu_Double, Fxu_Single
+ // (currently, Fxu_Var, Fxu_Pair, Fxu_Double take 10 machine words)
+ int nSizeMax, nSizeCur;
+ nSizeMax = -1;
+ nSizeCur = sizeof(Fxu_Cube);
+ if ( nSizeMax < nSizeCur )
+ nSizeMax = nSizeCur;
+ nSizeCur = sizeof(Fxu_Var);
+ if ( nSizeMax < nSizeCur )
+ nSizeMax = nSizeCur;
+ nSizeCur = sizeof(Fxu_Lit);
+ if ( nSizeMax < nSizeCur )
+ nSizeMax = nSizeCur;
+ nSizeCur = sizeof(Fxu_Pair);
+ if ( nSizeMax < nSizeCur )
+ nSizeMax = nSizeCur;
+ nSizeCur = sizeof(Fxu_Double);
+ if ( nSizeMax < nSizeCur )
+ nSizeMax = nSizeCur;
+ nSizeCur = sizeof(Fxu_Single);
+ if ( nSizeMax < nSizeCur )
+ nSizeMax = nSizeCur;
+ p->pMemMan = Extra_MmFixedStart( nSizeMax );
+ }
+#endif
+ p->pHeapDouble = Fxu_HeapDoubleStart();
+ p->pHeapSingle = Fxu_HeapSingleStart();
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixDelete( Fxu_Matrix * p )
+{
+ Fxu_HeapDoubleCheck( p->pHeapDouble );
+ Fxu_HeapDoubleStop( p->pHeapDouble );
+ Fxu_HeapSingleStop( p->pHeapSingle );
+
+ // delete other things
+#ifdef USE_SYSTEM_MEMORY_MANAGEMENT
+ // this code is not needed when the custom memory manager is used
+ {
+ Fxu_Cube * pCube, * pCube2;
+ Fxu_Var * pVar, * pVar2;
+ Fxu_Lit * pLit, * pLit2;
+ Fxu_Double * pDiv, * pDiv2;
+ Fxu_Single * pSingle, * pSingle2;
+ Fxu_Pair * pPair, * pPair2;
+ int i;
+ // delete the divisors
+ Fxu_MatrixForEachDoubleSafe( p, pDiv, pDiv2, i )
+ {
+ Fxu_DoubleForEachPairSafe( pDiv, pPair, pPair2 )
+ MEM_FREE_FXU( p, Fxu_Pair, 1, pPair );
+ MEM_FREE_FXU( p, Fxu_Double, 1, pDiv );
+ }
+ Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 )
+ MEM_FREE_FXU( p, Fxu_Single, 1, pSingle );
+ // delete the entries
+ Fxu_MatrixForEachCube( p, pCube )
+ Fxu_CubeForEachLiteralSafe( pCube, pLit, pLit2 )
+ MEM_FREE_FXU( p, Fxu_Lit, 1, pLit );
+ // delete the cubes
+ Fxu_MatrixForEachCubeSafe( p, pCube, pCube2 )
+ MEM_FREE_FXU( p, Fxu_Cube, 1, pCube );
+ // delete the vars
+ Fxu_MatrixForEachVariableSafe( p, pVar, pVar2 )
+ MEM_FREE_FXU( p, Fxu_Var, 1, pVar );
+ }
+#else
+ Extra_MmFixedStop( p->pMemMan, 0 );
+#endif
+
+ FREE( p->pppPairs );
+ FREE( p->ppPairs );
+ FREE( p->pPairsTemp );
+ FREE( p->pTable );
+ FREE( p->ppVars );
+ FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds a variable to the matrix.]
+
+ Description [This procedure always adds variables at the end of the matrix.
+ It assigns the var's node and number. It adds the var to the linked list of
+ all variables and to the table of all nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p )
+{
+ Fxu_Var * pVar;
+ pVar = MEM_ALLOC_FXU( p, Fxu_Var, 1 );
+ memset( pVar, 0, sizeof(Fxu_Var) );
+ pVar->iVar = p->lVars.nItems;
+ p->ppVars[pVar->iVar] = pVar;
+ Fxu_ListMatrixAddVariable( p, pVar );
+ return pVar;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds a literal to the matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube )
+{
+ Fxu_Cube * pCube;
+ pCube = MEM_ALLOC_FXU( p, Fxu_Cube, 1 );
+ memset( pCube, 0, sizeof(Fxu_Cube) );
+ pCube->pVar = pVar;
+ pCube->iCube = iCube;
+ Fxu_ListMatrixAddCube( p, pCube );
+ return pCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds a literal to the matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar )
+{
+ Fxu_Lit * pLit;
+ pLit = MEM_ALLOC_FXU( p, Fxu_Lit, 1 );
+ memset( pLit, 0, sizeof(Fxu_Lit) );
+ // insert the literal into two linked lists
+ Fxu_ListCubeAddLiteral( pCube, pLit );
+ Fxu_ListVarAddLiteral( pVar, pLit );
+ // set the back pointers
+ pLit->pCube = pCube;
+ pLit->pVar = pVar;
+ pLit->iCube = pCube->iCube;
+ pLit->iVar = pVar->iVar;
+ // increment the literal counter
+ p->nEntries++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the divisor from the matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv )
+{
+ // delete divisor from the table
+ Fxu_ListTableDelDivisor( p, pDiv );
+ // recycle the divisor
+ MEM_FREE_FXU( p, Fxu_Double, 1, pDiv );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the literal fromthe matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit )
+{
+ // delete the literal
+ Fxu_ListCubeDelLiteral( pLit->pCube, pLit );
+ Fxu_ListVarDelLiteral( pLit->pVar, pLit );
+ MEM_FREE_FXU( p, Fxu_Lit, 1, pLit );
+ // increment the literal counter
+ p->nEntries--;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates and adds a single cube divisor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight )
+{
+ Fxu_Single * pSingle;
+ assert( pVar1->iVar < pVar2->iVar );
+ pSingle = MEM_ALLOC_FXU( p, Fxu_Single, 1 );
+ memset( pSingle, 0, sizeof(Fxu_Single) );
+ pSingle->Num = p->lSingles.nItems;
+ pSingle->Weight = Weight;
+ pSingle->HNum = 0;
+ pSingle->pVar1 = pVar1;
+ pSingle->pVar2 = pVar2;
+ Fxu_ListMatrixAddSingle( p, pSingle );
+ // add to the heap
+ Fxu_HeapSingleInsert( p->pHeapSingle, pSingle );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 )
+{
+ Fxu_Pair * pPair;
+ Fxu_Double * pDiv;
+ int nBase, nLits1, nLits2;
+ int fFound;
+ unsigned Key;
+
+ // canonicize the pair
+ Fxu_PairCanonicize( &pCube1, &pCube2 );
+
+/*
+ // compute the hash key
+ if ( p->fMvNetwork )
+// if ( 0 )
+ { // in case of MV network, if all the values in the cube-free divisor
+ // belong to the same MV variable, this cube pair is not a divisor
+ Key = Fxu_PairHashKeyMv( p, pCube1, pCube2, &nBase, &nLits1, &nLits2 );
+ if ( Key == 0 )
+ return;
+ }
+ else
+*/
+ Key = Fxu_PairHashKey( p, pCube1, pCube2, &nBase, &nLits1, &nLits2 );
+
+ // create the cube pair
+ pPair = Fxu_PairAlloc( p, pCube1, pCube2 );
+ pPair->nBase = nBase;
+ pPair->nLits1 = nLits1;
+ pPair->nLits2 = nLits2;
+
+ // check if the divisor for this pair already exists
+ fFound = 0;
+ Key %= p->nTableSize;
+ Fxu_TableForEachDouble( p, Key, pDiv )
+ if ( Fxu_PairCompare( pPair, pDiv->lPairs.pTail ) ) // they are equal
+ {
+ fFound = 1;
+ break;
+ }
+
+ if ( !fFound )
+ { // create the new divisor
+ pDiv = MEM_ALLOC_FXU( p, Fxu_Double, 1 );
+ memset( pDiv, 0, sizeof(Fxu_Double) );
+ pDiv->Key = Key;
+ // set the number of this divisor
+ pDiv->Num = p->nDivsTotal++; // p->nDivs;
+ // insert the divisor in the table
+ Fxu_ListTableAddDivisor( p, pDiv );
+ // set the initial cost of the divisor
+ pDiv->Weight -= pPair->nLits1 + pPair->nLits2;
+ }
+
+ // link the pair to the cubes
+ Fxu_PairAdd( pPair );
+ // connect the pair and the divisor
+ pPair->pDiv = pDiv;
+ Fxu_ListDoubleAddPairLast( pDiv, pPair );
+ // update the max number of pairs in a divisor
+// if ( p->nPairsMax < pDiv->lPairs.nItems )
+// p->nPairsMax = pDiv->lPairs.nItems;
+ // update the divisor's weight
+ pDiv->Weight += pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase;
+ if ( fFound ) // update the divisor in the heap
+ Fxu_HeapDoubleUpdate( p->pHeapDouble, pDiv );
+ else // add the new divisor to the heap
+ Fxu_HeapDoubleInsert( p->pHeapDouble, pDiv );
+}
+
+/*
+ {
+ int piVarsC1[100], piVarsC2[100], nVarsC1, nVarsC2;
+ Fxu_Double * pDivCur;
+ Fxu_MatrixGetDoubleVars( p, pDiv, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
+ pDivCur = Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 );
+ assert( pDivCur == pDiv );
+ }
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuPair.c b/src/opt/fxu/fxuPair.c
new file mode 100644
index 00000000..be6be5e9
--- /dev/null
+++ b/src/opt/fxu/fxuPair.c
@@ -0,0 +1,555 @@
+/**CFile****************************************************************
+
+ FileName [fxuPair.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Operations on cube pairs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuPair.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAX_PRIMES 304
+
+static s_Primes[MAX_PRIMES] =
+{
+ 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
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find the canonical permutation of two cubes in the pair.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 )
+{
+ Fxu_Lit * pLit1, * pLit2;
+ Fxu_Cube * pCubeTemp;
+
+ // walk through the cubes to determine
+ // the one that has higher first variable
+ pLit1 = (*ppCube1)->lLits.pHead;
+ pLit2 = (*ppCube2)->lLits.pHead;
+ while ( 1 )
+ {
+ if ( pLit1->iVar == pLit2->iVar )
+ {
+ pLit1 = pLit1->pHNext;
+ pLit2 = pLit2->pHNext;
+ continue;
+ }
+ assert( pLit1 && pLit2 ); // this is true if the covers are SCC-free
+ if ( pLit1->iVar > pLit2->iVar )
+ { // swap the cubes
+ pCubeTemp = *ppCube1;
+ *ppCube1 = *ppCube2;
+ *ppCube2 = pCubeTemp;
+ }
+ break;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the canonical permutation of two cubes in the pair.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_PairCanonicize2( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 )
+{
+ Fxu_Cube * pCubeTemp;
+ // canonicize the pair by ordering the cubes
+ if ( (*ppCube1)->iCube > (*ppCube2)->iCube )
+ { // swap the cubes
+ pCubeTemp = *ppCube1;
+ *ppCube1 = *ppCube2;
+ *ppCube2 = pCubeTemp;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 )
+{
+ int Offset1 = 100, Offset2 = 200, i;
+ unsigned Key;
+ // compute the hash key
+ Key = 0;
+ for ( i = 0; i < nVarsC1; i++ )
+ Key ^= s_Primes[Offset1+i] * piVarsC1[i];
+ for ( i = 0; i < nVarsC2; i++ )
+ Key ^= s_Primes[Offset2+i] * piVarsC2[i];
+ return Key;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the hash key of the divisor represented by the pair of cubes.]
+
+ Description [Goes through the variables in both cubes. Skips the identical
+ ones (this corresponds to making the cubes cube-free). Computes the hash
+ value of the cubes. Assigns the number of literals in the base and in the
+ cubes without base.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2,
+ int * pnBase, int * pnLits1, int * pnLits2 )
+{
+ int Offset1 = 100, Offset2 = 200;
+ int nBase, nLits1, nLits2;
+ Fxu_Lit * pLit1, * pLit2;
+ unsigned Key;
+
+ // compute the hash key
+ Key = 0;
+ nLits1 = 0;
+ nLits2 = 0;
+ nBase = 0;
+ pLit1 = pCube1->lLits.pHead;
+ pLit2 = pCube2->lLits.pHead;
+ while ( 1 )
+ {
+ if ( pLit1 && pLit2 )
+ {
+ if ( pLit1->iVar == pLit2->iVar )
+ { // ensure cube-free
+ pLit1 = pLit1->pHNext;
+ pLit2 = pLit2->pHNext;
+ // add this literal to the base
+ nBase++;
+ }
+ else if ( pLit1->iVar < pLit2->iVar )
+ {
+ Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar;
+ pLit1 = pLit1->pHNext;
+ nLits1++;
+ }
+ else
+ {
+ Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar;
+ pLit2 = pLit2->pHNext;
+ nLits2++;
+ }
+ }
+ else if ( pLit1 && !pLit2 )
+ {
+ Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar;
+ pLit1 = pLit1->pHNext;
+ nLits1++;
+ }
+ else if ( !pLit1 && pLit2 )
+ {
+ Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar;
+ pLit2 = pLit2->pHNext;
+ nLits2++;
+ }
+ else
+ break;
+ }
+ *pnBase = nBase;
+ *pnLits1 = nLits1;
+ *pnLits2 = nLits2;
+ return Key;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the two pairs.]
+
+ Description [Returns 1 if the divisors represented by these pairs
+ are equal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 )
+{
+ Fxu_Lit * pD1C1, * pD1C2;
+ Fxu_Lit * pD2C1, * pD2C2;
+ int TopVar1, TopVar2;
+ int Code;
+
+ if ( pPair1->nLits1 != pPair2->nLits1 )
+ return 0;
+ if ( pPair1->nLits2 != pPair2->nLits2 )
+ return 0;
+
+ pD1C1 = pPair1->pCube1->lLits.pHead;
+ pD1C2 = pPair1->pCube2->lLits.pHead;
+
+ pD2C1 = pPair2->pCube1->lLits.pHead;
+ pD2C2 = pPair2->pCube2->lLits.pHead;
+
+ Code = pD1C1? 8: 0;
+ Code |= pD1C2? 4: 0;
+ Code |= pD2C1? 2: 0;
+ Code |= pD2C2? 1: 0;
+ assert( Code == 15 );
+
+ while ( 1 )
+ {
+ switch ( Code )
+ {
+ case 0: // -- -- NULL NULL NULL NULL
+ return 1;
+ case 1: // -- -1 NULL NULL NULL pD2C2
+ return 0;
+ case 2: // -- 1- NULL NULL pD2C1 NULL
+ return 0;
+ case 3: // -- 11 NULL NULL pD2C1 pD2C2
+ if ( pD2C1->iVar != pD2C2->iVar )
+ return 0;
+ pD2C1 = pD2C1->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ break;
+ case 4: // -1 -- NULL pD1C2 NULL NULL
+ return 0;
+ case 5: // -1 -1 NULL pD1C2 NULL pD2C2
+ if ( pD1C2->iVar != pD2C2->iVar )
+ return 0;
+ pD1C2 = pD1C2->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ break;
+ case 6: // -1 1- NULL pD1C2 pD2C1 NULL
+ return 0;
+ case 7: // -1 11 NULL pD1C2 pD2C1 pD2C2
+ TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar );
+ if ( TopVar2 == pD1C2->iVar )
+ {
+ if ( pD2C1->iVar <= pD2C2->iVar )
+ return 0;
+ pD1C2 = pD1C2->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ }
+ else if ( TopVar2 < pD1C2->iVar )
+ {
+ if ( pD2C1->iVar != pD2C2->iVar )
+ return 0;
+ pD2C1 = pD2C1->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ }
+ else
+ return 0;
+ break;
+ case 8: // 1- -- pD1C1 NULL NULL NULL
+ return 0;
+ case 9: // 1- -1 pD1C1 NULL NULL pD2C2
+ return 0;
+ case 10: // 1- 1- pD1C1 NULL pD2C1 NULL
+ if ( pD1C1->iVar != pD2C1->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD2C1 = pD2C1->pHNext;
+ break;
+ case 11: // 1- 11 pD1C1 NULL pD2C1 pD2C2
+ TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar );
+ if ( TopVar2 == pD1C1->iVar )
+ {
+ if ( pD2C1->iVar >= pD2C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD2C1 = pD2C1->pHNext;
+ }
+ else if ( TopVar2 < pD1C1->iVar )
+ {
+ if ( pD2C1->iVar != pD2C2->iVar )
+ return 0;
+ pD2C1 = pD2C1->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ }
+ else
+ return 0;
+ break;
+ case 12: // 11 -- pD1C1 pD1C2 NULL NULL
+ if ( pD1C1->iVar != pD1C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD1C2 = pD1C2->pHNext;
+ break;
+ case 13: // 11 -1 pD1C1 pD1C2 NULL pD2C2
+ TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar );
+ if ( TopVar1 == pD2C2->iVar )
+ {
+ if ( pD1C1->iVar <= pD1C2->iVar )
+ return 0;
+ pD1C2 = pD1C2->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ }
+ else if ( TopVar1 < pD2C2->iVar )
+ {
+ if ( pD1C1->iVar != pD1C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD1C2 = pD1C2->pHNext;
+ }
+ else
+ return 0;
+ break;
+ case 14: // 11 1- pD1C1 pD1C2 pD2C1 NULL
+ TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar );
+ if ( TopVar1 == pD2C1->iVar )
+ {
+ if ( pD1C1->iVar >= pD1C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD2C1 = pD2C1->pHNext;
+ }
+ else if ( TopVar1 < pD2C1->iVar )
+ {
+ if ( pD1C1->iVar != pD1C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD1C2 = pD1C2->pHNext;
+ }
+ else
+ return 0;
+ break;
+ case 15: // 11 11 pD1C1 pD1C2 pD2C1 pD2C2
+ TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar );
+ TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar );
+ if ( TopVar1 == TopVar2 )
+ {
+ if ( pD1C1->iVar == pD1C2->iVar )
+ {
+ if ( pD2C1->iVar != pD2C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD1C2 = pD1C2->pHNext;
+ pD2C1 = pD2C1->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ }
+ else
+ {
+ if ( pD2C1->iVar == pD2C2->iVar )
+ return 0;
+ if ( pD1C1->iVar < pD1C2->iVar )
+ {
+ if ( pD2C1->iVar > pD2C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD2C1 = pD2C1->pHNext;
+ }
+ else
+ {
+ if ( pD2C1->iVar < pD2C2->iVar )
+ return 0;
+ pD1C2 = pD1C2->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ }
+ }
+ }
+ else if ( TopVar1 < TopVar2 )
+ {
+ if ( pD1C1->iVar != pD1C2->iVar )
+ return 0;
+ pD1C1 = pD1C1->pHNext;
+ pD1C2 = pD1C2->pHNext;
+ }
+ else
+ {
+ if ( pD2C1->iVar != pD2C2->iVar )
+ return 0;
+ pD2C1 = pD2C1->pHNext;
+ pD2C2 = pD2C2->pHNext;
+ }
+ break;
+ default:
+ assert( 0 );
+ break;
+ }
+
+ Code = pD1C1? 8: 0;
+ Code |= pD1C2? 4: 0;
+ Code |= pD2C1? 2: 0;
+ Code |= pD2C2? 1: 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the storage for cubes pairs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes )
+{
+ int k;
+// assert( pVar->nCubes == 0 );
+ pVar->nCubes = nCubes;
+ // allocate memory for all the pairs
+ pVar->ppPairs = ALLOC( Fxu_Pair **, nCubes );
+ pVar->ppPairs[0] = ALLOC( Fxu_Pair *, nCubes * nCubes );
+ memset( pVar->ppPairs[0], 0, sizeof(Fxu_Pair *) * nCubes * nCubes );
+ for ( k = 1; k < nCubes; k++ )
+ pVar->ppPairs[k] = pVar->ppPairs[k-1] + nCubes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears all pairs associated with this cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_PairClearStorage( Fxu_Cube * pCube )
+{
+ Fxu_Var * pVar;
+ int i;
+ pVar = pCube->pVar;
+ for ( i = 0; i < pVar->nCubes; i++ )
+ {
+ pVar->ppPairs[pCube->iCube][i] = NULL;
+ pVar->ppPairs[i][pCube->iCube] = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears all pairs associated with this cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_PairFreeStorage( Fxu_Var * pVar )
+{
+ if ( pVar->ppPairs )
+ {
+ FREE( pVar->ppPairs[0] );
+ FREE( pVar->ppPairs );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the pair to storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 )
+{
+ Fxu_Pair * pPair;
+ assert( pCube1->pVar == pCube2->pVar );
+ pPair = MEM_ALLOC_FXU( p, Fxu_Pair, 1 );
+ memset( pPair, 0, sizeof(Fxu_Pair) );
+ pPair->pCube1 = pCube1;
+ pPair->pCube2 = pCube2;
+ pPair->iCube1 = pCube1->iCube;
+ pPair->iCube2 = pCube2->iCube;
+ return pPair;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the pair to storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_PairAdd( Fxu_Pair * pPair )
+{
+ Fxu_Var * pVar;
+
+ pVar = pPair->pCube1->pVar;
+ assert( pVar == pPair->pCube2->pVar );
+
+ pVar->ppPairs[pPair->iCube1][pPair->iCube2] = pPair;
+ pVar->ppPairs[pPair->iCube2][pPair->iCube1] = pPair;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuPrint.c b/src/opt/fxu/fxuPrint.c
new file mode 100644
index 00000000..2d25c0e9
--- /dev/null
+++ b/src/opt/fxu/fxuPrint.c
@@ -0,0 +1,195 @@
+/**CFile****************************************************************
+
+ FileName [fxuPrint.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Various printing procedures.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuPrint.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p )
+{
+ Fxu_Var * pVar;
+ Fxu_Cube * pCube;
+ Fxu_Double * pDiv;
+ Fxu_Single * pSingle;
+ Fxu_Lit * pLit;
+ Fxu_Pair * pPair;
+ int i, LastNum;
+ int fStdout;
+
+ fStdout = 1;
+ if ( pFile == NULL )
+ {
+ pFile = fopen( "matrix.txt", "w" );
+ fStdout = 0;
+ }
+
+ fprintf( pFile, "Matrix has %d vars, %d cubes, %d literals, %d divisors.\n",
+ p->lVars.nItems, p->lCubes.nItems, p->nEntries, p->nDivs );
+ fprintf( pFile, "Divisors selected so far: single = %d, double = %d.\n",
+ p->nDivs1, p->nDivs2 );
+ fprintf( pFile, "\n" );
+
+ // print the numbers on top of the matrix
+ for ( i = 0; i < 12; i++ )
+ fprintf( pFile, " " );
+ Fxu_MatrixForEachVariable( p, pVar )
+ fprintf( pFile, "%d", pVar->iVar % 10 );
+ fprintf( pFile, "\n" );
+
+ // print the rows
+ Fxu_MatrixForEachCube( p, pCube )
+ {
+ fprintf( pFile, "%4d", pCube->iCube );
+ fprintf( pFile, " " );
+ fprintf( pFile, "%4d", pCube->pVar->iVar );
+ fprintf( pFile, " " );
+
+ // print the literals
+ LastNum = -1;
+ Fxu_CubeForEachLiteral( pCube, pLit )
+ {
+ for ( i = LastNum + 1; i < pLit->pVar->iVar; i++ )
+ fprintf( pFile, "." );
+ fprintf( pFile, "1" );
+ LastNum = i;
+ }
+ for ( i = LastNum + 1; i < p->lVars.nItems; i++ )
+ fprintf( pFile, "." );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, "\n" );
+
+ // print the double-cube divisors
+ fprintf( pFile, "The double divisors are:\n" );
+ Fxu_MatrixForEachDouble( p, pDiv, i )
+ {
+ fprintf( pFile, "Divisor #%3d (lit=%d,%d) (w=%2d): ",
+ pDiv->Num, pDiv->lPairs.pHead->nLits1,
+ pDiv->lPairs.pHead->nLits2, pDiv->Weight );
+ Fxu_DoubleForEachPair( pDiv, pPair )
+ fprintf( pFile, " <%d, %d> (b=%d)",
+ pPair->pCube1->iCube, pPair->pCube2->iCube, pPair->nBase );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, "\n" );
+
+ // print the divisors associated with each cube
+ fprintf( pFile, "The cubes are:\n" );
+ Fxu_MatrixForEachCube( p, pCube )
+ {
+ fprintf( pFile, "Cube #%3d: ", pCube->iCube );
+ if ( pCube->pVar->ppPairs )
+ Fxu_CubeForEachPair( pCube, pPair, i )
+ fprintf( pFile, " <%d %d> (d=%d) (b=%d)",
+ pPair->iCube1, pPair->iCube2, pPair->pDiv->Num, pPair->nBase );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, "\n" );
+
+ // print the single-cube divisors
+ fprintf( pFile, "The single divisors are:\n" );
+ Fxu_MatrixForEachSingle( p, pSingle )
+ {
+ fprintf( pFile, "Single-cube divisor #%5d: Var1 = %4d. Var2 = %4d. Weight = %2d\n",
+ pSingle->Num, pSingle->pVar1->iVar, pSingle->pVar2->iVar, pSingle->Weight );
+ }
+ fprintf( pFile, "\n" );
+
+/*
+ {
+ int Index;
+ fprintf( pFile, "Distribution of divisors in the hash table:\n" );
+ for ( Index = 0; Index < p->nTableSize; Index++ )
+ fprintf( pFile, " %d", p->pTable[Index].nItems );
+ fprintf( pFile, "\n" );
+ }
+*/
+ if ( !fStdout )
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p )
+{
+ Fxu_Double * pDiv;
+ int WeightMax;
+ int * pProfile;
+ int Counter1; // the number of -1 weight
+ int CounterL; // the number of less than -1 weight
+ int i;
+
+ WeightMax = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
+ pProfile = ALLOC( int, (WeightMax + 1) );
+ memset( pProfile, 0, sizeof(int) * (WeightMax + 1) );
+
+ Counter1 = 0;
+ CounterL = 0;
+ Fxu_MatrixForEachDouble( p, pDiv, i )
+ {
+ assert( pDiv->Weight <= WeightMax );
+ if ( pDiv->Weight == -1 )
+ Counter1++;
+ else if ( pDiv->Weight < 0 )
+ CounterL++;
+ else
+ pProfile[ pDiv->Weight ]++;
+ }
+
+ fprintf( pFile, "The double divisors profile:\n" );
+ fprintf( pFile, "Weight < -1 divisors = %6d\n", CounterL );
+ fprintf( pFile, "Weight -1 divisors = %6d\n", Counter1 );
+ for ( i = 0; i <= WeightMax; i++ )
+ if ( pProfile[i] )
+ fprintf( pFile, "Weight %3d divisors = %6d\n", i, pProfile[i] );
+ fprintf( pFile, "End of divisor profile printout\n" );
+ FREE( pProfile );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c
new file mode 100644
index 00000000..652d807b
--- /dev/null
+++ b/src/opt/fxu/fxuReduce.c
@@ -0,0 +1,194 @@
+/**CFile****************************************************************
+
+ FileName [fxuReduce.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Procedures to reduce the number of considered cube pairs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuReduce.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fxuInt.h"
+#include "fxu.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes the pairs to use for creating two-cube divisors.]
+
+ Description [This procedure takes the matrix with variables and cubes
+ allocated (p), the original covers of the nodes (i-sets) and their number
+ (ppCovers,nCovers). The maximum number of pairs to compute and the total
+ number of pairs in existence. This procedure adds to the storage of
+ divisors exactly the given number of pairs (nPairsMax) while taking
+ first those pairs that have the smallest number of literals in their
+ cube-free form.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax )
+{
+ unsigned char * pnLitsDiff; // storage for the counters of diff literals
+ int * pnPairCounters; // the counters of pairs for each number of diff literals
+ Fxu_Cube * pCubeFirst, * pCubeLast;
+ Fxu_Cube * pCube1, * pCube2;
+ Fxu_Var * pVar;
+ int nCubes, nBitsMax, nSum;
+ int CutOffNum, CutOffQuant;
+ int iPair, iQuant, k, c;
+ int clk = clock();
+ char * pSopCover;
+ int nFanins;
+
+ assert( nPairsMax < nPairsTotal );
+
+ // allocate storage for counter of diffs
+ pnLitsDiff = ALLOC( unsigned char, nPairsTotal );
+ // go through the covers and precompute the distances between the pairs
+ iPair = 0;
+ nBitsMax = -1;
+ for ( c = 0; c < vCovers->nSize; c++ )
+ if ( pSopCover = vCovers->pArray[c] )
+ {
+ nFanins = Abc_SopGetVarNum(pSopCover);
+ // precompute the differences
+ Fxu_CountPairDiffs( pSopCover, pnLitsDiff + iPair );
+ // update the counter
+ nCubes = Abc_SopGetCubeNum( pSopCover );
+ iPair += nCubes * (nCubes - 1) / 2;
+ if ( nBitsMax < nFanins )
+ nBitsMax = nFanins;
+ }
+ assert( iPair == nPairsTotal );
+
+ // allocate storage for counters of cube pairs by difference
+ pnPairCounters = ALLOC( int, 2 * nBitsMax );
+ memset( pnPairCounters, 0, sizeof(int) * 2 * nBitsMax );
+ // count the number of different pairs
+ for ( k = 0; k < nPairsTotal; k++ )
+ pnPairCounters[ pnLitsDiff[k] ]++;
+ // determine what pairs to take starting from the lower
+ // so that there would be exactly pPairsMax pairs
+ assert( pnPairCounters[0] == 0 ); // otherwise, covers are not dup-free
+ assert( pnPairCounters[1] == 0 ); // otherwise, covers are not SCC-free
+ nSum = 0;
+ for ( k = 0; k < 2 * nBitsMax; k++ )
+ {
+ nSum += pnPairCounters[k];
+ if ( nSum >= nPairsMax )
+ {
+ CutOffNum = k;
+ CutOffQuant = pnPairCounters[k] - (nSum - nPairsMax);
+ break;
+ }
+ }
+ FREE( pnPairCounters );
+
+ // set to 0 all the pairs above the cut-off number and quantity
+ iQuant = 0;
+ iPair = 0;
+ for ( k = 0; k < nPairsTotal; k++ )
+ if ( pnLitsDiff[k] > CutOffNum )
+ pnLitsDiff[k] = 0;
+ else if ( pnLitsDiff[k] == CutOffNum )
+ {
+ if ( iQuant++ >= CutOffQuant )
+ pnLitsDiff[k] = 0;
+ else
+ iPair++;
+ }
+ else
+ iPair++;
+ assert( iPair == nPairsMax );
+
+ // collect the corresponding pairs and add the divisors
+ iPair = 0;
+ for ( c = 0; c < vCovers->nSize; c++ )
+ if ( pSopCover = vCovers->pArray[c] )
+ {
+ // get the var
+ pVar = p->ppVars[2*c+1];
+ // get the first cube
+ pCubeFirst = pVar->pFirst;
+ // get the last cube
+ pCubeLast = pCubeFirst;
+ for ( k = 0; k < pVar->nCubes; k++ )
+ pCubeLast = pCubeLast->pNext;
+ assert( pCubeLast == NULL || pCubeLast->pVar != pVar );
+
+ // go through the cube pairs
+ for ( pCube1 = pCubeFirst; pCube1 != pCubeLast; pCube1 = pCube1->pNext )
+ for ( pCube2 = pCube1->pNext; pCube2 != pCubeLast; pCube2 = pCube2->pNext )
+ if ( pnLitsDiff[iPair++] )
+ { // create the divisors for this pair
+ Fxu_MatrixAddDivisor( p, pCube1, pCube2 );
+ }
+ }
+ assert( iPair == nPairsTotal );
+ FREE( pnLitsDiff );
+//PRT( "Preprocess", clock() - clk );
+ return 1;
+}
+
+
+/**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 Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] )
+{
+ char * pCube1, * pCube2;
+ int nOnes, nCubePairs, nFanins, v;
+ nCubePairs = 0;
+ nFanins = Abc_SopGetVarNum(pCover);
+ Abc_SopForEachCube( pCover, nFanins, pCube1 )
+ Abc_SopForEachCube( pCube1, nFanins, pCube2 )
+ {
+ if ( pCube1 == pCube2 )
+ continue;
+ nOnes = 0;
+ for ( v = 0; v < nFanins; v++ )
+ nOnes += (pCube1[v] != pCube2[v]);
+ pDiffs[nCubePairs++] = nOnes;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuSelect.c b/src/opt/fxu/fxuSelect.c
new file mode 100644
index 00000000..b56407a9
--- /dev/null
+++ b/src/opt/fxu/fxuSelect.c
@@ -0,0 +1,603 @@
+/**CFile****************************************************************
+
+ FileName [fxuSelect.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Procedures to select the best divisor/complement pair.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuSelect.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAX_SIZE_LOOKAHEAD 20
+
+static int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar );
+
+static Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle );
+static Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble );
+static Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble );
+
+Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p,
+ int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 );
+void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble,
+ int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Selects the best pair (Single,Double) and returns their weight.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble )
+{
+ // the top entries
+ Fxu_Single * pSingles[MAX_SIZE_LOOKAHEAD];
+ Fxu_Double * pDoubles[MAX_SIZE_LOOKAHEAD];
+ // the complements
+ Fxu_Double * pSCompl[MAX_SIZE_LOOKAHEAD];
+ Fxu_Single * pDComplS[MAX_SIZE_LOOKAHEAD];
+ Fxu_Double * pDComplD[MAX_SIZE_LOOKAHEAD];
+ Fxu_Pair * pPair;
+ int nSingles;
+ int nDoubles;
+ int i;
+ int WeightBest;
+ int WeightCur;
+ int iNum, fBestS;
+
+ // collect the top entries from the queues
+ for ( nSingles = 0; nSingles < MAX_SIZE_LOOKAHEAD; nSingles++ )
+ {
+ pSingles[nSingles] = Fxu_HeapSingleGetMax( p->pHeapSingle );
+ if ( pSingles[nSingles] == NULL )
+ break;
+ }
+ // put them back into the queue
+ for ( i = 0; i < nSingles; i++ )
+ if ( pSingles[i] )
+ Fxu_HeapSingleInsert( p->pHeapSingle, pSingles[i] );
+
+ // the same for doubles
+ // collect the top entries from the queues
+ for ( nDoubles = 0; nDoubles < MAX_SIZE_LOOKAHEAD; nDoubles++ )
+ {
+ pDoubles[nDoubles] = Fxu_HeapDoubleGetMax( p->pHeapDouble );
+ if ( pDoubles[nDoubles] == NULL )
+ break;
+ }
+ // put them back into the queue
+ for ( i = 0; i < nDoubles; i++ )
+ if ( pDoubles[i] )
+ Fxu_HeapDoubleInsert( p->pHeapDouble, pDoubles[i] );
+
+ // for each single, find the complement double (if any)
+ for ( i = 0; i < nSingles; i++ )
+ if ( pSingles[i] )
+ pSCompl[i] = Fxu_MatrixFindComplementSingle( p, pSingles[i] );
+
+ // for each double, find the complement single or double (if any)
+ for ( i = 0; i < nDoubles; i++ )
+ if ( pDoubles[i] )
+ {
+ pPair = pDoubles[i]->lPairs.pHead;
+ if ( pPair->nLits1 == 1 && pPair->nLits2 == 1 )
+ {
+ pDComplS[i] = Fxu_MatrixFindComplementDouble2( p, pDoubles[i] );
+ pDComplD[i] = NULL;
+ }
+// else if ( pPair->nLits1 == 2 && pPair->nLits2 == 2 )
+// {
+// pDComplS[i] = NULL;
+// pDComplD[i] = Fxu_MatrixFindComplementDouble4( p, pDoubles[i] );
+// }
+ else
+ {
+ pDComplS[i] = NULL;
+ pDComplD[i] = NULL;
+ }
+ }
+
+ // select the best pair
+ WeightBest = -1;
+ for ( i = 0; i < nSingles; i++ )
+ {
+ WeightCur = pSingles[i]->Weight;
+ if ( pSCompl[i] )
+ {
+ // add the weight of the double
+ WeightCur += pSCompl[i]->Weight;
+ // there is no need to implement this double, so...
+ pPair = pSCompl[i]->lPairs.pHead;
+ WeightCur += pPair->nLits1 + pPair->nLits2;
+ }
+ if ( WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ *ppSingle = pSingles[i];
+ *ppDouble = pSCompl[i];
+ fBestS = 1;
+ iNum = i;
+ }
+ }
+ for ( i = 0; i < nDoubles; i++ )
+ {
+ WeightCur = pDoubles[i]->Weight;
+ if ( pDComplS[i] )
+ {
+ // add the weight of the single
+ WeightCur += pDComplS[i]->Weight;
+ // there is no need to implement this double, so...
+ pPair = pDoubles[i]->lPairs.pHead;
+ WeightCur += pPair->nLits1 + pPair->nLits2;
+ }
+ if ( WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ *ppSingle = pDComplS[i];
+ *ppDouble = pDoubles[i];
+ fBestS = 0;
+ iNum = i;
+ }
+ }
+/*
+ // print the statistics
+ printf( "\n" );
+ for ( i = 0; i < nSingles; i++ )
+ {
+ printf( "Single #%d: Weight = %3d. ", i, pSingles[i]->Weight );
+ printf( "Compl: " );
+ if ( pSCompl[i] == NULL )
+ printf( "None." );
+ else
+ printf( "D Weight = %3d Sum = %3d",
+ pSCompl[i]->Weight, pSCompl[i]->Weight + pSingles[i]->Weight );
+ printf( "\n" );
+ }
+ printf( "\n" );
+ for ( i = 0; i < nDoubles; i++ )
+ {
+ printf( "Double #%d: Weight = %3d. ", i, pDoubles[i]->Weight );
+ printf( "Compl: " );
+ if ( pDComplS[i] == NULL && pDComplD[i] == NULL )
+ printf( "None." );
+ else if ( pDComplS[i] )
+ printf( "S Weight = %3d Sum = %3d",
+ pDComplS[i]->Weight, pDComplS[i]->Weight + pDoubles[i]->Weight );
+ else if ( pDComplD[i] )
+ printf( "D Weight = %3d Sum = %3d",
+ pDComplD[i]->Weight, pDComplD[i]->Weight + pDoubles[i]->Weight );
+ printf( "\n" );
+ }
+ if ( WeightBest == -1 )
+ printf( "Selected NONE\n" );
+ else
+ {
+ printf( "Selected = %s. ", fBestS? "S": "D" );
+ printf( "Number = %d. ", iNum );
+ printf( "Weight = %d.\n", WeightBest );
+ }
+ printf( "\n" );
+*/
+ return WeightBest;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle )
+{
+// int * pValue2Node = p->pValue2Node;
+ int iVar1, iVar2;
+ int iVar1C, iVar2C;
+ // get the variables of this single div
+ iVar1 = pSingle->pVar1->iVar;
+ iVar2 = pSingle->pVar2->iVar;
+ iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
+ iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
+ if ( iVar1C == -1 || iVar2C == -1 )
+ return NULL;
+ assert( iVar1C < iVar2C );
+ return Fxu_MatrixFindDouble( p, &iVar1C, &iVar2C, 1, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble )
+{
+// int * pValue2Node = p->pValue2Node;
+ int piVarsC1[10], piVarsC2[10];
+ int nVarsC1, nVarsC2;
+ int iVar1, iVar2, iVarTemp;
+ int iVar1C, iVar2C;
+ Fxu_Single * pSingle;
+
+ // get the variables of this double div
+ Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
+ assert( nVarsC1 == 1 );
+ assert( nVarsC2 == 1 );
+ iVar1 = piVarsC1[0];
+ iVar2 = piVarsC2[0];
+ assert( iVar1 < iVar2 );
+
+ iVar1C = Fxu_MatrixFindComplement( p, iVar1 );
+ iVar2C = Fxu_MatrixFindComplement( p, iVar2 );
+ if ( iVar1C == -1 || iVar2C == -1 )
+ return NULL;
+
+ // go through the queque and find this one
+// assert( iVar1C < iVar2C );
+ if ( iVar1C > iVar2C )
+ {
+ iVarTemp = iVar1C;
+ iVar1C = iVar2C;
+ iVar2C = iVarTemp;
+ }
+
+ Fxu_MatrixForEachSingle( p, pSingle )
+ if ( pSingle->pVar1->iVar == iVar1C && pSingle->pVar2->iVar == iVar2C )
+ return pSingle;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble )
+{
+// int * pValue2Node = p->pValue2Node;
+ int piVarsC1[10], piVarsC2[10];
+ int nVarsC1, nVarsC2;
+ int iVar11, iVar12, iVar21, iVar22;
+ int iVar11C, iVar12C, iVar21C, iVar22C;
+ int RetValue;
+
+ // get the variables of this double div
+ Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 );
+ assert( nVarsC1 == 2 && nVarsC2 == 2 );
+
+ iVar11 = piVarsC1[0];
+ iVar12 = piVarsC1[1];
+ iVar21 = piVarsC2[0];
+ iVar22 = piVarsC2[1];
+ assert( iVar11 < iVar21 );
+
+ iVar11C = Fxu_MatrixFindComplement( p, iVar11 );
+ iVar12C = Fxu_MatrixFindComplement( p, iVar12 );
+ iVar21C = Fxu_MatrixFindComplement( p, iVar21 );
+ iVar22C = Fxu_MatrixFindComplement( p, iVar22 );
+ if ( iVar11C == -1 || iVar12C == -1 || iVar21C == -1 || iVar22C == -1 )
+ return NULL;
+ if ( iVar11C != iVar21 || iVar12C != iVar22 ||
+ iVar21C != iVar11 || iVar22C != iVar12 )
+ return NULL;
+
+ // a'b' + ab => a'b + ab'
+ // a'b + ab' => a'b' + ab
+ // swap the second pair in each cube
+ RetValue = piVarsC1[1];
+ piVarsC1[1] = piVarsC2[1];
+ piVarsC2[1] = RetValue;
+
+ return Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, 2, 2 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar )
+{
+ return iVar ^ 1;
+/*
+// int * pValue2Node = p->pValue2Node;
+ int iVarC;
+ int iNode;
+ int Beg, End;
+
+ // get the nodes
+ iNode = pValue2Node[iVar];
+ // get the first node with the same var
+ for ( Beg = iVar; Beg >= 0; Beg-- )
+ if ( pValue2Node[Beg] != iNode )
+ {
+ Beg++;
+ break;
+ }
+ // get the last node with the same var
+ for ( End = iVar; ; End++ )
+ if ( pValue2Node[End] != iNode )
+ {
+ End--;
+ break;
+ }
+
+ // if one of the vars is not binary, quit
+ if ( End - Beg > 1 )
+ return -1;
+
+ // get the complements
+ if ( iVar == Beg )
+ iVarC = End;
+ else if ( iVar == End )
+ iVarC = Beg;
+ else
+ {
+ assert( 0 );
+ }
+ return iVarC;
+*/
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble,
+ int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 )
+{
+ Fxu_Pair * pPair;
+ Fxu_Lit * pLit1, * pLit2;
+ int nLits1, nLits2;
+
+ // get the first pair
+ pPair = pDouble->lPairs.pHead;
+ // init the parameters
+ nLits1 = 0;
+ nLits2 = 0;
+ pLit1 = pPair->pCube1->lLits.pHead;
+ pLit2 = pPair->pCube2->lLits.pHead;
+ while ( 1 )
+ {
+ if ( pLit1 && pLit2 )
+ {
+ if ( pLit1->iVar == pLit2->iVar )
+ { // ensure cube-free
+ pLit1 = pLit1->pHNext;
+ pLit2 = pLit2->pHNext;
+ }
+ else if ( pLit1->iVar < pLit2->iVar )
+ {
+ piVarsC1[nLits1++] = pLit1->iVar;
+ pLit1 = pLit1->pHNext;
+ }
+ else
+ {
+ piVarsC2[nLits2++] = pLit2->iVar;
+ pLit2 = pLit2->pHNext;
+ }
+ }
+ else if ( pLit1 && !pLit2 )
+ {
+ piVarsC1[nLits1++] = pLit1->iVar;
+ pLit1 = pLit1->pHNext;
+ }
+ else if ( !pLit1 && pLit2 )
+ {
+ piVarsC2[nLits2++] = pLit2->iVar;
+ pLit2 = pLit2->pHNext;
+ }
+ else
+ break;
+ }
+ *pnVarsC1 = nLits1;
+ *pnVarsC2 = nLits2;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p,
+ int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 )
+{
+ int piVarsC1_[100], piVarsC2_[100];
+ int nVarsC1_, nVarsC2_, i;
+ Fxu_Double * pDouble;
+ Fxu_Pair * pPair;
+ unsigned Key;
+
+ assert( nVarsC1 > 0 );
+ assert( nVarsC2 > 0 );
+ assert( piVarsC1[0] < piVarsC2[0] );
+
+ // get the hash key
+ Key = Fxu_PairHashKeyArray( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 );
+
+ // check if the divisor for this pair already exists
+ Key %= p->nTableSize;
+ Fxu_TableForEachDouble( p, Key, pDouble )
+ {
+ pPair = pDouble->lPairs.pHead;
+ if ( pPair->nLits1 != nVarsC1 )
+ continue;
+ if ( pPair->nLits2 != nVarsC2 )
+ continue;
+ // get the cubes of this divisor
+ Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1_, piVarsC2_, &nVarsC1_, &nVarsC2_ );
+ // compare lits of the first cube
+ for ( i = 0; i < nVarsC1; i++ )
+ if ( piVarsC1[i] != piVarsC1_[i] )
+ break;
+ if ( i != nVarsC1 )
+ continue;
+ // compare lits of the second cube
+ for ( i = 0; i < nVarsC2; i++ )
+ if ( piVarsC2[i] != piVarsC2_[i] )
+ break;
+ if ( i != nVarsC2 )
+ continue;
+ return pDouble;
+ }
+ return NULL;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_SelectSCD( Fxu_Matrix * p, int WeightLimit, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 )
+{
+// int * pValue2Node = p->pValue2Node;
+ Fxu_Var * pVar1;
+ Fxu_Var * pVar2, * pVarTemp;
+ Fxu_Lit * pLitV, * pLitH;
+ int Coin;
+ int CounterAll;
+ int CounterTest;
+ int WeightCur;
+ int WeightBest;
+
+ CounterAll = 0;
+ CounterTest = 0;
+
+ WeightBest = -10;
+
+ // iterate through the columns in the matrix
+ Fxu_MatrixForEachVariable( p, pVar1 )
+ {
+ // start collecting the affected vars
+ Fxu_MatrixRingVarsStart( p );
+
+ // go through all the literals of this variable
+ for ( pLitV = pVar1->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
+ {
+ // for this literal, go through all the horizontal literals
+ for ( pLitH = pLitV->pHNext; pLitH; pLitH = pLitH->pHNext )
+ {
+ // get another variable
+ pVar2 = pLitH->pVar;
+ CounterAll++;
+ // skip the var if it is already used
+ if ( pVar2->pOrder )
+ continue;
+ // skip the var if it belongs to the same node
+// if ( pValue2Node[pVar1->iVar] == pValue2Node[pVar2->iVar] )
+// continue;
+ // collect the var
+ Fxu_MatrixRingVarsAdd( p, pVar2 );
+ }
+ }
+ // stop collecting the selected vars
+ Fxu_MatrixRingVarsStop( p );
+
+ // iterate through the selected vars
+ Fxu_MatrixForEachVarInRing( p, pVar2 )
+ {
+ CounterTest++;
+
+ // count the coincidence
+ Coin = Fxu_SingleCountCoincidence( p, pVar1, pVar2 );
+ assert( Coin > 0 );
+
+ // get the new weight
+ WeightCur = Coin - 2;
+
+ // compare the weights
+ if ( WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ *ppVar1 = pVar1;
+ *ppVar2 = pVar2;
+ }
+ }
+ // unmark the vars
+ Fxu_MatrixForEachVarInRingSafe( p, pVar2, pVarTemp )
+ pVar2->pOrder = NULL;
+ Fxu_MatrixRingVarsReset( p );
+ }
+
+// if ( WeightBest == WeightLimit )
+// return -1;
+ return WeightBest;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuSingle.c b/src/opt/fxu/fxuSingle.c
new file mode 100644
index 00000000..5af5c341
--- /dev/null
+++ b/src/opt/fxu/fxuSingle.c
@@ -0,0 +1,166 @@
+/**CFile****************************************************************
+
+ FileName [fxuSingle.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Procedures to compute the set of single-cube divisors.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuSingle.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes and adds all single-cube divisors to storage.]
+
+ Description [This procedure should be called once when the matrix is
+ already contructed before the process of logic extraction begins..]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixComputeSingles( Fxu_Matrix * p )
+{
+ Fxu_Var * pVar;
+ // iterate through the columns in the matrix
+ Fxu_MatrixForEachVariable( p, pVar )
+ Fxu_MatrixComputeSinglesOne( p, pVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the single-cube divisors associated with a new column.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
+{
+// int * pValue2Node = p->pValue2Node;
+ Fxu_Lit * pLitV, * pLitH;
+ Fxu_Var * pVar2;
+ int Coin;
+// int CounterAll;
+// int CounterTest;
+ int WeightCur;
+
+ // start collecting the affected vars
+ Fxu_MatrixRingVarsStart( p );
+ // go through all the literals of this variable
+ for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
+ // for this literal, go through all the horizontal literals
+ for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev )
+ {
+ // get another variable
+ pVar2 = pLitH->pVar;
+// CounterAll++;
+ // skip the var if it is already used
+ if ( pVar2->pOrder )
+ continue;
+ // skip the var if it belongs to the same node
+// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] )
+// continue;
+ // collect the var
+ Fxu_MatrixRingVarsAdd( p, pVar2 );
+ }
+ // stop collecting the selected vars
+ Fxu_MatrixRingVarsStop( p );
+
+ // iterate through the selected vars
+ Fxu_MatrixForEachVarInRing( p, pVar2 )
+ {
+// CounterTest++;
+ // count the coincidence
+ Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
+ assert( Coin > 0 );
+ // get the new weight
+ WeightCur = Coin - 2;
+ if ( WeightCur >= 0 )
+ Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
+ }
+
+ // unmark the vars
+ Fxu_MatrixRingVarsUnmark( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the coincidence count of two columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 )
+{
+ Fxu_Lit * pLit1, * pLit2;
+ int Result;
+
+ // compute the coincidence count
+ Result = 0;
+ pLit1 = pVar1->lLits.pHead;
+ pLit2 = pVar2->lLits.pHead;
+ while ( 1 )
+ {
+ if ( pLit1 && pLit2 )
+ {
+ if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar )
+ { // the variables are the same
+ if ( pLit1->iCube == pLit2->iCube )
+ { // the literals are the same
+ pLit1 = pLit1->pVNext;
+ pLit2 = pLit2->pVNext;
+ // add this literal to the coincidence
+ Result++;
+ }
+ else if ( pLit1->iCube < pLit2->iCube )
+ pLit1 = pLit1->pVNext;
+ else
+ pLit2 = pLit2->pVNext;
+ }
+ else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar )
+ pLit1 = pLit1->pVNext;
+ else
+ pLit2 = pLit2->pVNext;
+ }
+ else if ( pLit1 && !pLit2 )
+ pLit1 = pLit1->pVNext;
+ else if ( !pLit1 && pLit2 )
+ pLit2 = pLit2->pVNext;
+ else
+ break;
+ }
+ return Result;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/fxuUpdate.c b/src/opt/fxu/fxuUpdate.c
new file mode 100644
index 00000000..b781e0b1
--- /dev/null
+++ b/src/opt/fxu/fxuUpdate.c
@@ -0,0 +1,802 @@
+/**CFile****************************************************************
+
+ FileName [fxuUpdate.c]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Updating the sparse matrix when divisors are accepted.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fxuUpdate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fxuInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar );
+static void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv );
+static void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem );
+static void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew );
+
+static void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes );
+static int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 );
+static void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble );
+
+static void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube );
+static void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube );
+static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p );
+static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Updates the matrix after selecting two divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble )
+{
+ Fxu_Cube * pCube, * pCubeNew;
+ Fxu_Var * pVarC, * pVarD;
+ Fxu_Var * pVar1, * pVar2;
+
+ // consider trivial cases
+ if ( pSingle == NULL )
+ {
+ assert( pDouble->Weight == Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ) );
+ Fxu_UpdateDouble( p );
+ return;
+ }
+ if ( pDouble == NULL )
+ {
+ assert( pSingle->Weight == Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ) );
+ Fxu_UpdateSingle( p );
+ return;
+ }
+
+ // get the variables of the single
+ pVar1 = pSingle->pVar1;
+ pVar2 = pSingle->pVar2;
+
+ // remove the best double from the heap
+ Fxu_HeapDoubleDelete( p->pHeapDouble, pDouble );
+ // remove the best divisor from the table
+ Fxu_ListTableDelDivisor( p, pDouble );
+
+ // create two new columns (vars)
+ Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 );
+ // create one new row (cube)
+ pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 );
+ pCubeNew->pFirst = pCubeNew;
+ // set the first cube of the positive var
+ pVarD->pFirst = pCubeNew;
+
+ // start collecting the affected vars and cubes
+ Fxu_MatrixRingCubesStart( p );
+ Fxu_MatrixRingVarsStart( p );
+ // add the vars
+ Fxu_MatrixRingVarsAdd( p, pVar1 );
+ Fxu_MatrixRingVarsAdd( p, pVar2 );
+ // remove the literals and collect the affected cubes
+ // remove the divisors associated with this cube
+ // add to the affected cube the literal corresponding to the new column
+ Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD );
+ // replace each two cubes of the pair by one new cube
+ // the new cube contains the base and the new literal
+ Fxu_UpdateDoublePairs( p, pDouble, pVarC );
+ // stop collecting the affected vars and cubes
+ Fxu_MatrixRingCubesStop( p );
+ Fxu_MatrixRingVarsStop( p );
+
+ // add the literals to the new cube
+ assert( pVar1->iVar < pVar2->iVar );
+ assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 );
+ Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 );
+ Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 );
+
+ // create new doubles; we cannot add them in the same loop
+ // because we first have to create *all* new cubes for each node
+ Fxu_MatrixForEachCubeInRing( p, pCube )
+ Fxu_UpdateAddNewDoubles( p, pCube );
+ // update the singles after removing some literals
+ Fxu_UpdateCleanOldSingles( p );
+
+ // undo the temporary rings with cubes and vars
+ Fxu_MatrixRingCubesUnmark( p );
+ Fxu_MatrixRingVarsUnmark( p );
+ // we should undo the rings before creating new singles
+
+ // create new singles
+ Fxu_UpdateAddNewSingles( p, pVarC );
+ Fxu_UpdateAddNewSingles( p, pVarD );
+
+ // recycle the divisor
+ MEM_FREE_FXU( p, Fxu_Double, 1, pDouble );
+ p->nDivs3++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates after accepting single cube divisor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateSingle( Fxu_Matrix * p )
+{
+ Fxu_Single * pSingle;
+ Fxu_Cube * pCube, * pCubeNew;
+ Fxu_Var * pVarC, * pVarD;
+ Fxu_Var * pVar1, * pVar2;
+
+ // read the best divisor from the heap
+ pSingle = Fxu_HeapSingleReadMax( p->pHeapSingle );
+ // get the variables of this single-cube divisor
+ pVar1 = pSingle->pVar1;
+ pVar2 = pSingle->pVar2;
+
+ // create two new columns (vars)
+ Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 );
+ // create one new row (cube)
+ pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 );
+ pCubeNew->pFirst = pCubeNew;
+ // set the first cube
+ pVarD->pFirst = pCubeNew;
+
+ // start collecting the affected vars and cubes
+ Fxu_MatrixRingCubesStart( p );
+ Fxu_MatrixRingVarsStart( p );
+ // add the vars
+ Fxu_MatrixRingVarsAdd( p, pVar1 );
+ Fxu_MatrixRingVarsAdd( p, pVar2 );
+ // remove the literals and collect the affected cubes
+ // remove the divisors associated with this cube
+ // add to the affected cube the literal corresponding to the new column
+ Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD );
+ // stop collecting the affected vars and cubes
+ Fxu_MatrixRingCubesStop( p );
+ Fxu_MatrixRingVarsStop( p );
+
+ // add the literals to the new cube
+ assert( pVar1->iVar < pVar2->iVar );
+ assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 );
+ Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 );
+ Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 );
+
+ // create new doubles; we cannot add them in the same loop
+ // because we first have to create *all* new cubes for each node
+ Fxu_MatrixForEachCubeInRing( p, pCube )
+ Fxu_UpdateAddNewDoubles( p, pCube );
+ // update the singles after removing some literals
+ Fxu_UpdateCleanOldSingles( p );
+ // we should undo the rings before creating new singles
+
+ // unmark the cubes
+ Fxu_MatrixRingCubesUnmark( p );
+ Fxu_MatrixRingVarsUnmark( p );
+
+ // create new singles
+ Fxu_UpdateAddNewSingles( p, pVarC );
+ Fxu_UpdateAddNewSingles( p, pVarD );
+ p->nDivs1++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the matrix after accepting a double cube divisor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateDouble( Fxu_Matrix * p )
+{
+ Fxu_Double * pDiv;
+ Fxu_Cube * pCube, * pCubeNew1, * pCubeNew2;
+ Fxu_Var * pVarC, * pVarD;
+
+ // remove the best divisor from the heap
+ pDiv = Fxu_HeapDoubleGetMax( p->pHeapDouble );
+ // remove the best divisor from the table
+ Fxu_ListTableDelDivisor( p, pDiv );
+
+ // create two new columns (vars)
+ Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 2 );
+ // create two new rows (cubes)
+ pCubeNew1 = Fxu_MatrixAddCube( p, pVarD, 0 );
+ pCubeNew1->pFirst = pCubeNew1;
+ pCubeNew2 = Fxu_MatrixAddCube( p, pVarD, 1 );
+ pCubeNew2->pFirst = pCubeNew1;
+ // set the first cube
+ pVarD->pFirst = pCubeNew1;
+
+ // add the literals to the new cubes
+ Fxu_UpdateMatrixDoubleCreateCubes( p, pCubeNew1, pCubeNew2, pDiv );
+
+ // start collecting the affected cubes and vars
+ Fxu_MatrixRingCubesStart( p );
+ Fxu_MatrixRingVarsStart( p );
+ // replace each two cubes of the pair by one new cube
+ // the new cube contains the base and the new literal
+ Fxu_UpdateDoublePairs( p, pDiv, pVarD );
+ // stop collecting the affected cubes and vars
+ Fxu_MatrixRingCubesStop( p );
+ Fxu_MatrixRingVarsStop( p );
+
+ // create new doubles; we cannot add them in the same loop
+ // because we first have to create *all* new cubes for each node
+ Fxu_MatrixForEachCubeInRing( p, pCube )
+ Fxu_UpdateAddNewDoubles( p, pCube );
+ // update the singles after removing some literals
+ Fxu_UpdateCleanOldSingles( p );
+
+ // undo the temporary rings with cubes and vars
+ Fxu_MatrixRingCubesUnmark( p );
+ Fxu_MatrixRingVarsUnmark( p );
+ // we should undo the rings before creating new singles
+
+ // create new singles
+ Fxu_UpdateAddNewSingles( p, pVarC );
+ Fxu_UpdateAddNewSingles( p, pVarD );
+
+ // recycle the divisor
+ MEM_FREE_FXU( p, Fxu_Double, 1, pDiv );
+ p->nDivs2++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Update the pairs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar )
+{
+ Fxu_Pair * pPair;
+ Fxu_Cube * pCubeUse, * pCubeRem;
+ int i;
+
+ // collect and sort the pairs
+ Fxu_UpdatePairsSort( p, pDouble );
+ for ( i = 0; i < p->nPairsTemp; i++ )
+ {
+ // get the pair
+ pPair = p->pPairsTemp[i];
+ // out of the two cubes, select the one which comes earlier
+ pCubeUse = Fxu_PairMinCube( pPair );
+ pCubeRem = Fxu_PairMaxCube( pPair );
+ // collect the affected cube
+ assert( pCubeUse->pOrder == NULL );
+ Fxu_MatrixRingCubesAdd( p, pCubeUse );
+
+ // remove some literals from pCubeUse and all literals from pCubeRem
+ Fxu_UpdateMatrixDoubleClean( p, pCubeUse, pCubeRem );
+ // add a literal that depends on the new variable
+ Fxu_MatrixAddLiteral( p, pCubeUse, pVar );
+ // check the literal count
+ assert( pCubeUse->lLits.nItems == pPair->nBase + 1 );
+ assert( pCubeRem->lLits.nItems == 0 );
+
+ // update the divisors by removing useless pairs
+ Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeUse );
+ Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeRem );
+ // remove the pair
+ MEM_FREE_FXU( p, Fxu_Pair, 1, pPair );
+ }
+ p->nPairsTemp = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add two cubes corresponding to the given double-cube divisor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv )
+{
+ Fxu_Lit * pLit1, * pLit2;
+ Fxu_Pair * pPair;
+ int nBase, nLits1, nLits2;
+
+ // fill in the SOP and copy the fanins
+ nBase = nLits1 = nLits2 = 0;
+ pPair = pDiv->lPairs.pHead;
+ pLit1 = pPair->pCube1->lLits.pHead;
+ pLit2 = pPair->pCube2->lLits.pHead;
+ while ( 1 )
+ {
+ if ( pLit1 && pLit2 )
+ {
+ if ( pLit1->iVar == pLit2->iVar )
+ { // skip the cube free part
+ pLit1 = pLit1->pHNext;
+ pLit2 = pLit2->pHNext;
+ nBase++;
+ }
+ else if ( pLit1->iVar < pLit2->iVar )
+ { // add literal to the first cube
+ Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar );
+ // move to the next literal in this cube
+ pLit1 = pLit1->pHNext;
+ nLits1++;
+ }
+ else
+ { // add literal to the second cube
+ Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar );
+ // move to the next literal in this cube
+ pLit2 = pLit2->pHNext;
+ nLits2++;
+ }
+ }
+ else if ( pLit1 && !pLit2 )
+ { // add literal to the first cube
+ Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar );
+ // move to the next literal in this cube
+ pLit1 = pLit1->pHNext;
+ nLits1++;
+ }
+ else if ( !pLit1 && pLit2 )
+ { // add literal to the second cube
+ Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar );
+ // move to the next literal in this cube
+ pLit2 = pLit2->pHNext;
+ nLits2++;
+ }
+ else
+ break;
+ }
+ assert( pPair->nLits1 == nLits1 );
+ assert( pPair->nLits2 == nLits2 );
+ assert( pPair->nBase == nBase );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Create the node equal to double-cube divisor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem )
+{
+ Fxu_Lit * pLit1, * bLit1Next;
+ Fxu_Lit * pLit2, * bLit2Next;
+
+ // initialize the starting literals
+ pLit1 = pCubeUse->lLits.pHead;
+ pLit2 = pCubeRem->lLits.pHead;
+ bLit1Next = pLit1? pLit1->pHNext: NULL;
+ bLit2Next = pLit2? pLit2->pHNext: NULL;
+ // go through the pair and remove the literals in the base
+ // from the first cube and all literals from the second cube
+ while ( 1 )
+ {
+ if ( pLit1 && pLit2 )
+ {
+ if ( pLit1->iVar == pLit2->iVar )
+ { // this literal is present in both cubes - it belongs to the base
+ // mark the affected var
+ if ( pLit1->pVar->pOrder == NULL )
+ Fxu_MatrixRingVarsAdd( p, pLit1->pVar );
+ // leave the base in pCubeUse; delete it from pCubeRem
+ Fxu_MatrixDelLiteral( p, pLit2 );
+ // step to the next literals
+ pLit1 = bLit1Next;
+ pLit2 = bLit2Next;
+ bLit1Next = pLit1? pLit1->pHNext: NULL;
+ bLit2Next = pLit2? pLit2->pHNext: NULL;
+ }
+ else if ( pLit1->iVar < pLit2->iVar )
+ { // this literal is present in pCubeUse - remove it
+ // mark the affected var
+ if ( pLit1->pVar->pOrder == NULL )
+ Fxu_MatrixRingVarsAdd( p, pLit1->pVar );
+ // delete this literal
+ Fxu_MatrixDelLiteral( p, pLit1 );
+ // step to the next literals
+ pLit1 = bLit1Next;
+ bLit1Next = pLit1? pLit1->pHNext: NULL;
+ }
+ else
+ { // this literal is present in pCubeRem - remove it
+ // mark the affected var
+ if ( pLit2->pVar->pOrder == NULL )
+ Fxu_MatrixRingVarsAdd( p, pLit2->pVar );
+ // delete this literal
+ Fxu_MatrixDelLiteral( p, pLit2 );
+ // step to the next literals
+ pLit2 = bLit2Next;
+ bLit2Next = pLit2? pLit2->pHNext: NULL;
+ }
+ }
+ else if ( pLit1 && !pLit2 )
+ { // this literal is present in pCubeUse - leave it
+ // mark the affected var
+ if ( pLit1->pVar->pOrder == NULL )
+ Fxu_MatrixRingVarsAdd( p, pLit1->pVar );
+ // delete this literal
+ Fxu_MatrixDelLiteral( p, pLit1 );
+ // step to the next literals
+ pLit1 = bLit1Next;
+ bLit1Next = pLit1? pLit1->pHNext: NULL;
+ }
+ else if ( !pLit1 && pLit2 )
+ { // this literal is present in pCubeRem - remove it
+ // mark the affected var
+ if ( pLit2->pVar->pOrder == NULL )
+ Fxu_MatrixRingVarsAdd( p, pLit2->pVar );
+ // delete this literal
+ Fxu_MatrixDelLiteral( p, pLit2 );
+ // step to the next literals
+ pLit2 = bLit2Next;
+ bLit2Next = pLit2? pLit2->pHNext: NULL;
+ }
+ else
+ break;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the matrix after selecting a single cube divisor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew )
+{
+ Fxu_Lit * pLit1, * bLit1Next;
+ Fxu_Lit * pLit2, * bLit2Next;
+
+ // initialize the starting literals
+ pLit1 = pVar1->lLits.pHead;
+ pLit2 = pVar2->lLits.pHead;
+ bLit1Next = pLit1? pLit1->pVNext: NULL;
+ bLit2Next = pLit2? pLit2->pVNext: NULL;
+ while ( 1 )
+ {
+ if ( pLit1 && pLit2 )
+ {
+ if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar )
+ { // these literals coincide
+ if ( pLit1->iCube == pLit2->iCube )
+ { // these literals coincide
+
+ // collect the affected cube
+ assert( pLit1->pCube->pOrder == NULL );
+ Fxu_MatrixRingCubesAdd( p, pLit1->pCube );
+
+ // add the literal to this cube corresponding to the new column
+ Fxu_MatrixAddLiteral( p, pLit1->pCube, pVarNew );
+ // clean the old cubes
+ Fxu_UpdateCleanOldDoubles( p, NULL, pLit1->pCube );
+
+ // remove the literals
+ Fxu_MatrixDelLiteral( p, pLit1 );
+ Fxu_MatrixDelLiteral( p, pLit2 );
+
+ // go to the next literals
+ pLit1 = bLit1Next;
+ pLit2 = bLit2Next;
+ bLit1Next = pLit1? pLit1->pVNext: NULL;
+ bLit2Next = pLit2? pLit2->pVNext: NULL;
+ }
+ else if ( pLit1->iCube < pLit2->iCube )
+ {
+ pLit1 = bLit1Next;
+ bLit1Next = pLit1? pLit1->pVNext: NULL;
+ }
+ else
+ {
+ pLit2 = bLit2Next;
+ bLit2Next = pLit2? pLit2->pVNext: NULL;
+ }
+ }
+ else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar )
+ {
+ pLit1 = bLit1Next;
+ bLit1Next = pLit1? pLit1->pVNext: NULL;
+ }
+ else
+ {
+ pLit2 = bLit2Next;
+ bLit2Next = pLit2? pLit2->pVNext: NULL;
+ }
+ }
+ else if ( pLit1 && !pLit2 )
+ {
+ pLit1 = bLit1Next;
+ bLit1Next = pLit1? pLit1->pVNext: NULL;
+ }
+ else if ( !pLit1 && pLit2 )
+ {
+ pLit2 = bLit2Next;
+ bLit2Next = pLit2? pLit2->pVNext: NULL;
+ }
+ else
+ break;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sort the pairs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble )
+{
+ Fxu_Pair * pPair;
+ // order the pairs by the first cube to ensure that
+ // new literals are added to the matrix from top to bottom
+ // collect pairs into the array
+ p->nPairsTemp = 0;
+ Fxu_DoubleForEachPair( pDouble, pPair )
+ p->pPairsTemp[ p->nPairsTemp++ ] = pPair;
+ if ( p->nPairsTemp > 1 )
+ { // sort
+ qsort( (void *)p->pPairsTemp, p->nPairsTemp, sizeof(Fxu_Pair *),
+ (int (*)(const void *, const void *)) Fxu_UpdatePairCompare );
+ assert( Fxu_UpdatePairCompare( p->pPairsTemp, p->pPairsTemp + p->nPairsTemp - 1 ) < 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the vars by their number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 )
+{
+ Fxu_Cube * pC1 = (*ppP1)->pCube1;
+ Fxu_Cube * pC2 = (*ppP2)->pCube1;
+ int iP1CubeMin, iP2CubeMin;
+ if ( pC1->pVar->iVar < pC2->pVar->iVar )
+ return -1;
+ if ( pC1->pVar->iVar > pC2->pVar->iVar )
+ return 1;
+ iP1CubeMin = Fxu_PairMinCubeInt( *ppP1 );
+ iP2CubeMin = Fxu_PairMinCubeInt( *ppP2 );
+ if ( iP1CubeMin < iP2CubeMin )
+ return -1;
+ if ( iP1CubeMin > iP2CubeMin )
+ return 1;
+ assert( 0 );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Create new variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes )
+{
+ Fxu_Var * pVarC, * pVarD;
+
+ // add a new column for the complement
+ pVarC = Fxu_MatrixAddVar( p );
+ pVarC->nCubes = 0;
+ // add a new column for the divisor
+ pVarD = Fxu_MatrixAddVar( p );
+ pVarD->nCubes = nCubes;
+
+ // mark this entry in the Value2Node array
+// assert( p->pValue2Node[pVarC->iVar] > 0 );
+// p->pValue2Node[pVarD->iVar ] = p->pValue2Node[pVarC->iVar];
+// p->pValue2Node[pVarD->iVar+1] = p->pValue2Node[pVarC->iVar]+1;
+
+ *ppVarC = pVarC;
+ *ppVarD = pVarD;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube )
+{
+ Fxu_Double * pDivCur;
+ Fxu_Pair * pPair;
+ int i;
+
+ // if the cube is a recently introduced one
+ // it does not have pairs allocated
+ // in this case, there is nothing to update
+ if ( pCube->pVar->ppPairs == NULL )
+ return;
+
+ // go through all the pairs of this cube
+ Fxu_CubeForEachPair( pCube, pPair, i )
+ {
+ // get the divisor of this pair
+ pDivCur = pPair->pDiv;
+ // skip the current divisor
+ if ( pDivCur == pDiv )
+ continue;
+ // remove this pair
+ Fxu_ListDoubleDelPair( pDivCur, pPair );
+ // the divisor may have become useless by now
+ if ( pDivCur->lPairs.nItems == 0 )
+ {
+ assert( pDivCur->Weight == pPair->nBase - 1 );
+ Fxu_HeapDoubleDelete( p->pHeapDouble, pDivCur );
+ Fxu_MatrixDelDivisor( p, pDivCur );
+ }
+ else
+ {
+ // update the divisor's weight
+ pDivCur->Weight -= pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase;
+ Fxu_HeapDoubleUpdate( p->pHeapDouble, pDivCur );
+ }
+ MEM_FREE_FXU( p, Fxu_Pair, 1, pPair );
+ }
+ // finally erase all the pair info associated with this cube
+ Fxu_PairClearStorage( pCube );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the new divisors that depend on the cube.]
+
+ Description [Go through all the non-empty cubes of this cover
+ (except the given cube) and, for each of them, add the new divisor
+ with the given cube.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube )
+{
+ Fxu_Cube * pTemp;
+ assert( pCube->pOrder );
+
+ // if the cube is a recently introduced one
+ // it does not have pairs allocated
+ // in this case, there is nothing to update
+ if ( pCube->pVar->ppPairs == NULL )
+ return;
+
+ for ( pTemp = pCube->pFirst; pTemp->pVar == pCube->pVar; pTemp = pTemp->pNext )
+ {
+ // do not add pairs with the empty cubes
+ if ( pTemp->lLits.nItems == 0 )
+ continue;
+ // to prevent adding duplicated pairs of the new cubes
+ // do not add the pair, if the current cube is marked
+ if ( pTemp->pOrder && pTemp >= pCube )
+ continue;
+ Fxu_MatrixAddDivisor( p, pTemp, pCube );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes old single cube divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p )
+{
+ Fxu_Single * pSingle, * pSingle2;
+ int WeightNew;
+
+ Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 )
+ {
+ // if at least one of the variables is marked, recalculate
+ if ( pSingle->pVar1->pOrder || pSingle->pVar2->pOrder )
+ {
+ // get the new weight
+ WeightNew = -2 + Fxu_SingleCountCoincidence( p, pSingle->pVar1, pSingle->pVar2 );
+ if ( WeightNew >= 0 )
+ {
+ pSingle->Weight = WeightNew;
+ Fxu_HeapSingleUpdate( p->pHeapSingle, pSingle );
+ }
+ else
+ {
+ Fxu_HeapSingleDelete( p->pHeapSingle, pSingle );
+ Fxu_ListMatrixDelSingle( p, pSingle );
+ MEM_FREE_FXU( p, Fxu_Single, 1, pSingle );
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the single cube divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar )
+{
+ Fxu_MatrixComputeSinglesOne( p, pVar );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/fxu/module.make b/src/opt/fxu/module.make
new file mode 100644
index 00000000..331712d1
--- /dev/null
+++ b/src/opt/fxu/module.make
@@ -0,0 +1,12 @@
+SRC += fxu.c \
+ fxuCreate.c \
+ fxuHeapD.c \
+ fxuHeapS.c \
+ fxuList.c \
+ fxuMatrix.c \
+ fxuPair.c \
+ fxuPrint.c \
+ fxuReduce.c \
+ fxuSelect.c \
+ fxuSingle.c \
+ fxuUpdate.c