/**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