/**CFile****************************************************************

  FileName    [rsbDec6.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Truth-table-based resubstitution.]

  Synopsis    [Implementation of the algorithm.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: rsbDec6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]

***********************************************************************/

#include "rsbInt.h"

ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline unsigned Rsb_DecTry0( word c ) 
{
    return (unsigned)(c != 0);
}
static inline unsigned Rsb_DecTry1( word c, word f1 ) 
{
    return (Rsb_DecTry0(c&f1) << 1) | Rsb_DecTry0(c&~f1);
}
static inline unsigned Rsb_DecTry2( word c, word f1, word f2 ) 
{
    return (Rsb_DecTry1(c&f2, f1) << 2) | Rsb_DecTry1(c&~f2, f1);
}
static inline unsigned Rsb_DecTry3( word c, word f1, word f2, word f3 ) 
{
    return (Rsb_DecTry2(c&f3, f1, f2) << 4) | Rsb_DecTry2(c&~f3, f1, f2);
}
static inline unsigned Rsb_DecTry4( word c, word f1, word f2, word f3, word f4 ) 
{
    return (Rsb_DecTry3(c&f4, f1, f2, f3) << 8) | Rsb_DecTry3(c&~f4, f1, f2, f3);
}
static inline unsigned Rsb_DecTry5( word c, word f1, word f2, word f3, word f4, word f5 ) 
{
    return (Rsb_DecTry4(c&f5, f1, f2, f3, f4) << 16) | Rsb_DecTry4(c&~f5, f1, f2, f3, f4);
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Rsb_DecTryCex( word * g, int iCexA, int iCexB ) 
{
    return Abc_TtGetBit(g, iCexA) == Abc_TtGetBit(g, iCexB);
}
static inline void Rsb_DecVerifyCex( word * f, word ** g, int nGs, int iCexA, int iCexB ) 
{
    int i;
    // f distinquished it
    if ( Rsb_DecTryCex( f, iCexA, iCexB ) )
        printf( "Verification of CEX has failed: f(A) == f(B)!!!\n" );
    // g do not distinguish it
    for ( i = 0; i < nGs; i++ )
        if ( !Rsb_DecTryCex( g[i], iCexA, iCexB ) )
            printf( "Verification of CEX has failed: g[%d](A) != g[%d](B)!!!\n", i, i );
}
static inline void Rsb_DecRecordCex( word ** g, int nGs, int iCexA, int iCexB, word * pCexes, int nCexes ) 
{
    int i;
    assert( nCexes < 64 );
    for ( i = 0; i < nGs; i++ )
        if ( Rsb_DecTryCex(g[i], iCexA, iCexB) )
            Abc_TtSetBit( pCexes + i, nCexes );
}

/**Function*************************************************************

  Synopsis    [Checks decomposability of f with divisors g.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline word Rsb_DecCofactor( word ** g, int nGs, int w, int iMint ) 
{
    int i;
    word Cof = ~(word)0;
    for ( i = 0; i < nGs; i++ )
        Cof &=  ((iMint >> i) & 1) ? g[i][w] : ~g[i][w];
    return Cof;
}
unsigned Rsb_DecCheck( int nVars, word * f, word ** g, int nGs, unsigned * pPat, int * pCexA, int * pCexB ) 
{
    word CofA, CofB;
    int nWords = Abc_TtWordNum( nVars );
    int w, k, iMint, iShift = ( 1 << nGs );
    unsigned uMask = (~(unsigned)0) >> (32-iShift);
    unsigned uTotal = 0;
    assert( nGs > 0 && nGs < 5 );
    for ( w = 0; w < nWords; w++ )
    {
        // generate decomposition pattern
        if ( nGs == 1 )
            pPat[w] = Rsb_DecTry2( ~(word)0, g[0][w], f[w] );
        else if ( nGs == 2 )
            pPat[w] = Rsb_DecTry3( ~(word)0, g[0][w], g[1][w], f[w] );
        else if ( nGs == 3 )
            pPat[w] = Rsb_DecTry4( ~(word)0, g[0][w], g[1][w], g[2][w], f[w] );
        else if ( nGs == 4 )
            pPat[w] = Rsb_DecTry5( ~(word)0, g[0][w], g[1][w], g[2][w], g[3][w], f[w] );
        // check if it is consistent
        iMint = Abc_Tt6FirstBit( (pPat[w] >> iShift) & pPat[w] & uMask );
        if ( iMint >= 0 )
        {   // generate a cex
            CofA = Rsb_DecCofactor( g, nGs, w, iMint );
            assert( (~f[w] & CofA) && (f[w] & CofA) );
            *pCexA = w * 64 + Abc_Tt6FirstBit( ~f[w] & CofA );
            *pCexB = w * 64 + Abc_Tt6FirstBit(  f[w] & CofA );
            return 0;
        }
        uTotal |= pPat[w];
        if ( w == 0 )
            continue;
        // check if it is consistent with other patterns seen so far
        iMint = Abc_Tt6FirstBit( (uTotal >> iShift) & uTotal & uMask );
        if ( iMint == -1 )
            continue;
        // find an overlap and generate a cex
        for ( k = 0; k < w; k++ )
        {
            iMint = Abc_Tt6FirstBit( ((pPat[k] | pPat[w]) >> iShift) & (pPat[k] | pPat[w]) & uMask );
            if ( iMint == -1 )
                continue;
            CofA = Rsb_DecCofactor( g, nGs, k, iMint );
            CofB = Rsb_DecCofactor( g, nGs, w, iMint );
            if ( (~f[k] & CofA) && (f[w] & CofB) )
            {
                *pCexA = k * 64 + Abc_Tt6FirstBit( ~f[k] & CofA );
                *pCexB = w * 64 + Abc_Tt6FirstBit(  f[w] & CofB );
            }
            else
            {
                assert( (f[k] & CofA) && (~f[w] & CofB) );
                *pCexA = k * 64 + Abc_Tt6FirstBit(  f[k] & CofA );
                *pCexB = w * 64 + Abc_Tt6FirstBit( ~f[w] & CofB );
            }
            return 0;
        }
    }
    return uTotal;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Rsb_DecPrintTable( word * pCexes, int nGs, int nGsAll, Vec_Int_t * vTries ) 
{
    int pCands[16], nCands;
    int i, c, Cand, iStart = 0;
    if ( Vec_IntSize(vTries) == 0 )
        return;

//    printf( "\n" );
    for ( i = 0; i < 4; i++ )
        printf( "    " );
    printf( "  " );
    for ( i = 0; i < nGs; i++ )
        printf( "%d", (i % 100) / 10 );
    printf( "|" );
    for ( ; i < nGsAll; i++ )
        printf( "%d", (i % 100) / 10 );
    printf( "\n" );

    for ( i = 0; i < 4; i++ )
        printf( "    " );
    printf( "  " );
    for ( i = 0; i < nGs; i++ )
        printf( "%d", i % 10 );
    printf( "|" );
    for ( ; i < nGsAll; i++ )
        printf( "%d", i % 10 );
    printf( "\n" );
    printf( "\n" );

    for ( c = 0; iStart < Vec_IntSize(vTries); c++ )
    {
        // collect candidates
        for ( i = 0; i < 4; i++ )
            pCands[i] = -1;
        nCands = 0;
        Vec_IntForEachEntryStart( vTries, Cand, i, iStart )
            if ( Cand == -1 )
            {
                iStart = i + 1;
                break;
            }
            else
                pCands[nCands++] = Cand;
        assert( nCands <= 4 );
        // print them
        for ( i = 0; i < 4; i++ )
            if ( pCands[i] >= 0 )
                printf( "%4d", pCands[i] );
            else
                printf( "    " );
        // print the bit-string
        printf( "  " );
        for ( i = 0; i < nGs; i++ )
            printf( "%c", Abc_TtGetBit( pCexes + i, c ) ? '.' : '+' );
        printf( "|" );
        for ( ; i < nGsAll; i++ )
            printf( "%c", Abc_TtGetBit( pCexes + i, c ) ? '.' : '+' );
        printf( "  %3d\n", c );
    }
    printf( "\n" );

    // write the number of ones
    for ( i = 0; i < 4; i++ )
        printf( "    " );
    printf( "  " );
    for ( i = 0; i < nGs; i++ )
        printf( "%d", Abc_TtCountOnes(pCexes[i]) / 10 );
    printf( "|" );
    for ( ; i < nGsAll; i++ )
        printf( "%d", Abc_TtCountOnes(pCexes[i]) / 10 );
    printf( "\n" );

    for ( i = 0; i < 4; i++ )
        printf( "    " );
    printf( "  " );
    for ( i = 0; i < nGs; i++ )
        printf( "%d", Abc_TtCountOnes(pCexes[i]) % 10 );
    printf( "|" );
    for ( ; i < nGsAll; i++ )
        printf( "%d", Abc_TtCountOnes(pCexes[i]) % 10 );
    printf( "\n" );
    printf( "\n" );
}

/**Function*************************************************************

  Synopsis    [Init ]

  Description [Returns the numbers of the decomposition functions and 
  the truth table of a function up to 4 variables.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Rsb_DecInitCexes( int nVars, word * f, word ** g, int nGs, int nGsAll, word * pCexes, Vec_Int_t * vTries ) 
{
    int nWords = Abc_TtWordNum( nVars );
    int ValueB = Abc_TtGetBit( f, 0 );
    int ValueE = Abc_TtGetBit( f, 64*nWords-1 );
    int iCexT0, iCexT1, iCexF0, iCexF1;

    iCexT0 = ValueB  ? 0           : Abc_TtFindFirstBit( f, nVars );
    iCexT1 = ValueE  ? 64*nWords-1 : Abc_TtFindLastBit( f, nVars );

    iCexF0 = !ValueB ? 0           : Abc_TtFindFirstZero( f, nVars );
    iCexF1 = !ValueE ? 64*nWords-1 : Abc_TtFindLastZero( f, nVars );

    assert( !Rsb_DecTryCex( f, iCexT0, iCexF0 ) );
    assert( !Rsb_DecTryCex( f, iCexT0, iCexF1 ) );
    assert( !Rsb_DecTryCex( f, iCexT1, iCexF0 ) );
    assert( !Rsb_DecTryCex( f, iCexT1, iCexF1 ) );

    Rsb_DecRecordCex( g, nGsAll, iCexT0, iCexF0, pCexes, 0 );
    Rsb_DecRecordCex( g, nGsAll, iCexT0, iCexF1, pCexes, 1 );
    Rsb_DecRecordCex( g, nGsAll, iCexT1, iCexF0, pCexes, 2 );
    Rsb_DecRecordCex( g, nGsAll, iCexT1, iCexF1, pCexes, 3 );

    if ( vTries )
    {
    Vec_IntPush( vTries, -1 );
    Vec_IntPush( vTries, -1 );
    Vec_IntPush( vTries, -1 );
    Vec_IntPush( vTries, -1 );
    }
    return 4;
}

/**Function*************************************************************

  Synopsis    [Finds a setset of gs to decompose f.]

  Description [Returns the numbers of the decomposition functions and 
  the truth table of a function up to 4 variables.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
unsigned Rsb_DecPerformInt( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, int nGsAll, int fFindAll ) 
{
    word * pCexes = Vec_WrdArray(p->vCexes);
    unsigned * pPat = (unsigned *)Vec_IntArray(p->vDecPats);
    /*
    The following filtering hueristic can be used:
    after the first round (if there is more than 5 cexes, 
    remove all the divisors, except fanins of the node
    This should lead to a speadup without sacrifying quality.

    Another idea is to precompute several counter-examples
    like the first and last 0 and 1 mints of the function
    which yields 4 cexes.
    */

    word * pDivs[16];
    unsigned uTruth = 0;
    int i, k, j, n, iCexA, iCexB, nCexes = 0;
    memset( pCexes, 0, sizeof(word) * nGsAll );  
    Vec_IntClear( p->vTries );
    // populate the counter-examples with the three most obvious
//    nCexes = Rsb_DecInitCexes( nVars, f, g, nGs, nGsAll, pCexes, vTries );
    // start by checking each function
    p->vFanins->nSize = 1;
    for ( i = 0; i < nGs; i++ )
    {
        if ( pCexes[i] )
            continue;
        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
        if ( uTruth )
        {
            if ( fFindAll )
            {
                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 1 );
                Kit_DsdPrintFromTruth( &uTruth, 1 ); printf( "   " );
                Vec_IntPrint(p->vFanins);
                continue;
            }
            else
                return uTruth;
        }
        if ( nCexes == 64 )
            return 0;
        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
        if ( !p->fVerbose )
            continue;
        Vec_IntPush( p->vTries, i );
        Vec_IntPush( p->vTries, -1 );
    }
    if ( p->nDecMax == 1 )
        return 0;
    // continue by checking pairs
    p->vFanins->nSize = 2;
    for ( i = 1; i < nGs; i++ )
    for ( k = 0; k < i; k++ )
    {
        if ( pCexes[i] & pCexes[k] )
            continue;
        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
        pDivs[1] = g[k];  p->vFanins->pArray[1] = k;
        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
        if ( uTruth )
        {
            if ( fFindAll )
            {
                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 2 );
                Kit_DsdPrintFromTruth( &uTruth, 2 ); printf( "   " );
                Vec_IntPrint(p->vFanins);
                continue;
            }
            else
                return uTruth;
        }
        if ( nCexes == 64 )
            return 0;
        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
        if ( !p->fVerbose )
            continue;
        Vec_IntPush( p->vTries, i );
        Vec_IntPush( p->vTries, k );
        Vec_IntPush( p->vTries, -1 );
    }
    if ( p->nDecMax == 2 )
        return 0;
    // continue by checking triples
    p->vFanins->nSize = 3;
    for ( i = 2; i < nGs; i++ )
    for ( k = 1; k < i; k++ )
    for ( j = 0; j < k; j++ )
    {
        if ( pCexes[i] & pCexes[k] & pCexes[j] )
            continue;
        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
        pDivs[1] = g[k];  p->vFanins->pArray[1] = k;
        pDivs[2] = g[j];  p->vFanins->pArray[2] = j;
        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
        if ( uTruth )
        {
            if ( fFindAll )
            {
                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 3 );
                Kit_DsdPrintFromTruth( &uTruth, 3 ); printf( "   " );
                Vec_IntPrint(p->vFanins);
                continue;
            }
            else
                return uTruth;
        }
        if ( nCexes == 64 )
            return 0;
        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
        if ( !p->fVerbose )
            continue;
        Vec_IntPush( p->vTries, i );
        Vec_IntPush( p->vTries, k );
        Vec_IntPush( p->vTries, j );
        Vec_IntPush( p->vTries, -1 );
    }
    if ( p->nDecMax == 3 )
        return 0;
    // continue by checking quadras
    p->vFanins->nSize = 4;
    for ( i = 3; i < nGs; i++ )
    for ( k = 2; k < i; k++ )
    for ( j = 1; j < k; j++ )
    for ( n = 0; n < j; n++ )
    {
        if ( pCexes[i] & pCexes[k] & pCexes[j] & pCexes[n] )
            continue;
        pDivs[0] = g[i];  p->vFanins->pArray[0] = i;
        pDivs[1] = g[k];  p->vFanins->pArray[1] = k;
        pDivs[2] = g[j];  p->vFanins->pArray[2] = j;
        pDivs[3] = g[n];  p->vFanins->pArray[3] = n;
        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB );
        if ( uTruth )
        {
            if ( fFindAll )
            {
                uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 4 );
                Kit_DsdPrintFromTruth( &uTruth, 4 ); printf( "   " );
                Vec_IntPrint(p->vFanins);
                continue;
            }
            else
                return uTruth;
        }
        if ( nCexes == 64 )
            return 0;
        Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB );
        Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ );
        if ( !p->fVerbose )
            continue;
        Vec_IntPush( p->vTries, i );
        Vec_IntPush( p->vTries, k );
        Vec_IntPush( p->vTries, j );
        Vec_IntPush( p->vTries, n );
        Vec_IntPush( p->vTries, -1 );
    }
//    printf( "%d ", nCexes );
    if ( p->nDecMax == 4 )
        return 0;
    return 0;
}

/**Function*************************************************************

  Synopsis    [Verifies 4-input decomposition.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Rsb_DecPrintFunc( Rsb_Man_t * p, unsigned Truth4, word * f, word ** ppGs, int nGs, int nVarsAll )
{
    int nVars  =  Vec_IntSize(p->vFanins);
    word Copy  =  Truth4;
    word wOn   =  Abc_Tt6Stretch( Copy >> (1 << nVars), nVars );
    word wOnDc = ~Abc_Tt6Stretch( Copy, nVars );
    word wIsop =  Abc_Tt6Isop( wOn, wOnDc, nVars );
    int i;

    printf( "Offset : " );
    Abc_TtPrintBinary( &Copy, nVars );  //printf( "\n" );
    Copy >>= ((word)1 << nVars);
    printf( "Onset  : " );
    Abc_TtPrintBinary( &Copy, nVars );  //printf( "\n" );
    printf( "Result : " );
    Abc_TtPrintBinary( &wIsop, nVars ); //printf( "\n" );
    Kit_DsdPrintFromTruth( (unsigned *)&wIsop, nVars );  printf( "\n" );

    // print functions
    printf( "Func   : " );
    Abc_TtPrintBinary( f, nVarsAll );   //printf( "\n" );
    Kit_DsdPrintFromTruth( (unsigned *)f, nVarsAll );    printf( "\n" );
    for ( i = 0; i < nGs; i++ )
    {
        printf( "Div%3d : ", i );
        Kit_DsdPrintFromTruth( (unsigned *)ppGs[i], nVarsAll );  printf( "\n" );
    }
    printf( "Solution : " );
    for ( i = 0; i < Vec_IntSize(p->vFanins); i++ )
        printf( "%d ", Vec_IntEntry(p->vFanins, i) );
    printf( "\n" );
}

/**Function*************************************************************

  Synopsis    [Verifies 4-input decomposition.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Rsb_DecVerify( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, unsigned Truth4, word * pTemp1, word * pTemp2 )
{
    word * pFanins[16];
    int b, m, Num, nSuppSize;
    int nWords = Abc_TtWordNum(nVars);
    Truth4 >>= (1 << Vec_IntSize(p->vFanins));
    Truth4 = (unsigned)Abc_Tt6Stretch( (word)Truth4, Vec_IntSize(p->vFanins) );
//Kit_DsdPrintFromTruth( (unsigned *)&Truth4, Vec_IntSize(p->vFanins) );
//printf( "\n" );
//    nSuppSize = Rsb_Word6SupportSize( Truth4 );
//    assert( nSuppSize == Vec_IntSize(p->vFanins) );
    nSuppSize = Vec_IntSize(p->vFanins);
    // collect the fanins
    Vec_IntForEachEntry( p->vFanins, Num, b )
    {
        assert( Num < nGs );
        pFanins[b] = g[Num];
    }
    // create the or of ands
    Abc_TtClear( pTemp1, nWords );
    for ( m = 0; m < (1<<nSuppSize); m++ )
    {
        if ( ((Truth4 >> m) & 1) == 0 )
            continue;
        Abc_TtFill( pTemp2, nWords );
        for ( b = 0; b < nSuppSize; b++ )
            if ( (m >> b) & 1 )
                Abc_TtAnd( pTemp2, pTemp2, pFanins[b], nWords, 0 );
            else
                Abc_TtSharp( pTemp2, pTemp2, pFanins[b], nWords );
        Abc_TtOr( pTemp1, pTemp1, pTemp2, nWords );
    }
    // check the function
    if ( !Abc_TtEqual( pTemp1, f, nWords ) )
        printf( "Verification failed.\n" );
//    else
//        printf( "Verification passed.\n" );
    return 1;
}

/**Function*************************************************************

  Synopsis    [Finds a setset of gs to decompose f.]

  Description [Returns the numbers of the decomposition functions and 
  the truth table of a function up to 4 variables.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
unsigned Rsb_ManPerform( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, int nGsAll, int fVerbose0 ) 
{
    word * pCexes = Vec_WrdArray(p->vCexes);
    unsigned * pPat = (unsigned *)Vec_IntArray(p->vDecPats);
    int fVerbose = 0;//(nGs > 40);
    Vec_Int_t * vTries = NULL;
    unsigned uTruth;

    // verify original decomposition
    if ( Vec_IntSize(p->vFaninsOld) && Vec_IntSize(p->vFaninsOld) <= 4 )
    {
        word * pDivs[8];
        int i, Entry, iCexA, iCexB;
        Vec_IntForEachEntry( p->vFaninsOld, Entry, i )
            pDivs[i] = g[Entry];
        uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFaninsOld), pPat, &iCexA, &iCexB );
//        assert( uTruth != 0 );
        if ( fVerbose )
        {
            printf( "Verified orig decomp with %d vars {", Vec_IntSize(p->vFaninsOld) );
            Vec_IntForEachEntry( p->vFaninsOld, Entry, i )
                printf( " %d", Entry );
            printf( " }\n" );
        }
        if ( uTruth )
        {
//            if ( fVerbose )
//                Rsb_DecPrintFunc( p, uTruth );
        }
        else 
        {
            printf( "Verified orig decomp with %d vars {", Vec_IntSize(p->vFaninsOld) );
            Vec_IntForEachEntry( p->vFaninsOld, Entry, i )
                printf( " %d", Entry );
            printf( " }\n" );
            printf( "Verification FAILED.\n" );
        }
    }
    // start tries
if ( fVerbose )
vTries = Vec_IntAlloc( 100 );
    assert( nGs < nGsAll );
    uTruth = Rsb_DecPerformInt( p, nVars, f, g, nGs, nGsAll, 0 );

    if ( uTruth )
    {
        if ( fVerbose )
        {
            int i, Entry;
            printf( "Found decomp with %d vars {", Vec_IntSize(p->vFanins) );
            Vec_IntForEachEntry( p->vFanins, Entry, i )
                printf( " %d", Entry );
            printf( " }\n" );
//            Rsb_DecPrintFunc( p, uTruth );
//            Rsb_DecVerify( nVars, f, g, nGs, p->vFanins, uTruth, g[nGsAll], g[nGsAll+1] );
        }
    }
    else 
    {
        Vec_IntShrink( p->vFanins, 0 );
        if ( fVerbose )
        printf( "Did not find decomposition with 4 variables.\n" );
    }

if ( fVerbose )
Rsb_DecPrintTable( pCexes, nGs, nGsAll, vTries );
if ( fVerbose )
Vec_IntFree( vTries );
    return uTruth;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Rsb_ManPerformResub6( Rsb_Man_t * p, int nVarsAll, word uTruth, Vec_Wrd_t * vDivTruths, word * puTruth0, word * puTruth1, int fVerbose )
{
    word * pGs[200];
    unsigned uTruthRes;
    int i, nVars, nGs = Vec_WrdSize(vDivTruths);
    assert( nGs < 200 );
    for ( i = 0; i < nGs; i++ )
        pGs[i] = Vec_WrdEntryP(vDivTruths,i);
    uTruthRes = Rsb_DecPerformInt( p, nVarsAll, &uTruth, pGs, nGs, nGs, 0 );
    if ( uTruthRes == 0 )
        return 0;

    if ( fVerbose )
        Rsb_DecPrintFunc( p, uTruthRes, &uTruth, pGs, nGs, nVarsAll );
    if ( fVerbose )
        Rsb_DecPrintTable( Vec_WrdArray(p->vCexes), nGs, nGs, p->vTries );

    nVars = Vec_IntSize(p->vFanins);
    *puTruth0 = Abc_Tt6Stretch( uTruthRes,                 nVars );
    *puTruth1 = Abc_Tt6Stretch( uTruthRes >> (1 << nVars), nVars );
    return 1;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Rsb_ManPerformResub6Test()
{
    Rsb_Man_t * p;
    Vec_Wrd_t * vDivTruths;
    int RetValue;
    word a = s_Truths6[0];
    word b = s_Truths6[1];
    word c = s_Truths6[2];
    word d = s_Truths6[3];
    word e = s_Truths6[4];
    word f = s_Truths6[5];
    word ab = a & b;
    word cd = c & d;
    word ef = e & f;
    word F = ab | cd | ef;
    word uTruth0, uTruth1;

    vDivTruths = Vec_WrdAlloc( 100 );
    Vec_WrdPush( vDivTruths, a );
    Vec_WrdPush( vDivTruths, b );
    Vec_WrdPush( vDivTruths, c );
    Vec_WrdPush( vDivTruths, d );
    Vec_WrdPush( vDivTruths, e );
    Vec_WrdPush( vDivTruths, f );
    Vec_WrdPush( vDivTruths, ab );
    Vec_WrdPush( vDivTruths, cd );
    Vec_WrdPush( vDivTruths, ef );

    p = Rsb_ManAlloc( 6, 64, 4, 1 );

    RetValue = Rsb_ManPerformResub6( p, 6, F, vDivTruths, &uTruth0, &uTruth1, 1 );

    Rsb_ManFree( p );
    Vec_WrdFree( vDivTruths );
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END

