#include "util_hack.h"
#include "cuddInt.h"
Go to the source code of this file.
Data Structures | |
union | hack |
Defines | |
#define | DD_STACK_SIZE 128 |
#define | DD_RED 0 |
#define | DD_BLACK 1 |
#define | DD_PAGE_SIZE 8192 |
#define | DD_PAGE_MASK ~(DD_PAGE_SIZE - 1) |
#define | DD_INSERT_COMPARE(x, y) (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK)) |
#define | DD_COLOR(p) ((p)->index) |
#define | DD_IS_BLACK(p) ((p)->index == DD_BLACK) |
#define | DD_IS_RED(p) ((p)->index == DD_RED) |
#define | DD_LEFT(p) cuddT(p) |
#define | DD_RIGHT(p) cuddE(p) |
#define | DD_NEXT(p) ((p)->next) |
Functions | |
static void ddRehashZdd | ARGS ((DdManager *unique, int i)) |
static int ddResizeTable | ARGS ((DdManager *unique, int index)) |
static int cuddFindParent | ARGS ((DdManager *table, DdNode *node)) |
static DD_INLINE void ddFixLimits | ARGS ((DdManager *unique)) |
static void cuddOrderedInsert | ARGS ((DdNodePtr *root, DdNodePtr node)) |
static DdNode *cuddOrderedThread | ARGS ((DdNode *root, DdNode *list)) |
static void cuddRotateLeft | ARGS ((DdNodePtr *nodeP)) |
static void cuddDoRebalance | ARGS ((DdNodePtr **stack, int stackN)) |
static void ddPatchTree | ARGS ((DdManager *dd, MtrNode *treenode)) |
static void ddReportRefMess | ARGS ((DdManager *unique, int i, char *caller)) |
unsigned int | Cudd_Prime (unsigned int p) |
DdNode * | cuddAllocNode (DdManager *unique) |
DdManager * | cuddInitTable (unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo) |
void | cuddFreeTable (DdManager *unique) |
int | cuddGarbageCollect (DdManager *unique, int clearCache) |
int | cuddGarbageCollectZdd (DdManager *unique, int clearCache) |
DdNode * | cuddZddGetNode (DdManager *zdd, int id, DdNode *T, DdNode *E) |
DdNode * | cuddZddGetNodeIVO (DdManager *dd, int index, DdNode *g, DdNode *h) |
DdNode * | cuddUniqueInter (DdManager *unique, int index, DdNode *T, DdNode *E) |
DdNode * | cuddUniqueInterIVO (DdManager *unique, int index, DdNode *T, DdNode *E) |
DdNode * | cuddUniqueInterZdd (DdManager *unique, int index, DdNode *T, DdNode *E) |
DdNode * | cuddUniqueConst (DdManager *unique, CUDD_VALUE_TYPE value) |
void | cuddRehash (DdManager *unique, int i) |
void | cuddShrinkSubtable (DdManager *unique, int i) |
int | cuddInsertSubtables (DdManager *unique, int n, int level) |
int | cuddDestroySubtables (DdManager *unique, int n) |
int | cuddResizeTableZdd (DdManager *unique, int index) |
void | cuddSlowTableGrowth (DdManager *unique) |
static void | ddRehashZdd (DdManager *unique, int i) |
static int | ddResizeTable (DdManager *unique, int index) |
static int | cuddFindParent (DdManager *table, DdNode *node) |
static DD_INLINE void | ddFixLimits (DdManager *unique) |
static void | cuddOrderedInsert (DdNodePtr *root, DdNodePtr node) |
static DdNode * | cuddOrderedThread (DdNode *root, DdNode *list) |
static DD_INLINE void | cuddRotateLeft (DdNodePtr *nodeP) |
static DD_INLINE void | cuddRotateRight (DdNodePtr *nodeP) |
static void | cuddDoRebalance (DdNodePtr **stack, int stackN) |
static void | ddPatchTree (DdManager *dd, MtrNode *treenode) |
static void | ddReportRefMess (DdManager *unique, int i, char *caller) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddTable.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" |
#define DD_BLACK 1 |
Definition at line 68 of file cuddTable.c.
#define DD_COLOR | ( | p | ) | ((p)->index) |
Definition at line 104 of file cuddTable.c.
#define DD_INSERT_COMPARE | ( | x, | |||
y | ) | (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK)) |
Definition at line 71 of file cuddTable.c.
#define DD_IS_BLACK | ( | p | ) | ((p)->index == DD_BLACK) |
Definition at line 105 of file cuddTable.c.
#define DD_IS_RED | ( | p | ) | ((p)->index == DD_RED) |
Definition at line 106 of file cuddTable.c.
#define DD_LEFT | ( | p | ) | cuddT(p) |
Definition at line 107 of file cuddTable.c.
#define DD_NEXT | ( | p | ) | ((p)->next) |
Definition at line 109 of file cuddTable.c.
#define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1) |
Definition at line 70 of file cuddTable.c.
#define DD_PAGE_SIZE 8192 |
Definition at line 69 of file cuddTable.c.
#define DD_RED 0 |
Definition at line 67 of file cuddTable.c.
#define DD_RIGHT | ( | p | ) | cuddE(p) |
Definition at line 108 of file cuddTable.c.
#define DD_STACK_SIZE 128 |
CFile***********************************************************************
FileName [cuddTable.c]
PackageName [cudd]
Synopsis [Unique table management functions.]
Description [External procedures included in this module:
Internal procedures included in this module:
Static procedures included in this module:
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]
Definition at line 66 of file cuddTable.c.
static void ddReportRefMess ARGS | ( | (DdManager *unique, int i, char *caller) | ) | [static] |
static void cuddDoRebalance ARGS | ( | (DdNodePtr **stack, int stackN) | ) | [static] |
static void cuddRotateRight ARGS | ( | (DdNodePtr *nodeP) | ) | [static] |
static DD_INLINE void ddFixLimits ARGS | ( | (DdManager *unique) | ) | [static] |
static int ddResizeTable ARGS | ( | (DdManager *unique, int index) | ) | [static] |
static void ddRehashZdd ARGS | ( | (DdManager *unique, int i) | ) | [static] |
AutomaticStart
unsigned int Cudd_Prime | ( | unsigned int | p | ) |
AutomaticEnd Function********************************************************************
Synopsis [Returns the next prime >= p.]
Description []
SideEffects [None]
Definition at line 152 of file cuddTable.c.
00154 { 00155 int i,pn; 00156 00157 p--; 00158 do { 00159 p++; 00160 if (p&1) { 00161 pn = 1; 00162 i = 3; 00163 while ((unsigned) (i * i) <= p) { 00164 if (p % i == 0) { 00165 pn = 0; 00166 break; 00167 } 00168 i += 2; 00169 } 00170 } else { 00171 pn = 0; 00172 } 00173 } while (!pn); 00174 return(p); 00175 00176 } /* end of Cudd_Prime */
Function********************************************************************
Synopsis [Fast storage allocation for DdNodes in the table.]
Description [Fast storage allocation for DdNodes in the table. The first 4 bytes of a chunk contain a pointer to the next block; the rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to a new node if successful; NULL is memory is full.]
SideEffects [None]
SeeAlso [cuddDynamicAllocNode]
Definition at line 199 of file cuddTable.c.
00201 { 00202 int i; 00203 DdNodePtr *mem; 00204 DdNode *list, *node; 00205 extern void (*MMoutOfMemory)(long); 00206 void (*saveHandler)(long); 00207 00208 if (unique->nextFree == NULL) { /* free list is empty */ 00209 /* Check for exceeded limits. */ 00210 if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) > 00211 unique->maxLive) { 00212 unique->errorCode = CUDD_TOO_MANY_NODES; 00213 return(NULL); 00214 } 00215 if (unique->stash == NULL || unique->memused > unique->maxmemhard) { 00216 (void) cuddGarbageCollect(unique,1); 00217 mem = NULL; 00218 } 00219 if (unique->nextFree == NULL) { 00220 if (unique->memused > unique->maxmemhard) { 00221 unique->errorCode = CUDD_MAX_MEM_EXCEEDED; 00222 return(NULL); 00223 } 00224 /* Try to allocate a new block. */ 00225 saveHandler = MMoutOfMemory; 00226 MMoutOfMemory = Cudd_OutOfMem; 00227 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00228 MMoutOfMemory = saveHandler; 00229 if (mem == NULL) { 00230 /* No more memory: Try collecting garbage. If this succeeds, 00231 ** we end up with mem still NULL, but unique->nextFree != 00232 ** NULL. */ 00233 if (cuddGarbageCollect(unique,1) == 0) { 00234 /* Last resort: Free the memory stashed away, if there 00235 ** any. If this succeeeds, mem != NULL and 00236 ** unique->nextFree still NULL. */ 00237 if (unique->stash != NULL) { 00238 FREE(unique->stash); 00239 unique->stash = NULL; 00240 /* Inhibit resizing of tables. */ 00241 cuddSlowTableGrowth(unique); 00242 /* Now try again. */ 00243 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00244 } 00245 if (mem == NULL) { 00246 /* Out of luck. Call the default handler to do 00247 ** whatever it specifies for a failed malloc. 00248 ** If this handler returns, then set error code, 00249 ** print warning, and return. */ 00250 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); 00251 unique->errorCode = CUDD_MEMORY_OUT; 00252 #ifdef DD_VERBOSE 00253 (void) fprintf(unique->err, 00254 "cuddAllocNode: out of memory"); 00255 (void) fprintf(unique->err, "Memory in use = %ld\n", 00256 unique->memused); 00257 #endif 00258 return(NULL); 00259 } 00260 } 00261 } 00262 if (mem != NULL) { /* successful allocation; slice memory */ 00263 ptruint offset; 00264 unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); 00265 mem[0] = (DdNodePtr) unique->memoryList; 00266 unique->memoryList = mem; 00267 00268 /* Here we rely on the fact that a DdNode is as large 00269 ** as 4 pointers. */ 00270 offset = (ptruint) mem & (sizeof(DdNode) - 1); 00271 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); 00272 assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0); 00273 list = (DdNode *) mem; 00274 00275 i = 1; 00276 do { 00277 list[i - 1].next = &list[i]; 00278 } while (++i < DD_MEM_CHUNK); 00279 00280 list[DD_MEM_CHUNK-1].next = NULL; 00281 00282 unique->nextFree = &list[0]; 00283 } 00284 } 00285 } 00286 unique->allocated++; 00287 node = unique->nextFree; 00288 unique->nextFree = node->next; 00289 return(node); 00290 00291 } /* end of cuddAllocNode */
int cuddDestroySubtables | ( | DdManager * | unique, | |
int | n | |||
) |
Function********************************************************************
Synopsis [Destroys the n most recently created subtables in a unique table.]
Description [Destroys the n most recently created subtables in a unique table. n should be positive. The subtables should not contain any live nodes, except the (isolated) projection function. The projection functions are freed. Returns 1 if successful; 0 otherwise.]
SideEffects [The variable map used for fast variable substitution is destroyed if it exists. In this case the cache is also cleared.]
SeeAlso [cuddInsertSubtables Cudd_SetVarMap]
Definition at line 2072 of file cuddTable.c.
02075 { 02076 DdSubtable *subtables; 02077 DdNodePtr *nodelist; 02078 DdNodePtr *vars; 02079 int firstIndex, lastIndex; 02080 int index, level, newlevel; 02081 int lowestLevel; 02082 int shift; 02083 int found; 02084 02085 /* Sanity check and set up. */ 02086 if (n <= 0) return(0); 02087 if (n > unique->size) n = unique->size; 02088 02089 subtables = unique->subtables; 02090 vars = unique->vars; 02091 firstIndex = unique->size - n; 02092 lastIndex = unique->size; 02093 02094 /* Check for nodes labeled by the variables being destroyed 02095 ** that may still be in use. It is allowed to destroy a variable 02096 ** only if there are no such nodes. Also, find the lowest level 02097 ** among the variables being destroyed. This will make further 02098 ** processing more efficient. 02099 */ 02100 lowestLevel = unique->size; 02101 for (index = firstIndex; index < lastIndex; index++) { 02102 level = unique->perm[index]; 02103 if (level < lowestLevel) lowestLevel = level; 02104 nodelist = subtables[level].nodelist; 02105 if (subtables[level].keys - subtables[level].dead != 1) return(0); 02106 /* The projection function should be isolated. If the ref count 02107 ** is 1, everything is OK. If the ref count is saturated, then 02108 ** we need to make sure that there are no nodes pointing to it. 02109 ** As for the external references, we assume the application is 02110 ** responsible for them. 02111 */ 02112 if (vars[index]->ref != 1) { 02113 if (vars[index]->ref != DD_MAXREF) return(0); 02114 found = cuddFindParent(unique,vars[index]); 02115 if (found) { 02116 return(0); 02117 } else { 02118 vars[index]->ref = 1; 02119 } 02120 } 02121 Cudd_RecursiveDeref(unique,vars[index]); 02122 } 02123 02124 /* Collect garbage, because we cannot afford having dead nodes pointing 02125 ** to the dead nodes in the subtables being destroyed. 02126 */ 02127 (void) cuddGarbageCollect(unique,1); 02128 02129 /* Here we know we can destroy our subtables. */ 02130 for (index = firstIndex; index < lastIndex; index++) { 02131 level = unique->perm[index]; 02132 nodelist = subtables[level].nodelist; 02133 #ifdef DD_DEBUG 02134 assert(subtables[level].keys == 0); 02135 #endif 02136 FREE(nodelist); 02137 unique->memused -= sizeof(DdNodePtr) * subtables[level].slots; 02138 unique->slots -= subtables[level].slots; 02139 unique->dead -= subtables[level].dead; 02140 } 02141 02142 /* Here all subtables to be destroyed have their keys field == 0 and 02143 ** their hash tables have been freed. 02144 ** We now scan the subtables from level lowestLevel + 1 to level size - 1, 02145 ** shifting the subtables as required. We keep a running count of 02146 ** how many subtables have been moved, so that we know by how many 02147 ** positions each subtable should be shifted. 02148 */ 02149 shift = 1; 02150 for (level = lowestLevel + 1; level < unique->size; level++) { 02151 if (subtables[level].keys == 0) { 02152 shift++; 02153 continue; 02154 } 02155 newlevel = level - shift; 02156 subtables[newlevel].slots = subtables[level].slots; 02157 subtables[newlevel].shift = subtables[level].shift; 02158 subtables[newlevel].keys = subtables[level].keys; 02159 subtables[newlevel].maxKeys = subtables[level].maxKeys; 02160 subtables[newlevel].dead = subtables[level].dead; 02161 subtables[newlevel].nodelist = subtables[level].nodelist; 02162 index = unique->invperm[level]; 02163 unique->perm[index] = newlevel; 02164 unique->invperm[newlevel] = index; 02165 subtables[newlevel].bindVar = subtables[level].bindVar; 02166 subtables[newlevel].varType = subtables[level].varType; 02167 subtables[newlevel].pairIndex = subtables[level].pairIndex; 02168 subtables[newlevel].varHandled = subtables[level].varHandled; 02169 subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped; 02170 } 02171 /* Destroy the map. If a surviving variable is 02172 ** mapped to a dying variable, and the map were used again, 02173 ** an out-of-bounds access to unique->vars would result. */ 02174 if (unique->map != NULL) { 02175 cuddCacheFlush(unique); 02176 FREE(unique->map); 02177 unique->map = NULL; 02178 } 02179 02180 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 02181 unique->size -= n; 02182 02183 return(1); 02184 02185 } /* end of cuddDestroySubtables */
static void cuddDoRebalance | ( | DdNodePtr ** | stack, | |
int | stackN | |||
) | [static] |
Function********************************************************************
Synopsis [Rebalances a red/black tree.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 2970 of file cuddTable.c.
02973 { 02974 DdNodePtr *xP, *parentP, *grandpaP; 02975 DdNode *x, *y, *parent, *grandpa; 02976 02977 xP = stack[stackN]; 02978 x = *xP; 02979 /* Work our way back up, re-balancing the tree. */ 02980 while (--stackN >= 0) { 02981 parentP = stack[stackN]; 02982 parent = *parentP; 02983 if (DD_IS_BLACK(parent)) break; 02984 /* Since the root is black, here a non-null grandparent exists. */ 02985 grandpaP = stack[stackN-1]; 02986 grandpa = *grandpaP; 02987 if (parent == DD_LEFT(grandpa)) { 02988 y = DD_RIGHT(grandpa); 02989 if (y != NULL && DD_IS_RED(y)) { 02990 DD_COLOR(parent) = DD_BLACK; 02991 DD_COLOR(y) = DD_BLACK; 02992 DD_COLOR(grandpa) = DD_RED; 02993 x = grandpa; 02994 stackN--; 02995 } else { 02996 if (x == DD_RIGHT(parent)) { 02997 cuddRotateLeft(parentP); 02998 DD_COLOR(x) = DD_BLACK; 02999 } else { 03000 DD_COLOR(parent) = DD_BLACK; 03001 } 03002 DD_COLOR(grandpa) = DD_RED; 03003 cuddRotateRight(grandpaP); 03004 break; 03005 } 03006 } else { 03007 y = DD_LEFT(grandpa); 03008 if (y != NULL && DD_IS_RED(y)) { 03009 DD_COLOR(parent) = DD_BLACK; 03010 DD_COLOR(y) = DD_BLACK; 03011 DD_COLOR(grandpa) = DD_RED; 03012 x = grandpa; 03013 stackN--; 03014 } else { 03015 if (x == DD_LEFT(parent)) { 03016 cuddRotateRight(parentP); 03017 DD_COLOR(x) = DD_BLACK; 03018 } else { 03019 DD_COLOR(parent) = DD_BLACK; 03020 } 03021 DD_COLOR(grandpa) = DD_RED; 03022 cuddRotateLeft(grandpaP); 03023 } 03024 } 03025 } 03026 DD_COLOR(*(stack[0])) = DD_BLACK; 03027 03028 } /* end of cuddDoRebalance */
Function********************************************************************
Synopsis [Searches the subtables above node for a parent.]
Description [Searches the subtables above node for a parent. Returns 1 as soon as one parent is found. Returns 0 is the search is fruitless.]
SideEffects [None]
SeeAlso []
Definition at line 2726 of file cuddTable.c.
02729 { 02730 int i,j; 02731 int slots; 02732 DdNodePtr *nodelist; 02733 DdNode *f; 02734 02735 for (i = cuddI(table,node->index) - 1; i >= 0; i--) { 02736 nodelist = table->subtables[i].nodelist; 02737 slots = table->subtables[i].slots; 02738 02739 for (j = 0; j < slots; j++) { 02740 f = nodelist[j]; 02741 while (cuddT(f) > node) { 02742 f = f->next; 02743 } 02744 while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) { 02745 f = f->next; 02746 } 02747 if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) { 02748 return(1); 02749 } 02750 } 02751 } 02752 02753 return(0); 02754 02755 } /* end of cuddFindParent */
void cuddFreeTable | ( | DdManager * | unique | ) |
Function********************************************************************
Synopsis [Frees the resources associated to a unique table.]
Description []
SideEffects [None]
SeeAlso [cuddInitTable]
Definition at line 551 of file cuddTable.c.
00553 { 00554 DdNodePtr *next; 00555 DdNodePtr *memlist = unique->memoryList; 00556 int i; 00557 00558 if (unique->univ != NULL) cuddZddFreeUniv(unique); 00559 while (memlist != NULL) { 00560 next = (DdNodePtr *) memlist[0]; /* link to next block */ 00561 FREE(memlist); 00562 memlist = next; 00563 } 00564 unique->nextFree = NULL; 00565 unique->memoryList = NULL; 00566 00567 for (i = 0; i < unique->size; i++) { 00568 FREE(unique->subtables[i].nodelist); 00569 } 00570 for (i = 0; i < unique->sizeZ; i++) { 00571 FREE(unique->subtableZ[i].nodelist); 00572 } 00573 FREE(unique->constants.nodelist); 00574 FREE(unique->subtables); 00575 FREE(unique->subtableZ); 00576 FREE(unique->acache); 00577 FREE(unique->perm); 00578 FREE(unique->permZ); 00579 FREE(unique->invperm); 00580 FREE(unique->invpermZ); 00581 FREE(unique->vars); 00582 if (unique->map != NULL) FREE(unique->map); 00583 FREE(unique->stack); 00584 #ifndef DD_NO_DEATH_ROW 00585 FREE(unique->deathRow); 00586 #endif 00587 if (unique->tree != NULL) Mtr_FreeTree(unique->tree); 00588 if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); 00589 if (unique->linear != NULL) FREE(unique->linear); 00590 while (unique->preGCHook != NULL) 00591 Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK); 00592 while (unique->postGCHook != NULL) 00593 Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK); 00594 while (unique->preReorderingHook != NULL) 00595 Cudd_RemoveHook(unique,unique->preReorderingHook->f, 00596 CUDD_PRE_REORDERING_HOOK); 00597 while (unique->postReorderingHook != NULL) 00598 Cudd_RemoveHook(unique,unique->postReorderingHook->f, 00599 CUDD_POST_REORDERING_HOOK); 00600 FREE(unique); 00601 00602 } /* end of cuddFreeTable */
int cuddGarbageCollect | ( | DdManager * | unique, | |
int | clearCache | |||
) |
Function********************************************************************
Synopsis [Performs garbage collection on a unique table.]
Description [Performs garbage collection on a unique table. If clearCache is 0, the cache is not cleared. This should only be specified if the cache has been cleared right before calling cuddGarbageCollect. (As in the case of dynamic reordering.) Returns the total number of deleted nodes.]
SideEffects [None]
SeeAlso [cuddGarbageCollectZdd]
Definition at line 621 of file cuddTable.c.
00624 { 00625 DdHook *hook; 00626 DdCache *cache = unique->cache; 00627 DdNode *sentinel = &(unique->sentinel); 00628 DdNodePtr *nodelist; 00629 int i, j, deleted, totalDeleted; 00630 DdCache *c; 00631 DdNode *node,*next; 00632 DdNodePtr *lastP; 00633 int slots; 00634 long localTime; 00635 #ifndef DD_UNSORTED_FREE_LIST 00636 DdNodePtr tree; 00637 #endif 00638 00639 #ifndef DD_NO_DEATH_ROW 00640 cuddClearDeathRow(unique); 00641 #endif 00642 00643 hook = unique->preGCHook; 00644 while (hook != NULL) { 00645 int res = (hook->f)(unique,"BDD",NULL); 00646 if (res == 0) return(0); 00647 hook = hook->next; 00648 } 00649 00650 if (unique->dead == 0) { 00651 hook = unique->postGCHook; 00652 while (hook != NULL) { 00653 int res = (hook->f)(unique,"BDD",NULL); 00654 if (res == 0) return(0); 00655 hook = hook->next; 00656 } 00657 return(0); 00658 } 00659 00660 /* If many nodes are being reclaimed, we want to resize the tables 00661 ** more aggressively, to reduce the frequency of garbage collection. 00662 */ 00663 if (clearCache && unique->gcFrac == DD_GC_FRAC_LO && 00664 unique->slots <= unique->looseUpTo && unique->stash != NULL) { 00665 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); 00666 #ifdef DD_VERBOSE 00667 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI); 00668 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 00669 #endif 00670 unique->gcFrac = DD_GC_FRAC_HI; 00671 return(0); 00672 } 00673 00674 localTime = util_cpu_time(); 00675 00676 unique->garbageCollections++; 00677 #ifdef DD_VERBOSE 00678 (void) fprintf(unique->err, 00679 "garbage collecting (%d dead out of %d, min %d)...", 00680 unique->dead, unique->keys, unique->minDead); 00681 #endif 00682 00683 /* Remove references to garbage collected nodes from the cache. */ 00684 if (clearCache) { 00685 slots = unique->cacheSlots; 00686 for (i = 0; i < slots; i++) { 00687 c = &cache[i]; 00688 if (c->data != NULL) { 00689 if (cuddClean(c->f)->ref == 0 || 00690 cuddClean(c->g)->ref == 0 || 00691 (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || 00692 (c->data != DD_NON_CONSTANT && 00693 Cudd_Regular(c->data)->ref == 0)) { 00694 c->data = NULL; 00695 unique->cachedeletions++; 00696 } 00697 } 00698 } 00699 cuddLocalCacheClearDead(unique); 00700 } 00701 00702 /* Now return dead nodes to free list. Count them for sanity check. */ 00703 totalDeleted = 0; 00704 #ifndef DD_UNSORTED_FREE_LIST 00705 tree = NULL; 00706 #endif 00707 00708 for (i = 0; i < unique->size; i++) { 00709 if (unique->subtables[i].dead == 0) continue; 00710 nodelist = unique->subtables[i].nodelist; 00711 00712 deleted = 0; 00713 slots = unique->subtables[i].slots; 00714 for (j = 0; j < slots; j++) { 00715 lastP = &(nodelist[j]); 00716 node = *lastP; 00717 while (node != sentinel) { 00718 next = node->next; 00719 if (node->ref == 0) { 00720 deleted++; 00721 #ifndef DD_UNSORTED_FREE_LIST 00722 #ifdef __osf__ 00723 #pragma pointer_size save 00724 #pragma pointer_size short 00725 #endif 00726 cuddOrderedInsert(&tree,node); 00727 #ifdef __osf__ 00728 #pragma pointer_size restore 00729 #endif 00730 #else 00731 cuddDeallocNode(unique,node); 00732 #endif 00733 } else { 00734 *lastP = node; 00735 lastP = &(node->next); 00736 } 00737 node = next; 00738 } 00739 *lastP = sentinel; 00740 } 00741 if ((unsigned) deleted != unique->subtables[i].dead) { 00742 ddReportRefMess(unique, i, "cuddGarbageCollect"); 00743 } 00744 totalDeleted += deleted; 00745 unique->subtables[i].keys -= deleted; 00746 unique->subtables[i].dead = 0; 00747 } 00748 if (unique->constants.dead != 0) { 00749 nodelist = unique->constants.nodelist; 00750 deleted = 0; 00751 slots = unique->constants.slots; 00752 for (j = 0; j < slots; j++) { 00753 lastP = &(nodelist[j]); 00754 node = *lastP; 00755 while (node != NULL) { 00756 next = node->next; 00757 if (node->ref == 0) { 00758 deleted++; 00759 #ifndef DD_UNSORTED_FREE_LIST 00760 #ifdef __osf__ 00761 #pragma pointer_size save 00762 #pragma pointer_size short 00763 #endif 00764 cuddOrderedInsert(&tree,node); 00765 #ifdef __osf__ 00766 #pragma pointer_size restore 00767 #endif 00768 #else 00769 cuddDeallocNode(unique,node); 00770 #endif 00771 } else { 00772 *lastP = node; 00773 lastP = &(node->next); 00774 } 00775 node = next; 00776 } 00777 *lastP = NULL; 00778 } 00779 if ((unsigned) deleted != unique->constants.dead) { 00780 ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect"); 00781 } 00782 totalDeleted += deleted; 00783 unique->constants.keys -= deleted; 00784 unique->constants.dead = 0; 00785 } 00786 if ((unsigned) totalDeleted != unique->dead) { 00787 ddReportRefMess(unique, -1, "cuddGarbageCollect"); 00788 } 00789 unique->keys -= totalDeleted; 00790 unique->dead = 0; 00791 #ifdef DD_STATS 00792 unique->nodesFreed += (double) totalDeleted; 00793 #endif 00794 00795 #ifndef DD_UNSORTED_FREE_LIST 00796 unique->nextFree = cuddOrderedThread(tree,unique->nextFree); 00797 #endif 00798 00799 unique->GCTime += util_cpu_time() - localTime; 00800 00801 hook = unique->postGCHook; 00802 while (hook != NULL) { 00803 int res = (hook->f)(unique,"BDD",NULL); 00804 if (res == 0) return(0); 00805 hook = hook->next; 00806 } 00807 00808 #ifdef DD_VERBOSE 00809 (void) fprintf(unique->err," done\n"); 00810 #endif 00811 00812 return(totalDeleted); 00813 00814 } /* end of cuddGarbageCollect */
int cuddGarbageCollectZdd | ( | DdManager * | unique, | |
int | clearCache | |||
) |
Function********************************************************************
Synopsis [Performs garbage collection on a ZDD unique table.]
Description [Performs garbage collection on a ZDD unique table. If clearCache is 0, the cache is not cleared. This should only be specified if the cache has been cleared right before calling cuddGarbageCollectZdd. (As in the case of dynamic reordering.) Returns the total number of deleted nodes.]
SideEffects [None]
SeeAlso [cuddGarbageCollect]
Definition at line 833 of file cuddTable.c.
00836 { 00837 DdHook *hook; 00838 DdCache *cache = unique->cache; 00839 DdNodePtr *nodelist; 00840 int i, j, deleted, totalDeleted; 00841 DdCache *c; 00842 DdNode *node,*next; 00843 DdNodePtr *lastP; 00844 int slots; 00845 long localTime; 00846 #ifndef DD_UNSORTED_FREE_LIST 00847 DdNodePtr tree; 00848 #endif 00849 00850 hook = unique->preGCHook; 00851 while (hook != NULL) { 00852 int res = (hook->f)(unique,"ZDD",NULL); 00853 if (res == 0) return(0); 00854 hook = hook->next; 00855 } 00856 00857 if (unique->deadZ == 0) { 00858 hook = unique->postGCHook; 00859 while (hook != NULL) { 00860 int res = (hook->f)(unique,"ZDD",NULL); 00861 if (res == 0) return(0); 00862 hook = hook->next; 00863 } 00864 return(0); 00865 } 00866 00867 /* If many nodes are being reclaimed, we want to resize the tables 00868 ** more aggressively, to reduce the frequency of garbage collection. 00869 */ 00870 if (clearCache && unique->slots <= unique->looseUpTo) { 00871 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); 00872 #ifdef DD_VERBOSE 00873 if (unique->gcFrac == DD_GC_FRAC_LO) { 00874 (void) fprintf(unique->err,"GC fraction = %.2f\t", 00875 DD_GC_FRAC_HI); 00876 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 00877 } 00878 #endif 00879 unique->gcFrac = DD_GC_FRAC_HI; 00880 } 00881 00882 localTime = util_cpu_time(); 00883 00884 unique->garbageCollections++; 00885 #ifdef DD_VERBOSE 00886 (void) fprintf(unique->err,"garbage collecting (%d dead out of %d)...", 00887 unique->deadZ,unique->keysZ); 00888 #endif 00889 00890 /* Remove references to garbage collected nodes from the cache. */ 00891 if (clearCache) { 00892 slots = unique->cacheSlots; 00893 for (i = 0; i < slots; i++) { 00894 c = &cache[i]; 00895 if (c->data != NULL) { 00896 if (cuddClean(c->f)->ref == 0 || 00897 cuddClean(c->g)->ref == 0 || 00898 (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || 00899 (c->data != DD_NON_CONSTANT && 00900 Cudd_Regular(c->data)->ref == 0)) { 00901 c->data = NULL; 00902 unique->cachedeletions++; 00903 } 00904 } 00905 } 00906 } 00907 00908 /* Now return dead nodes to free list. Count them for sanity check. */ 00909 totalDeleted = 0; 00910 #ifndef DD_UNSORTED_FREE_LIST 00911 tree = NULL; 00912 #endif 00913 00914 for (i = 0; i < unique->sizeZ; i++) { 00915 if (unique->subtableZ[i].dead == 0) continue; 00916 nodelist = unique->subtableZ[i].nodelist; 00917 00918 deleted = 0; 00919 slots = unique->subtableZ[i].slots; 00920 for (j = 0; j < slots; j++) { 00921 lastP = &(nodelist[j]); 00922 node = *lastP; 00923 while (node != NULL) { 00924 next = node->next; 00925 if (node->ref == 0) { 00926 deleted++; 00927 #ifndef DD_UNSORTED_FREE_LIST 00928 #ifdef __osf__ 00929 #pragma pointer_size save 00930 #pragma pointer_size short 00931 #endif 00932 cuddOrderedInsert(&tree,node); 00933 #ifdef __osf__ 00934 #pragma pointer_size restore 00935 #endif 00936 #else 00937 cuddDeallocNode(unique,node); 00938 #endif 00939 } else { 00940 *lastP = node; 00941 lastP = &(node->next); 00942 } 00943 node = next; 00944 } 00945 *lastP = NULL; 00946 } 00947 if ((unsigned) deleted != unique->subtableZ[i].dead) { 00948 ddReportRefMess(unique, i, "cuddGarbageCollectZdd"); 00949 } 00950 totalDeleted += deleted; 00951 unique->subtableZ[i].keys -= deleted; 00952 unique->subtableZ[i].dead = 0; 00953 } 00954 00955 /* No need to examine the constant table for ZDDs. 00956 ** If we did we should be careful not to count whatever dead 00957 ** nodes we found there among the dead ZDD nodes. */ 00958 if ((unsigned) totalDeleted != unique->deadZ) { 00959 ddReportRefMess(unique, -1, "cuddGarbageCollectZdd"); 00960 } 00961 unique->keysZ -= totalDeleted; 00962 unique->deadZ = 0; 00963 #ifdef DD_STATS 00964 unique->nodesFreed += (double) totalDeleted; 00965 #endif 00966 00967 #ifndef DD_UNSORTED_FREE_LIST 00968 unique->nextFree = cuddOrderedThread(tree,unique->nextFree); 00969 #endif 00970 00971 unique->GCTime += util_cpu_time() - localTime; 00972 00973 hook = unique->postGCHook; 00974 while (hook != NULL) { 00975 int res = (hook->f)(unique,"ZDD",NULL); 00976 if (res == 0) return(0); 00977 hook = hook->next; 00978 } 00979 00980 #ifdef DD_VERBOSE 00981 (void) fprintf(unique->err," done\n"); 00982 #endif 00983 00984 return(totalDeleted); 00985 00986 } /* end of cuddGarbageCollectZdd */
DdManager* cuddInitTable | ( | unsigned int | numVars, | |
unsigned int | numVarsZ, | |||
unsigned int | numSlots, | |||
unsigned int | looseUpTo | |||
) |
Function********************************************************************
Synopsis [Creates and initializes the unique table.]
Description [Creates and initializes the unique table. Returns a pointer to the table if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_Init cuddFreeTable]
Definition at line 307 of file cuddTable.c.
00312 { 00313 DdManager *unique = ALLOC(DdManager,1); 00314 int i, j; 00315 DdNodePtr *nodelist; 00316 DdNode *sentinel; 00317 unsigned int slots; 00318 int shift; 00319 00320 if (unique == NULL) { 00321 return(NULL); 00322 } 00323 sentinel = &(unique->sentinel); 00324 sentinel->ref = 0; 00325 sentinel->index = 0; 00326 cuddT(sentinel) = NULL; 00327 cuddE(sentinel) = NULL; 00328 sentinel->next = NULL; 00329 unique->epsilon = DD_EPSILON; 00330 unique->maxGrowth = DD_MAX_REORDER_GROWTH; 00331 unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH; 00332 unique->reordCycle = 0; /* do not use alternate threshold */ 00333 unique->size = numVars; 00334 unique->sizeZ = numVarsZ; 00335 unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars); 00336 unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ); 00337 00338 /* Adjust the requested number of slots to a power of 2. */ 00339 slots = 8; 00340 while (slots < numSlots) { 00341 slots <<= 1; 00342 } 00343 unique->initSlots = slots; 00344 shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots); 00345 00346 unique->slots = (numVars + numVarsZ + 1) * slots; 00347 unique->keys = 0; 00348 unique->maxLive = ~0; /* very large number */ 00349 unique->keysZ = 0; 00350 unique->dead = 0; 00351 unique->deadZ = 0; 00352 unique->gcFrac = DD_GC_FRAC_HI; 00353 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); 00354 unique->looseUpTo = looseUpTo; 00355 unique->gcEnabled = 1; 00356 unique->allocated = 0; 00357 unique->reclaimed = 0; 00358 unique->subtables = ALLOC(DdSubtable,unique->maxSize); 00359 if (unique->subtables == NULL) { 00360 unique->errorCode = CUDD_MEMORY_OUT; 00361 return(0); 00362 } 00363 unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ); 00364 if (unique->subtableZ == NULL) { 00365 unique->errorCode = CUDD_MEMORY_OUT; 00366 return(0); 00367 } 00368 unique->perm = ALLOC(int,unique->maxSize); 00369 if (unique->perm == NULL) { 00370 unique->errorCode = CUDD_MEMORY_OUT; 00371 return(0); 00372 } 00373 unique->invperm = ALLOC(int,unique->maxSize); 00374 if (unique->invperm == NULL) { 00375 unique->errorCode = CUDD_MEMORY_OUT; 00376 return(0); 00377 } 00378 unique->permZ = ALLOC(int,unique->maxSizeZ); 00379 if (unique->permZ == NULL) { 00380 unique->errorCode = CUDD_MEMORY_OUT; 00381 return(0); 00382 } 00383 unique->invpermZ = ALLOC(int,unique->maxSizeZ); 00384 if (unique->invpermZ == NULL) { 00385 unique->errorCode = CUDD_MEMORY_OUT; 00386 return(0); 00387 } 00388 unique->map = NULL; 00389 unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); 00390 if (unique->stack == NULL) { 00391 unique->errorCode = CUDD_MEMORY_OUT; 00392 return(0); 00393 } 00394 unique->stack[0] = NULL; /* to suppress harmless UMR */ 00395 00396 #ifndef DD_NO_DEATH_ROW 00397 unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2); 00398 unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth); 00399 if (unique->deathRow == NULL) { 00400 unique->errorCode = CUDD_MEMORY_OUT; 00401 return(0); 00402 } 00403 for (i = 0; i < unique->deathRowDepth; i++) { 00404 unique->deathRow[i] = NULL; 00405 } 00406 unique->nextDead = 0; 00407 unique->deadMask = unique->deathRowDepth - 1; 00408 #endif 00409 00410 for (i = 0; (unsigned) i < numVars; i++) { 00411 unique->subtables[i].slots = slots; 00412 unique->subtables[i].shift = shift; 00413 unique->subtables[i].keys = 0; 00414 unique->subtables[i].dead = 0; 00415 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00416 unique->subtables[i].bindVar = 0; 00417 unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 00418 unique->subtables[i].pairIndex = 0; 00419 unique->subtables[i].varHandled = 0; 00420 unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; 00421 00422 nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots); 00423 if (nodelist == NULL) { 00424 unique->errorCode = CUDD_MEMORY_OUT; 00425 return(NULL); 00426 } 00427 for (j = 0; (unsigned) j < slots; j++) { 00428 nodelist[j] = sentinel; 00429 } 00430 unique->perm[i] = i; 00431 unique->invperm[i] = i; 00432 } 00433 for (i = 0; (unsigned) i < numVarsZ; i++) { 00434 unique->subtableZ[i].slots = slots; 00435 unique->subtableZ[i].shift = shift; 00436 unique->subtableZ[i].keys = 0; 00437 unique->subtableZ[i].dead = 0; 00438 unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00439 nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots); 00440 if (nodelist == NULL) { 00441 unique->errorCode = CUDD_MEMORY_OUT; 00442 return(NULL); 00443 } 00444 for (j = 0; (unsigned) j < slots; j++) { 00445 nodelist[j] = NULL; 00446 } 00447 unique->permZ[i] = i; 00448 unique->invpermZ[i] = i; 00449 } 00450 unique->constants.slots = slots; 00451 unique->constants.shift = shift; 00452 unique->constants.keys = 0; 00453 unique->constants.dead = 0; 00454 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00455 nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots); 00456 if (nodelist == NULL) { 00457 unique->errorCode = CUDD_MEMORY_OUT; 00458 return(NULL); 00459 } 00460 for (j = 0; (unsigned) j < slots; j++) { 00461 nodelist[j] = NULL; 00462 } 00463 00464 unique->memoryList = NULL; 00465 unique->nextFree = NULL; 00466 00467 unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ) 00468 * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) * 00469 slots * sizeof(DdNodePtr) + 00470 (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr); 00471 #ifndef DD_NO_DEATH_ROW 00472 unique->memused += unique->deathRowDepth * sizeof(DdNodePtr); 00473 #endif 00474 00475 /* Initialize fields concerned with automatic dynamic reordering */ 00476 unique->reorderings = 0; 00477 unique->autoDyn = 0; /* initially disabled */ 00478 unique->autoDynZ = 0; /* initially disabled */ 00479 unique->realign = 0; /* initially disabled */ 00480 unique->realignZ = 0; /* initially disabled */ 00481 unique->reordered = 0; 00482 unique->autoMethod = CUDD_REORDER_SIFT; 00483 unique->autoMethodZ = CUDD_REORDER_SIFT; 00484 unique->nextDyn = DD_FIRST_REORDER; 00485 unique->countDead = ~0; 00486 unique->siftMaxVar = DD_SIFT_MAX_VAR; 00487 unique->siftMaxSwap = DD_SIFT_MAX_SWAPS; 00488 unique->tree = NULL; 00489 unique->treeZ = NULL; 00490 unique->groupcheck = CUDD_GROUP_CHECK7; 00491 unique->recomb = DD_DEFAULT_RECOMB; 00492 unique->symmviolation = 0; 00493 unique->arcviolation = 0; 00494 unique->populationSize = 0; 00495 unique->numberXovers = 0; 00496 unique->linear = NULL; 00497 unique->linearSize = 0; 00498 00499 /* Initialize ZDD universe. */ 00500 unique->univ = (DdNodePtr *)NULL; 00501 00502 /* Initialize auxiliary fields. */ 00503 unique->localCaches = NULL; 00504 unique->preGCHook = NULL; 00505 unique->postGCHook = NULL; 00506 unique->preReorderingHook = NULL; 00507 unique->postReorderingHook = NULL; 00508 unique->out = stdout; 00509 unique->err = stderr; 00510 unique->errorCode = CUDD_NO_ERROR; 00511 00512 /* Initialize statistical counters. */ 00513 unique->maxmemhard = (long) ((~ (unsigned long) 0) >> 1); 00514 unique->garbageCollections = 0; 00515 unique->GCTime = 0; 00516 unique->reordTime = 0; 00517 #ifdef DD_STATS 00518 unique->nodesDropped = 0; 00519 unique->nodesFreed = 0; 00520 #endif 00521 unique->peakLiveNodes = 0; 00522 #ifdef DD_UNIQUE_PROFILE 00523 unique->uniqueLookUps = 0; 00524 unique->uniqueLinks = 0; 00525 #endif 00526 #ifdef DD_COUNT 00527 unique->recursiveCalls = 0; 00528 unique->swapSteps = 0; 00529 #ifdef DD_STATS 00530 unique->nextSample = 250000; 00531 #endif 00532 #endif 00533 00534 return(unique); 00535 00536 } /* end of cuddInitTable */
int cuddInsertSubtables | ( | DdManager * | unique, | |
int | n, | |||
int | level | |||
) |
Function********************************************************************
Synopsis [Inserts n new subtables in a unique table at level.]
Description [Inserts n new subtables in a unique table at level. The number n should be positive, and level should be an existing level. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddDestroySubtables]
Definition at line 1759 of file cuddTable.c.
01763 { 01764 DdSubtable *newsubtables; 01765 DdNodePtr *newnodelist; 01766 DdNodePtr *newvars; 01767 DdNode *sentinel = &(unique->sentinel); 01768 int oldsize,newsize; 01769 int i,j,index,reorderSave; 01770 unsigned int numSlots = unique->initSlots; 01771 int *newperm, *newinvperm, *newmap; 01772 DdNode *one, *zero; 01773 01774 #ifdef DD_DEBUG 01775 assert(n > 0 && level < unique->size); 01776 #endif 01777 01778 oldsize = unique->size; 01779 /* Easy case: there is still room in the current table. */ 01780 if (oldsize + n <= unique->maxSize) { 01781 /* Shift the tables at and below level. */ 01782 for (i = oldsize - 1; i >= level; i--) { 01783 unique->subtables[i+n].slots = unique->subtables[i].slots; 01784 unique->subtables[i+n].shift = unique->subtables[i].shift; 01785 unique->subtables[i+n].keys = unique->subtables[i].keys; 01786 unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys; 01787 unique->subtables[i+n].dead = unique->subtables[i].dead; 01788 unique->subtables[i+n].nodelist = unique->subtables[i].nodelist; 01789 unique->subtables[i+n].bindVar = unique->subtables[i].bindVar; 01790 unique->subtables[i+n].varType = unique->subtables[i].varType; 01791 unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex; 01792 unique->subtables[i+n].varHandled = unique->subtables[i].varHandled; 01793 unique->subtables[i+n].varToBeGrouped = 01794 unique->subtables[i].varToBeGrouped; 01795 01796 index = unique->invperm[i]; 01797 unique->invperm[i+n] = index; 01798 unique->perm[index] += n; 01799 } 01800 /* Create new subtables. */ 01801 for (i = 0; i < n; i++) { 01802 unique->subtables[level+i].slots = numSlots; 01803 unique->subtables[level+i].shift = sizeof(int) * 8 - 01804 cuddComputeFloorLog2(numSlots); 01805 unique->subtables[level+i].keys = 0; 01806 unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 01807 unique->subtables[level+i].dead = 0; 01808 unique->subtables[level+i].bindVar = 0; 01809 unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT; 01810 unique->subtables[level+i].pairIndex = 0; 01811 unique->subtables[level+i].varHandled = 0; 01812 unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE; 01813 01814 unique->perm[oldsize+i] = level + i; 01815 unique->invperm[level+i] = oldsize + i; 01816 newnodelist = unique->subtables[level+i].nodelist = 01817 ALLOC(DdNodePtr, numSlots); 01818 if (newnodelist == NULL) { 01819 unique->errorCode = CUDD_MEMORY_OUT; 01820 return(0); 01821 } 01822 for (j = 0; j < numSlots; j++) { 01823 newnodelist[j] = sentinel; 01824 } 01825 } 01826 if (unique->map != NULL) { 01827 for (i = 0; i < n; i++) { 01828 unique->map[oldsize+i] = oldsize + i; 01829 } 01830 } 01831 } else { 01832 /* The current table is too small: we need to allocate a new, 01833 ** larger one; move all old subtables, and initialize the new 01834 ** subtables. 01835 */ 01836 newsize = oldsize + n + DD_DEFAULT_RESIZE; 01837 #ifdef DD_VERBOSE 01838 (void) fprintf(unique->err, 01839 "Increasing the table size from %d to %d\n", 01840 unique->maxSize, newsize); 01841 #endif 01842 /* Allocate memory for new arrays (except nodelists). */ 01843 newsubtables = ALLOC(DdSubtable,newsize); 01844 if (newsubtables == NULL) { 01845 unique->errorCode = CUDD_MEMORY_OUT; 01846 return(0); 01847 } 01848 newvars = ALLOC(DdNodePtr,newsize); 01849 if (newvars == NULL) { 01850 unique->errorCode = CUDD_MEMORY_OUT; 01851 FREE(newsubtables); 01852 return(0); 01853 } 01854 newperm = ALLOC(int,newsize); 01855 if (newperm == NULL) { 01856 unique->errorCode = CUDD_MEMORY_OUT; 01857 FREE(newsubtables); 01858 FREE(newvars); 01859 return(0); 01860 } 01861 newinvperm = ALLOC(int,newsize); 01862 if (newinvperm == NULL) { 01863 unique->errorCode = CUDD_MEMORY_OUT; 01864 FREE(newsubtables); 01865 FREE(newvars); 01866 FREE(newperm); 01867 return(0); 01868 } 01869 if (unique->map != NULL) { 01870 newmap = ALLOC(int,newsize); 01871 if (newmap == NULL) { 01872 unique->errorCode = CUDD_MEMORY_OUT; 01873 FREE(newsubtables); 01874 FREE(newvars); 01875 FREE(newperm); 01876 FREE(newinvperm); 01877 return(0); 01878 } 01879 unique->memused += (newsize - unique->maxSize) * sizeof(int); 01880 } 01881 unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * 01882 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 01883 /* Copy levels before insertion points from old tables. */ 01884 for (i = 0; i < level; i++) { 01885 newsubtables[i].slots = unique->subtables[i].slots; 01886 newsubtables[i].shift = unique->subtables[i].shift; 01887 newsubtables[i].keys = unique->subtables[i].keys; 01888 newsubtables[i].maxKeys = unique->subtables[i].maxKeys; 01889 newsubtables[i].dead = unique->subtables[i].dead; 01890 newsubtables[i].nodelist = unique->subtables[i].nodelist; 01891 newsubtables[i].bindVar = unique->subtables[i].bindVar; 01892 newsubtables[i].varType = unique->subtables[i].varType; 01893 newsubtables[i].pairIndex = unique->subtables[i].pairIndex; 01894 newsubtables[i].varHandled = unique->subtables[i].varHandled; 01895 newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; 01896 01897 newvars[i] = unique->vars[i]; 01898 newperm[i] = unique->perm[i]; 01899 newinvperm[i] = unique->invperm[i]; 01900 } 01901 /* Finish initializing permutation for new table to old one. */ 01902 for (i = level; i < oldsize; i++) { 01903 newperm[i] = unique->perm[i]; 01904 } 01905 /* Initialize new levels. */ 01906 for (i = level; i < level + n; i++) { 01907 newsubtables[i].slots = numSlots; 01908 newsubtables[i].shift = sizeof(int) * 8 - 01909 cuddComputeFloorLog2(numSlots); 01910 newsubtables[i].keys = 0; 01911 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 01912 newsubtables[i].dead = 0; 01913 newsubtables[i].bindVar = 0; 01914 newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 01915 newsubtables[i].pairIndex = 0; 01916 newsubtables[i].varHandled = 0; 01917 newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; 01918 01919 newperm[oldsize + i - level] = i; 01920 newinvperm[i] = oldsize + i - level; 01921 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 01922 if (newnodelist == NULL) { 01923 /* We are going to leak some memory. We should clean up. */ 01924 unique->errorCode = CUDD_MEMORY_OUT; 01925 return(0); 01926 } 01927 for (j = 0; j < numSlots; j++) { 01928 newnodelist[j] = sentinel; 01929 } 01930 } 01931 /* Copy the old tables for levels past the insertion point. */ 01932 for (i = level; i < oldsize; i++) { 01933 newsubtables[i+n].slots = unique->subtables[i].slots; 01934 newsubtables[i+n].shift = unique->subtables[i].shift; 01935 newsubtables[i+n].keys = unique->subtables[i].keys; 01936 newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys; 01937 newsubtables[i+n].dead = unique->subtables[i].dead; 01938 newsubtables[i+n].nodelist = unique->subtables[i].nodelist; 01939 newsubtables[i+n].bindVar = unique->subtables[i].bindVar; 01940 newsubtables[i+n].varType = unique->subtables[i].varType; 01941 newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex; 01942 newsubtables[i+n].varHandled = unique->subtables[i].varHandled; 01943 newsubtables[i+n].varToBeGrouped = 01944 unique->subtables[i].varToBeGrouped; 01945 01946 newvars[i] = unique->vars[i]; 01947 index = unique->invperm[i]; 01948 newinvperm[i+n] = index; 01949 newperm[index] += n; 01950 } 01951 /* Update the map. */ 01952 if (unique->map != NULL) { 01953 for (i = 0; i < oldsize; i++) { 01954 newmap[i] = unique->map[i]; 01955 } 01956 for (i = oldsize; i < oldsize + n; i++) { 01957 newmap[i] = i; 01958 } 01959 FREE(unique->map); 01960 unique->map = newmap; 01961 } 01962 /* Install the new tables and free the old ones. */ 01963 FREE(unique->subtables); 01964 unique->subtables = newsubtables; 01965 unique->maxSize = newsize; 01966 FREE(unique->vars); 01967 unique->vars = newvars; 01968 FREE(unique->perm); 01969 unique->perm = newperm; 01970 FREE(unique->invperm); 01971 unique->invperm = newinvperm; 01972 /* Update the stack for iterative procedures. */ 01973 if (newsize > unique->maxSizeZ) { 01974 FREE(unique->stack); 01975 unique->stack = ALLOC(DdNodePtr,newsize + 1); 01976 if (unique->stack == NULL) { 01977 unique->errorCode = CUDD_MEMORY_OUT; 01978 return(0); 01979 } 01980 unique->stack[0] = NULL; /* to suppress harmless UMR */ 01981 unique->memused += 01982 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 01983 * sizeof(DdNode *); 01984 } 01985 } 01986 /* Update manager parameters to account for the new subtables. */ 01987 unique->slots += n * numSlots; 01988 ddFixLimits(unique); 01989 unique->size += n; 01990 01991 /* Now that the table is in a coherent state, create the new 01992 ** projection functions. We need to temporarily disable reordering, 01993 ** because we cannot reorder without projection functions in place. 01994 **/ 01995 one = unique->one; 01996 zero = Cudd_Not(one); 01997 01998 reorderSave = unique->autoDyn; 01999 unique->autoDyn = 0; 02000 for (i = oldsize; i < oldsize + n; i++) { 02001 unique->vars[i] = cuddUniqueInter(unique,i,one,zero); 02002 if (unique->vars[i] == NULL) { 02003 unique->autoDyn = reorderSave; 02004 /* Shift everything back so table remains coherent. */ 02005 for (j = oldsize; j < i; j++) { 02006 Cudd_IterDerefBdd(unique,unique->vars[j]); 02007 cuddDeallocNode(unique,unique->vars[j]); 02008 unique->vars[j] = NULL; 02009 } 02010 for (j = level; j < oldsize; j++) { 02011 unique->subtables[j].slots = unique->subtables[j+n].slots; 02012 unique->subtables[j].slots = unique->subtables[j+n].slots; 02013 unique->subtables[j].shift = unique->subtables[j+n].shift; 02014 unique->subtables[j].keys = unique->subtables[j+n].keys; 02015 unique->subtables[j].maxKeys = 02016 unique->subtables[j+n].maxKeys; 02017 unique->subtables[j].dead = unique->subtables[j+n].dead; 02018 FREE(unique->subtables[j].nodelist); 02019 unique->subtables[j].nodelist = 02020 unique->subtables[j+n].nodelist; 02021 unique->subtables[j+n].nodelist = NULL; 02022 unique->subtables[j].bindVar = 02023 unique->subtables[j+n].bindVar; 02024 unique->subtables[j].varType = 02025 unique->subtables[j+n].varType; 02026 unique->subtables[j].pairIndex = 02027 unique->subtables[j+n].pairIndex; 02028 unique->subtables[j].varHandled = 02029 unique->subtables[j+n].varHandled; 02030 unique->subtables[j].varToBeGrouped = 02031 unique->subtables[j+n].varToBeGrouped; 02032 index = unique->invperm[j+n]; 02033 unique->invperm[j] = index; 02034 unique->perm[index] -= n; 02035 } 02036 unique->size = oldsize; 02037 unique->slots -= n * numSlots; 02038 ddFixLimits(unique); 02039 (void) Cudd_DebugCheck(unique); 02040 return(0); 02041 } 02042 cuddRef(unique->vars[i]); 02043 } 02044 if (unique->tree != NULL) { 02045 unique->tree->size += n; 02046 unique->tree->index = unique->invperm[0]; 02047 ddPatchTree(unique,unique->tree); 02048 } 02049 unique->autoDyn = reorderSave; 02050 02051 return(1); 02052 02053 } /* end of cuddInsertSubtables */
Function********************************************************************
Synopsis [Inserts a DdNode in a red/black search tree.]
Description [Inserts a DdNode in a red/black search tree. Nodes from the same "page" (defined by DD_PAGE_MASK) are linked in a LIFO list.]
SideEffects [None]
SeeAlso [cuddOrderedThread]
Definition at line 2801 of file cuddTable.c.
02804 { 02805 DdNode *scan; 02806 DdNodePtr *scanP; 02807 DdNodePtr *stack[DD_STACK_SIZE]; 02808 int stackN = 0; 02809 02810 scanP = root; 02811 while ((scan = *scanP) != NULL) { 02812 stack[stackN++] = scanP; 02813 if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */ 02814 DD_NEXT(node) = DD_NEXT(scan); 02815 DD_NEXT(scan) = node; 02816 return; 02817 } 02818 scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan); 02819 } 02820 DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL; 02821 DD_COLOR(node) = DD_RED; 02822 *scanP = node; 02823 stack[stackN] = &node; 02824 cuddDoRebalance(stack,stackN); 02825 02826 } /* end of cuddOrderedInsert */
Function********************************************************************
Synopsis [Threads all the nodes of a search tree into a linear list.]
Description [Threads all the nodes of a search tree into a linear list. For each node of the search tree, the "left" child, if non-null, has a lower address than its parent, and the "right" child, if non-null, has a higher address than its parent. The list is sorted in order of increasing addresses. The search tree is destroyed as a result of this operation. The last element of the linear list is made to point to the address passed in list. Each node if the search tree is a linearly-linked list of nodes from the same memory page (as defined in DD_PAGE_MASK). When a node is added to the linear list, all the elements of the linked list are added.]
SideEffects [The search tree is destroyed as a result of this operation.]
SeeAlso [cuddOrderedInsert]
Definition at line 2850 of file cuddTable.c.
02853 { 02854 DdNode *current, *next, *prev, *end; 02855 02856 current = root; 02857 /* The first word in the node is used to implement a stack that holds 02858 ** the nodes from the root of the tree to the current node. Here we 02859 ** put the root of the tree at the bottom of the stack. 02860 */ 02861 *((DdNodePtr *) current) = NULL; 02862 02863 while (current != NULL) { 02864 if (DD_RIGHT(current) != NULL) { 02865 /* If possible, we follow the "right" link. Eventually we'll 02866 ** find the node with the largest address in the current tree. 02867 ** In this phase we use the first word of a node to implemen 02868 ** a stack of the nodes on the path from the root to "current". 02869 ** Also, we disconnect the "right" pointers to indicate that 02870 ** we have already followed them. 02871 */ 02872 next = DD_RIGHT(current); 02873 DD_RIGHT(current) = NULL; 02874 *((DdNodePtr *)next) = current; 02875 current = next; 02876 } else { 02877 /* We can't proceed along the "right" links any further. 02878 ** Hence "current" is the largest element in the current tree. 02879 ** We make this node the new head of "list". (Repeating this 02880 ** operation until the tree is empty yields the desired linear 02881 ** threading of all nodes.) 02882 */ 02883 prev = *((DdNodePtr *) current); /* save prev node on stack in prev */ 02884 /* Traverse the linked list of current until the end. */ 02885 for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end)); 02886 DD_NEXT(end) = list; /* attach "list" at end and make */ 02887 list = current; /* "current" the new head of "list" */ 02888 /* Now, if current has a "left" child, we push it on the stack. 02889 ** Otherwise, we just continue with the parent of "current". 02890 */ 02891 if (DD_LEFT(current) != NULL) { 02892 next = DD_LEFT(current); 02893 *((DdNodePtr *) next) = prev; 02894 current = next; 02895 } else { 02896 current = prev; 02897 } 02898 } 02899 } 02900 02901 return(list); 02902 02903 } /* end of cuddOrderedThread */
void cuddRehash | ( | DdManager * | unique, | |
int | i | |||
) |
Function********************************************************************
Synopsis [Rehashes a unique subtable.]
Description [Doubles the size of a unique subtable and rehashes its contents.]
SideEffects [None]
SeeAlso []
Definition at line 1493 of file cuddTable.c.
01496 { 01497 unsigned int slots, oldslots; 01498 int shift, oldshift; 01499 int j, pos; 01500 DdNodePtr *nodelist, *oldnodelist; 01501 DdNode *node, *next; 01502 DdNode *sentinel = &(unique->sentinel); 01503 hack split; 01504 extern void (*MMoutOfMemory)(long); 01505 void (*saveHandler)(long); 01506 01507 if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) { 01508 unique->gcFrac = DD_GC_FRAC_LO; 01509 unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); 01510 #ifdef DD_VERBOSE 01511 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); 01512 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 01513 #endif 01514 } 01515 01516 if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) { 01517 unique->gcFrac = DD_GC_FRAC_MIN; 01518 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); 01519 #ifdef DD_VERBOSE 01520 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN); 01521 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 01522 #endif 01523 cuddShrinkDeathRow(unique); 01524 if (cuddGarbageCollect(unique,1) > 0) return; 01525 } 01526 01527 if (i != CUDD_CONST_INDEX) { 01528 oldslots = unique->subtables[i].slots; 01529 oldshift = unique->subtables[i].shift; 01530 oldnodelist = unique->subtables[i].nodelist; 01531 01532 /* Compute the new size of the subtable. */ 01533 slots = oldslots << 1; 01534 shift = oldshift - 1; 01535 01536 saveHandler = MMoutOfMemory; 01537 MMoutOfMemory = Cudd_OutOfMem; 01538 nodelist = ALLOC(DdNodePtr, slots); 01539 MMoutOfMemory = saveHandler; 01540 if (nodelist == NULL) { 01541 (void) fprintf(unique->err, 01542 "Unable to resize subtable %d for lack of memory\n", 01543 i); 01544 /* Prevent frequent resizing attempts. */ 01545 (void) cuddGarbageCollect(unique,1); 01546 if (unique->stash != NULL) { 01547 FREE(unique->stash); 01548 unique->stash = NULL; 01549 /* Inhibit resizing of tables. */ 01550 cuddSlowTableGrowth(unique); 01551 } 01552 return; 01553 } 01554 unique->subtables[i].nodelist = nodelist; 01555 unique->subtables[i].slots = slots; 01556 unique->subtables[i].shift = shift; 01557 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01558 01559 /* Move the nodes from the old table to the new table. 01560 ** This code depends on the type of hash function. 01561 ** It assumes that the effect of doubling the size of the table 01562 ** is to retain one more bit of the 32-bit hash value. 01563 ** The additional bit is the LSB. */ 01564 for (j = 0; (unsigned) j < oldslots; j++) { 01565 DdNodePtr *evenP, *oddP; 01566 node = oldnodelist[j]; 01567 evenP = &(nodelist[j<<1]); 01568 oddP = &(nodelist[(j<<1)+1]); 01569 while (node != sentinel) { 01570 next = node->next; 01571 pos = ddHash(cuddT(node), cuddE(node), shift); 01572 if (pos & 1) { 01573 *oddP = node; 01574 oddP = &(node->next); 01575 } else { 01576 *evenP = node; 01577 evenP = &(node->next); 01578 } 01579 node = next; 01580 } 01581 *evenP = *oddP = sentinel; 01582 } 01583 FREE(oldnodelist); 01584 01585 #ifdef DD_VERBOSE 01586 (void) fprintf(unique->err, 01587 "rehashing layer %d: keys %d dead %d new size %d\n", 01588 i, unique->subtables[i].keys, 01589 unique->subtables[i].dead, slots); 01590 #endif 01591 } else { 01592 oldslots = unique->constants.slots; 01593 oldshift = unique->constants.shift; 01594 oldnodelist = unique->constants.nodelist; 01595 01596 /* The constant subtable is never subjected to reordering. 01597 ** Therefore, when it is resized, it is because it has just 01598 ** reached the maximum load. We can safely just double the size, 01599 ** with no need for the loop we use for the other tables. 01600 */ 01601 slots = oldslots << 1; 01602 shift = oldshift - 1; 01603 saveHandler = MMoutOfMemory; 01604 MMoutOfMemory = Cudd_OutOfMem; 01605 nodelist = ALLOC(DdNodePtr, slots); 01606 MMoutOfMemory = saveHandler; 01607 if (nodelist == NULL) { 01608 int j; 01609 (void) fprintf(unique->err, 01610 "Unable to resize constant subtable for lack of memory\n"); 01611 (void) cuddGarbageCollect(unique,1); 01612 for (j = 0; j < unique->size; j++) { 01613 unique->subtables[j].maxKeys <<= 1; 01614 } 01615 unique->constants.maxKeys <<= 1; 01616 return; 01617 } 01618 unique->constants.slots = slots; 01619 unique->constants.shift = shift; 01620 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01621 unique->constants.nodelist = nodelist; 01622 for (j = 0; (unsigned) j < slots; j++) { 01623 nodelist[j] = NULL; 01624 } 01625 for (j = 0; (unsigned) j < oldslots; j++) { 01626 node = oldnodelist[j]; 01627 while (node != NULL) { 01628 next = node->next; 01629 split.value = cuddV(node); 01630 pos = ddHash(split.bits[0], split.bits[1], shift); 01631 node->next = nodelist[pos]; 01632 nodelist[pos] = node; 01633 node = next; 01634 } 01635 } 01636 FREE(oldnodelist); 01637 01638 #ifdef DD_VERBOSE 01639 (void) fprintf(unique->err, 01640 "rehashing constants: keys %d dead %d new size %d\n", 01641 unique->constants.keys,unique->constants.dead,slots); 01642 #endif 01643 } 01644 01645 /* Update global data */ 01646 01647 unique->memused += (slots - oldslots) * sizeof(DdNodePtr); 01648 unique->slots += (slots - oldslots); 01649 ddFixLimits(unique); 01650 01651 } /* end of cuddRehash */
int cuddResizeTableZdd | ( | DdManager * | unique, | |
int | index | |||
) |
Function********************************************************************
Synopsis [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index.]
Description [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index. When new ZDD variables are created, it is possible to preserve the functions unchanged, or it is possible to preserve the covers unchanged, but not both. cuddResizeTableZdd preserves the covers. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [ddResizeTable]
Definition at line 2205 of file cuddTable.c.
02208 { 02209 DdSubtable *newsubtables; 02210 DdNodePtr *newnodelist; 02211 int oldsize,newsize; 02212 int i,j,reorderSave; 02213 unsigned int numSlots = unique->initSlots; 02214 int *newperm, *newinvperm; 02215 DdNode *one, *zero; 02216 02217 oldsize = unique->sizeZ; 02218 /* Easy case: there is still room in the current table. */ 02219 if (index < unique->maxSizeZ) { 02220 for (i = oldsize; i <= index; i++) { 02221 unique->subtableZ[i].slots = numSlots; 02222 unique->subtableZ[i].shift = sizeof(int) * 8 - 02223 cuddComputeFloorLog2(numSlots); 02224 unique->subtableZ[i].keys = 0; 02225 unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02226 unique->subtableZ[i].dead = 0; 02227 unique->permZ[i] = i; 02228 unique->invpermZ[i] = i; 02229 newnodelist = unique->subtableZ[i].nodelist = 02230 ALLOC(DdNodePtr, numSlots); 02231 if (newnodelist == NULL) { 02232 unique->errorCode = CUDD_MEMORY_OUT; 02233 return(0); 02234 } 02235 for (j = 0; j < numSlots; j++) { 02236 newnodelist[j] = NULL; 02237 } 02238 } 02239 } else { 02240 /* The current table is too small: we need to allocate a new, 02241 ** larger one; move all old subtables, and initialize the new 02242 ** subtables up to index included. 02243 */ 02244 newsize = index + DD_DEFAULT_RESIZE; 02245 #ifdef DD_VERBOSE 02246 (void) fprintf(unique->err, 02247 "Increasing the ZDD table size from %d to %d\n", 02248 unique->maxSizeZ, newsize); 02249 #endif 02250 newsubtables = ALLOC(DdSubtable,newsize); 02251 if (newsubtables == NULL) { 02252 unique->errorCode = CUDD_MEMORY_OUT; 02253 return(0); 02254 } 02255 newperm = ALLOC(int,newsize); 02256 if (newperm == NULL) { 02257 unique->errorCode = CUDD_MEMORY_OUT; 02258 return(0); 02259 } 02260 newinvperm = ALLOC(int,newsize); 02261 if (newinvperm == NULL) { 02262 unique->errorCode = CUDD_MEMORY_OUT; 02263 return(0); 02264 } 02265 unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) * 02266 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 02267 if (newsize > unique->maxSize) { 02268 FREE(unique->stack); 02269 unique->stack = ALLOC(DdNodePtr,newsize + 1); 02270 if (unique->stack == NULL) { 02271 unique->errorCode = CUDD_MEMORY_OUT; 02272 return(0); 02273 } 02274 unique->stack[0] = NULL; /* to suppress harmless UMR */ 02275 unique->memused += 02276 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 02277 * sizeof(DdNode *); 02278 } 02279 for (i = 0; i < oldsize; i++) { 02280 newsubtables[i].slots = unique->subtableZ[i].slots; 02281 newsubtables[i].shift = unique->subtableZ[i].shift; 02282 newsubtables[i].keys = unique->subtableZ[i].keys; 02283 newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys; 02284 newsubtables[i].dead = unique->subtableZ[i].dead; 02285 newsubtables[i].nodelist = unique->subtableZ[i].nodelist; 02286 newperm[i] = unique->permZ[i]; 02287 newinvperm[i] = unique->invpermZ[i]; 02288 } 02289 for (i = oldsize; i <= index; i++) { 02290 newsubtables[i].slots = numSlots; 02291 newsubtables[i].shift = sizeof(int) * 8 - 02292 cuddComputeFloorLog2(numSlots); 02293 newsubtables[i].keys = 0; 02294 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02295 newsubtables[i].dead = 0; 02296 newperm[i] = i; 02297 newinvperm[i] = i; 02298 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 02299 if (newnodelist == NULL) { 02300 unique->errorCode = CUDD_MEMORY_OUT; 02301 return(0); 02302 } 02303 for (j = 0; j < numSlots; j++) { 02304 newnodelist[j] = NULL; 02305 } 02306 } 02307 FREE(unique->subtableZ); 02308 unique->subtableZ = newsubtables; 02309 unique->maxSizeZ = newsize; 02310 FREE(unique->permZ); 02311 unique->permZ = newperm; 02312 FREE(unique->invpermZ); 02313 unique->invpermZ = newinvperm; 02314 } 02315 unique->slots += (index + 1 - unique->sizeZ) * numSlots; 02316 ddFixLimits(unique); 02317 unique->sizeZ = index + 1; 02318 02319 /* Now that the table is in a coherent state, update the ZDD 02320 ** universe. We need to temporarily disable reordering, 02321 ** because we cannot reorder without universe in place. 02322 */ 02323 one = unique->one; 02324 zero = unique->zero; 02325 02326 reorderSave = unique->autoDynZ; 02327 unique->autoDynZ = 0; 02328 cuddZddFreeUniv(unique); 02329 if (!cuddZddInitUniv(unique)) { 02330 unique->autoDynZ = reorderSave; 02331 return(0); 02332 } 02333 unique->autoDynZ = reorderSave; 02334 02335 return(1); 02336 02337 } /* end of cuddResizeTableZdd */
static DD_INLINE void cuddRotateLeft | ( | DdNodePtr * | nodeP | ) | [static] |
Function********************************************************************
Synopsis [Performs the left rotation for red/black trees.]
Description []
SideEffects [None]
SeeAlso [cuddRotateRight]
Definition at line 2919 of file cuddTable.c.
static DD_INLINE void cuddRotateRight | ( | DdNodePtr * | nodeP | ) | [static] |
Function********************************************************************
Synopsis [Performs the right rotation for red/black trees.]
Description []
SideEffects [None]
SeeAlso [cuddRotateLeft]
Definition at line 2945 of file cuddTable.c.
void cuddShrinkSubtable | ( | DdManager * | unique, | |
int | i | |||
) |
Function********************************************************************
Synopsis [Shrinks a subtable.]
Description [Shrinks a subtable.]
SideEffects [None]
SeeAlso [cuddRehash]
Definition at line 1666 of file cuddTable.c.
01669 { 01670 int j; 01671 int shift, posn; 01672 DdNodePtr *nodelist, *oldnodelist; 01673 DdNode *node, *next; 01674 DdNode *sentinel = &(unique->sentinel); 01675 unsigned int slots, oldslots; 01676 extern void (*MMoutOfMemory)(long); 01677 void (*saveHandler)(long); 01678 01679 oldnodelist = unique->subtables[i].nodelist; 01680 oldslots = unique->subtables[i].slots; 01681 slots = oldslots >> 1; 01682 saveHandler = MMoutOfMemory; 01683 MMoutOfMemory = Cudd_OutOfMem; 01684 nodelist = ALLOC(DdNodePtr, slots); 01685 MMoutOfMemory = saveHandler; 01686 if (nodelist == NULL) { 01687 return; 01688 } 01689 unique->subtables[i].nodelist = nodelist; 01690 unique->subtables[i].slots = slots; 01691 unique->subtables[i].shift++; 01692 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01693 #ifdef DD_VERBOSE 01694 (void) fprintf(unique->err, 01695 "shrunk layer %d (%d keys) from %d to %d slots\n", 01696 i, unique->subtables[i].keys, oldslots, slots); 01697 #endif 01698 01699 for (j = 0; (unsigned) j < slots; j++) { 01700 nodelist[j] = sentinel; 01701 } 01702 shift = unique->subtables[i].shift; 01703 for (j = 0; (unsigned) j < oldslots; j++) { 01704 node = oldnodelist[j]; 01705 while (node != sentinel) { 01706 DdNode *looking, *T, *E; 01707 DdNodePtr *previousP; 01708 next = node->next; 01709 posn = ddHash(cuddT(node), cuddE(node), shift); 01710 previousP = &(nodelist[posn]); 01711 looking = *previousP; 01712 T = cuddT(node); 01713 E = cuddE(node); 01714 while (T < cuddT(looking)) { 01715 previousP = &(looking->next); 01716 looking = *previousP; 01717 #ifdef DD_UNIQUE_PROFILE 01718 unique->uniqueLinks++; 01719 #endif 01720 } 01721 while (T == cuddT(looking) && E < cuddE(looking)) { 01722 previousP = &(looking->next); 01723 looking = *previousP; 01724 #ifdef DD_UNIQUE_PROFILE 01725 unique->uniqueLinks++; 01726 #endif 01727 } 01728 node->next = *previousP; 01729 *previousP = node; 01730 node = next; 01731 } 01732 } 01733 FREE(oldnodelist); 01734 01735 unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *); 01736 unique->slots += slots - oldslots; 01737 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 01738 unique->cacheSlack = (int) 01739 ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) 01740 - 2 * (int) unique->cacheSlots; 01741 01742 } /* end of cuddShrinkSubtable */
void cuddSlowTableGrowth | ( | DdManager * | unique | ) |
Function********************************************************************
Synopsis [Adjusts parameters of a table to slow down its growth.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 2352 of file cuddTable.c.
02354 { 02355 int i; 02356 02357 unique->maxCacheHard = unique->cacheSlots - 1; 02358 unique->cacheSlack = -(unique->cacheSlots + 1); 02359 for (i = 0; i < unique->size; i++) { 02360 unique->subtables[i].maxKeys <<= 2; 02361 } 02362 unique->gcFrac = DD_GC_FRAC_MIN; 02363 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); 02364 cuddShrinkDeathRow(unique); 02365 (void) fprintf(unique->err,"Slowing down table growth: "); 02366 (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac); 02367 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 02368 02369 } /* end of cuddSlowTableGrowth */
Function********************************************************************
Synopsis [Checks the unique table for the existence of a constant node.]
Description [Checks the unique table for the existence of a constant node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. Returns a pointer to the new node.]
SideEffects [None]
Definition at line 1412 of file cuddTable.c.
01415 { 01416 int pos; 01417 DdNodePtr *nodelist; 01418 DdNode *looking; 01419 hack split; 01420 01421 #ifdef DD_UNIQUE_PROFILE 01422 unique->uniqueLookUps++; 01423 #endif 01424 01425 if (unique->constants.keys > unique->constants.maxKeys) { 01426 if (unique->gcEnabled && ((unique->dead > unique->minDead) || 01427 (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */ 01428 (void) cuddGarbageCollect(unique,1); 01429 } else { 01430 cuddRehash(unique,CUDD_CONST_INDEX); 01431 } 01432 } 01433 01434 cuddAdjust(value); /* for the case of crippled infinities */ 01435 01436 if (ddAbs(value) < unique->epsilon) { 01437 value = 0.0; 01438 } 01439 split.value = value; 01440 01441 pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift); 01442 nodelist = unique->constants.nodelist; 01443 looking = nodelist[pos]; 01444 01445 /* Here we compare values both for equality and for difference less 01446 * than epsilon. The first comparison is required when values are 01447 * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for 01448 * every X. 01449 */ 01450 while (looking != NULL) { 01451 if (looking->type.value == value || 01452 ddEqualVal(looking->type.value,value,unique->epsilon)) { 01453 if (looking->ref == 0) { 01454 cuddReclaim(unique,looking); 01455 } 01456 return(looking); 01457 } 01458 looking = looking->next; 01459 #ifdef DD_UNIQUE_PROFILE 01460 unique->uniqueLinks++; 01461 #endif 01462 } 01463 01464 unique->keys++; 01465 unique->constants.keys++; 01466 01467 looking = cuddAllocNode(unique); 01468 if (looking == NULL) return(NULL); 01469 looking->ref = 0; 01470 looking->index = CUDD_CONST_INDEX; 01471 looking->type.value = value; 01472 looking->next = nodelist[pos]; 01473 nodelist[pos] = looking; 01474 01475 return(looking); 01476 01477 } /* end of cuddUniqueConst */
Function********************************************************************
Synopsis [Checks the unique table for the existence of an internal node.]
Description [Checks the unique table for the existence of an internal node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.]
SideEffects [None]
SeeAlso [cuddUniqueInterZdd]
Definition at line 1090 of file cuddTable.c.
01095 { 01096 int pos; 01097 unsigned int level; 01098 int retval; 01099 DdNodePtr *nodelist; 01100 DdNode *looking; 01101 DdNodePtr *previousP; 01102 DdSubtable *subtable; 01103 int gcNumber; 01104 01105 #ifdef DD_UNIQUE_PROFILE 01106 unique->uniqueLookUps++; 01107 #endif 01108 01109 if (index >= unique->size) { 01110 if (!ddResizeTable(unique,index)) return(NULL); 01111 } 01112 01113 level = unique->perm[index]; 01114 subtable = &(unique->subtables[level]); 01115 01116 #ifdef DD_DEBUG 01117 assert(level < (unsigned) cuddI(unique,T->index)); 01118 assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); 01119 #endif 01120 01121 pos = ddHash(T, E, subtable->shift); 01122 nodelist = subtable->nodelist; 01123 previousP = &(nodelist[pos]); 01124 looking = *previousP; 01125 01126 while (T < cuddT(looking)) { 01127 previousP = &(looking->next); 01128 looking = *previousP; 01129 #ifdef DD_UNIQUE_PROFILE 01130 unique->uniqueLinks++; 01131 #endif 01132 } 01133 while (T == cuddT(looking) && E < cuddE(looking)) { 01134 previousP = &(looking->next); 01135 looking = *previousP; 01136 #ifdef DD_UNIQUE_PROFILE 01137 unique->uniqueLinks++; 01138 #endif 01139 } 01140 if (T == cuddT(looking) && E == cuddE(looking)) { 01141 if (looking->ref == 0) { 01142 cuddReclaim(unique,looking); 01143 } 01144 return(looking); 01145 } 01146 01147 /* countDead is 0 if deads should be counted and ~0 if they should not. */ 01148 if (unique->autoDyn && 01149 unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) { 01150 #ifdef DD_DEBUG 01151 retval = Cudd_DebugCheck(unique); 01152 if (retval != 0) return(NULL); 01153 retval = Cudd_CheckKeys(unique); 01154 if (retval != 0) return(NULL); 01155 #endif 01156 retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */ 01157 if (retval == 0) unique->reordered = 2; 01158 #ifdef DD_DEBUG 01159 retval = Cudd_DebugCheck(unique); 01160 if (retval != 0) unique->reordered = 2; 01161 retval = Cudd_CheckKeys(unique); 01162 if (retval != 0) unique->reordered = 2; 01163 #endif 01164 return(NULL); 01165 } 01166 01167 if (subtable->keys > subtable->maxKeys) { 01168 if (unique->gcEnabled && 01169 ((unique->dead > unique->minDead) || 01170 ((unique->dead > unique->minDead / 2) && 01171 (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */ 01172 (void) cuddGarbageCollect(unique,1); 01173 } else { 01174 cuddRehash(unique,(int)level); 01175 } 01176 /* Update pointer to insertion point. In the case of rehashing, 01177 ** the slot may have changed. In the case of garbage collection, 01178 ** the predecessor may have been dead. */ 01179 pos = ddHash(T, E, subtable->shift); 01180 nodelist = subtable->nodelist; 01181 previousP = &(nodelist[pos]); 01182 looking = *previousP; 01183 01184 while (T < cuddT(looking)) { 01185 previousP = &(looking->next); 01186 looking = *previousP; 01187 #ifdef DD_UNIQUE_PROFILE 01188 unique->uniqueLinks++; 01189 #endif 01190 } 01191 while (T == cuddT(looking) && E < cuddE(looking)) { 01192 previousP = &(looking->next); 01193 looking = *previousP; 01194 #ifdef DD_UNIQUE_PROFILE 01195 unique->uniqueLinks++; 01196 #endif 01197 } 01198 } 01199 01200 gcNumber = unique->garbageCollections; 01201 looking = cuddAllocNode(unique); 01202 if (looking == NULL) { 01203 return(NULL); 01204 } 01205 unique->keys++; 01206 subtable->keys++; 01207 01208 if (gcNumber != unique->garbageCollections) { 01209 DdNode *looking2; 01210 pos = ddHash(T, E, subtable->shift); 01211 nodelist = subtable->nodelist; 01212 previousP = &(nodelist[pos]); 01213 looking2 = *previousP; 01214 01215 while (T < cuddT(looking2)) { 01216 previousP = &(looking2->next); 01217 looking2 = *previousP; 01218 #ifdef DD_UNIQUE_PROFILE 01219 unique->uniqueLinks++; 01220 #endif 01221 } 01222 while (T == cuddT(looking2) && E < cuddE(looking2)) { 01223 previousP = &(looking2->next); 01224 looking2 = *previousP; 01225 #ifdef DD_UNIQUE_PROFILE 01226 unique->uniqueLinks++; 01227 #endif 01228 } 01229 } 01230 looking->ref = 0; 01231 looking->index = index; 01232 cuddT(looking) = T; 01233 cuddE(looking) = E; 01234 looking->next = *previousP; 01235 *previousP = looking; 01236 cuddSatInc(T->ref); /* we know T is a regular pointer */ 01237 cuddRef(E); 01238 01239 #ifdef DD_DEBUG 01240 cuddCheckCollisionOrdering(unique,level,pos); 01241 #endif 01242 01243 return(looking); 01244 01245 } /* end of cuddUniqueInter */
Function********************************************************************
Synopsis [Wrapper for cuddUniqueInter that is independent of variable ordering.]
Description [Wrapper for cuddUniqueInter that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of T and E in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]
SideEffects [None]
SeeAlso [cuddUniqueInter Cudd_MakeBddFromZddCover]
Definition at line 1265 of file cuddTable.c.
01270 { 01271 DdNode *result; 01272 DdNode *v; 01273 01274 v = cuddUniqueInter(unique, index, DD_ONE(unique), 01275 Cudd_Not(DD_ONE(unique))); 01276 if (v == NULL) 01277 return(NULL); 01278 cuddRef(v); 01279 result = cuddBddIteRecur(unique, v, T, E); 01280 Cudd_RecursiveDeref(unique, v); 01281 return(result); 01282 }
Function********************************************************************
Synopsis [Checks the unique table for the existence of an internal ZDD node.]
Description [Checks the unique table for the existence of an internal ZDD node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.]
SideEffects [None]
SeeAlso [cuddUniqueInter]
Definition at line 1304 of file cuddTable.c.
01309 { 01310 int pos; 01311 unsigned int level; 01312 int retval; 01313 DdNodePtr *nodelist; 01314 DdNode *looking; 01315 DdSubtable *subtable; 01316 01317 #ifdef DD_UNIQUE_PROFILE 01318 unique->uniqueLookUps++; 01319 #endif 01320 01321 if (index >= unique->sizeZ) { 01322 if (!cuddResizeTableZdd(unique,index)) return(NULL); 01323 } 01324 01325 level = unique->permZ[index]; 01326 subtable = &(unique->subtableZ[level]); 01327 01328 #ifdef DD_DEBUG 01329 assert(level < (unsigned) cuddIZ(unique,T->index)); 01330 assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index)); 01331 #endif 01332 01333 if (subtable->keys > subtable->maxKeys) { 01334 if (unique->gcEnabled && ((unique->deadZ > unique->minDead) || 01335 (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */ 01336 (void) cuddGarbageCollectZdd(unique,1); 01337 } else { 01338 ddRehashZdd(unique,(int)level); 01339 } 01340 } 01341 01342 pos = ddHash(T, E, subtable->shift); 01343 nodelist = subtable->nodelist; 01344 looking = nodelist[pos]; 01345 01346 while (looking != NULL) { 01347 if (cuddT(looking) == T && cuddE(looking) == E) { 01348 if (looking->ref == 0) { 01349 cuddReclaimZdd(unique,looking); 01350 } 01351 return(looking); 01352 } 01353 looking = looking->next; 01354 #ifdef DD_UNIQUE_PROFILE 01355 unique->uniqueLinks++; 01356 #endif 01357 } 01358 01359 /* countDead is 0 if deads should be counted and ~0 if they should not. */ 01360 if (unique->autoDynZ && 01361 unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) { 01362 #ifdef DD_DEBUG 01363 retval = Cudd_DebugCheck(unique); 01364 if (retval != 0) return(NULL); 01365 retval = Cudd_CheckKeys(unique); 01366 if (retval != 0) return(NULL); 01367 #endif 01368 retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */ 01369 if (retval == 0) unique->reordered = 2; 01370 #ifdef DD_DEBUG 01371 retval = Cudd_DebugCheck(unique); 01372 if (retval != 0) unique->reordered = 2; 01373 retval = Cudd_CheckKeys(unique); 01374 if (retval != 0) unique->reordered = 2; 01375 #endif 01376 return(NULL); 01377 } 01378 01379 unique->keysZ++; 01380 subtable->keys++; 01381 01382 looking = cuddAllocNode(unique); 01383 if (looking == NULL) return(NULL); 01384 looking->ref = 0; 01385 looking->index = index; 01386 cuddT(looking) = T; 01387 cuddE(looking) = E; 01388 looking->next = nodelist[pos]; 01389 nodelist[pos] = looking; 01390 cuddRef(T); 01391 cuddRef(E); 01392 01393 return(looking); 01394 01395 } /* end of cuddUniqueInterZdd */
Function********************************************************************
Synopsis [Wrapper for cuddUniqueInterZdd.]
Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD reduction rule. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]
SideEffects [None]
SeeAlso [cuddUniqueInterZdd]
Definition at line 1003 of file cuddTable.c.
01008 { 01009 DdNode *node; 01010 01011 if (T == DD_ZERO(zdd)) 01012 return(E); 01013 node = cuddUniqueInterZdd(zdd, id, T, E); 01014 return(node); 01015 01016 } /* end of cuddZddGetNode */
Function********************************************************************
Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable ordering.]
Description [Wrapper for cuddUniqueInterZdd that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of g and h in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.]
SideEffects [None]
SeeAlso [cuddZddGetNode cuddZddIsop]
Definition at line 1036 of file cuddTable.c.
01041 { 01042 DdNode *f, *r, *t; 01043 DdNode *zdd_one = DD_ONE(dd); 01044 DdNode *zdd_zero = DD_ZERO(dd); 01045 01046 f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero); 01047 if (f == NULL) { 01048 return(NULL); 01049 } 01050 cuddRef(f); 01051 t = cuddZddProduct(dd, f, g); 01052 if (t == NULL) { 01053 Cudd_RecursiveDerefZdd(dd, f); 01054 return(NULL); 01055 } 01056 cuddRef(t); 01057 Cudd_RecursiveDerefZdd(dd, f); 01058 r = cuddZddUnion(dd, t, h); 01059 if (r == NULL) { 01060 Cudd_RecursiveDerefZdd(dd, t); 01061 return(NULL); 01062 } 01063 cuddRef(r); 01064 Cudd_RecursiveDerefZdd(dd, t); 01065 01066 cuddDeref(r); 01067 return(r); 01068 01069 } /* end of cuddZddGetNodeIVO */
static DD_INLINE void ddFixLimits | ( | DdManager * | unique | ) | [static] |
Function********************************************************************
Synopsis [Adjusts the values of table limits.]
Description [Adjusts the values of table fields controlling the. sizes of subtables and computed table. If the computed table is too small according to the new values, it is resized.]
SideEffects [Modifies manager fields. May resize computed table.]
SeeAlso []
Definition at line 2773 of file cuddTable.c.
02775 { 02776 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 02777 unique->cacheSlack = (int) ddMin(unique->maxCacheHard, 02778 DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - 02779 2 * (int) unique->cacheSlots; 02780 if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0) 02781 cuddCacheResize(unique); 02782 return; 02783 02784 } /* end of ddFixLimits */
Function********************************************************************
Synopsis [Fixes a variable tree after the insertion of new subtables.]
Description [Fixes a variable tree after the insertion of new subtables. After such an insertion, the low fields of the tree below the insertion point are inconsistent.]
SideEffects [None]
SeeAlso []
Definition at line 3046 of file cuddTable.c.
03049 { 03050 MtrNode *auxnode = treenode; 03051 03052 while (auxnode != NULL) { 03053 auxnode->low = dd->perm[auxnode->index]; 03054 if (auxnode->child != NULL) { 03055 ddPatchTree(dd, auxnode->child); 03056 } 03057 auxnode = auxnode->younger; 03058 } 03059 03060 return; 03061 03062 } /* end of ddPatchTree */
static void ddRehashZdd | ( | DdManager * | unique, | |
int | i | |||
) | [static] |
Function********************************************************************
Synopsis [Rehashes a ZDD unique subtable.]
Description []
SideEffects [None]
SeeAlso [cuddRehash]
Definition at line 2389 of file cuddTable.c.
02392 { 02393 unsigned int slots, oldslots; 02394 int shift, oldshift; 02395 int j, pos; 02396 DdNodePtr *nodelist, *oldnodelist; 02397 DdNode *node, *next; 02398 extern void (*MMoutOfMemory)(long); 02399 void (*saveHandler)(long); 02400 02401 if (unique->slots > unique->looseUpTo) { 02402 unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); 02403 #ifdef DD_VERBOSE 02404 if (unique->gcFrac == DD_GC_FRAC_HI) { 02405 (void) fprintf(unique->err,"GC fraction = %.2f\t", 02406 DD_GC_FRAC_LO); 02407 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 02408 } 02409 #endif 02410 unique->gcFrac = DD_GC_FRAC_LO; 02411 } 02412 02413 assert(i != CUDD_MAXINDEX); 02414 oldslots = unique->subtableZ[i].slots; 02415 oldshift = unique->subtableZ[i].shift; 02416 oldnodelist = unique->subtableZ[i].nodelist; 02417 02418 /* Compute the new size of the subtable. Normally, we just 02419 ** double. However, after reordering, a table may be severely 02420 ** overloaded. Therefore, we iterate. */ 02421 slots = oldslots; 02422 shift = oldshift; 02423 do { 02424 slots <<= 1; 02425 shift--; 02426 } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys); 02427 02428 saveHandler = MMoutOfMemory; 02429 MMoutOfMemory = Cudd_OutOfMem; 02430 nodelist = ALLOC(DdNodePtr, slots); 02431 MMoutOfMemory = saveHandler; 02432 if (nodelist == NULL) { 02433 int j; 02434 (void) fprintf(unique->err, 02435 "Unable to resize ZDD subtable %d for lack of memory.\n", 02436 i); 02437 (void) cuddGarbageCollectZdd(unique,1); 02438 for (j = 0; j < unique->sizeZ; j++) { 02439 unique->subtableZ[j].maxKeys <<= 1; 02440 } 02441 return; 02442 } 02443 unique->subtableZ[i].nodelist = nodelist; 02444 unique->subtableZ[i].slots = slots; 02445 unique->subtableZ[i].shift = shift; 02446 unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 02447 for (j = 0; (unsigned) j < slots; j++) { 02448 nodelist[j] = NULL; 02449 } 02450 for (j = 0; (unsigned) j < oldslots; j++) { 02451 node = oldnodelist[j]; 02452 while (node != NULL) { 02453 next = node->next; 02454 pos = ddHash(cuddT(node), cuddE(node), shift); 02455 node->next = nodelist[pos]; 02456 nodelist[pos] = node; 02457 node = next; 02458 } 02459 } 02460 FREE(oldnodelist); 02461 02462 #ifdef DD_VERBOSE 02463 (void) fprintf(unique->err, 02464 "rehashing layer %d: keys %d dead %d new size %d\n", 02465 i, unique->subtableZ[i].keys, 02466 unique->subtableZ[i].dead, slots); 02467 #endif 02468 02469 /* Update global data. */ 02470 unique->memused += (slots - oldslots) * sizeof(DdNode *); 02471 unique->slots += (slots - oldslots); 02472 ddFixLimits(unique); 02473 02474 } /* end of ddRehashZdd */
static void ddReportRefMess | ( | DdManager * | unique, | |
int | i, | |||
char * | caller | |||
) | [static] |
Function********************************************************************
Synopsis [Reports problem in garbage collection.]
Description []
SideEffects [None]
SeeAlso [cuddGarbageCollect cuddGarbageCollectZdd]
Definition at line 3123 of file cuddTable.c.
03127 { 03128 if (i == CUDD_CONST_INDEX) { 03129 (void) fprintf(unique->err, 03130 "%s: problem in constants\n", caller); 03131 } else if (i != -1) { 03132 (void) fprintf(unique->err, 03133 "%s: problem in table %d\n", caller, i); 03134 } 03135 (void) fprintf(unique->err, " dead count != deleted\n"); 03136 (void) fprintf(unique->err, " This problem is often due to a missing \ 03137 call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \ 03138 See the CUDD Programmer's Guide for additional details."); 03139 abort(); 03140 03141 } /* end of ddReportRefMess */
static int ddResizeTable | ( | DdManager * | unique, | |
int | index | |||
) | [static] |
Function********************************************************************
Synopsis [Increases the number of subtables in a unique table so that it meets or exceeds index.]
Description [Increases the number of subtables in a unique table so that it meets or exceeds index. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddResizeTableZdd]
Definition at line 2491 of file cuddTable.c.
02494 { 02495 DdSubtable *newsubtables; 02496 DdNodePtr *newnodelist; 02497 DdNodePtr *newvars; 02498 DdNode *sentinel = &(unique->sentinel); 02499 int oldsize,newsize; 02500 int i,j,reorderSave; 02501 int numSlots = unique->initSlots; 02502 int *newperm, *newinvperm, *newmap; 02503 DdNode *one, *zero; 02504 02505 oldsize = unique->size; 02506 /* Easy case: there is still room in the current table. */ 02507 if (index < unique->maxSize) { 02508 for (i = oldsize; i <= index; i++) { 02509 unique->subtables[i].slots = numSlots; 02510 unique->subtables[i].shift = sizeof(int) * 8 - 02511 cuddComputeFloorLog2(numSlots); 02512 unique->subtables[i].keys = 0; 02513 unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02514 unique->subtables[i].dead = 0; 02515 unique->subtables[i].bindVar = 0; 02516 unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 02517 unique->subtables[i].pairIndex = 0; 02518 unique->subtables[i].varHandled = 0; 02519 unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; 02520 02521 unique->perm[i] = i; 02522 unique->invperm[i] = i; 02523 newnodelist = unique->subtables[i].nodelist = 02524 ALLOC(DdNodePtr, numSlots); 02525 if (newnodelist == NULL) { 02526 for (j = oldsize; j < i; j++) { 02527 FREE(unique->subtables[j].nodelist); 02528 } 02529 unique->errorCode = CUDD_MEMORY_OUT; 02530 return(0); 02531 } 02532 for (j = 0; j < numSlots; j++) { 02533 newnodelist[j] = sentinel; 02534 } 02535 } 02536 if (unique->map != NULL) { 02537 for (i = oldsize; i <= index; i++) { 02538 unique->map[i] = i; 02539 } 02540 } 02541 } else { 02542 /* The current table is too small: we need to allocate a new, 02543 ** larger one; move all old subtables, and initialize the new 02544 ** subtables up to index included. 02545 */ 02546 newsize = index + DD_DEFAULT_RESIZE; 02547 #ifdef DD_VERBOSE 02548 (void) fprintf(unique->err, 02549 "Increasing the table size from %d to %d\n", 02550 unique->maxSize, newsize); 02551 #endif 02552 newsubtables = ALLOC(DdSubtable,newsize); 02553 if (newsubtables == NULL) { 02554 unique->errorCode = CUDD_MEMORY_OUT; 02555 return(0); 02556 } 02557 newvars = ALLOC(DdNodePtr,newsize); 02558 if (newvars == NULL) { 02559 FREE(newsubtables); 02560 unique->errorCode = CUDD_MEMORY_OUT; 02561 return(0); 02562 } 02563 newperm = ALLOC(int,newsize); 02564 if (newperm == NULL) { 02565 FREE(newsubtables); 02566 FREE(newvars); 02567 unique->errorCode = CUDD_MEMORY_OUT; 02568 return(0); 02569 } 02570 newinvperm = ALLOC(int,newsize); 02571 if (newinvperm == NULL) { 02572 FREE(newsubtables); 02573 FREE(newvars); 02574 FREE(newperm); 02575 unique->errorCode = CUDD_MEMORY_OUT; 02576 return(0); 02577 } 02578 if (unique->map != NULL) { 02579 newmap = ALLOC(int,newsize); 02580 if (newmap == NULL) { 02581 FREE(newsubtables); 02582 FREE(newvars); 02583 FREE(newperm); 02584 FREE(newinvperm); 02585 unique->errorCode = CUDD_MEMORY_OUT; 02586 return(0); 02587 } 02588 unique->memused += (newsize - unique->maxSize) * sizeof(int); 02589 } 02590 unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * 02591 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 02592 if (newsize > unique->maxSizeZ) { 02593 FREE(unique->stack); 02594 unique->stack = ALLOC(DdNodePtr,newsize + 1); 02595 if (unique->stack == NULL) { 02596 FREE(newsubtables); 02597 FREE(newvars); 02598 FREE(newperm); 02599 FREE(newinvperm); 02600 if (unique->map != NULL) { 02601 FREE(newmap); 02602 } 02603 unique->errorCode = CUDD_MEMORY_OUT; 02604 return(0); 02605 } 02606 unique->stack[0] = NULL; /* to suppress harmless UMR */ 02607 unique->memused += 02608 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 02609 * sizeof(DdNode *); 02610 } 02611 for (i = 0; i < oldsize; i++) { 02612 newsubtables[i].slots = unique->subtables[i].slots; 02613 newsubtables[i].shift = unique->subtables[i].shift; 02614 newsubtables[i].keys = unique->subtables[i].keys; 02615 newsubtables[i].maxKeys = unique->subtables[i].maxKeys; 02616 newsubtables[i].dead = unique->subtables[i].dead; 02617 newsubtables[i].nodelist = unique->subtables[i].nodelist; 02618 newsubtables[i].bindVar = unique->subtables[i].bindVar; 02619 newsubtables[i].varType = unique->subtables[i].varType; 02620 newsubtables[i].pairIndex = unique->subtables[i].pairIndex; 02621 newsubtables[i].varHandled = unique->subtables[i].varHandled; 02622 newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; 02623 02624 newvars[i] = unique->vars[i]; 02625 newperm[i] = unique->perm[i]; 02626 newinvperm[i] = unique->invperm[i]; 02627 } 02628 for (i = oldsize; i <= index; i++) { 02629 newsubtables[i].slots = numSlots; 02630 newsubtables[i].shift = sizeof(int) * 8 - 02631 cuddComputeFloorLog2(numSlots); 02632 newsubtables[i].keys = 0; 02633 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02634 newsubtables[i].dead = 0; 02635 newsubtables[i].bindVar = 0; 02636 newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 02637 newsubtables[i].pairIndex = 0; 02638 newsubtables[i].varHandled = 0; 02639 newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; 02640 02641 newperm[i] = i; 02642 newinvperm[i] = i; 02643 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 02644 if (newnodelist == NULL) { 02645 unique->errorCode = CUDD_MEMORY_OUT; 02646 return(0); 02647 } 02648 for (j = 0; j < numSlots; j++) { 02649 newnodelist[j] = sentinel; 02650 } 02651 } 02652 if (unique->map != NULL) { 02653 for (i = 0; i < oldsize; i++) { 02654 newmap[i] = unique->map[i]; 02655 } 02656 for (i = oldsize; i <= index; i++) { 02657 newmap[i] = i; 02658 } 02659 FREE(unique->map); 02660 unique->map = newmap; 02661 } 02662 FREE(unique->subtables); 02663 unique->subtables = newsubtables; 02664 unique->maxSize = newsize; 02665 FREE(unique->vars); 02666 unique->vars = newvars; 02667 FREE(unique->perm); 02668 unique->perm = newperm; 02669 FREE(unique->invperm); 02670 unique->invperm = newinvperm; 02671 } 02672 02673 /* Now that the table is in a coherent state, create the new 02674 ** projection functions. We need to temporarily disable reordering, 02675 ** because we cannot reorder without projection functions in place. 02676 **/ 02677 one = unique->one; 02678 zero = Cudd_Not(one); 02679 02680 unique->size = index + 1; 02681 unique->slots += (index + 1 - oldsize) * numSlots; 02682 ddFixLimits(unique); 02683 02684 reorderSave = unique->autoDyn; 02685 unique->autoDyn = 0; 02686 for (i = oldsize; i <= index; i++) { 02687 unique->vars[i] = cuddUniqueInter(unique,i,one,zero); 02688 if (unique->vars[i] == NULL) { 02689 unique->autoDyn = reorderSave; 02690 for (j = oldsize; j < i; j++) { 02691 Cudd_IterDerefBdd(unique,unique->vars[j]); 02692 cuddDeallocNode(unique,unique->vars[j]); 02693 unique->vars[j] = NULL; 02694 } 02695 for (j = oldsize; j <= index; j++) { 02696 FREE(unique->subtables[j].nodelist); 02697 unique->subtables[j].nodelist = NULL; 02698 } 02699 unique->size = oldsize; 02700 unique->slots -= (index + 1 - oldsize) * numSlots; 02701 ddFixLimits(unique); 02702 return(0); 02703 } 02704 cuddRef(unique->vars[i]); 02705 } 02706 unique->autoDyn = reorderSave; 02707 02708 return(1); 02709 02710 } /* end of ddResizeTable */
char rcsid [] DD_UNUSED = "$Id: cuddTable.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static] |
Definition at line 94 of file cuddTable.c.