blob: 7894735d210e0e637bd3e461195238c30154cf0c [file] [log] [blame]
/**CFile****************************************************************
FileName [reoSwap.c]
PackageName [REO: A specialized DD reordering engine.]
Synopsis [Implementation of the two-variable swap.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - October 15, 2002.]
Revision [$Id: reoSwap.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
***********************************************************************/
#include "reo.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define AddToLinkedList( ppList, pLink ) (((pLink)->Next = *(ppList)), (*(ppList) = (pLink)))
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description [Takes the level (lev0) of the plane, which should be swapped
with the next plane. Returns the gain using the current cost function.]
SideEffects []
SeeAlso []
***********************************************************************/
double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp )
{
// the levels in the decision diagram
int lev1 = lev0 + 1, lev2 = lev0 + 2;
// the new nodes on lev0
reo_unit * pLoop, * pUnit;
// the new nodes on lev1
reo_unit * pNewPlane20 = NULL, * pNewPlane21 = NULL; // Suppress "might be used uninitialized"
reo_unit * pNewPlane20R;
reo_unit * pUnitE, * pUnitER, * pUnitT;
// the nodes below lev1
reo_unit * pNew1E = NULL, * pNew1T = NULL, * pNew2E = NULL, * pNew2T = NULL;
reo_unit * pNew1ER = NULL, * pNew2ER = NULL;
// the old linked lists
reo_unit * pListOld0 = p->pPlanes[lev0].pHead;
reo_unit * pListOld1 = p->pPlanes[lev1].pHead;
// working planes and one more temporary plane
reo_unit * pListNew0 = NULL, ** ppListNew0 = &pListNew0;
reo_unit * pListNew1 = NULL, ** ppListNew1 = &pListNew1;
reo_unit * pListTemp = NULL, ** ppListTemp = &pListTemp;
// various integer variables
int fComp, fCompT, fFound, HKey, fInteract, temp, c;
int nWidthCofs = -1; // Suppress "might be used uninitialized"
// statistical variables
int nNodesUpMovedDown = 0;
int nNodesDownMovedUp = 0;
int nNodesUnrefRemoved = 0;
int nNodesUnrefAdded = 0;
int nWidthReduction = 0;
double AplWeightTotalLev0 = 0.0; // Suppress "might be used uninitialized"
double AplWeightTotalLev1 = 0.0; // Suppress "might be used uninitialized"
double AplWeightHalf = 0.0; // Suppress "might be used uninitialized"
double AplWeightPrev = 0.0; // Suppress "might be used uninitialized"
double AplWeightAfter = 0.0; // Suppress "might be used uninitialized"
double nCostGain;
// set the old lists
assert( lev0 >= 0 && lev1 < p->nSupp );
pListOld0 = p->pPlanes[lev0].pHead;
pListOld1 = p->pPlanes[lev1].pHead;
// make sure the planes have nodes
assert( p->pPlanes[lev0].statsNodes && p->pPlanes[lev1].statsNodes );
assert( pListOld0 && pListOld1 );
if ( p->fMinWidth )
{
// verify that the width parameters are set correctly
reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 );
reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 );
// start the storage for cofactors
nWidthCofs = 0;
}
else if ( p->fMinApl )
{
AplWeightPrev = p->nAplCur;
AplWeightAfter = p->nAplCur;
AplWeightTotalLev0 = 0.0;
AplWeightTotalLev1 = 0.0;
}
// check if the planes interact
fInteract = 0; // assume that they do not interact
for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next )
{
if ( pUnit->pT->lev == lev1 || Unit_Regular(pUnit->pE)->lev == lev1 )
{
fInteract = 1;
break;
}
// change the level now, this is done for efficiency reasons
pUnit->lev = lev1;
}
// set the new signature for hashing
p->nSwaps++;
if ( !fInteract )
// if ( 0 )
{
// perform the swap without interaction
p->nNISwaps++;
// change the levels
if ( p->fMinWidth )
{
// go through the current lower level, which will become upper
for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next )
{
pUnit->lev = lev0;
pUnitER = Unit_Regular(pUnit->pE);
if ( pUnitER->TopRef > lev0 )
{
if ( pUnitER->Sign != p->nSwaps )
{
if ( pUnitER->TopRef == lev2 )
{
pUnitER->TopRef = lev1;
nWidthReduction--;
}
else
{
assert( pUnitER->TopRef == lev1 );
}
pUnitER->Sign = p->nSwaps;
}
}
pUnitT = pUnit->pT;
if ( pUnitT->TopRef > lev0 )
{
if ( pUnitT->Sign != p->nSwaps )
{
if ( pUnitT->TopRef == lev2 )
{
pUnitT->TopRef = lev1;
nWidthReduction--;
}
else
{
assert( pUnitT->TopRef == lev1 );
}
pUnitT->Sign = p->nSwaps;
}
}
}
// go through the current upper level, which will become lower
for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next )
{
pUnit->lev = lev1;
pUnitER = Unit_Regular(pUnit->pE);
if ( pUnitER->TopRef > lev0 )
{
if ( pUnitER->Sign != p->nSwaps )
{
assert( pUnitER->TopRef == lev1 );
pUnitER->TopRef = lev2;
pUnitER->Sign = p->nSwaps;
nWidthReduction++;
}
}
pUnitT = pUnit->pT;
if ( pUnitT->TopRef > lev0 )
{
if ( pUnitT->Sign != p->nSwaps )
{
assert( pUnitT->TopRef == lev1 );
pUnitT->TopRef = lev2;
pUnitT->Sign = p->nSwaps;
nWidthReduction++;
}
}
}
}
else
{
// for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next )
// pUnit->lev = lev1;
for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next )
pUnit->lev = lev0;
}
// set the new linked lists, which will be attached to the planes
pListNew0 = pListOld1;
pListNew1 = pListOld0;
if ( p->fMinApl )
{
AplWeightTotalLev0 = p->pPlanes[lev1].statsCost;
AplWeightTotalLev1 = p->pPlanes[lev0].statsCost;
}
// set the changes in terms of nodes
nNodesUpMovedDown = p->pPlanes[lev0].statsNodes;
nNodesDownMovedUp = p->pPlanes[lev1].statsNodes;
goto finish;
}
p->Signature++;
// two-variable swap is done in three easy steps
// previously I thought that steps (1) and (2) can be merged into one step
// now it is clear that this cannot be done without changing a lot of other stuff...
// (1) walk through the upper level, find units without cofactors in the lower level
// and move them to the new lower level (while adding to the cache)
// (2) walk through the uppoer level, and tranform all the remaning nodes
// while employing cache for the new lower level
// (3) walk through the old lower level, find those nodes whose ref counters are not zero,
// and move them to the new uppoer level, free other nodes
// (1) walk through the upper level, find units without cofactors in the lower level
// and move them to the new lower level (while adding to the cache)
for ( pLoop = pListOld0; pLoop; )
{
pUnit = pLoop;
pLoop = pLoop->Next;
pUnitE = pUnit->pE;
pUnitER = Unit_Regular(pUnitE);
pUnitT = pUnit->pT;
if ( pUnitER->lev != lev1 && pUnitT->lev != lev1 )
{
// before after
//
// <p1> .
// 0 / \ 1 .
// / \ .
// / \ .
// / \ <p2n> .
// / \ 0 / \ 1 .
// / \ / \ .
// / \ / \ .
// F0 F1 F0 F1
// move to plane-2-new
// nothing changes in the process (cofactors, ref counter, APL weight)
pUnit->lev = lev1;
AddToLinkedList( ppListNew1, pUnit );
if ( p->fMinApl )
AplWeightTotalLev1 += pUnit->Weight;
// add to cache - find the cell with different signature (not the current one!)
for ( HKey = hashKey3(p->Signature, pUnitE, pUnitT, p->nTableSize);
p->HTable[HKey].Sign == p->Signature;
HKey = (HKey+1) % p->nTableSize );
assert( p->HTable[HKey].Sign != p->Signature );
p->HTable[HKey].Sign = p->Signature;
p->HTable[HKey].Arg1 = pUnitE;
p->HTable[HKey].Arg2 = pUnitT;
p->HTable[HKey].Arg3 = pUnit;
nNodesUpMovedDown++;
if ( p->fMinWidth )
{
// update the cofactors's top ref
if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
assert( pUnitER->TopRef == lev1 );
pUnitER->TopRefNew = lev2;
if ( pUnitER->Sign != p->nSwaps )
{
pUnitER->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pUnitER;
}
}
if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
assert( pUnitT->TopRef == lev1 );
pUnitT->TopRefNew = lev2;
if ( pUnitT->Sign != p->nSwaps )
{
pUnitT->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pUnitT;
}
}
}
}
else
{
// add to the temporary plane
AddToLinkedList( ppListTemp, pUnit );
}
}
// (2) walk through the uppoer level, and tranform all the remaning nodes
// while employing cache for the new lower level
for ( pLoop = pListTemp; pLoop; )
{
pUnit = pLoop;
pLoop = pLoop->Next;
pUnitE = pUnit->pE;
pUnitER = Unit_Regular(pUnitE);
pUnitT = pUnit->pT;
fComp = (int)(pUnitER != pUnitE);
// count the amount of weight to reduce the APL of the children of this node
if ( p->fMinApl )
AplWeightHalf = 0.5 * pUnit->Weight;
// determine what situation is this
if ( pUnitER->lev == lev1 && pUnitT->lev == lev1 )
{
if ( fComp == 0 )
{
// before after
//
// <p1> <p1n> .
// 0 / \ 1 0 / \ 1 .
// / \ / \ .
// / \ / \ .
// <p2> <p2> <p2n> <p2n> .
// 0 / \ 1 0 / \ 1 0 / \ 1 0 / \ 1 .
// / \ / \ / \ / \ .
// / \ / \ / \ / \ .
// F0 F1 F2 F3 F0 F2 F1 F3 .
// pNew1E pNew1T pNew2E pNew2T
//
pNew1E = pUnitE->pE; // F0
pNew1T = pUnitT->pE; // F2
pNew2E = pUnitE->pT; // F1
pNew2T = pUnitT->pT; // F3
}
else
{
// before after
//
// <p1> <p1n> .
// 0 . \ 1 0 / \ 1 .
// . \ / \ .
// . \ / \ .
// <p2> <p2> <p2n> <p2n> .
// 0 / \ 1 0 / \ 1 0 . \ 1 0 . \ 1 .
// / \ / \ . \ . \ .
// / \ / \ . \ . \ .
// F0 F1 F2 F3 F0 F2 F1 F3 .
// pNew1E pNew1T pNew2E pNew2T
//
pNew1E = Unit_Not(pUnitER->pE); // F0
pNew1T = pUnitT->pE; // F2
pNew2E = Unit_Not(pUnitER->pT); // F1
pNew2T = pUnitT->pT; // F3
}
// subtract ref counters - on the level P2
pUnitER->n--;
pUnitT->n--;
// mark the change in the APL weights
if ( p->fMinApl )
{
pUnitER->Weight -= AplWeightHalf;
pUnitT->Weight -= AplWeightHalf;
AplWeightAfter -= pUnit->Weight;
}
}
else if ( pUnitER->lev == lev1 )
{
if ( fComp == 0 )
{
// before after
//
// <p1> <p1n> .
// 0 / \ 1 0 / \ 1 .
// / \ / \ .
// / \ / \ .
// <p2> \ <p2n> <p2n> .
// 0 / \ 1 \ 0 / \ 1 0 / \ 1 .
// / \ \ / \ / \ .
// / \ \ / \ / \ .
// F0 F1 F3 F0 F3 F1 F3 .
// pNew1E pNew1T pNew2E pNew2T
//
pNew1E = pUnitER->pE; // F0
pNew1T = pUnitT; // F3
pNew2E = pUnitER->pT; // F1
pNew2T = pUnitT; // F3
}
else
{
// before after
//
// <p1> <p1n> .
// 0 . \ 1 0 / \ 1 .
// . \ / \ .
// . \ / \ .
// <p2> \ <p2n> <p2n> .
// 0 / \ 1 \ 0 . \ 1 0 . \ 1 .
// / \ \ . \ . \ .
// / \ \ . \ . \ .
// F0 F1 F3 F0 F3 F1 F3 .
// pNew1E pNew1T pNew2E pNew2T
//
pNew1E = Unit_Not(pUnitER->pE); // F0
pNew1T = pUnitT; // F3
pNew2E = Unit_Not(pUnitER->pT); // F1
pNew2T = pUnitT; // F3
}
// subtract ref counter - on the level P2
pUnitER->n--;
// subtract ref counter - on other levels
pUnitT->n--; ///
// mark the change in the APL weights
if ( p->fMinApl )
{
pUnitER->Weight -= AplWeightHalf;
AplWeightAfter -= AplWeightHalf;
}
}
else if ( pUnitT->lev == lev1 )
{
// before after
//
// <p1> <p1n> .
// 0 / \ 1 0 / \ 1 .
// / \ / \ .
// / \ / \ .
// / <p2> <p2n> <p2n> .
// / 0 / \ 1 0 / \ 1 0 / \ 1 .
// / / \ / \ / \ .
// / / \ / \ / \ .
// F0 F2 F3 F0 F2 F0 F3 .
// pNew1E pNew1T pNew2E pNew2T
//
pNew1E = pUnitE; // F0
pNew1T = pUnitT->pE; // F2
pNew2E = pUnitE; // F0
pNew2T = pUnitT->pT; // F3
// subtract incoming edge counter - on the level P2
pUnitT->n--;
// subtract ref counter - on other levels
pUnitER->n--; ///
// mark the change in the APL weights
if ( p->fMinApl )
{
pUnitT->Weight -= AplWeightHalf;
AplWeightAfter -= AplWeightHalf;
}
}
else
{
assert( 0 ); // should never happen
}
// consider all the cases except the last one
if ( pNew1E == pNew1T )
{
pNewPlane20 = pNew1T;
if ( p->fMinWidth )
{
// update the cofactors's top ref
if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
pNew1T->TopRefNew = lev1;
if ( pNew1T->Sign != p->nSwaps )
{
pNew1T->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pNew1T;
}
}
}
}
else
{
// pNew1T can be complemented
fCompT = Cudd_IsComplement(pNew1T);
if ( fCompT )
{
pNew1E = Unit_Not(pNew1E);
pNew1T = Unit_Not(pNew1T);
}
// check the hash-table
fFound = 0;
for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize);
p->HTable[HKey].Sign == p->Signature;
HKey = (HKey+1) % p->nTableSize )
if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T )
{ // the entry is present
// assign this entry
pNewPlane20 = p->HTable[HKey].Arg3;
assert( pNewPlane20->lev == lev1 );
fFound = 1;
p->HashSuccess++;
break;
}
if ( !fFound )
{ // create the new entry
pNewPlane20 = reoUnitsGetNextUnit( p ); // increments the unit counter
pNewPlane20->pE = pNew1E;
pNewPlane20->pT = pNew1T;
pNewPlane20->n = 0; // ref will be added later
pNewPlane20->lev = lev1;
if ( p->fMinWidth )
{
pNewPlane20->TopRef = lev1;
pNewPlane20->Sign = 0;
}
// set the weight of this node
if ( p->fMinApl )
pNewPlane20->Weight = 0.0;
// increment ref counters of children
pNew1ER = Unit_Regular(pNew1E);
pNew1ER->n++; //
pNew1T->n++; //
// insert into the data structure
AddToLinkedList( ppListNew1, pNewPlane20 );
// add this entry to cache
assert( p->HTable[HKey].Sign != p->Signature );
p->HTable[HKey].Sign = p->Signature;
p->HTable[HKey].Arg1 = pNew1E;
p->HTable[HKey].Arg2 = pNew1T;
p->HTable[HKey].Arg3 = pNewPlane20;
nNodesUnrefAdded++;
if ( p->fMinWidth )
{
// update the cofactors's top ref
if ( pNew1ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
if ( pNew1ER->Sign != p->nSwaps )
{
pNew1ER->TopRefNew = lev2;
if ( pNew1ER->Sign != p->nSwaps )
{
pNew1ER->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pNew1ER;
}
}
// otherwise the level is already set correctly
else
{
assert( pNew1ER->TopRefNew == lev1 || pNew1ER->TopRefNew == lev2 );
}
}
// update the cofactors's top ref
if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
if ( pNew1T->Sign != p->nSwaps )
{
pNew1T->TopRefNew = lev2;
if ( pNew1T->Sign != p->nSwaps )
{
pNew1T->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pNew1T;
}
}
// otherwise the level is already set correctly
else
{
assert( pNew1T->TopRefNew == lev1 || pNew1T->TopRefNew == lev2 );
}
}
}
}
if ( p->fMinApl )
{
// increment the weight of this node
pNewPlane20->Weight += AplWeightHalf;
// mark the change in the APL weight
AplWeightAfter += AplWeightHalf;
// update the total weight of this level
AplWeightTotalLev1 += AplWeightHalf;
}
if ( fCompT )
pNewPlane20 = Unit_Not(pNewPlane20);
}
if ( pNew2E == pNew2T )
{
pNewPlane21 = pNew2T;
if ( p->fMinWidth )
{
// update the cofactors's top ref
if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
pNew2T->TopRefNew = lev1;
if ( pNew2T->Sign != p->nSwaps )
{
pNew2T->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pNew2T;
}
}
}
}
else
{
assert( !Cudd_IsComplement(pNew2T) );
// check the hash-table
fFound = 0;
for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize);
p->HTable[HKey].Sign == p->Signature;
HKey = (HKey+1) % p->nTableSize )
if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T )
{ // the entry is present
// assign this entry
pNewPlane21 = p->HTable[HKey].Arg3;
assert( pNewPlane21->lev == lev1 );
fFound = 1;
p->HashSuccess++;
break;
}
if ( !fFound )
{ // create the new entry
pNewPlane21 = reoUnitsGetNextUnit( p ); // increments the unit counter
pNewPlane21->pE = pNew2E;
pNewPlane21->pT = pNew2T;
pNewPlane21->n = 0; // ref will be added later
pNewPlane21->lev = lev1;
if ( p->fMinWidth )
{
pNewPlane21->TopRef = lev1;
pNewPlane21->Sign = 0;
}
// set the weight of this node
if ( p->fMinApl )
pNewPlane21->Weight = 0.0;
// increment ref counters of children
pNew2ER = Unit_Regular(pNew2E);
pNew2ER->n++; //
pNew2T->n++; //
// insert into the data structure
// reoUnitsAddUnitToPlane( &P2new, pNewPlane21 );
AddToLinkedList( ppListNew1, pNewPlane21 );
// add this entry to cache
assert( p->HTable[HKey].Sign != p->Signature );
p->HTable[HKey].Sign = p->Signature;
p->HTable[HKey].Arg1 = pNew2E;
p->HTable[HKey].Arg2 = pNew2T;
p->HTable[HKey].Arg3 = pNewPlane21;
nNodesUnrefAdded++;
if ( p->fMinWidth )
{
// update the cofactors's top ref
if ( pNew2ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
if ( pNew2ER->Sign != p->nSwaps )
{
pNew2ER->TopRefNew = lev2;
if ( pNew2ER->Sign != p->nSwaps )
{
pNew2ER->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pNew2ER;
}
}
// otherwise the level is already set correctly
else
{
assert( pNew2ER->TopRefNew == lev1 || pNew2ER->TopRefNew == lev2 );
}
}
// update the cofactors's top ref
if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
if ( pNew2T->Sign != p->nSwaps )
{
pNew2T->TopRefNew = lev2;
if ( pNew2T->Sign != p->nSwaps )
{
pNew2T->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pNew2T;
}
}
// otherwise the level is already set correctly
else
{
assert( pNew2T->TopRefNew == lev1 || pNew2T->TopRefNew == lev2 );
}
}
}
}
if ( p->fMinApl )
{
// increment the weight of this node
pNewPlane21->Weight += AplWeightHalf;
// mark the change in the APL weight
AplWeightAfter += AplWeightHalf;
// update the total weight of this level
AplWeightTotalLev1 += AplWeightHalf;
}
}
// in all cases, the node will be added to the plane-1
// this should be the same node (pUnit) as was originally there
// because it is referenced by the above nodes
assert( !Cudd_IsComplement(pNewPlane21) );
// should be the case; otherwise reordering is not a local operation
pUnit->pE = pNewPlane20;
pUnit->pT = pNewPlane21;
assert( pUnit->lev == lev0 );
// reference counter remains the same; the APL weight remains the same
// increment ref counters of children
pNewPlane20R = Unit_Regular(pNewPlane20);
pNewPlane20R->n++; ///
pNewPlane21->n++; ///
// insert into the data structure
AddToLinkedList( ppListNew0, pUnit );
if ( p->fMinApl )
AplWeightTotalLev0 += pUnit->Weight;
}
// (3) walk through the old lower level, find those nodes whose ref counters are not zero,
// and move them to the new uppoer level, free other nodes
for ( pLoop = pListOld1; pLoop; )
{
pUnit = pLoop;
pLoop = pLoop->Next;
if ( pUnit->n )
{
assert( !p->fMinApl || pUnit->Weight > 0.0 );
// the node should be added to the new level
// no need to check the hash table
pUnit->lev = lev0;
AddToLinkedList( ppListNew0, pUnit );
if ( p->fMinApl )
AplWeightTotalLev0 += pUnit->Weight;
nNodesDownMovedUp++;
if ( p->fMinWidth )
{
pUnitER = Unit_Regular(pUnit->pE);
pUnitT = pUnit->pT;
// update the cofactors's top ref
if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
pUnitER->TopRefNew = lev1;
if ( pUnitER->Sign != p->nSwaps )
{
pUnitER->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pUnitER;
}
}
if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels
{
pUnitT->TopRefNew = lev1;
if ( pUnitT->Sign != p->nSwaps )
{
pUnitT->Sign = p->nSwaps; // set the current signature
p->pWidthCofs[ nWidthCofs++ ] = pUnitT;
}
}
}
}
else
{
assert( !p->fMinApl || pUnit->Weight == 0.0 );
// decrement reference counters of children
pUnitER = Unit_Regular(pUnit->pE);
pUnitT = pUnit->pT;
pUnitER->n--; ///
pUnitT->n--; ///
// the node should be thrown away
reoUnitsRecycleUnit( p, pUnit );
nNodesUnrefRemoved++;
}
}
finish:
// attach the new levels to the planes
p->pPlanes[lev0].pHead = pListNew0;
p->pPlanes[lev1].pHead = pListNew1;
// swap the sift status
temp = p->pPlanes[lev0].fSifted;
p->pPlanes[lev0].fSifted = p->pPlanes[lev1].fSifted;
p->pPlanes[lev1].fSifted = temp;
// swap variables in the variable map
if ( p->pOrderInt )
{
temp = p->pOrderInt[lev0];
p->pOrderInt[lev0] = p->pOrderInt[lev1];
p->pOrderInt[lev1] = temp;
}
// adjust the node profile
p->pPlanes[lev0].statsNodes -= (nNodesUpMovedDown - nNodesDownMovedUp);
p->pPlanes[lev1].statsNodes -= (nNodesDownMovedUp - nNodesUpMovedDown) + nNodesUnrefRemoved - nNodesUnrefAdded;
p->nNodesCur -= nNodesUnrefRemoved - nNodesUnrefAdded;
// adjust the node profile on this level
if ( p->fMinWidth )
{
for ( c = 0; c < nWidthCofs; c++ )
{
if ( p->pWidthCofs[c]->TopRefNew < p->pWidthCofs[c]->TopRef )
{
p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew;
nWidthReduction--;
}
else if ( p->pWidthCofs[c]->TopRefNew > p->pWidthCofs[c]->TopRef )
{
p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew;
nWidthReduction++;
}
}
// verify that the profile is okay
reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 );
reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 );
// compute the total gain in terms of width
nCostGain = (nNodesDownMovedUp - nNodesUpMovedDown + nNodesUnrefRemoved - nNodesUnrefAdded) + nWidthReduction;
// adjust the width on this level
p->pPlanes[lev1].statsWidth -= (int)nCostGain;
// set the cost
p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsWidth;
}
else if ( p->fMinApl )
{
// compute the total gain in terms of APL
nCostGain = AplWeightPrev - AplWeightAfter;
// make sure that the ALP is updated correctly
// assert( p->pPlanes[lev0].statsCost + p->pPlanes[lev1].statsCost - nCostGain ==
// AplWeightTotalLev0 + AplWeightTotalLev1 );
// adjust the profile
p->pPlanes[lev0].statsApl = AplWeightTotalLev0;
p->pPlanes[lev1].statsApl = AplWeightTotalLev1;
// set the cost
p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsApl;
p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsApl;
}
else
{
// compute the total gain in terms of the number of nodes
nCostGain = nNodesUnrefRemoved - nNodesUnrefAdded;
// adjust the profile (adjusted above)
// set the cost
p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsNodes;
p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsNodes;
}
return nCostGain;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END