diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2012-09-18 13:23:58 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2012-09-18 13:23:58 -0700 |
commit | e0eb270324ab71403ded07e9700152c2755e5095 (patch) | |
tree | f89a2a168e6648989e54b025ea08cecf5c6c4efd /src | |
parent | 508b6f1b1356f87340d7e722c288b9ddccdd542e (diff) | |
download | abc-e0eb270324ab71403ded07e9700152c2755e5095.tar.gz abc-e0eb270324ab71403ded07e9700152c2755e5095.tar.bz2 abc-e0eb270324ab71403ded07e9700152c2755e5095.zip |
Changes to command 'upsize'.
Diffstat (limited to 'src')
-rw-r--r-- | src/base/abc/abc.h | 3 | ||||
-rw-r--r-- | src/map/scl/scl.c | 43 | ||||
-rw-r--r-- | src/map/scl/sclFile.c | 1 | ||||
-rw-r--r-- | src/map/scl/sclInt.h | 3 | ||||
-rw-r--r-- | src/map/scl/sclMan.h | 2 | ||||
-rw-r--r-- | src/map/scl/sclSize.c | 2 | ||||
-rw-r--r-- | src/map/scl/sclUpsize.c | 309 | ||||
-rw-r--r-- | src/misc/vec/vecFlt.h | 36 |
8 files changed, 352 insertions, 47 deletions
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 26264586..83aa3f7b 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -457,6 +457,9 @@ static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_At #define Abc_NtkForEachObjVec( vIds, pNtk, pObj, i ) \ for ( i = 0; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \ if ( (pObj) == NULL ) {} else +#define Abc_NtkForEachObjVecStart( vIds, pNtk, pObj, i, Start ) \ + for ( i = Start; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \ + if ( (pObj) == NULL ) {} else #define Abc_NtkForEachNet( pNtk, pNet, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 2d14c1c7..7d8a8baa 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -642,34 +642,46 @@ usage: int Scl_CommandUpsize( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int Degree = 2; - int nRange = 5; + int Window = 5; + int Ratio = 5; + int nIters = 20; int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NWvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WRIvh" ) ) != EOF ) { switch ( c ) { - case 'N': + case 'W': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); + Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); goto usage; } - Degree = atoi(argv[globalUtilOptind]); + Window = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( Degree < 0 ) + if ( Window < 0 ) goto usage; break; - case 'W': + case 'R': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); + goto usage; + } + Ratio = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Ratio < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); goto usage; } - nRange = atoi(argv[globalUtilOptind]); + nIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nRange < 0 ) + if ( nIters < 0 ) goto usage; break; case 'v': @@ -703,14 +715,15 @@ int Scl_CommandUpsize( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } - Abc_SclUpsizingPerform( pAbc->pLibScl, pNtk, Degree, nRange, fVerbose ); + Abc_SclUpsizePerform( pAbc->pLibScl, pNtk, Window, Ratio, nIters, fVerbose ); return 0; usage: - fprintf( pAbc->Err, "usage: upsize [-NW num] [-vh]\n" ); + fprintf( pAbc->Err, "usage: upsize [-WRI num] [-vh]\n" ); fprintf( pAbc->Err, "\t selectively increases gate sizes in timing-critical regions\n" ); - fprintf( pAbc->Err, "\t-N <num> : the max fanout count of gates to upsize [default = %d]\n", Degree ); - fprintf( pAbc->Err, "\t-W <num> : delay window (in percents) of near-critical COs [default = %d]\n", nRange ); + fprintf( pAbc->Err, "\t-W <num> : delay window (in percents) of near-critical COs [default = %d]\n", Window ); + fprintf( pAbc->Err, "\t-R <num> : ratio of critical nodes (in percents) to update [default = %d]\n", Ratio ); + fprintf( pAbc->Err, "\t-I <num> : the number of upsizing iterations to perform [default = %d]\n", nIters ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; diff --git a/src/map/scl/sclFile.c b/src/map/scl/sclFile.c index 395bcf3b..794820b3 100644 --- a/src/map/scl/sclFile.c +++ b/src/map/scl/sclFile.c @@ -121,6 +121,7 @@ static void Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p ) for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) { SC_Cell * pCell = Abc_SclCellAlloc(); + pCell->Id = Vec_PtrSize(p->vCells); Vec_PtrPush( p->vCells, pCell ); pCell->pName = Vec_StrGetS(vOut, pPos); diff --git a/src/map/scl/sclInt.h b/src/map/scl/sclInt.h index 5dc00cf2..e2efec94 100644 --- a/src/map/scl/sclInt.h +++ b/src/map/scl/sclInt.h @@ -155,6 +155,7 @@ struct SC_Pin_ struct SC_Cell_ { char * pName; + int Id; int seq; // -- set to TRUE by parser if a sequential element int unsupp; // -- set to TRUE by parser if cell contains information we cannot handle float area; @@ -436,7 +437,7 @@ extern void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUse /*=== sclSize.c =============================================================*/ extern void Abc_SclSizingPerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * p ); /*=== sclUpsize.c =============================================================*/ -extern void Abc_SclUpsizingPerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int Degree, int nRange, int fVerbose ); +extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int Window, int Ratio, int nIters, int fVerbose ); /*=== sclUtil.c =============================================================*/ extern void Abc_SclHashCells( SC_Lib * p ); extern int Abc_SclCellFind( SC_Lib * p, char * pName ); diff --git a/src/map/scl/sclMan.h b/src/map/scl/sclMan.h index cc9316d5..5bc254ea 100644 --- a/src/map/scl/sclMan.h +++ b/src/map/scl/sclMan.h @@ -200,7 +200,7 @@ static inline float Abc_SclGetMaxDelay( SC_Man * p ) fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) ); return fMaxArr; } -static inline float Abc_SclGetMaxDelayNode( SC_Man * p, Abc_Obj_t * pNode ) +static inline float Abc_SclGetMaxDelayNodeFanins( SC_Man * p, Abc_Obj_t * pNode ) { float fMaxArr = 0; Abc_Obj_t * pObj; diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c index fea4d89e..d2e5fd3a 100644 --- a/src/map/scl/sclSize.c +++ b/src/map/scl/sclSize.c @@ -103,7 +103,7 @@ void Abc_SclFindCriticalCone_rec( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vVis Abc_NodeSetTravIdCurrent( pObj ); assert( Abc_ObjIsNode(pObj) ); // compute timing critical fanin - fArrMax = Abc_SclGetMaxDelayNode( p, pObj ) * (100.0 - RangeF) / 100.0; + fArrMax = Abc_SclGetMaxDelayNodeFanins( p, pObj ) * (100.0 - RangeF) / 100.0; // traverse all fanins whose arrival times are within a window Abc_ObjForEachFanin( pObj, pNext, i ) if ( Abc_SclObjTimeMax(p, pNext) >= fArrMax ) diff --git a/src/map/scl/sclUpsize.c b/src/map/scl/sclUpsize.c index 27631d0a..916fe57e 100644 --- a/src/map/scl/sclUpsize.c +++ b/src/map/scl/sclUpsize.c @@ -28,13 +28,15 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern Vec_Int_t * Abc_SclFindCriticalCoWindow( SC_Man * p, int Window ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Begin by upsizing gates will many fanouts.] + Synopsis [Collect near-critical COs.] Description [] @@ -43,30 +45,123 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -int Abc_SclManUpsize( SC_Man * p, int Degree ) +Vec_Int_t * Abc_SclFindCriticalCoWindow( SC_Man * p, int Window ) { - SC_Cell * pOld, * pNew; + float fMaxArr = Abc_SclGetMaxDelay( p ) * (100.0 - Window) / 100.0; + Vec_Int_t * vPivots; Abc_Obj_t * pObj; - int i, Count = 0; - Abc_NtkForEachNode1( p->pNtk, pObj, i ) + int i; + vPivots = Vec_IntAlloc( 100 ); + Abc_NtkForEachCo( p->pNtk, pObj, i ) + if ( Abc_SclObjTimeMax(p, pObj) >= fMaxArr ) + Vec_IntPush( vPivots, Abc_ObjId(pObj) ); + assert( Vec_IntSize(vPivots) > 0 ); + return vPivots; +} + +/**Function************************************************************* + + Synopsis [Collect near-critical internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SclFindCriticalNodeWindow_rec( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vPath, float fSlack ) +{ + Abc_Obj_t * pNext; + float fArrMax, fSlackFan; + int i; + if ( Abc_ObjIsCi(pObj) ) + return; + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + assert( Abc_ObjIsNode(pObj) ); + // compute the max arrival time of the fanins + fArrMax = Abc_SclGetMaxDelayNodeFanins( p, pObj ); + // traverse all fanins whose arrival times are within a window + Abc_ObjForEachFanin( pObj, pNext, i ) { - if ( Abc_ObjFanoutNum(pObj) < Degree ) - continue; - // find new gate - pOld = Abc_SclObjCell( p, pObj ); - pNew = Abc_SclObjResiable( p, pObj, 1 ); - if ( pNew == NULL ) - continue; - Vec_IntWriteEntry( p->vGates, Abc_ObjId(pObj), Abc_SclCellFind(p->pLib, pNew->pName) ); - Count++; + fSlackFan = fSlack - (fArrMax - Abc_SclObjTimeMax(p, pNext)); + if ( fSlackFan >= 0 ) + Abc_SclFindCriticalNodeWindow_rec( p, pNext, vPath, fSlackFan ); } - return Count; + Vec_IntPush( vPath, Abc_ObjId(pObj) ); +} +Vec_Int_t * Abc_SclFindCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPathCos, int Window ) +{ + float fMaxArr = Abc_SclGetMaxDelay( p ); + float fSlack = fMaxArr * Window / 100.0; + Vec_Int_t * vPath = Vec_IntAlloc( 100 ); + Abc_Obj_t * pObj; + int i; + Abc_NtkIncrementTravId( p->pNtk ); + Abc_NtkForEachObjVec( vPathCos, p->pNtk, pObj, i ) + Abc_SclFindCriticalNodeWindow_rec( p, Abc_ObjFanin0(pObj), vPath, fSlack - (fMaxArr - Abc_SclObjTimeMax(p, pObj)) ); + // label critical nodes + Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i ) + pObj->fMarkA = 1; + return vPath; +} +void Abc_SclUnmarkCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPath ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Find the array of nodes to be updated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_SclFindNodesToUpdate( Abc_Obj_t * pObj ) +{ + Vec_Int_t * vNodes; + Abc_Obj_t * pNext, * pNext2; + int i, k, Start; + assert( Abc_ObjIsNode(pObj) ); + assert( pObj->fMarkA ); + vNodes = Vec_IntAlloc( 16 ); + // collect fanins, node, and fanouts + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( Abc_ObjIsNode(pNext) ) + Vec_IntPush( vNodes, Abc_ObjId(pNext) ); + Vec_IntPush( vNodes, Abc_ObjId(pObj) ); + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( Abc_ObjIsNode(pNext) && pNext->fMarkA ) + Vec_IntPush( vNodes, Abc_ObjId(pNext) ), pNext->fMarkB = 1; + // remember this position + Start = Vec_IntSize(vNodes); + // label collected nodes + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( Abc_ObjIsNode(pNext) && pNext->fMarkA ) + Abc_ObjForEachFanout( pNext, pNext2, k ) + if ( Abc_ObjIsNode(pNext2) && pNext2->fMarkA && !pNext2->fMarkB ) + Vec_IntPush( vNodes, Abc_ObjId(pNext2) ), pNext2->fMarkB = 1; + // clean the fanouts + Abc_NtkForEachObjVec( vNodes, pObj->pNtk, pNext, i ) + pNext->fMarkB = 0; + // save position at the last entry + Vec_IntPush( vNodes, Start ); + return vNodes; } /**Function************************************************************* - Synopsis [] + Synopsis [Compute gain in changing the gate size.] Description [] @@ -75,29 +170,185 @@ int Abc_SclManUpsize( SC_Man * p, int Degree ) SeeAlso [] ***********************************************************************/ -void Abc_SclUpsizingPerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int Degree, int nRange, int fVerbose ) +float Abc_SclFindGain( SC_Man * p, Vec_Int_t * vCone ) { - SC_Man * p; - int nUpsizes; + double dGain = 0; + Abc_Obj_t * pObj; + int i, Start; + Start = Vec_IntEntryLast( vCone ); + vCone->nSize--; + + Abc_SclConeStore( p, vCone ); + Abc_SclTimeCone( p, vCone ); + Abc_NtkForEachObjVecStart( vCone, p->pNtk, pObj, i, Start ) + dGain += Abc_SclObjGain( p, pObj ); + Abc_SclConeRestore( p, vCone ); + dGain /= (Vec_IntSize(vCone) - Start); + + vCone->nSize++; + return (float)dGain; +} - // prepare the manager; collect init stats - p = Abc_SclManStart( pLib, pNtk, 1 ); +/**Function************************************************************* - // perform upsizing - nUpsizes = Abc_SclManUpsize( p, Degree ); + Synopsis [Begin by upsizing gates will many fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] - // recompute timing - Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay ); +***********************************************************************/ +int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio ) +{ + SC_Cell * pCellOld, * pCellNew; + Vec_Flt_t * vSavings; + Vec_Int_t * vBests; + Vec_Int_t * vCone; + Vec_Int_t * vUpdates; + Abc_Obj_t * pObj; + float dGain, dGainBest = 0; + int i, k, Entry, gateBest = -1; + int nUpsizes = 0; + + vSavings = Vec_FltAlloc( Vec_IntSize(vPathNodes) ); + vBests = Vec_IntAlloc( Vec_IntSize(vPathNodes) ); + Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pObj, i ) + { + dGainBest = 0; + pCellOld = Abc_SclObjCell( p, pObj ); + assert( pCellOld->Id == Vec_IntEntry(p->vGates, Abc_ObjId(pObj)) ); + // try different gate sizes for this node + vCone = Abc_SclFindNodesToUpdate( pObj ); + SC_RingForEachCell( pCellOld, pCellNew, k ) + { + Vec_IntWriteEntry( p->vGates, Abc_ObjId(pObj), pCellNew->Id ); + //printf( "changing %s for %s at node %d ", pCellOld->pName, pCellNew->pName, Abc_ObjId(pObj) ); + Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); + dGain = Abc_SclFindGain( p, vCone ); + Abc_SclUpdateLoad( p, pObj, pCellNew, pCellOld ); + //printf( "gain is %f\n", dGain ); + if ( dGainBest < dGain ) + { + dGainBest = dGain; + gateBest = pCellNew->Id; + } + } + Vec_IntFree( vCone ); + Vec_IntWriteEntry( p->vGates, Abc_ObjId(pObj), pCellOld->Id ); + Vec_FltPush( vSavings, dGainBest ); + Vec_IntPush( vBests, gateBest ); + } + assert( Vec_IntSize(vBests) == Vec_IntSize(vPathNodes) ); + + // we have computed the gains - find the best ones + { + Vec_Int_t * vCosts; + int * pPerm; + float Max = Vec_FltFindMax( vSavings ); + float Factor = 1.0 * (1<<28) / Max; + float This; + int i, Limit; + // find a good factor + vCosts = Vec_IntAlloc( Vec_FltSize(vSavings) ); + Vec_FltForEachEntry( vSavings, This, i ) + { + Vec_IntPush( vCosts, (int)(This * Factor) ); + assert( (int)(This * Factor) < (1<<30) ); + } + pPerm = Abc_QuickSortCost( Vec_IntArray(vCosts), Vec_IntSize(vCosts), 1 ); + assert( Vec_FltEntry(vSavings, pPerm[0]) >= Vec_FltEntry(vSavings, pPerm[Vec_FltSize(vSavings)-1]) ); + // find those that are good to update + Limit = Abc_MinInt( 1, (int)(0.01 * Ratio * Vec_IntSize(vBests)) ); + vUpdates = Vec_IntAlloc( Limit ); + for ( i = 0; i < Limit; i++ ) + if ( Vec_FltEntry(vSavings, pPerm[i]) > 0 ) + Vec_IntPush( vUpdates, pPerm[i] ); + } + + // update the network + Vec_IntForEachEntry( vUpdates, Entry, i ) + { + pObj = Abc_NtkObj( p->pNtk, Vec_IntEntry(vPathNodes, Entry) ); + // find new gate + pCellOld = Abc_SclObjCell( p, pObj ); + pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(vBests, Abc_ObjId(pObj)) ); + assert( pCellNew != NULL ); + // update gate + Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); + p->SumArea += pCellNew->area - pCellOld->area; + Vec_IntWriteEntry( p->vGates, Abc_ObjId(pObj), pCellNew->Id ); + } + + + Vec_IntFree( vUpdates ); + Vec_IntFree( vBests ); + Vec_FltFree( vSavings ); + return nUpsizes; +} + + +/**Function************************************************************* + + Synopsis [Print cumulative statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] - // print cumulative statistics - printf( "Resized: %d. ", nUpsizes ); - printf( "Delay: " ); +***********************************************************************/ +void Abc_SclUpsizePrint( SC_Man * p, int Iter, Vec_Int_t * vPathPos, Vec_Int_t * vPathNodes, int nUpsizes ) +{ + printf( "Iter %3d ", Iter ); + printf( "PathPOs:%5d. ", Vec_IntSize(vPathPos) ); + printf( "PathNodes:%6d. ", Vec_IntSize(vPathNodes) ); + printf( "Resized:%5d. ", nUpsizes ); + printf( "D: " ); printf( "%.2f -> %.2f ps ", SC_LibTimePs(p->pLib, p->MaxDelay0), SC_LibTimePs(p->pLib, p->MaxDelay) ); printf( "(%+.1f %%). ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 ); - printf( "Area: " ); + printf( "A: " ); printf( "%.2f -> %.2f ", p->SumArea0, p->SumArea ); printf( "(%+.1f %%). ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 ); Abc_PrintTime( 1, "Time", clock() - p->clkStart ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int Window, int Ratio, int nIters, int fVerbose ) +{ + SC_Man * p; + Vec_Int_t * vPathPos; // critical POs + Vec_Int_t * vPathNodes; // critical nodes and PIs + int i, nUpsizes; + + // prepare the manager; collect init stats + p = Abc_SclManStart( pLib, pNtk, 1 ); + + // perform upsizing + for ( i = 0; i < nIters; i++ ) + { + vPathPos = Abc_SclFindCriticalCoWindow( p, Window ); + vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, Window ); + nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, Ratio ); + Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes ); + Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay ); + Abc_SclUpsizePrint( p, i, vPathPos, vPathNodes, nUpsizes ); + Vec_IntFree( vPathPos ); + Vec_IntFree( vPathNodes ); + } +// Abc_NtkCleanMarkAB( pNtk ); // save the result and quit Abc_SclManSetGates( pLib, pNtk, p->vGates ); // updates gate pointers diff --git a/src/misc/vec/vecFlt.h b/src/misc/vec/vecFlt.h index 873139f7..6b4b8f9b 100644 --- a/src/misc/vec/vecFlt.h +++ b/src/misc/vec/vecFlt.h @@ -619,6 +619,42 @@ static inline int Vec_FltRemove( Vec_Flt_t * p, float Entry ) /**Function************************************************************* + Synopsis [Find entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Vec_FltFindMax( Vec_Flt_t * p ) +{ + int i; + float Best; + if ( p->nSize == 0 ) + return 0; + Best = p->pArray[0]; + for ( i = 1; i < p->nSize; i++ ) + if ( Best < p->pArray[i] ) + Best = p->pArray[i]; + return Best; +} +static inline float Vec_FltFindMin( Vec_Flt_t * p ) +{ + int i; + float Best; + if ( p->nSize == 0 ) + return 0; + Best = p->pArray[0]; + for ( i = 1; i < p->nSize; i++ ) + if ( Best > p->pArray[i] ) + Best = p->pArray[i]; + return Best; +} + +/**Function************************************************************* + Synopsis [Comparison procedure for two floats.] Description [] |