| /**CFile**************************************************************** |
| |
| FileName [luckyFast16.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Semi-canonical form computation package.] |
| |
| Synopsis [Truth table minimization procedures for up to 16 vars.] |
| |
| Author [Jake] |
| |
| Date [Started - September 2012] |
| |
| ***********************************************************************/ |
| |
| #include "luckyInt.h" |
| //#define LUCKY_VERIFY |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| static word SFmask[5][4] = { |
| {ABC_CONST(0x8888888888888888),ABC_CONST(0x4444444444444444),ABC_CONST(0x2222222222222222),ABC_CONST(0x1111111111111111)}, |
| {ABC_CONST(0xC0C0C0C0C0C0C0C0),ABC_CONST(0x3030303030303030),ABC_CONST(0x0C0C0C0C0C0C0C0C),ABC_CONST(0x0303030303030303)}, |
| {ABC_CONST(0xF000F000F000F000),ABC_CONST(0x0F000F000F000F00),ABC_CONST(0x00F000F000F000F0),ABC_CONST(0x000F000F000F000F)}, |
| {ABC_CONST(0xFF000000FF000000),ABC_CONST(0x00FF000000FF0000),ABC_CONST(0x0000FF000000FF00),ABC_CONST(0x000000FF000000FF)}, |
| {ABC_CONST(0xFFFF000000000000),ABC_CONST(0x0000FFFF00000000),ABC_CONST(0x00000000FFFF0000),ABC_CONST(0x000000000000FFFF)} |
| }; |
| |
| // we need next two functions only for verification of lucky method in debugging mode |
| void swapAndFlip(word* pAfter, int nVars, int iVarInPosition, int jVar, char * pCanonPerm, unsigned* pUCanonPhase) |
| { |
| int Temp; |
| swap_ij(pAfter, nVars, iVarInPosition, jVar); |
| |
| Temp = pCanonPerm[iVarInPosition]; |
| pCanonPerm[iVarInPosition] = pCanonPerm[jVar]; |
| pCanonPerm[jVar] = Temp; |
| |
| if ( ((*pUCanonPhase & (1 << iVarInPosition)) > 0) != ((*pUCanonPhase & (1 << jVar)) > 0) ) |
| { |
| *pUCanonPhase ^= (1 << iVarInPosition); |
| *pUCanonPhase ^= (1 << jVar); |
| } |
| if((*pUCanonPhase>>iVarInPosition) & 1) |
| Kit_TruthChangePhase_64bit( pAfter, nVars, iVarInPosition ); |
| |
| } |
| int luckyCheck(word* pAfter, word* pBefore, int nVars, char * pCanonPerm, unsigned uCanonPhase) |
| { |
| int i,j; |
| char tempChar; |
| for(j=0;j<nVars;j++) |
| { |
| tempChar = 'a'+ j; |
| for(i=j;i<nVars;i++) |
| { |
| if(tempChar != pCanonPerm[i]) |
| continue; |
| swapAndFlip(pAfter , nVars, j, i, pCanonPerm, &uCanonPhase); |
| break; |
| } |
| } |
| if((uCanonPhase>>nVars) & 1) |
| Kit_TruthNot_64bit(pAfter, nVars ); |
| if(memcmp(pAfter, pBefore, Kit_TruthWordNum_64bit( nVars )*sizeof(word)) == 0) |
| return 0; |
| else |
| return 1; |
| } |
| |
| ////////////////////////////////////lessThen5///////////////////////////////////////////////////////////////////////////////////////////// |
| |
| // there are 4 parts in every block to compare and rearrange - quoters(0Q,1Q,2Q,3Q) |
| //updataInfo updates CanonPerm and CanonPhase based on what quoter in position iQ and jQ |
| void updataInfo(int iQ, int jQ, int iVar, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| *pCanonPhase = adjustInfoAfterSwap(pCanonPerm, *pCanonPhase, iVar, ((abs(iQ-jQ)-1)<<2) + iQ ); |
| |
| } |
| |
| // returns the first shift from the left in word x that has One bit in it. |
| // blockSize = ShiftSize/4 |
| int firstShiftWithOneBit(word x, int blockSize) |
| { |
| int n = 0; |
| if(blockSize == 16){ return 0;} |
| if (x >= ABC_CONST(0x0000000100000000)) {n = n + 32; x = x >> 32;} |
| if(blockSize == 8){ return (64-n)/32;} |
| if (x >= ABC_CONST(0x0000000000010000)) {n = n + 16; x = x >> 16;} |
| if(blockSize == 4){ return (64-n)/16;} |
| if (x >= ABC_CONST(0x0000000000000100)) {n = n + 8; x = x >> 8;} |
| if(blockSize == 2){ return (64-n)/8;} |
| if (x >= ABC_CONST(0x0000000000000010)) {n = n + 4; x = x >> 4;} |
| return (64-n)/4; |
| |
| } |
| |
| // It rearranges InOut (swaps and flips through rearrangement of quoters) |
| // It updates Info at the end |
| void arrangeQuoters_superFast_lessThen5(word* pInOut, int start, int iQ, int jQ, int kQ, int lQ, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int i, blockSize = 1<<iVar; |
| // printf("in arrangeQuoters_superFast_lessThen5\n"); |
| // printf("start = %d, iQ = %d,jQ = %d,kQ = %d,lQ = %d, iVar = %d, nWords = %d\n", start, iQ, jQ, kQ , lQ, iVar, nWords); |
| for(i=start;i>=0;i--) |
| { |
| assert( iQ*blockSize < 64 ); |
| assert( jQ*blockSize < 64 ); |
| assert( kQ*blockSize < 64 ); |
| assert( lQ*blockSize < 64 ); |
| assert( 3*blockSize < 64 ); |
| pInOut[i] = (pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize) | |
| (((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize))>>blockSize) | |
| (((pInOut[i] & SFmask[iVar][kQ])<<(kQ*blockSize))>>2*blockSize) | |
| (((pInOut[i] & SFmask[iVar][lQ])<<(lQ*blockSize))>>3*blockSize); |
| } |
| updataInfo(iQ, jQ, iVar, pCanonPerm, pCanonPhase); |
| // printf("out arrangeQuoters_superFast_lessThen5\n"); |
| |
| } |
| // static word SFmask[5][4] = { |
| // {0x8888888888888888,0x4444444444444444,0x2222222222222222,0x1111111111111111}, |
| // {0xC0C0C0C0C0C0C0C0,0x3030303030303030,0x0C0C0C0C0C0C0C0C,0x0303030303030303}, |
| // {0xF000F000F000F000,0x0F000F000F000F00,0x00F000F000F000F0,0x000F000F000F000F}, |
| // {0xFF000000FF000000,0x00FF000000FF0000,0x0000FF000000FF00,0x000000FF000000FF}, |
| // {0xFFFF000000000000,0x0000FFFF00000000,0x00000000FFFF0000,0x000000000000FFFF} |
| // }; |
| //It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in 0Q and 3Q |
| int minTemp0_fast(word* pInOut, int iVar, int nWords, int* pDifStart) |
| { |
| int i, blockSize = 1<<iVar; |
| word temp; |
| for(i=nWords - 1; i>=0; i--) |
| { |
| assert( 3*blockSize < 64 ); |
| temp = ((pInOut[i] & SFmask[iVar][0])) ^ ((pInOut[i] & SFmask[iVar][3])<<(3*blockSize)); |
| if( temp == 0) |
| continue; |
| else |
| { |
| *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); |
| if( ((pInOut[i] & SFmask[iVar][0])) < ((pInOut[i] & SFmask[iVar][3])<<(3*blockSize)) ) |
| return 0; |
| else |
| return 3; |
| } |
| } |
| *pDifStart=0; |
| return 0; |
| |
| } |
| |
| //It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in 1Q and 2Q |
| int minTemp1_fast(word* pInOut, int iVar, int nWords, int* pDifStart) |
| { |
| int i, blockSize = 1<<iVar; |
| word temp; |
| for(i=nWords - 1; i>=0; i--) |
| { |
| assert( 2*blockSize < 64 ); |
| temp = ((pInOut[i] & SFmask[iVar][1])<<(blockSize)) ^ ((pInOut[i] & SFmask[iVar][2])<<(2*blockSize)); |
| if( temp == 0) |
| continue; |
| else |
| { |
| *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); |
| if( ((pInOut[i] & SFmask[iVar][1])<<(blockSize)) < ((pInOut[i] & SFmask[iVar][2])<<(2*blockSize)) ) |
| return 1; |
| else |
| return 2; |
| } |
| } |
| *pDifStart=0; |
| return 1; |
| } |
| |
| //It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and 1 if jQ is |
| // DifStart contains the information about the first different bit in iQ and jQ |
| int minTemp2_fast(word* pInOut, int iVar, int iQ, int jQ, int nWords, int* pDifStart) |
| { |
| int i, blockSize = 1<<iVar; |
| word temp; |
| for(i=nWords - 1; i>=0; i--) |
| { |
| assert( jQ*blockSize < 64 ); |
| temp = ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) ^ ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)); |
| if( temp == 0) |
| continue; |
| else |
| { |
| *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); |
| if( ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) <= ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)) ) |
| return 0; |
| else |
| return 1; |
| } |
| } |
| *pDifStart=0; |
| return 0; |
| } |
| // same as minTemp2_fast but this one has a start position |
| int minTemp3_fast(word* pInOut, int iVar, int start, int finish, int iQ, int jQ, int* pDifStart) |
| { |
| int i, blockSize = 1<<iVar; |
| word temp; |
| for(i=start; i>=finish; i--) |
| { |
| assert( jQ*blockSize < 64 ); |
| temp = ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) ^ ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)); |
| if( temp == 0) |
| continue; |
| else |
| { |
| *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); |
| if( ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) <= ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)) ) |
| return 0; |
| else |
| return 1; |
| } |
| } |
| *pDifStart=0; |
| return 0; |
| } |
| |
| // It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them |
| void minimalSwapAndFlipIVar_superFast_lessThen5(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int min1, min2, DifStart0, DifStart1, DifStartMin, DifStart4=0; |
| int M[2]; |
| M[0] = minTemp0_fast(pInOut, iVar, nWords, &DifStart0); // 0, 3 |
| M[1] = minTemp1_fast(pInOut, iVar, nWords, &DifStart1); // 1, 2 |
| min1 = minTemp2_fast(pInOut, iVar, M[0], M[1], nWords, &DifStartMin); |
| // printf("\nDifStart0 = %d, DifStart1 = %d, DifStartMin = %d\n",DifStart0, DifStart1, DifStartMin); |
| // printf("M[0] = %d, M[1] = %d, min1 = %d\n", M[0], M[1], min1); |
| if(DifStart0 != DifStart1) |
| { |
| // printf("if\n"); |
| if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 ) |
| arrangeQuoters_superFast_lessThen5(pInOut, DifStartMin/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase); |
| else if( DifStart0 > DifStart1) |
| arrangeQuoters_superFast_lessThen5(pInOut,luckyMax(DifStartMin/100, DifStart0/100), M[0], M[1], 3 - M[1], 3 - M[0], iVar, nWords, pCanonPerm, pCanonPhase); |
| else |
| arrangeQuoters_superFast_lessThen5(pInOut,luckyMax(DifStartMin/100, DifStart1/100), M[1], M[0], 3 - M[0], 3 - M[1], iVar, nWords, pCanonPerm, pCanonPhase); |
| } |
| else |
| { |
| // printf("else\n"); |
| if(DifStartMin>=DifStart0) |
| arrangeQuoters_superFast_lessThen5(pInOut, DifStartMin/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase); |
| else |
| { |
| min2 = minTemp3_fast(pInOut, iVar, DifStart0/100, DifStartMin/100, 3-M[0], 3-M[1], &DifStart4); // no reuse DifStart1 because DifStart1 = DifStart1=0 |
| // printf("after minTemp3_fast min2 = %d, DifStart4 = %d\n", min2, DifStart4); |
| if(DifStart4>DifStartMin) |
| arrangeQuoters_superFast_lessThen5(pInOut, DifStart0/100, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], iVar, nWords, pCanonPerm, pCanonPhase); |
| else |
| arrangeQuoters_superFast_lessThen5(pInOut, DifStart0/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase); |
| } |
| } |
| } |
| |
| void minimalSwapAndFlipIVar_superFast_lessThen5_noEBFC(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int DifStart1; |
| if(minTemp1_fast(pInOut, iVar, nWords, &DifStart1) == 2) |
| arrangeQuoters_superFast_lessThen5(pInOut, DifStart1/100, 0, 2, 1, 3, iVar, nWords, pCanonPerm, pCanonPhase); |
| } |
| ////////////////////////////////////iVar = 5///////////////////////////////////////////////////////////////////////////////////////////// |
| |
| // It rearranges InOut (swaps and flips through rearrangement of quoters) |
| // It updates Info at the end |
| void arrangeQuoters_superFast_iVar5(unsigned* pInOut, unsigned* temp, int start, int iQ, int jQ, int kQ, int lQ, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int i,blockSize,shiftSize; |
| unsigned* tempPtr = temp+start; |
| // printf("in arrangeQuoters_superFast_iVar5\n"); |
| |
| if(iQ == 0 && jQ == 1) |
| return; |
| blockSize = sizeof(unsigned); |
| shiftSize = 4; |
| for(i=start-1;i>0;i-=shiftSize) |
| { |
| tempPtr -= 1; |
| memcpy(tempPtr, pInOut+i-iQ, blockSize); |
| tempPtr -= 1; |
| memcpy(tempPtr, pInOut+i-jQ, blockSize); |
| tempPtr -= 1; |
| memcpy(tempPtr, pInOut+i-kQ, blockSize); |
| tempPtr -= 1; |
| memcpy(tempPtr, pInOut+i-lQ, blockSize); |
| } |
| memcpy(pInOut, temp, start*sizeof(unsigned)); |
| updataInfo(iQ, jQ, 5, pCanonPerm, pCanonPhase); |
| } |
| |
| //It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in 0Q and 3Q |
| int minTemp0_fast_iVar5(unsigned* pInOut, int nWords, int* pDifStart) |
| { |
| int i, temp; |
| // printf("in minTemp0_fast_iVar5\n"); |
| for(i=(nWords)*2 - 1; i>=0; i-=4) |
| { |
| temp = CompareWords(pInOut[i],pInOut[i-3]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+1; |
| return 0; |
| } |
| else |
| { |
| *pDifStart = i+1; |
| return 3; |
| } |
| } |
| *pDifStart=0; |
| return 0; |
| } |
| |
| //It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in 1Q and 2Q |
| int minTemp1_fast_iVar5(unsigned* pInOut, int nWords, int* pDifStart) |
| { |
| int i, temp; |
| // printf("in minTemp1_fast_iVar5\n"); |
| for(i=(nWords)*2 - 2; i>=0; i-=4) |
| { |
| temp = CompareWords(pInOut[i],pInOut[i-1]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+2; |
| return 1; |
| } |
| else |
| { |
| *pDifStart = i+2; |
| return 2; |
| } |
| } |
| *pDifStart=0; |
| return 1; |
| } |
| |
| //It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in iQ and jQ |
| int minTemp2_fast_iVar5(unsigned* pInOut, int iQ, int jQ, int nWords, int* pDifStart) |
| { |
| int i, temp; |
| // printf("in minTemp2_fast_iVar5\n"); |
| |
| for(i=(nWords)*2 - 1; i>=0; i-=4) |
| { |
| temp = CompareWords(pInOut[i-iQ],pInOut[i-jQ]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+1; |
| return 0; |
| } |
| else |
| { |
| *pDifStart = i+1; |
| return 1; |
| } |
| } |
| *pDifStart=0; |
| return 0; |
| } |
| |
| // same as minTemp2_fast but this one has a start position |
| int minTemp3_fast_iVar5(unsigned* pInOut, int start, int finish, int iQ, int jQ, int* pDifStart) |
| { |
| int i, temp; |
| // printf("in minTemp3_fast_iVar5\n"); |
| |
| for(i=start-1; i>=finish; i-=4) |
| { |
| temp = CompareWords(pInOut[i-iQ],pInOut[i-jQ]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+1; |
| return 0; |
| } |
| else |
| { |
| *pDifStart = i+1; |
| return 1; |
| } |
| } |
| *pDifStart=0; |
| return 0; |
| } |
| |
| // It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them |
| void minimalSwapAndFlipIVar_superFast_iVar5(unsigned* pInOut, int nWords, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int min1, min2, DifStart0, DifStart1, DifStartMin; |
| int M[2]; |
| unsigned temp[2048]; |
| // printf("in minimalSwapAndFlipIVar_superFast_iVar5\n"); |
| M[0] = minTemp0_fast_iVar5(pInOut, nWords, &DifStart0); // 0, 3 |
| M[1] = minTemp1_fast_iVar5(pInOut, nWords, &DifStart1); // 1, 2 |
| min1 = minTemp2_fast_iVar5(pInOut, M[0], M[1], nWords, &DifStartMin); |
| if(DifStart0 != DifStart1) |
| { |
| if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 ) |
| arrangeQuoters_superFast_iVar5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase); |
| else if( DifStart0 > DifStart1) |
| arrangeQuoters_superFast_iVar5(pInOut, temp, luckyMax(DifStartMin,DifStart0), M[0], M[1], 3 - M[1], 3 - M[0], pCanonPerm, pCanonPhase); |
| else |
| arrangeQuoters_superFast_iVar5(pInOut, temp, luckyMax(DifStartMin,DifStart1), M[1], M[0], 3 - M[0], 3 - M[1], pCanonPerm, pCanonPhase); |
| } |
| else |
| { |
| if(DifStartMin>=DifStart0) |
| arrangeQuoters_superFast_iVar5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase); |
| else |
| { |
| min2 = minTemp3_fast_iVar5(pInOut, DifStart0, DifStartMin, 3-M[0], 3-M[1], &DifStart1); // reuse DifStart1 because DifStart1 = DifStart1=0 |
| if(DifStart1>DifStartMin) |
| arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart0, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], pCanonPerm, pCanonPhase); |
| else |
| arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart0, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase); |
| } |
| } |
| } |
| |
| void minimalSwapAndFlipIVar_superFast_iVar5_noEBFC(unsigned* pInOut, int nWords, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int DifStart1; |
| unsigned temp[2048]; |
| if(minTemp1_fast_iVar5(pInOut, nWords, &DifStart1) == 2) |
| arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart1, 0, 2, 1, 3, pCanonPerm, pCanonPhase); |
| } |
| |
| ////////////////////////////////////moreThen5///////////////////////////////////////////////////////////////////////////////////////////// |
| |
| // It rearranges InOut (swaps and flips through rearrangement of quoters) |
| // It updates Info at the end |
| void arrangeQuoters_superFast_moreThen5(word* pInOut, word* temp, int start, int iQ, int jQ, int kQ, int lQ, int iVar, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int i,wordBlock,blockSize,shiftSize; |
| word* tempPtr = temp+start; |
| // printf("in arrangeQuoters_superFast_moreThen5\n"); |
| |
| if(iQ == 0 && jQ == 1) |
| return; |
| wordBlock = (1<<(iVar-6)); |
| blockSize = wordBlock*sizeof(word); |
| shiftSize = wordBlock*4; |
| for(i=start-wordBlock;i>0;i-=shiftSize) |
| { |
| tempPtr -= wordBlock; |
| memcpy(tempPtr, pInOut+i-iQ*wordBlock, blockSize); |
| tempPtr -= wordBlock; |
| memcpy(tempPtr, pInOut+i-jQ*wordBlock, blockSize); |
| tempPtr -= wordBlock; |
| memcpy(tempPtr, pInOut+i-kQ*wordBlock, blockSize); |
| tempPtr -= wordBlock; |
| memcpy(tempPtr, pInOut+i-lQ*wordBlock, blockSize); |
| } |
| memcpy(pInOut, temp, start*sizeof(word)); |
| updataInfo(iQ, jQ, iVar, pCanonPerm, pCanonPhase); |
| // printf("out arrangeQuoters_superFast_moreThen5\n"); |
| |
| } |
| |
| //It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in 0Q and 3Q |
| int minTemp0_fast_moreThen5(word* pInOut, int iVar, int nWords, int* pDifStart) |
| { |
| int i, j, temp; |
| int wordBlock = 1<<(iVar-6); |
| int wordDif = 3*wordBlock; |
| int shiftBlock = wordBlock*4; |
| // printf("in minTemp0_fast_moreThen5\n"); |
| |
| for(i=nWords - 1; i>=0; i-=shiftBlock) |
| for(j=0;j<wordBlock;j++) |
| { |
| temp = CompareWords(pInOut[i-j],pInOut[i-j-wordDif]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+1; |
| return 0; |
| } |
| else |
| { |
| *pDifStart = i+1; |
| return 3; |
| } |
| } |
| *pDifStart=0; |
| // printf("out minTemp0_fast_moreThen5\n"); |
| |
| return 0; |
| } |
| |
| //It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in 1Q and 2Q |
| int minTemp1_fast_moreThen5(word* pInOut, int iVar, int nWords, int* pDifStart) |
| { |
| int i, j, temp; |
| int wordBlock = 1<<(iVar-6); |
| int shiftBlock = wordBlock*4; |
| // printf("in minTemp1_fast_moreThen5\n"); |
| |
| for(i=nWords - wordBlock - 1; i>=0; i-=shiftBlock) |
| for(j=0;j<wordBlock;j++) |
| { |
| temp = CompareWords(pInOut[i-j],pInOut[i-j-wordBlock]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+wordBlock+1; |
| return 1; |
| } |
| else |
| { |
| *pDifStart = i+wordBlock+1; |
| return 2; |
| } |
| } |
| *pDifStart=0; |
| // printf("out minTemp1_fast_moreThen5\n"); |
| |
| return 1; |
| } |
| |
| //It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and visa versa |
| // DifStart contains the information about the first different bit in iQ and jQ |
| int minTemp2_fast_moreThen5(word* pInOut, int iVar, int iQ, int jQ, int nWords, int* pDifStart) |
| { |
| int i, j, temp; |
| int wordBlock = 1<<(iVar-6); |
| int shiftBlock = wordBlock*4; |
| // printf("in minTemp2_fast_moreThen5\n"); |
| |
| for(i=nWords - 1; i>=0; i-=shiftBlock) |
| for(j=0;j<wordBlock;j++) |
| { |
| temp = CompareWords(pInOut[i-j-iQ*wordBlock],pInOut[i-j-jQ*wordBlock]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+1; |
| return 0; |
| } |
| else |
| { |
| *pDifStart = i+1; |
| return 1; |
| } |
| } |
| *pDifStart=0; |
| // printf("out minTemp2_fast_moreThen5\n"); |
| |
| return 0; |
| } |
| |
| // same as minTemp2_fast but this one has a start position |
| int minTemp3_fast_moreThen5(word* pInOut, int iVar, int start, int finish, int iQ, int jQ, int* pDifStart) |
| { |
| int i, j, temp; |
| int wordBlock = 1<<(iVar-6); |
| int shiftBlock = wordBlock*4; |
| // printf("in minTemp3_fast_moreThen5\n"); |
| |
| for(i=start-1; i>=finish; i-=shiftBlock) |
| for(j=0;j<wordBlock;j++) |
| { |
| temp = CompareWords(pInOut[i-j-iQ*wordBlock],pInOut[i-j-jQ*wordBlock]); |
| if(temp == 0) |
| continue; |
| else if(temp == -1) |
| { |
| *pDifStart = i+1; |
| return 0; |
| } |
| else |
| { |
| *pDifStart = i+1; |
| return 1; |
| } |
| } |
| *pDifStart=0; |
| // printf("out minTemp3_fast_moreThen5\n"); |
| |
| return 0; |
| } |
| |
| // It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them |
| void minimalSwapAndFlipIVar_superFast_moreThen5(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int min1, min2, DifStart0, DifStart1, DifStartMin; |
| int M[2]; |
| word temp[1024]; |
| // printf("in minimalSwapAndFlipIVar_superFast_moreThen5\n"); |
| M[0] = minTemp0_fast_moreThen5(pInOut, iVar, nWords, &DifStart0); // 0, 3 |
| M[1] = minTemp1_fast_moreThen5(pInOut, iVar, nWords, &DifStart1); // 1, 2 |
| min1 = minTemp2_fast_moreThen5(pInOut, iVar, M[0], M[1], nWords, &DifStartMin); |
| if(DifStart0 != DifStart1) |
| { |
| if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 ) |
| arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase); |
| else if( DifStart0 > DifStart1) |
| arrangeQuoters_superFast_moreThen5(pInOut, temp, luckyMax(DifStartMin,DifStart0), M[0], M[1], 3 - M[1], 3 - M[0], iVar, pCanonPerm, pCanonPhase); |
| else |
| arrangeQuoters_superFast_moreThen5(pInOut, temp, luckyMax(DifStartMin,DifStart1), M[1], M[0], 3 - M[0], 3 - M[1], iVar, pCanonPerm, pCanonPhase); |
| } |
| else |
| { |
| if(DifStartMin>=DifStart0) |
| arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase); |
| else |
| { |
| min2 = minTemp3_fast_moreThen5(pInOut, iVar, DifStart0, DifStartMin, 3-M[0], 3-M[1], &DifStart1); // reuse DifStart1 because DifStart1 = DifStart1=0 |
| if(DifStart1>DifStartMin) |
| arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart0, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], iVar, pCanonPerm, pCanonPhase); |
| else |
| arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart0, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase); |
| } |
| } |
| // printf("out minimalSwapAndFlipIVar_superFast_moreThen5\n"); |
| |
| } |
| |
| void minimalSwapAndFlipIVar_superFast_moreThen5_noEBFC(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int DifStart1; |
| word temp[1024]; |
| if(minTemp1_fast_moreThen5(pInOut, iVar, nWords, &DifStart1) == 2) |
| arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart1, 0, 2, 1, 3, iVar, pCanonPerm, pCanonPhase); |
| } |
| |
| /////////////////////////////////// for all ///////////////////////////////////////////////////////////////////////////////////////////// |
| void minimalInitialFlip_fast_16Vars(word* pInOut, int nVars, unsigned* pCanonPhase) |
| { |
| word oneWord=1; |
| if( (pInOut[Kit_TruthWordNum_64bit( nVars ) -1]>>63) & oneWord ) |
| { |
| Kit_TruthNot_64bit( pInOut, nVars ); |
| (* pCanonPhase) ^=(1<<nVars); |
| } |
| |
| } |
| |
| // this function finds minimal for all TIED(and tied only) iVars |
| //it finds tied vars based on rearranged Store info - group of tied vars has the same bit count in Store |
| int minimalSwapAndFlipIVar_superFast_all(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int i; |
| word pDuplicate[1024]; |
| int bitInfoTemp = pStore[0]; |
| memcpy(pDuplicate,pInOut,nWords*sizeof(word)); |
| // printf("in minimalSwapAndFlipIVar_superFast_all\n"); |
| for(i=0;i<5;i++) |
| { |
| if(bitInfoTemp == pStore[i+1]) |
| minimalSwapAndFlipIVar_superFast_lessThen5(pInOut, i, nWords, pCanonPerm, pCanonPhase); |
| else |
| { |
| bitInfoTemp = pStore[i+1]; |
| continue; |
| } |
| } |
| if(bitInfoTemp == pStore[i+1]) |
| minimalSwapAndFlipIVar_superFast_iVar5((unsigned*) pInOut, nWords, pCanonPerm, pCanonPhase); |
| else |
| bitInfoTemp = pStore[i+1]; |
| |
| for(i=6;i<nVars-1;i++) |
| { |
| if(bitInfoTemp == pStore[i+1]) |
| minimalSwapAndFlipIVar_superFast_moreThen5(pInOut, i, nWords, pCanonPerm, pCanonPhase); |
| else |
| { |
| bitInfoTemp = pStore[i+1]; |
| continue; |
| } |
| } |
| // printf("out minimalSwapAndFlipIVar_superFast_all\n"); |
| |
| if(memcmp(pInOut,pDuplicate , nWords*sizeof(word)) == 0) |
| return 0; |
| else |
| return 1; |
| } |
| |
| int minimalSwapAndFlipIVar_superFast_all_noEBFC(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| int i; |
| word pDuplicate[1024]; |
| int bitInfoTemp = pStore[0]; |
| memcpy(pDuplicate,pInOut,nWords*sizeof(word)); |
| for(i=0;i<5;i++) |
| { |
| if(bitInfoTemp == pStore[i+1]) |
| minimalSwapAndFlipIVar_superFast_lessThen5_noEBFC(pInOut, i, nWords, pCanonPerm, pCanonPhase); |
| else |
| { |
| bitInfoTemp = pStore[i+1]; |
| continue; |
| } |
| } |
| if(bitInfoTemp == pStore[i+1]) |
| minimalSwapAndFlipIVar_superFast_iVar5_noEBFC((unsigned*) pInOut, nWords, pCanonPerm, pCanonPhase); |
| else |
| bitInfoTemp = pStore[i+1]; |
| |
| for(i=6;i<nVars-1;i++) |
| { |
| if(bitInfoTemp == pStore[i+1]) |
| minimalSwapAndFlipIVar_superFast_moreThen5_noEBFC(pInOut, i, nWords, pCanonPerm, pCanonPhase); |
| else |
| { |
| bitInfoTemp = pStore[i+1]; |
| continue; |
| } |
| } |
| if(memcmp(pInOut,pDuplicate , nWords*sizeof(word)) == 0) |
| return 0; |
| else |
| return 1; |
| } |
| |
| |
| // old version with out noEBFC |
| // void luckyCanonicizerS_F_first_16Vars(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) |
| // { |
| // while( minimalSwapAndFlipIVar_superFast_all(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0) |
| // continue; |
| // } |
| |
| void luckyCanonicizerS_F_first_16Vars1(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| if(((* pCanonPhase) >> (nVars+1)) & 1) |
| while( minimalSwapAndFlipIVar_superFast_all(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0) |
| continue; |
| else |
| while( minimalSwapAndFlipIVar_superFast_all_noEBFC(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0) |
| continue; |
| } |
| |
| void luckyCanonicizerS_F_first_16Vars11(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| word duplicate[1024]; |
| char pCanonPerm1[16]; |
| unsigned uCanonPhase1; |
| |
| if((* pCanonPhase) >> (nVars+2) ) |
| { |
| memcpy(duplicate, pInOut, sizeof(word)*nWords); |
| Kit_TruthNot_64bit(duplicate, nVars); |
| uCanonPhase1 = *pCanonPhase; |
| uCanonPhase1 ^= (1 << nVars); |
| memcpy(pCanonPerm1,pCanonPerm,sizeof(char)*16); |
| luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase); |
| luckyCanonicizerS_F_first_16Vars1(duplicate, nVars, nWords, pStore, pCanonPerm1, &uCanonPhase1); |
| if(memCompare(pInOut, duplicate,nVars) == 1) |
| { |
| *pCanonPhase = uCanonPhase1; |
| memcpy(pCanonPerm,pCanonPerm1,sizeof(char)*16); |
| memcpy(pInOut, duplicate, sizeof(word)*nWords); |
| } |
| } |
| else |
| { |
| luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase); |
| } |
| } |
| |
| void luckyCanonicizer_final_fast_16Vars(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| assert( nVars > 6 && nVars <= 16 ); |
| (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( pInOut, nVars, pCanonPerm, pStore ); |
| luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); |
| } |
| |
| void bitReverceOrder(word* x, int nVars) |
| { |
| int i; |
| for(i= nVars-1;i>=0;i--) |
| Kit_TruthChangePhase_64bit( x, nVars, i ); |
| } |
| |
| |
| void luckyCanonicizer_final_fast_16Vars1(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) |
| { |
| assert( nVars > 6 && nVars <= 16 ); |
| (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( pInOut, nVars, pCanonPerm, pStore ); |
| luckyCanonicizerS_F_first_16Vars11(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); |
| bitReverceOrder(pInOut, nVars); |
| (*pCanonPhase) ^= (1<<nVars) -1; |
| luckyCanonicizerS_F_first_16Vars11(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); |
| // bitReverceOrder(pInOut, nVars); |
| // (*pCanonPhase) ^= (1<<nVars) -1; |
| // luckyCanonicizerS_F_first_16Vars11(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); |
| } |
| |
| |
| // top-level procedure calling two special cases (nVars <= 6 and nVars <= 16) |
| unsigned luckyCanonicizer_final_fast( word * pInOut, int nVars, char * pCanonPerm ) |
| { |
| int nWords; |
| int pStore[16]; |
| unsigned uCanonPhase = 0; |
| #ifdef LUCKY_VERIFY |
| word temp[1024] = {0}; |
| word duplicate[1024] = {0}; |
| Kit_TruthCopy_64bit( duplicate, pInOut, nVars ); |
| #endif |
| if ( nVars <= 6 ) |
| pInOut[0] = luckyCanonicizer_final_fast_6Vars( pInOut[0], pStore, pCanonPerm, &uCanonPhase); |
| else if ( nVars <= 16 ) |
| { |
| nWords = (nVars <= 6) ? 1 : (1 << (nVars - 6)); |
| luckyCanonicizer_final_fast_16Vars( pInOut, nVars, nWords, pStore, pCanonPerm, &uCanonPhase ); |
| } |
| else assert( 0 ); |
| #ifdef LUCKY_VERIFY |
| Kit_TruthCopy_64bit( temp, pInOut, nVars ); |
| assert( ! luckyCheck(temp, duplicate, nVars, pCanonPerm, uCanonPhase) ); |
| #endif |
| return uCanonPhase; |
| } |
| |
| unsigned luckyCanonicizer_final_fast1( word * pInOut, int nVars, char * pCanonPerm) |
| { |
| int nWords; |
| int pStore[16]; |
| unsigned uCanonPhase = 0; |
| #ifdef LUCKY_VERIFY |
| word temp[1024] = {0}; |
| word duplicate[1024] = {0}; |
| Kit_TruthCopy_64bit( duplicate, pInOut, nVars ); |
| #endif |
| if ( nVars <= 6 ) |
| pInOut[0] = luckyCanonicizer_final_fast_6Vars1( pInOut[0], pStore, pCanonPerm, &uCanonPhase); |
| else if ( nVars <= 16 ) |
| { |
| nWords = 1 << (nVars - 6); |
| luckyCanonicizer_final_fast_16Vars1( pInOut, nVars, nWords, pStore, pCanonPerm, &uCanonPhase ); |
| } |
| else assert( 0 ); |
| #ifdef LUCKY_VERIFY |
| Kit_TruthCopy_64bit( temp, pInOut, nVars ); |
| assert( ! luckyCheck(temp, duplicate, nVars, pCanonPerm, uCanonPhase) ); |
| #endif |
| return uCanonPhase; |
| } |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |
| |
| |