You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							808 lines
						
					
					
						
							20 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							808 lines
						
					
					
						
							20 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddRef.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Functions that manipulate the reference counts.] | |
|  | |
|   Description [External procedures included in this module: | |
| 		    <ul> | |
| 		    <li> Cudd_Ref() | |
| 		    <li> Cudd_RecursiveDeref() | |
| 		    <li> Cudd_IterDerefBdd() | |
| 		    <li> Cudd_DelayedDerefBdd() | |
| 		    <li> Cudd_RecursiveDerefZdd() | |
| 		    <li> Cudd_Deref() | |
| 		    <li> Cudd_CheckZeroRef() | |
| 		    </ul> | |
| 	       Internal procedures included in this module: | |
| 		    <ul> | |
| 		    <li> cuddReclaim() | |
| 		    <li> cuddReclaimZdd() | |
| 		    <li> cuddClearDeathRow() | |
| 		    <li> cuddShrinkDeathRow() | |
| 		    <li> cuddIsInDeathRow() | |
| 		    <li> cuddTimesInDeathRow() | |
| 		    </ul> | |
| 	      ] | |
|  | |
|   SeeAlso     [] | |
|  | |
|   Author      [Fabio Somenzi] | |
|  | |
|   Copyright   [Copyright (c) 1995-2012, Regents of the University of Colorado | |
|  | |
|   All rights reserved. | |
|  | |
|   Redistribution and use in source and binary forms, with or without | |
|   modification, are permitted provided that the following conditions | |
|   are met: | |
|  | |
|   Redistributions of source code must retain the above copyright | |
|   notice, this list of conditions and the following disclaimer. | |
|  | |
|   Redistributions in binary form must reproduce the above copyright | |
|   notice, this list of conditions and the following disclaimer in the | |
|   documentation and/or other materials provided with the distribution. | |
|  | |
|   Neither the name of the University of Colorado nor the names of its | |
|   contributors may be used to endorse or promote products derived from | |
|   this software without specific prior written permission. | |
|  | |
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
|   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
|   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
|   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
|   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
|   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
|   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
|   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
|   POSSIBILITY OF SUCH DAMAGE.] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "util.h" | |
| #include "cuddInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Constant declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.29 2012/02/05 01:07:19 fabio Exp $"; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Increases the reference count of a node, if it is not | |
|   saturated.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_RecursiveDeref Cudd_Deref] | |
|  | |
| ******************************************************************************/ | |
| void | |
| Cudd_Ref( | |
|   DdNode * n) | |
| { | |
| 
 | |
|     n = Cudd_Regular(n); | |
| 
 | |
|     cuddSatInc(n->ref); | |
| 
 | |
| } /* end of Cudd_Ref */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Decreases the reference count of node n.] | |
|  | |
|   Description [Decreases the reference count of node n. If n dies, | |
|   recursively decreases the reference counts of its children.  It is | |
|   used to dispose of a DD that is no longer needed.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd] | |
|  | |
| ******************************************************************************/ | |
| void | |
| Cudd_RecursiveDeref( | |
|   DdManager * table, | |
|   DdNode * n) | |
| { | |
|     DdNode *N; | |
|     int ord; | |
|     DdNodePtr *stack = table->stack; | |
|     int SP = 1; | |
| 
 | |
|     unsigned int live = table->keys - table->dead; | |
|     if (live > table->peakLiveNodes) { | |
| 	table->peakLiveNodes = live; | |
|     } | |
| 
 | |
|     N = Cudd_Regular(n); | |
| 
 | |
|     do { | |
| #ifdef DD_DEBUG | |
| 	assert(N->ref != 0); | |
| #endif | |
|  | |
| 	if (N->ref == 1) { | |
| 	    N->ref = 0; | |
| 	    table->dead++; | |
| #ifdef DD_STATS | |
| 	    table->nodesDropped++; | |
| #endif | |
| 	    if (cuddIsConstant(N)) { | |
| 		table->constants.dead++; | |
| 		N = stack[--SP]; | |
| 	    } else { | |
| 		ord = table->perm[N->index]; | |
| 		stack[SP++] = Cudd_Regular(cuddE(N)); | |
| 		table->subtables[ord].dead++; | |
| 		N = cuddT(N); | |
| 	    } | |
| 	} else { | |
| 	    cuddSatDec(N->ref); | |
| 	    N = stack[--SP]; | |
| 	} | |
|     } while (SP != 0); | |
| 
 | |
| } /* end of Cudd_RecursiveDeref */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Decreases the reference count of BDD node n.] | |
|  | |
|   Description [Decreases the reference count of node n. If n dies, | |
|   recursively decreases the reference counts of its children.  It is | |
|   used to dispose of a BDD that is no longer needed. It is more | |
|   efficient than Cudd_RecursiveDeref, but it cannot be used on | |
|   ADDs. The greater efficiency comes from being able to assume that no | |
|   constant node will ever die as a result of a call to this | |
|   procedure.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_RecursiveDeref Cudd_DelayedDerefBdd] | |
|  | |
| ******************************************************************************/ | |
| void | |
| Cudd_IterDerefBdd( | |
|   DdManager * table, | |
|   DdNode * n) | |
| { | |
|     DdNode *N; | |
|     int ord; | |
|     DdNodePtr *stack = table->stack; | |
|     int SP = 1; | |
| 
 | |
|     unsigned int live = table->keys - table->dead; | |
|     if (live > table->peakLiveNodes) { | |
| 	table->peakLiveNodes = live; | |
|     } | |
| 
 | |
|     N = Cudd_Regular(n); | |
| 
 | |
|     do { | |
| #ifdef DD_DEBUG | |
| 	assert(N->ref != 0); | |
| #endif | |
|  | |
| 	if (N->ref == 1) { | |
| 	    N->ref = 0; | |
| 	    table->dead++; | |
| #ifdef DD_STATS | |
| 	    table->nodesDropped++; | |
| #endif | |
| 	    ord = table->perm[N->index]; | |
| 	    stack[SP++] = Cudd_Regular(cuddE(N)); | |
| 	    table->subtables[ord].dead++; | |
| 	    N = cuddT(N); | |
| 	} else { | |
| 	    cuddSatDec(N->ref); | |
| 	    N = stack[--SP]; | |
| 	} | |
|     } while (SP != 0); | |
| 
 | |
| } /* end of Cudd_IterDerefBdd */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Decreases the reference count of BDD node n.] | |
|  | |
|   Description [Enqueues node n for later dereferencing. If the queue | |
|   is full decreases the reference count of the oldest node N to make | |
|   room for n. If N dies, recursively decreases the reference counts of | |
|   its children.  It is used to dispose of a BDD that is currently not | |
|   needed, but may be useful again in the near future. The dereferencing | |
|   proper is done as in Cudd_IterDerefBdd.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_RecursiveDeref Cudd_IterDerefBdd] | |
|  | |
| ******************************************************************************/ | |
| void | |
| Cudd_DelayedDerefBdd( | |
|   DdManager * table, | |
|   DdNode * n) | |
| { | |
|     DdNode *N; | |
|     int ord; | |
|     DdNodePtr *stack; | |
|     int SP; | |
| 
 | |
|     unsigned int live = table->keys - table->dead; | |
|     if (live > table->peakLiveNodes) { | |
| 	table->peakLiveNodes = live; | |
|     } | |
| 
 | |
|     n = Cudd_Regular(n); | |
| #ifdef DD_DEBUG | |
|     assert(n->ref != 0); | |
| #endif | |
|  | |
| #ifdef DD_NO_DEATH_ROW | |
|     N = n; | |
| #else | |
|     if (cuddIsConstant(n) || n->ref > 1) { | |
| #ifdef DD_DEBUG | |
| 	assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table))); | |
| #endif | |
| 	cuddSatDec(n->ref); | |
| 	return; | |
|     } | |
| 
 | |
|     N = table->deathRow[table->nextDead]; | |
| 
 | |
|     if (N != NULL) { | |
| #endif | |
| #ifdef DD_DEBUG | |
| 	assert(!Cudd_IsComplement(N)); | |
| #endif | |
| 	stack = table->stack; | |
| 	SP = 1; | |
| 	do { | |
| #ifdef DD_DEBUG | |
| 	    assert(N->ref != 0); | |
| #endif | |
| 	    if (N->ref == 1) { | |
| 		N->ref = 0; | |
| 		table->dead++; | |
| #ifdef DD_STATS | |
| 		table->nodesDropped++; | |
| #endif | |
| 		ord = table->perm[N->index]; | |
| 		stack[SP++] = Cudd_Regular(cuddE(N)); | |
| 		table->subtables[ord].dead++; | |
| 		N = cuddT(N); | |
| 	    } else { | |
| 		cuddSatDec(N->ref); | |
| 		N = stack[--SP]; | |
| 	    } | |
| 	} while (SP != 0); | |
| #ifndef DD_NO_DEATH_ROW | |
|     } | |
|     table->deathRow[table->nextDead] = n; | |
| 
 | |
|     /* Udate insertion point. */ | |
|     table->nextDead++; | |
|     table->nextDead &= table->deadMask; | |
| #if 0 | |
|     if (table->nextDead == table->deathRowDepth) { | |
| 	if (table->deathRowDepth < table->looseUpTo / 2) { | |
| 	    extern void (*MMoutOfMemory)(long); | |
| 	    void (*saveHandler)(long) = MMoutOfMemory; | |
| 	    DdNodePtr *newRow; | |
| 	    MMoutOfMemory = Cudd_OutOfMem; | |
| 	    newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth); | |
| 	    MMoutOfMemory = saveHandler; | |
| 	    if (newRow == NULL) { | |
| 		table->nextDead = 0; | |
| 	    } else { | |
| 		int i; | |
| 		table->memused += table->deathRowDepth; | |
| 		i = table->deathRowDepth; | |
| 		table->deathRowDepth <<= 1; | |
| 		for (; i < table->deathRowDepth; i++) { | |
| 		    newRow[i] = NULL; | |
| 		} | |
| 		table->deadMask = table->deathRowDepth - 1; | |
| 		table->deathRow = newRow; | |
| 	    } | |
| 	} else { | |
| 	    table->nextDead = 0; | |
| 	} | |
|     } | |
| #endif | |
| #endif | |
|  | |
| } /* end of Cudd_DelayedDerefBdd */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Decreases the reference count of ZDD node n.] | |
|  | |
|   Description [Decreases the reference count of ZDD node n. If n dies, | |
|   recursively decreases the reference counts of its children.  It is | |
|   used to dispose of a ZDD that is no longer needed.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref] | |
|  | |
| ******************************************************************************/ | |
| void | |
| Cudd_RecursiveDerefZdd( | |
|   DdManager * table, | |
|   DdNode * n) | |
| { | |
|     DdNode *N; | |
|     int ord; | |
|     DdNodePtr *stack = table->stack; | |
|     int SP = 1; | |
| 
 | |
|     N = n; | |
| 
 | |
|     do { | |
| #ifdef DD_DEBUG | |
| 	assert(N->ref != 0); | |
| #endif | |
|  | |
| 	cuddSatDec(N->ref); | |
|      | |
| 	if (N->ref == 0) { | |
| 	    table->deadZ++; | |
| #ifdef DD_STATS | |
| 	    table->nodesDropped++; | |
| #endif | |
| #ifdef DD_DEBUG | |
| 	    assert(!cuddIsConstant(N)); | |
| #endif | |
| 	    ord = table->permZ[N->index]; | |
| 	    stack[SP++] = cuddE(N); | |
| 	    table->subtableZ[ord].dead++; | |
| 	    N = cuddT(N); | |
| 	} else { | |
| 	    N = stack[--SP]; | |
| 	} | |
|     } while (SP != 0); | |
| 
 | |
| } /* end of Cudd_RecursiveDerefZdd */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Decreases the reference count of node.] | |
|  | |
|   Description [Decreases the reference count of node. It is primarily | |
|   used in recursive procedures to decrease the ref count of a result | |
|   node before returning it. This accomplishes the goal of removing the | |
|   protection applied by a previous Cudd_Ref.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref] | |
|  | |
| ******************************************************************************/ | |
| void | |
| Cudd_Deref( | |
|   DdNode * node) | |
| { | |
|     node = Cudd_Regular(node); | |
|     cuddSatDec(node->ref); | |
| 
 | |
| } /* end of Cudd_Deref */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Checks the unique table for nodes with non-zero reference | |
|   counts.] | |
|  | |
|   Description [Checks the unique table for nodes with non-zero | |
|   reference counts. It is normally called before Cudd_Quit to make sure | |
|   that there are no memory leaks due to missing Cudd_RecursiveDeref's. | |
|   Takes into account that reference counts may saturate and that the | |
|   basic constants and the projection functions are referenced by the | |
|   manager.  Returns the number of nodes with non-zero reference count. | |
|   (Except for the cases mentioned above.)] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| Cudd_CheckZeroRef( | |
|   DdManager * manager) | |
| { | |
|     int size; | |
|     int i, j; | |
|     int remain;	/* the expected number of remaining references to one */ | |
|     DdNodePtr *nodelist; | |
|     DdNode *node; | |
|     DdNode *sentinel = &(manager->sentinel); | |
|     DdSubtable *subtable; | |
|     int count = 0; | |
|     int index; | |
| 
 | |
| #ifndef DD_NO_DEATH_ROW | |
|     cuddClearDeathRow(manager); | |
| #endif | |
|  | |
|     /* First look at the BDD/ADD subtables. */ | |
|     remain = 1; /* reference from the manager */ | |
|     size = manager->size; | |
|     remain += 2 * size;	/* reference from the BDD projection functions */ | |
| 
 | |
|     for (i = 0; i < size; i++) { | |
| 	subtable = &(manager->subtables[i]); | |
| 	nodelist = subtable->nodelist; | |
| 	for (j = 0; (unsigned) j < subtable->slots; j++) { | |
| 	    node = nodelist[j]; | |
| 	    while (node != sentinel) { | |
| 		if (node->ref != 0 && node->ref != DD_MAXREF) { | |
| 		    index = (int) node->index; | |
| 		    if (node != manager->vars[index]) { | |
| 			count++; | |
| 		    } else { | |
| 			if (node->ref != 1) { | |
| 			    count++; | |
| 			} | |
| 		    } | |
| 		} | |
| 		node = node->next; | |
| 	    } | |
| 	} | |
|     } | |
| 
 | |
|     /* Then look at the ZDD subtables. */ | |
|     size = manager->sizeZ; | |
|     if (size) /* references from ZDD universe */ | |
| 	remain += 2; | |
| 
 | |
|     for (i = 0; i < size; i++) { | |
| 	subtable = &(manager->subtableZ[i]); | |
| 	nodelist = subtable->nodelist; | |
| 	for (j = 0; (unsigned) j < subtable->slots; j++) { | |
| 	    node = nodelist[j]; | |
| 	    while (node != NULL) { | |
| 		if (node->ref != 0 && node->ref != DD_MAXREF) { | |
| 		    index = (int) node->index; | |
| 		    if (node == manager->univ[manager->permZ[index]]) { | |
| 			if (node->ref > 2) { | |
| 			    count++; | |
| 			} | |
| 		    } else { | |
| 			count++; | |
| 		    } | |
| 		} | |
| 		node = node->next; | |
| 	    } | |
| 	} | |
|     } | |
| 
 | |
|     /* Now examine the constant table. Plusinfinity, minusinfinity, and | |
|     ** zero are referenced by the manager. One is referenced by the | |
|     ** manager, by the ZDD universe, and by all projection functions. | |
|     ** All other nodes should have no references. | |
|     */ | |
|     nodelist = manager->constants.nodelist; | |
|     for (j = 0; (unsigned) j < manager->constants.slots; j++) { | |
| 	node = nodelist[j]; | |
| 	while (node != NULL) { | |
| 	    if (node->ref != 0 && node->ref != DD_MAXREF) { | |
| 		if (node == manager->one) { | |
| 		    if ((int) node->ref != remain) { | |
| 			count++; | |
| 		    } | |
| 		} else if (node == manager->zero || | |
| 		node == manager->plusinfinity || | |
| 		node == manager->minusinfinity) { | |
| 		    if (node->ref != 1) { | |
| 			count++; | |
| 		    } | |
| 		} else { | |
| 		    count++; | |
| 		} | |
| 	    } | |
| 	    node = node->next; | |
| 	} | |
|     } | |
|     return(count); | |
| 
 | |
| } /* end of Cudd_CheckZeroRef */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Brings children of a dead node back.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddReclaimZdd] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddReclaim( | |
|   DdManager * table, | |
|   DdNode * n) | |
| { | |
|     DdNode *N; | |
|     int ord; | |
|     DdNodePtr *stack = table->stack; | |
|     int SP = 1; | |
|     double initialDead = table->dead; | |
| 
 | |
|     N = Cudd_Regular(n); | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(N->ref == 0); | |
| #endif | |
|  | |
|     do { | |
| 	if (N->ref == 0) { | |
| 	    N->ref = 1; | |
| 	    table->dead--; | |
| 	    if (cuddIsConstant(N)) { | |
| 		table->constants.dead--; | |
| 		N = stack[--SP]; | |
| 	    } else { | |
| 		ord = table->perm[N->index]; | |
| 		stack[SP++] = Cudd_Regular(cuddE(N)); | |
| 		table->subtables[ord].dead--; | |
| 		N = cuddT(N); | |
| 	    } | |
| 	} else { | |
| 	    cuddSatInc(N->ref); | |
| 	    N = stack[--SP]; | |
| 	} | |
|     } while (SP != 0); | |
| 
 | |
|     N = Cudd_Regular(n); | |
|     cuddSatDec(N->ref); | |
|     table->reclaimed += initialDead - table->dead; | |
| 
 | |
| } /* end of cuddReclaim */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Brings children of a dead ZDD node back.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddReclaim] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddReclaimZdd( | |
|   DdManager * table, | |
|   DdNode * n) | |
| { | |
|     DdNode *N; | |
|     int ord; | |
|     DdNodePtr *stack = table->stack; | |
|     int SP = 1; | |
| 
 | |
|     N = n; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(N->ref == 0); | |
| #endif | |
|  | |
|     do { | |
| 	cuddSatInc(N->ref); | |
| 
 | |
| 	if (N->ref == 1) { | |
| 	    table->deadZ--; | |
| 	    table->reclaimed++; | |
| #ifdef DD_DEBUG | |
| 	    assert(!cuddIsConstant(N)); | |
| #endif | |
| 	    ord = table->permZ[N->index]; | |
| 	    stack[SP++] = cuddE(N); | |
| 	    table->subtableZ[ord].dead--; | |
| 	    N = cuddT(N); | |
| 	} else { | |
| 	    N = stack[--SP]; | |
| 	} | |
|     } while (SP != 0); | |
| 
 | |
|     cuddSatDec(n->ref); | |
| 
 | |
| } /* end of cuddReclaimZdd */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Shrinks the death row.] | |
|  | |
|   Description [Shrinks the death row by a factor of four.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddClearDeathRow] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddShrinkDeathRow( | |
|   DdManager *table) | |
| { | |
| #ifndef DD_NO_DEATH_ROW | |
|     int i; | |
| 
 | |
|     if (table->deathRowDepth > 3) { | |
| 	for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { | |
| 	    if (table->deathRow[i] == NULL) break; | |
| 	    Cudd_IterDerefBdd(table,table->deathRow[i]); | |
| 	    table->deathRow[i] = NULL; | |
| 	} | |
| 	table->deathRowDepth /= 4; | |
| 	table->deadMask = table->deathRowDepth - 1; | |
| 	if ((unsigned) table->nextDead > table->deadMask) { | |
| 	    table->nextDead = 0; | |
| 	} | |
| 	table->deathRow = REALLOC(DdNodePtr, table->deathRow, | |
| 				   table->deathRowDepth); | |
|     } | |
| #endif | |
|  | |
| } /* end of cuddShrinkDeathRow */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Clears the death row.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef | |
|   cuddGarbageCollect] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddClearDeathRow( | |
|   DdManager *table) | |
| { | |
| #ifndef DD_NO_DEATH_ROW | |
|     int i; | |
| 
 | |
|     for (i = 0; i < table->deathRowDepth; i++) { | |
| 	if (table->deathRow[i] == NULL) break; | |
| 	Cudd_IterDerefBdd(table,table->deathRow[i]); | |
| 	table->deathRow[i] = NULL; | |
|     } | |
| #ifdef DD_DEBUG | |
|     for (; i < table->deathRowDepth; i++) { | |
| 	assert(table->deathRow[i] == NULL); | |
|     } | |
| #endif | |
|     table->nextDead = 0; | |
| #endif | |
|  | |
| } /* end of cuddClearDeathRow */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Checks whether a node is in the death row.] | |
|  | |
|   Description [Checks whether a node is in the death row. Returns the | |
|   position of the first occurrence if the node is present; -1 | |
|   otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DelayedDerefBdd cuddClearDeathRow] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddIsInDeathRow( | |
|   DdManager *dd, | |
|   DdNode *f) | |
| { | |
| #ifndef DD_NO_DEATH_ROW | |
|     int i; | |
| 
 | |
|     for (i = 0; i < dd->deathRowDepth; i++) { | |
| 	if (f == dd->deathRow[i]) { | |
| 	    return(i); | |
| 	} | |
|     } | |
| #endif | |
|  | |
|     return(-1); | |
| 
 | |
| } /* end of cuddIsInDeathRow */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Counts how many times a node is in the death row.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddTimesInDeathRow( | |
|   DdManager *dd, | |
|   DdNode *f) | |
| { | |
|     int count = 0; | |
| #ifndef DD_NO_DEATH_ROW | |
|     int i; | |
| 
 | |
|     for (i = 0; i < dd->deathRowDepth; i++) { | |
| 	count += f == dd->deathRow[i]; | |
|     } | |
| #endif | |
|  | |
|     return(count); | |
| 
 | |
| } /* end of cuddTimesInDeathRow */ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/
 |