diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2013-03-09 12:19:11 -0800 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2013-03-09 12:19:11 -0800 |
commit | eee8ceb0fac197365c27660ab393ba13da5915c2 (patch) | |
tree | 64929de057598a003653d613f51386b33d5ac7a6 | |
parent | ae091e695e50f0fa92d7e1e9484baf086e06a5a5 (diff) | |
download | abc-eee8ceb0fac197365c27660ab393ba13da5915c2.tar.gz abc-eee8ceb0fac197365c27660ab393ba13da5915c2.tar.bz2 abc-eee8ceb0fac197365c27660ab393ba13da5915c2.zip |
PO partitioning algorithm.
-rw-r--r-- | src/aig/gia/giaCone.c | 293 | ||||
-rw-r--r-- | src/base/abci/abc.c | 175 | ||||
-rw-r--r-- | src/misc/vec/vecInt.h | 22 |
3 files changed, 468 insertions, 22 deletions
diff --git a/src/aig/gia/giaCone.c b/src/aig/gia/giaCone.c index da4918ed..56dae32a 100644 --- a/src/aig/gia/giaCone.c +++ b/src/aig/gia/giaCone.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "gia.h" +#include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START @@ -271,7 +272,42 @@ int Gia_ManConeMark( Gia_Man_t * p, int iOut, int Limit ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManConeExtract( Gia_Man_t * p, int iOut, int nDelta, int nOutsMin, int nOutsMax ) +int Gia_ManCountFlops( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + int Limit = ABC_INFINITY; + Vec_Int_t * vRoots; + Gia_Obj_t * pObj; + int i, RetValue, iOut; + // start the outputs + vRoots = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vOuts, iOut, i ) + { + pObj = Gia_ManPo( p, iOut ); + Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); + } + // mark internal nodes + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachObjVec( vRoots, p, pObj, i ) + if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) ) + break; + RetValue = Vec_IntSize( vRoots ) - Vec_IntSize(vOuts); + Vec_IntFree( vRoots ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFindPoPartition3( Gia_Man_t * p, int iOut, int nDelta, int nOutsMin, int nOutsMax, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) { /* int i, Count = 0; @@ -283,11 +319,264 @@ Gia_Man_t * Gia_ManConeExtract( Gia_Man_t * p, int iOut, int nDelta, int nOutsMi // add other outputs as long as they are nDelta away */ - Opa_ManPerform( p ); +// Opa_ManPerform( p ); return NULL; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManFindPivots( Gia_Man_t * p, int SelectShift, int fVerbose ) +{ + Vec_Int_t * vPivots, * vWeights; + Vec_Int_t * vCount, * vResult; + int i, j, Count, * pPerm, Limit; +/* + Gia_Obj_t * pObj; + // count MUX controls + vCount = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + { + Gia_Obj_t * pNodeC, * pNodeT, * pNodeE; + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + pNodeC = Gia_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); + Vec_IntAddToEntry( vCount, Gia_ObjId(p, Gia_Regular(pNodeC)), 1 ); + } +*/ + // count references + Gia_ManCreateRefs( p ); + vCount = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) ); p->pRefs = NULL; + + // collect nodes + vPivots = Vec_IntAlloc( 100 ); + vWeights = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vCount, Count, i ) + { + if ( Count < 2 ) continue; + Vec_IntPush( vPivots, i ); + Vec_IntPush( vWeights, Count ); + } + Vec_IntFree( vCount ); + + if ( fVerbose ) + printf( "Selected %d nodes (out of %d) with more than one fanout.\n", Vec_IntSize(vWeights), Gia_ManPiNum(p) + Gia_ManAndNum(p) ); + + // permute + Gia_ManRandom(1); + Gia_ManRandom(0); + for ( i = 0; i < Vec_IntSize(vWeights); i++ ) + { + j = (Gia_ManRandom(0) >> 1) % Vec_IntSize(vWeights); + ABC_SWAP( int, vPivots->pArray[i], vPivots->pArray[j] ); + ABC_SWAP( int, vWeights->pArray[i], vWeights->pArray[j] ); + } + // sort + pPerm = Abc_QuickSortCost( Vec_IntArray(vWeights), Vec_IntSize(vWeights), 1 ); + // select + Limit = Abc_MinInt( 64, Vec_IntSize(vWeights) ); + vResult = Vec_IntAlloc( Limit ); + for ( i = 0; i < Limit; i++ ) + { + j = (i + SelectShift) % Vec_IntSize(vWeights); + if ( fVerbose ) + printf( "%6d : Pivot = %6d Weight = %6d\n", j, Vec_IntEntry(vPivots, pPerm[j]), Vec_IntEntry(vWeights, pPerm[j]) ); + Vec_IntPush( vResult, Vec_IntEntry(vPivots, pPerm[j]) ); + } + + Vec_IntFree( vPivots ); + Vec_IntFree( vWeights ); + ABC_FREE( pPerm ); + + return vResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDeriveSigns( Gia_Man_t * p, Vec_Int_t * vPivots, int fVerbose ) +{ + Vec_Wrd_t * vSigns; + Gia_Obj_t * pObj, * pObjRi; + int i, fChange = 1, Counter; + + Gia_ManFillValue( p ); + Gia_ManForEachObjVec( vPivots, p, pObj, i ) + pObj->Value = i; + + if ( fVerbose ) + printf( "Signature propagation: " ); + vSigns = Vec_WrdStart( Gia_ManObjNum(p) ); + while ( fChange ) + { + fChange = 0; + Gia_ManForEachObj( p, pObj, i ) + { + if ( ~pObj->Value ) + { + assert( pObj->Value >= 0 && pObj->Value < 64 ); + *Vec_WrdEntryP( vSigns, i ) |= ( 1 << pObj->Value ); + } + if ( Gia_ObjIsAnd(pObj) ) + *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSigns, Gia_ObjFaninId1(pObj, i)); + else if ( Gia_ObjIsCo(pObj) ) + *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)); + } + Counter = 0; + Gia_ManForEachRiRo( p, pObjRi, pObj, i ) + { + word Value = Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)); + *Vec_WrdEntryP( vSigns, Gia_ObjId(p, pObj) ) |= Vec_WrdEntry(vSigns, Gia_ObjId(p, pObjRi)); + if ( Value != Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) ) + fChange = 1, Counter++; + } + if ( fVerbose ) + printf( "%d ", Counter ); + } + if ( fVerbose ) + printf( "\n" ); + return vSigns; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManHashOutputs( Gia_Man_t * p, Vec_Wrd_t * vSigns, int fVerbose ) +{ + Gia_Obj_t * pObj; + Vec_Ptr_t * vBins; + Vec_Int_t * vBin; + int i, nBins = Abc_PrimeCudd( Gia_ManPoNum(p) ); + int * pBins = ABC_FALLOC( int, nBins ); + // create hash table of outputs + vBins = Vec_PtrAlloc( 1000 ); + Gia_ManForEachPo( p, pObj, i ) + { + word Sign = Vec_WrdEntry( vSigns, Gia_ObjId(p, pObj) ); + int Offset = (int)(Sign % nBins); + if ( pBins[Offset] == -1 ) + { + pBins[Offset] = Vec_PtrSize( vBins ); + vBin = Vec_IntAlloc( 4 ); + Vec_IntPush( vBin, Offset ); + Vec_PtrPush( vBins, vBin ); + } + vBin = (Vec_Int_t *)Vec_PtrEntry( vBins, pBins[Offset] ); + Vec_IntPush( vBin, i ); + } + ABC_FREE( pBins ); + Vec_VecSort( (Vec_Vec_t *)vBins, 1 ); + + if ( fVerbose ) + printf( "Computed %d partitions:\n", Vec_PtrSize(vBins) ); + Vec_PtrForEachEntry( Vec_Int_t *, vBins, vBin, i ) + { + if ( fVerbose ) + { + int Offset = Vec_IntEntry( vBin, 0 ); + word Sign = Vec_WrdEntry( vSigns, Offset ); + printf( "%6d : Support ", i ); + Extra_PrintBinary( stdout, &Offset, 64 ); + printf( " " ); + } + + // remove the first item + ABC_SWAP( int, vBin->pArray[0], vBin->pArray[Vec_IntSize(vBin)-1] ); + Vec_IntPop( vBin ); + Vec_IntSort( vBin, 0 ); + + if ( fVerbose ) + { + printf( "PO = %7d ", Vec_IntSize(vBin) ); + printf( "FF = %7d", Gia_ManCountFlops(p, vBin) ); + printf( "\n" ); + } + } +// printf( "\n" ); + return vBins; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFindPoPartition2( Gia_Man_t * p, int iStartNum, int nDelta, int nOutsMin, int nOutsMax, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) +{ + return NULL; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) +{ + Gia_Man_t * pGia = NULL; + Vec_Int_t * vPivots; + Vec_Wrd_t * vSigns; + Vec_Ptr_t * vParts; + Vec_Int_t * vPart; + vPivots = Gia_ManFindPivots( p, SelectShift, fVerbose ); + vSigns = Gia_ManDeriveSigns( p, vPivots, fVerbose ); + Vec_IntFree( vPivots ); + vParts = Gia_ManHashOutputs( p, vSigns, fVerbose ); + Vec_WrdFree( vSigns ); + if ( fSetLargest ) + { + vPart = Vec_VecEntryInt( (Vec_Vec_t *)vParts, 0 ); + pGia = Gia_ManDupCones( p, Vec_IntArray(vPart), Vec_IntSize(vPart), 1 ); + } + if ( pvPosEquivs ) + { + *pvPosEquivs = vParts; + printf( "Partitioning algorithm divided %d POs into %d groups.\n", Gia_ManPoNum(p), Vec_PtrSize(vParts) ); + } + else + Vec_VecFree( (Vec_Vec_t *)vParts ); + return pGia; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index bb021ca1..9bc24945 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -374,6 +374,8 @@ static int Abc_CommandAbc9Iso ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9CexInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cone ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PoPart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PoPart2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -862,6 +864,8 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&cexinfo", Abc_CommandAbc9CexInfo, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cycle", Abc_CommandAbc9Cycle, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cone", Abc_CommandAbc9Cone, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&popart", Abc_CommandAbc9PoPart, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&popart2", Abc_CommandAbc9PoPart2, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexcut", Abc_CommandAbc9CexCut, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexmerge", Abc_CommandAbc9CexMerge, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexmin", Abc_CommandAbc9CexMin, 0 ); @@ -29661,11 +29665,11 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManConeExtract( Gia_Man_t * p, int iOut, int nDelta, int nOutsMin, int nOutsMax ); Gia_Man_t * pTemp; - int c, iOutNum = 0, nDelta = 10, nOutsMin = 100, nOutsMax = 1000, fVerbose = 0; + Vec_Int_t * vPos; + int c, iOutNum = -1, nOutRange = 1, fUseAllCis = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ODLUvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ORavh" ) ) != EOF ) { switch ( c ) { @@ -29680,6 +29684,156 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( iOutNum < 0 ) goto usage; break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nOutRange = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOutRange < 0 ) + goto usage; + break; + case 'a': + fUseAllCis ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Cone(): There is no AIG.\n" ); + return 1; + } + if ( iOutNum < 0 || iOutNum + nOutRange >= Gia_ManPoNum(pAbc->pGia) ) + { + Abc_Print( -1, "Abc_CommandAbc9Cone(): Range of outputs to extract is incorrect.\n" ); + return 1; + } + vPos = Vec_IntStartRange( iOutNum, nOutRange ); + pTemp = Gia_ManDupCones( pAbc->pGia, Vec_IntArray(vPos), nOutRange, !fUseAllCis ); + Vec_IntFree( vPos ); + if ( pTemp ) + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &cone [-OR num] [-avh]\n" ); + Abc_Print( -2, "\t extracting multi-output sequential logic cones\n" ); + Abc_Print( -2, "\t-O num : the index of first PO to extract [default = %d]\n", iOutNum ); + Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract\n"); + Abc_Print( -2, "\t-a : toggle keeping all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9PoPart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ); + Gia_Man_t * pTemp; + Vec_Ptr_t * vPosEquivs = NULL; + int c, SelectShift = 0, fSetLargest = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Smvh" ) ) != EOF ) + { + switch ( c ) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + SelectShift = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( SelectShift < 0 ) + goto usage; + break; + case 'm': + fSetLargest ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9PoPart(): There is no AIG.\n" ); + return 1; + } + pTemp = Gia_ManFindPoPartition( pAbc->pGia, SelectShift, fSetLargest, fVerbose, &vPosEquivs ); + if ( pTemp ) + Abc_FrameUpdateGia( pAbc, pTemp ); + Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); + return 0; + +usage: + Abc_Print( -2, "usage: &popart [-S num] [-mvh]\n" ); + Abc_Print( -2, "\t partitioning of POs into equivalence classes\n" ); + Abc_Print( -2, "\t-S num : selection point shift to randomize the solution [default = %d]\n", SelectShift ); + Abc_Print( -2, "\t-m : toggle selecting the largest cluster [default = %s]\n", fSetLargest? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9PoPart2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManFindPoPartition2( Gia_Man_t * p, int iStartNum, int nDelta, int nOutsMin, int nOutsMax, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ); + Gia_Man_t * pTemp; + Vec_Ptr_t * vPosEquivs = NULL; + int c, iStartNum = 0, nDelta = 10, nOutsMin = 100, nOutsMax = 1000, fSetLargest = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "SDLUmvh" ) ) != EOF ) + { + switch ( c ) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + iStartNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iStartNum < 0 ) + goto usage; + break; case 'D': if ( globalUtilOptind >= argc ) { @@ -29713,6 +29867,9 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nOutsMax < 0 ) goto usage; break; + case 'm': + fSetLargest ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -29724,21 +29881,23 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( pAbc->pGia == NULL ) { - Abc_Print( -1, "Abc_CommandAbc9Cycle(): There is no AIG.\n" ); + Abc_Print( -1, "Abc_CommandAbc9PoPart(): There is no AIG.\n" ); return 1; } - pTemp = Gia_ManConeExtract( pAbc->pGia, iOutNum, nDelta, nOutsMin, nOutsMax ); + pTemp = Gia_ManFindPoPartition2( pAbc->pGia, iStartNum, nDelta, nOutsMin, nOutsMax, fSetLargest, fVerbose, &vPosEquivs ); if ( pTemp ) Abc_FrameUpdateGia( pAbc, pTemp ); + Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); return 0; usage: - Abc_Print( -2, "usage: &cone [-ODLU num] [-vh]\n" ); + Abc_Print( -2, "usage: &popart2 [-SDLU num] [-mvh]\n" ); Abc_Print( -2, "\t extracting multi-output sequential logic cones\n" ); - Abc_Print( -2, "\t-O num : the index of the PO to start the cluster [default = %d]\n", iOutNum ); + Abc_Print( -2, "\t-S num : the index of the PO to start the cluster [default = %d]\n", iStartNum ); Abc_Print( -2, "\t-D num : the max increase in flop count after adding one PO [default = %d]\n", nDelta ); Abc_Print( -2, "\t-L num : the minimum number of POs in a cluster [default = %d]\n", nOutsMin ); - Abc_Print( -2, "\t-U num : the maximum number of POs in a cluster [default = %d]\n", nOutsMin ); + Abc_Print( -2, "\t-U num : the maximum number of POs in a cluster [default = %d]\n", nOutsMax ); + Abc_Print( -2, "\t-m : toggle selecting the largest cluster [default = %s]\n", fSetLargest? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index 7ba75c46..9744a031 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -114,18 +114,6 @@ static inline Vec_Int_t * Vec_IntStart( int nSize ) memset( p->pArray, 0, sizeof(int) * nSize ); return p; } - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ static inline Vec_Int_t * Vec_IntStartFull( int nSize ) { Vec_Int_t * p; @@ -134,6 +122,16 @@ static inline Vec_Int_t * Vec_IntStartFull( int nSize ) memset( p->pArray, 0xff, sizeof(int) * nSize ); return p; } +static inline Vec_Int_t * Vec_IntStartRange( int First, int Range ) +{ + Vec_Int_t * p; + int i; + p = Vec_IntAlloc( Range ); + p->nSize = Range; + for ( i = 0; i < Range; i++ ) + p->pArray[i] = First + i; + return p; +} /**Function************************************************************* |