#include "mvc.h"
ABC_NAMESPACE_IMPL_START
static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem );
int s_fVerbose = 0;
void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
{
if ( Mvc_CoverReadCubeNum( pCover ) < Mvc_CoverReadCubeNum( pDiv ) )
{
*ppQuo = NULL;
*ppRem = NULL;
return;
}
if ( !Mvc_CoverCheckSuppContainment( pCover, pDiv ) )
{
*ppQuo = NULL;
*ppRem = NULL;
return;
}
Mvc_CoverDivideInternal( pCover, pDiv, ppQuo, ppRem );
}
void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
{
Mvc_Cover_t * pQuo, * pRem;
Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy;
Mvc_Cube_t * pCube1, * pCube2;
int * pGroups, nGroups; int nCubesC, nCubesD, nMerges, iCubeC, iCubeD;
int iMerge = -1; int fSkipG, GroupSize, g, c, RetValue;
int nCubes;
nCubesD = Mvc_CoverReadCubeNum( pDiv );
nCubesC = Mvc_CoverReadCubeNum( pCover );
if ( nCubesD == 1 )
{
if ( Mvc_CoverIsOneLiteral( pDiv ) )
Mvc_CoverDivideByLiteral( pCover, pDiv, ppQuo, ppRem );
else
Mvc_CoverDivideByCube( pCover, pDiv, ppQuo, ppRem );
return;
}
pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
Mvc_CoverAllocateMask( pDiv );
Mvc_CoverSupport( pDiv, pDiv->pMask );
Mvc_CoverSort( pDiv, NULL, Mvc_CubeCompareInt );
Mvc_CoverSort( pCover, pDiv->pMask, Mvc_CubeCompareIntOutsideAndUnderMask );
pGroups = MEM_ALLOC( pCover->pMem, int, nCubesC + 1 );
Mvc_CoverList2Array( pCover );
Mvc_CoverList2Array( pDiv );
pGroups[0] = 0;
nGroups = 1;
for ( c = 1; c < nCubesC; c++ )
{
pCube1 = pCover->pCubes[c-1];
pCube2 = pCover->pCubes[c ];
Mvc_CubeBitEqualOutsideMask( RetValue, pCube1, pCube2, pDiv->pMask );
if ( !RetValue )
pGroups[nGroups++] = c;
}
pGroups[nGroups] = nCubesC;
nCubes = 0;
for ( g = 0; g < nGroups; g++ )
{
GroupSize = pGroups[g+1] - pGroups[g];
if ( GroupSize < nCubesD )
{
for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
{
pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] );
Mvc_CoverAddCubeTail( pRem, pCubeCopy );
nCubes++;
}
continue;
}
for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
Mvc_CubeSetSize( pCover->pCubes[c], 1 );
iCubeD = 0;
iCubeC = 0;
pCubeD = pDiv->pCubes[iCubeD++];
pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
fSkipG = 0;
nMerges = 0;
while ( 1 )
{
RetValue = Mvc_CubeCompareIntUnderMask( pCubeC, pCubeD, pDiv->pMask );
if ( RetValue == -1 ) { if ( GroupSize - iCubeC < nCubesD - nMerges )
{
fSkipG = 1;
break;
}
pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
continue;
}
if ( RetValue == 1 ) { fSkipG = 1;
break;
}
Mvc_CubeSetSize( pCubeC, 0 );
iMerge = iCubeC-1;
nMerges++;
if ( iCubeD == nCubesD )
break;
assert( iCubeD < nCubesD );
pCubeD = pDiv->pCubes[iCubeD++];
assert( pGroups[g]+iCubeC < nCubesC );
pCubeC = pCover->pCubes[pGroups[g]+iCubeC++];
}
if ( fSkipG )
{
for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
{
pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] );
Mvc_CoverAddCubeTail( pRem, pCubeCopy );
nCubes++;
}
continue;
}
for ( c = pGroups[g]; c < pGroups[g+1]; c++ )
{
pCubeC = pCover->pCubes[c];
if ( Mvc_CubeReadSize(pCubeC) )
{
pCubeCopy = Mvc_CubeDup( pRem, pCubeC );
Mvc_CoverAddCubeTail( pRem, pCubeCopy );
nCubes++;
}
}
pCube1 = Mvc_CubeAlloc( pQuo );
Mvc_CubeBitSharp( pCube1, pCover->pCubes[pGroups[g]+iMerge], pDiv->pMask );
Mvc_CoverAddCubeTail( pQuo, pCube1 );
nCubes += nCubesD;
}
assert( nCubes == nCubesC );
MEM_FREE( pCover->pMem, int, nCubesC + 1, pGroups );
*ppRem = pRem;
*ppQuo = pQuo;
}
void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
{
Mvc_Cover_t * pQuo, * pRem;
Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy;
int CompResult;
assert( Mvc_CoverReadCubeNum(pDiv) == 1 );
pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
pCubeD = Mvc_CoverReadCubeHead( pDiv );
Mvc_CoverForEachCube( pCover, pCubeC )
{
Mvc_Cube2BitNotImpl( CompResult, pCubeD, pCubeC );
if ( !CompResult )
{ pCubeCopy = Mvc_CubeAlloc( pQuo );
Mvc_CubeBitSharp( pCubeCopy, pCubeC, pCubeD );
Mvc_CoverAddCubeTail( pQuo, pCubeCopy );
}
else
{
pCubeCopy = Mvc_CubeDup( pRem, pCubeC );
Mvc_CoverAddCubeTail( pRem, pCubeCopy );
}
}
*ppRem = pRem;
*ppQuo = pQuo;
}
void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem )
{
Mvc_Cover_t * pQuo, * pRem;
Mvc_Cube_t * pCubeC, * pCubeCopy;
int iLit;
assert( Mvc_CoverReadCubeNum(pDiv) == 1 );
pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits );
iLit = Mvc_CoverFirstCubeFirstLit( pDiv );
Mvc_CoverForEachCube( pCover, pCubeC )
{
pCubeCopy = Mvc_CubeDup( pCover, pCubeC );
if ( Mvc_CubeBitValue( pCubeCopy, iLit ) )
{ Mvc_CubeBitRemove( pCubeCopy, iLit );
Mvc_CoverAddCubeTail( pQuo, pCubeCopy );
}
else
{ Mvc_CoverAddCubeTail( pRem, pCubeCopy );
}
}
*ppRem = pRem;
*ppQuo = pQuo;
}
void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit )
{
Mvc_Cube_t * pCube, * pCube2, * pPrev;
pPrev = NULL;
Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 )
{
if ( Mvc_CubeBitValue( pCube, iLit ) == 0 )
{ Mvc_CoverDeleteCube( pCover, pPrev, pCube );
Mvc_CubeFree( pCover, pCube );
}
else
{ Mvc_CubeBitRemove( pCube, iLit );
pPrev = pCube;
}
}
}
void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem )
{
Mvc_Cover_t * pProd;
Mvc_Cover_t * pDiff;
pProd = Mvc_CoverAlgebraicMultiply( pDiv, pQuo );
pDiff = Mvc_CoverAlgebraicSubtract( pCover, pProd );
if ( Mvc_CoverAlgebraicEqual( pDiff, pRem ) )
printf( "Verification OKAY!\n" );
else
{
printf( "Verification FAILED!\n" );
printf( "pCover:\n" );
Mvc_CoverPrint( pCover );
printf( "pDiv:\n" );
Mvc_CoverPrint( pDiv );
printf( "pRem:\n" );
Mvc_CoverPrint( pRem );
printf( "pQuo:\n" );
Mvc_CoverPrint( pQuo );
}
Mvc_CoverFree( pProd );
Mvc_CoverFree( pDiff );
}
ABC_NAMESPACE_IMPL_END