| /**CFile**************************************************************** |
| |
| FileName [mvcDivide.c] |
| |
| PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] |
| |
| Synopsis [Procedures for algebraic division.] |
| |
| Author [MVSIS Group] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - February 1, 2003.] |
| |
| Revision [$Id: mvcDivide.c,v 1.5 2003/04/26 20:41:36 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "mvc.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ); |
| |
| int s_fVerbose = 0; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) |
| { |
| // check the number of cubes |
| if ( Mvc_CoverReadCubeNum( pCover ) < Mvc_CoverReadCubeNum( pDiv ) ) |
| { |
| *ppQuo = NULL; |
| *ppRem = NULL; |
| return; |
| } |
| |
| // make sure that support of pCover contains that of pDiv |
| if ( !Mvc_CoverCheckSuppContainment( pCover, pDiv ) ) |
| { |
| *ppQuo = NULL; |
| *ppRem = NULL; |
| return; |
| } |
| |
| // perform the general division |
| Mvc_CoverDivideInternal( pCover, pDiv, ppQuo, ppRem ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Merge the cubes inside the groups.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) |
| { |
| Mvc_Cover_t * pQuo, * pRem; |
| Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; |
| Mvc_Cube_t * pCube1, * pCube2; |
| int * pGroups, nGroups; // the cube groups |
| int nCubesC, nCubesD, nMerges, iCubeC, iCubeD; |
| int iMerge = -1; // Suppress "might be used uninitialized" |
| int fSkipG, GroupSize, g, c, RetValue; |
| int nCubes; |
| |
| // get cover sizes |
| nCubesD = Mvc_CoverReadCubeNum( pDiv ); |
| nCubesC = Mvc_CoverReadCubeNum( pCover ); |
| |
| // check trivial cases |
| if ( nCubesD == 1 ) |
| { |
| if ( Mvc_CoverIsOneLiteral( pDiv ) ) |
| Mvc_CoverDivideByLiteral( pCover, pDiv, ppQuo, ppRem ); |
| else |
| Mvc_CoverDivideByCube( pCover, pDiv, ppQuo, ppRem ); |
| return; |
| } |
| |
| // create the divisor and the remainder |
| pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); |
| pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); |
| |
| // get the support of the divisor |
| Mvc_CoverAllocateMask( pDiv ); |
| Mvc_CoverSupport( pDiv, pDiv->pMask ); |
| |
| // sort the cubes of the divisor |
| Mvc_CoverSort( pDiv, NULL, Mvc_CubeCompareInt ); |
| // sort the cubes of the cover |
| Mvc_CoverSort( pCover, pDiv->pMask, Mvc_CubeCompareIntOutsideAndUnderMask ); |
| |
| // allocate storage for cube groups |
| pGroups = MEM_ALLOC( pCover->pMem, int, nCubesC + 1 ); |
| |
| // mask contains variables in the support of Div |
| // split the cubes into groups using the mask |
| Mvc_CoverList2Array( pCover ); |
| Mvc_CoverList2Array( pDiv ); |
| pGroups[0] = 0; |
| nGroups = 1; |
| for ( c = 1; c < nCubesC; c++ ) |
| { |
| // get the cubes |
| pCube1 = pCover->pCubes[c-1]; |
| pCube2 = pCover->pCubes[c ]; |
| // compare the cubes |
| Mvc_CubeBitEqualOutsideMask( RetValue, pCube1, pCube2, pDiv->pMask ); |
| if ( !RetValue ) |
| pGroups[nGroups++] = c; |
| } |
| // finish off the last group |
| pGroups[nGroups] = nCubesC; |
| |
| // consider each group separately and decide |
| // whether it can produce a quotient cube |
| nCubes = 0; |
| for ( g = 0; g < nGroups; g++ ) |
| { |
| // if the group has less than nCubesD cubes, |
| // there is no way it can produce the quotient cube |
| // copy the cubes to the remainder |
| GroupSize = pGroups[g+1] - pGroups[g]; |
| if ( GroupSize < nCubesD ) |
| { |
| for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) |
| { |
| pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); |
| Mvc_CoverAddCubeTail( pRem, pCubeCopy ); |
| nCubes++; |
| } |
| continue; |
| } |
| |
| // mark the cubes as those that should be added to the remainder |
| for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) |
| Mvc_CubeSetSize( pCover->pCubes[c], 1 ); |
| |
| // go through the cubes in the group and at the same time |
| // go through the cubes in the divisor |
| iCubeD = 0; |
| iCubeC = 0; |
| pCubeD = pDiv->pCubes[iCubeD++]; |
| pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; |
| fSkipG = 0; |
| nMerges = 0; |
| |
| while ( 1 ) |
| { |
| // compare the topmost cubes in F and in D |
| RetValue = Mvc_CubeCompareIntUnderMask( pCubeC, pCubeD, pDiv->pMask ); |
| // cube are ordered in increasing order of their int value |
| if ( RetValue == -1 ) // pCubeC is above pCubeD |
| { // cube in C should be added to the remainder |
| // check that there is enough cubes in the group |
| if ( GroupSize - iCubeC < nCubesD - nMerges ) |
| { |
| fSkipG = 1; |
| break; |
| } |
| // get the next cube in the cover |
| pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; |
| continue; |
| } |
| if ( RetValue == 1 ) // pCubeD is above pCubeC |
| { // given cube in D does not have a corresponding cube in the cover |
| fSkipG = 1; |
| break; |
| } |
| // mark the cube as the one that should NOT be added to the remainder |
| Mvc_CubeSetSize( pCubeC, 0 ); |
| // remember this merged cube |
| iMerge = iCubeC-1; |
| nMerges++; |
| |
| // stop if we considered the last cube of the group |
| if ( iCubeD == nCubesD ) |
| break; |
| |
| // advance the cube of the divisor |
| assert( iCubeD < nCubesD ); |
| pCubeD = pDiv->pCubes[iCubeD++]; |
| |
| // advance the cube of the group |
| assert( pGroups[g]+iCubeC < nCubesC ); |
| pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; |
| } |
| |
| if ( fSkipG ) |
| { |
| // the group has failed, add all the cubes to the remainder |
| for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) |
| { |
| pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); |
| Mvc_CoverAddCubeTail( pRem, pCubeCopy ); |
| nCubes++; |
| } |
| continue; |
| } |
| |
| // the group has worked, add left-over cubes to the remainder |
| for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) |
| { |
| pCubeC = pCover->pCubes[c]; |
| if ( Mvc_CubeReadSize(pCubeC) ) |
| { |
| pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); |
| Mvc_CoverAddCubeTail( pRem, pCubeCopy ); |
| nCubes++; |
| } |
| } |
| |
| // create the quotient cube |
| pCube1 = Mvc_CubeAlloc( pQuo ); |
| Mvc_CubeBitSharp( pCube1, pCover->pCubes[pGroups[g]+iMerge], pDiv->pMask ); |
| // add the cube to the quotient |
| Mvc_CoverAddCubeTail( pQuo, pCube1 ); |
| nCubes += nCubesD; |
| } |
| assert( nCubes == nCubesC ); |
| |
| // deallocate the memory |
| MEM_FREE( pCover->pMem, int, nCubesC + 1, pGroups ); |
| |
| // return the results |
| *ppRem = pRem; |
| *ppQuo = pQuo; |
| // Mvc_CoverVerifyDivision( pCover, pDiv, pQuo, pRem ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Divides the cover by a cube.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) |
| { |
| Mvc_Cover_t * pQuo, * pRem; |
| Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; |
| int CompResult; |
| |
| // get the only cube of D |
| assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); |
| |
| // start the quotient and the remainder |
| pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); |
| pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); |
| |
| // get the first and only cube of the divisor |
| pCubeD = Mvc_CoverReadCubeHead( pDiv ); |
| |
| // iterate through the cubes in the cover |
| Mvc_CoverForEachCube( pCover, pCubeC ) |
| { |
| // check the containment of literals from pCubeD in pCube |
| Mvc_Cube2BitNotImpl( CompResult, pCubeD, pCubeC ); |
| if ( !CompResult ) |
| { // this cube belongs to the quotient |
| // alloc the cube |
| pCubeCopy = Mvc_CubeAlloc( pQuo ); |
| // clean the support of D |
| Mvc_CubeBitSharp( pCubeCopy, pCubeC, pCubeD ); |
| // add the cube to the quotient |
| Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); |
| } |
| else |
| { |
| // copy the cube |
| pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); |
| // add the cube to the remainder |
| Mvc_CoverAddCubeTail( pRem, pCubeCopy ); |
| } |
| } |
| // return the results |
| *ppRem = pRem; |
| *ppQuo = pQuo; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Divides the cover by a literal.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) |
| { |
| Mvc_Cover_t * pQuo, * pRem; |
| Mvc_Cube_t * pCubeC, * pCubeCopy; |
| int iLit; |
| |
| // get the only cube of D |
| assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); |
| |
| // start the quotient and the remainder |
| pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); |
| pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); |
| |
| // get the first and only literal in the divisor cube |
| iLit = Mvc_CoverFirstCubeFirstLit( pDiv ); |
| |
| // iterate through the cubes in the cover |
| Mvc_CoverForEachCube( pCover, pCubeC ) |
| { |
| // copy the cube |
| pCubeCopy = Mvc_CubeDup( pCover, pCubeC ); |
| // add the cube to the quotient or to the remainder depending on the literal |
| if ( Mvc_CubeBitValue( pCubeCopy, iLit ) ) |
| { // remove the literal |
| Mvc_CubeBitRemove( pCubeCopy, iLit ); |
| // add the cube ot the quotient |
| Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); |
| } |
| else |
| { // add the cube ot the remainder |
| Mvc_CoverAddCubeTail( pRem, pCubeCopy ); |
| } |
| } |
| // return the results |
| *ppRem = pRem; |
| *ppQuo = pQuo; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the quotient of division by literal.] |
| |
| Description [Reduces the cover to be the equal to the result of |
| division of the given cover by the literal.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit ) |
| { |
| Mvc_Cube_t * pCube, * pCube2, * pPrev; |
| // delete those cubes that do not have this literal |
| // remove this literal from other cubes |
| pPrev = NULL; |
| Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 ) |
| { |
| if ( Mvc_CubeBitValue( pCube, iLit ) == 0 ) |
| { // delete the cube from the cover |
| Mvc_CoverDeleteCube( pCover, pPrev, pCube ); |
| Mvc_CubeFree( pCover, pCube ); |
| // don't update the previous cube |
| } |
| else |
| { // delete this literal from the cube |
| Mvc_CubeBitRemove( pCube, iLit ); |
| // update the previous cube |
| pPrev = pCube; |
| } |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Verifies that the result of algebraic division is correct.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ) |
| { |
| Mvc_Cover_t * pProd; |
| Mvc_Cover_t * pDiff; |
| |
| pProd = Mvc_CoverAlgebraicMultiply( pDiv, pQuo ); |
| pDiff = Mvc_CoverAlgebraicSubtract( pCover, pProd ); |
| |
| if ( Mvc_CoverAlgebraicEqual( pDiff, pRem ) ) |
| printf( "Verification OKAY!\n" ); |
| else |
| { |
| printf( "Verification FAILED!\n" ); |
| printf( "pCover:\n" ); |
| Mvc_CoverPrint( pCover ); |
| printf( "pDiv:\n" ); |
| Mvc_CoverPrint( pDiv ); |
| printf( "pRem:\n" ); |
| Mvc_CoverPrint( pRem ); |
| printf( "pQuo:\n" ); |
| Mvc_CoverPrint( pQuo ); |
| } |
| |
| Mvc_CoverFree( pProd ); |
| Mvc_CoverFree( pDiff ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |