#include "util.h"
#include "cuddInt.h"
Go to the source code of this file.
Data Structures | |
union | hack |
Functions | |
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 | ddPatchTree (DdManager *dd, MtrNode *treenode) |
static int | cuddCheckCollisionOrdering (DdManager *unique, int i, int j) |
static void | ddReportRefMess (DdManager *unique, int i, const 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) |
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) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddTable.c,v 1.122 2009/02/19 16:24:28 fabio Exp $" |
unsigned int Cudd_Prime | ( | unsigned int | p | ) |
AutomaticEnd Function********************************************************************
Synopsis [Returns the next prime >= p.]
Description []
SideEffects [None]
Definition at line 184 of file cuddTable.c.
00186 { 00187 int i,pn; 00188 00189 p--; 00190 do { 00191 p++; 00192 if (p&1) { 00193 pn = 1; 00194 i = 3; 00195 while ((unsigned) (i * i) <= p) { 00196 if (p % i == 0) { 00197 pn = 0; 00198 break; 00199 } 00200 i += 2; 00201 } 00202 } else { 00203 pn = 0; 00204 } 00205 } while (!pn); 00206 return(p); 00207 00208 } /* 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 231 of file cuddTable.c.
00233 { 00234 int i; 00235 DdNodePtr *mem; 00236 DdNode *list, *node; 00237 extern DD_OOMFP MMoutOfMemory; 00238 DD_OOMFP saveHandler; 00239 00240 if (unique->nextFree == NULL) { /* free list is empty */ 00241 /* Check for exceeded limits. */ 00242 if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) > 00243 unique->maxLive) { 00244 unique->errorCode = CUDD_TOO_MANY_NODES; 00245 return(NULL); 00246 } 00247 if (unique->stash == NULL || unique->memused > unique->maxmemhard) { 00248 (void) cuddGarbageCollect(unique,1); 00249 mem = NULL; 00250 } 00251 if (unique->nextFree == NULL) { 00252 if (unique->memused > unique->maxmemhard) { 00253 unique->errorCode = CUDD_MAX_MEM_EXCEEDED; 00254 return(NULL); 00255 } 00256 /* Try to allocate a new block. */ 00257 saveHandler = MMoutOfMemory; 00258 MMoutOfMemory = Cudd_OutOfMem; 00259 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00260 MMoutOfMemory = saveHandler; 00261 if (mem == NULL) { 00262 /* No more memory: Try collecting garbage. If this succeeds, 00263 ** we end up with mem still NULL, but unique->nextFree != 00264 ** NULL. */ 00265 if (cuddGarbageCollect(unique,1) == 0) { 00266 /* Last resort: Free the memory stashed away, if there 00267 ** any. If this succeeeds, mem != NULL and 00268 ** unique->nextFree still NULL. */ 00269 if (unique->stash != NULL) { 00270 FREE(unique->stash); 00271 unique->stash = NULL; 00272 /* Inhibit resizing of tables. */ 00273 cuddSlowTableGrowth(unique); 00274 /* Now try again. */ 00275 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); 00276 } 00277 if (mem == NULL) { 00278 /* Out of luck. Call the default handler to do 00279 ** whatever it specifies for a failed malloc. 00280 ** If this handler returns, then set error code, 00281 ** print warning, and return. */ 00282 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); 00283 unique->errorCode = CUDD_MEMORY_OUT; 00284 #ifdef DD_VERBOSE 00285 (void) fprintf(unique->err, 00286 "cuddAllocNode: out of memory"); 00287 (void) fprintf(unique->err, "Memory in use = %lu\n", 00288 unique->memused); 00289 #endif 00290 return(NULL); 00291 } 00292 } 00293 } 00294 if (mem != NULL) { /* successful allocation; slice memory */ 00295 ptruint offset; 00296 unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); 00297 mem[0] = (DdNodePtr) unique->memoryList; 00298 unique->memoryList = mem; 00299 00300 /* Here we rely on the fact that a DdNode is as large 00301 ** as 4 pointers. */ 00302 offset = (ptruint) mem & (sizeof(DdNode) - 1); 00303 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); 00304 assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0); 00305 list = (DdNode *) mem; 00306 00307 i = 1; 00308 do { 00309 list[i - 1].ref = 0; 00310 list[i - 1].next = &list[i]; 00311 } while (++i < DD_MEM_CHUNK); 00312 00313 list[DD_MEM_CHUNK-1].ref = 0; 00314 list[DD_MEM_CHUNK-1].next = NULL; 00315 00316 unique->nextFree = &list[0]; 00317 } 00318 } 00319 } 00320 unique->allocated++; 00321 node = unique->nextFree; 00322 unique->nextFree = node->next; 00323 return(node); 00324 00325 } /* end of cuddAllocNode */
static int cuddCheckCollisionOrdering | ( | DdManager * | unique, | |
int | i, | |||
int | j | |||
) | [static] |
Function********************************************************************
Synopsis [Checks whether a collision list is ordered.]
Description []
SideEffects [None]
SeeAlso []
Definition at line 3097 of file cuddTable.c.
03101 { 03102 int slots; 03103 DdNode *node, *next; 03104 DdNodePtr *nodelist; 03105 DdNode *sentinel = &(unique->sentinel); 03106 03107 nodelist = unique->subtables[i].nodelist; 03108 slots = unique->subtables[i].slots; 03109 node = nodelist[j]; 03110 if (node == sentinel) return(1); 03111 next = node->next; 03112 while (next != sentinel) { 03113 if (cuddT(node) < cuddT(next) || 03114 (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) { 03115 (void) fprintf(unique->err, 03116 "Unordered list: index %u, position %d\n", i, j); 03117 return(0); 03118 } 03119 node = next; 03120 next = node->next; 03121 } 03122 return(1); 03123 03124 } /* end of cuddCheckCollisionOrdering */
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 2093 of file cuddTable.c.
02096 { 02097 DdSubtable *subtables; 02098 DdNodePtr *nodelist; 02099 DdNodePtr *vars; 02100 int firstIndex, lastIndex; 02101 int index, level, newlevel; 02102 int lowestLevel; 02103 int shift; 02104 int found; 02105 02106 /* Sanity check and set up. */ 02107 if (n <= 0) return(0); 02108 if (n > unique->size) n = unique->size; 02109 02110 subtables = unique->subtables; 02111 vars = unique->vars; 02112 firstIndex = unique->size - n; 02113 lastIndex = unique->size; 02114 02115 /* Check for nodes labeled by the variables being destroyed 02116 ** that may still be in use. It is allowed to destroy a variable 02117 ** only if there are no such nodes. Also, find the lowest level 02118 ** among the variables being destroyed. This will make further 02119 ** processing more efficient. 02120 */ 02121 lowestLevel = unique->size; 02122 for (index = firstIndex; index < lastIndex; index++) { 02123 level = unique->perm[index]; 02124 if (level < lowestLevel) lowestLevel = level; 02125 nodelist = subtables[level].nodelist; 02126 if (subtables[level].keys - subtables[level].dead != 1) return(0); 02127 /* The projection function should be isolated. If the ref count 02128 ** is 1, everything is OK. If the ref count is saturated, then 02129 ** we need to make sure that there are no nodes pointing to it. 02130 ** As for the external references, we assume the application is 02131 ** responsible for them. 02132 */ 02133 if (vars[index]->ref != 1) { 02134 if (vars[index]->ref != DD_MAXREF) return(0); 02135 found = cuddFindParent(unique,vars[index]); 02136 if (found) { 02137 return(0); 02138 } else { 02139 vars[index]->ref = 1; 02140 } 02141 } 02142 Cudd_RecursiveDeref(unique,vars[index]); 02143 } 02144 02145 /* Collect garbage, because we cannot afford having dead nodes pointing 02146 ** to the dead nodes in the subtables being destroyed. 02147 */ 02148 (void) cuddGarbageCollect(unique,1); 02149 02150 /* Here we know we can destroy our subtables. */ 02151 for (index = firstIndex; index < lastIndex; index++) { 02152 level = unique->perm[index]; 02153 nodelist = subtables[level].nodelist; 02154 #ifdef DD_DEBUG 02155 assert(subtables[level].keys == 0); 02156 #endif 02157 FREE(nodelist); 02158 unique->memused -= sizeof(DdNodePtr) * subtables[level].slots; 02159 unique->slots -= subtables[level].slots; 02160 unique->dead -= subtables[level].dead; 02161 } 02162 02163 /* Here all subtables to be destroyed have their keys field == 0 and 02164 ** their hash tables have been freed. 02165 ** We now scan the subtables from level lowestLevel + 1 to level size - 1, 02166 ** shifting the subtables as required. We keep a running count of 02167 ** how many subtables have been moved, so that we know by how many 02168 ** positions each subtable should be shifted. 02169 */ 02170 shift = 1; 02171 for (level = lowestLevel + 1; level < unique->size; level++) { 02172 if (subtables[level].keys == 0) { 02173 shift++; 02174 continue; 02175 } 02176 newlevel = level - shift; 02177 subtables[newlevel].slots = subtables[level].slots; 02178 subtables[newlevel].shift = subtables[level].shift; 02179 subtables[newlevel].keys = subtables[level].keys; 02180 subtables[newlevel].maxKeys = subtables[level].maxKeys; 02181 subtables[newlevel].dead = subtables[level].dead; 02182 subtables[newlevel].nodelist = subtables[level].nodelist; 02183 index = unique->invperm[level]; 02184 unique->perm[index] = newlevel; 02185 unique->invperm[newlevel] = index; 02186 subtables[newlevel].bindVar = subtables[level].bindVar; 02187 subtables[newlevel].varType = subtables[level].varType; 02188 subtables[newlevel].pairIndex = subtables[level].pairIndex; 02189 subtables[newlevel].varHandled = subtables[level].varHandled; 02190 subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped; 02191 } 02192 /* Destroy the map. If a surviving variable is 02193 ** mapped to a dying variable, and the map were used again, 02194 ** an out-of-bounds access to unique->vars would result. */ 02195 if (unique->map != NULL) { 02196 cuddCacheFlush(unique); 02197 FREE(unique->map); 02198 unique->map = NULL; 02199 } 02200 02201 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 02202 unique->size -= n; 02203 02204 return(1); 02205 02206 } /* end of cuddDestroySubtables */
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 2743 of file cuddTable.c.
02746 { 02747 int i,j; 02748 int slots; 02749 DdNodePtr *nodelist; 02750 DdNode *f; 02751 02752 for (i = cuddI(table,node->index) - 1; i >= 0; i--) { 02753 nodelist = table->subtables[i].nodelist; 02754 slots = table->subtables[i].slots; 02755 02756 for (j = 0; j < slots; j++) { 02757 f = nodelist[j]; 02758 while (cuddT(f) > node) { 02759 f = f->next; 02760 } 02761 while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) { 02762 f = f->next; 02763 } 02764 if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) { 02765 return(1); 02766 } 02767 } 02768 } 02769 02770 return(0); 02771 02772 } /* 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 649 of file cuddTable.c.
00651 { 00652 DdNodePtr *next; 00653 DdNodePtr *memlist = unique->memoryList; 00654 int i; 00655 00656 if (unique->univ != NULL) cuddZddFreeUniv(unique); 00657 while (memlist != NULL) { 00658 next = (DdNodePtr *) memlist[0]; /* link to next block */ 00659 FREE(memlist); 00660 memlist = next; 00661 } 00662 unique->nextFree = NULL; 00663 unique->memoryList = NULL; 00664 00665 for (i = 0; i < unique->size; i++) { 00666 FREE(unique->subtables[i].nodelist); 00667 } 00668 for (i = 0; i < unique->sizeZ; i++) { 00669 FREE(unique->subtableZ[i].nodelist); 00670 } 00671 FREE(unique->constants.nodelist); 00672 FREE(unique->subtables); 00673 FREE(unique->subtableZ); 00674 FREE(unique->acache); 00675 FREE(unique->perm); 00676 FREE(unique->permZ); 00677 FREE(unique->invperm); 00678 FREE(unique->invpermZ); 00679 FREE(unique->vars); 00680 if (unique->map != NULL) FREE(unique->map); 00681 FREE(unique->stack); 00682 #ifndef DD_NO_DEATH_ROW 00683 FREE(unique->deathRow); 00684 #endif 00685 if (unique->tree != NULL) Mtr_FreeTree(unique->tree); 00686 if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); 00687 if (unique->linear != NULL) FREE(unique->linear); 00688 while (unique->preGCHook != NULL) 00689 Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK); 00690 while (unique->postGCHook != NULL) 00691 Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK); 00692 while (unique->preReorderingHook != NULL) 00693 Cudd_RemoveHook(unique,unique->preReorderingHook->f, 00694 CUDD_PRE_REORDERING_HOOK); 00695 while (unique->postReorderingHook != NULL) 00696 Cudd_RemoveHook(unique,unique->postReorderingHook->f, 00697 CUDD_POST_REORDERING_HOOK); 00698 FREE(unique); 00699 00700 } /* end of cuddFreeTable */
int cuddGarbageCollect | ( | DdManager * | unique, | |
int | clearCache | |||
) |
Function********************************************************************
Synopsis [Performs garbage collection on the unique tables.]
Description [Performs garbage collection on the BDD and ZDD unique tables. 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 []
Definition at line 719 of file cuddTable.c.
00722 { 00723 DdHook *hook; 00724 DdCache *cache = unique->cache; 00725 DdNode *sentinel = &(unique->sentinel); 00726 DdNodePtr *nodelist; 00727 int i, j, deleted, totalDeleted, totalDeletedZ; 00728 DdCache *c; 00729 DdNode *node,*next; 00730 DdNodePtr *lastP; 00731 int slots; 00732 long localTime; 00733 #ifndef DD_UNSORTED_FREE_LIST 00734 #ifdef DD_RED_BLACK_FREE_LIST 00735 DdNodePtr tree; 00736 #else 00737 DdNodePtr *memListTrav, *nxtNode; 00738 DdNode *downTrav, *sentry; 00739 int k; 00740 #endif 00741 #endif 00742 00743 #ifndef DD_NO_DEATH_ROW 00744 cuddClearDeathRow(unique); 00745 #endif 00746 00747 hook = unique->preGCHook; 00748 while (hook != NULL) { 00749 int res = (hook->f)(unique,"DD",NULL); 00750 if (res == 0) return(0); 00751 hook = hook->next; 00752 } 00753 00754 if (unique->dead + unique->deadZ == 0) { 00755 hook = unique->postGCHook; 00756 while (hook != NULL) { 00757 int res = (hook->f)(unique,"DD",NULL); 00758 if (res == 0) return(0); 00759 hook = hook->next; 00760 } 00761 return(0); 00762 } 00763 00764 /* If many nodes are being reclaimed, we want to resize the tables 00765 ** more aggressively, to reduce the frequency of garbage collection. 00766 */ 00767 if (clearCache && unique->gcFrac == DD_GC_FRAC_LO && 00768 unique->slots <= unique->looseUpTo && unique->stash != NULL) { 00769 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); 00770 #ifdef DD_VERBOSE 00771 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI); 00772 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 00773 #endif 00774 unique->gcFrac = DD_GC_FRAC_HI; 00775 return(0); 00776 } 00777 00778 localTime = util_cpu_time(); 00779 00780 unique->garbageCollections++; 00781 #ifdef DD_VERBOSE 00782 (void) fprintf(unique->err, 00783 "garbage collecting (%d dead BDD nodes out of %d, min %d)...", 00784 unique->dead, unique->keys, unique->minDead); 00785 (void) fprintf(unique->err, 00786 " (%d dead ZDD nodes out of %d)...", 00787 unique->deadZ, unique->keysZ); 00788 #endif 00789 00790 /* Remove references to garbage collected nodes from the cache. */ 00791 if (clearCache) { 00792 slots = unique->cacheSlots; 00793 for (i = 0; i < slots; i++) { 00794 c = &cache[i]; 00795 if (c->data != NULL) { 00796 if (cuddClean(c->f)->ref == 0 || 00797 cuddClean(c->g)->ref == 0 || 00798 (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || 00799 (c->data != DD_NON_CONSTANT && 00800 Cudd_Regular(c->data)->ref == 0)) { 00801 c->data = NULL; 00802 unique->cachedeletions++; 00803 } 00804 } 00805 } 00806 cuddLocalCacheClearDead(unique); 00807 } 00808 00809 /* Now return dead nodes to free list. Count them for sanity check. */ 00810 totalDeleted = 0; 00811 #ifndef DD_UNSORTED_FREE_LIST 00812 #ifdef DD_RED_BLACK_FREE_LIST 00813 tree = NULL; 00814 #endif 00815 #endif 00816 00817 for (i = 0; i < unique->size; i++) { 00818 if (unique->subtables[i].dead == 0) continue; 00819 nodelist = unique->subtables[i].nodelist; 00820 00821 deleted = 0; 00822 slots = unique->subtables[i].slots; 00823 for (j = 0; j < slots; j++) { 00824 lastP = &(nodelist[j]); 00825 node = *lastP; 00826 while (node != sentinel) { 00827 next = node->next; 00828 if (node->ref == 0) { 00829 deleted++; 00830 #ifndef DD_UNSORTED_FREE_LIST 00831 #ifdef DD_RED_BLACK_FREE_LIST 00832 #ifdef __osf__ 00833 #pragma pointer_size save 00834 #pragma pointer_size short 00835 #endif 00836 cuddOrderedInsert(&tree,node); 00837 #ifdef __osf__ 00838 #pragma pointer_size restore 00839 #endif 00840 #endif 00841 #else 00842 cuddDeallocNode(unique,node); 00843 #endif 00844 } else { 00845 *lastP = node; 00846 lastP = &(node->next); 00847 } 00848 node = next; 00849 } 00850 *lastP = sentinel; 00851 } 00852 if ((unsigned) deleted != unique->subtables[i].dead) { 00853 ddReportRefMess(unique, i, "cuddGarbageCollect"); 00854 } 00855 totalDeleted += deleted; 00856 unique->subtables[i].keys -= deleted; 00857 unique->subtables[i].dead = 0; 00858 } 00859 if (unique->constants.dead != 0) { 00860 nodelist = unique->constants.nodelist; 00861 deleted = 0; 00862 slots = unique->constants.slots; 00863 for (j = 0; j < slots; j++) { 00864 lastP = &(nodelist[j]); 00865 node = *lastP; 00866 while (node != NULL) { 00867 next = node->next; 00868 if (node->ref == 0) { 00869 deleted++; 00870 #ifndef DD_UNSORTED_FREE_LIST 00871 #ifdef DD_RED_BLACK_FREE_LIST 00872 #ifdef __osf__ 00873 #pragma pointer_size save 00874 #pragma pointer_size short 00875 #endif 00876 cuddOrderedInsert(&tree,node); 00877 #ifdef __osf__ 00878 #pragma pointer_size restore 00879 #endif 00880 #endif 00881 #else 00882 cuddDeallocNode(unique,node); 00883 #endif 00884 } else { 00885 *lastP = node; 00886 lastP = &(node->next); 00887 } 00888 node = next; 00889 } 00890 *lastP = NULL; 00891 } 00892 if ((unsigned) deleted != unique->constants.dead) { 00893 ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect"); 00894 } 00895 totalDeleted += deleted; 00896 unique->constants.keys -= deleted; 00897 unique->constants.dead = 0; 00898 } 00899 if ((unsigned) totalDeleted != unique->dead) { 00900 ddReportRefMess(unique, -1, "cuddGarbageCollect"); 00901 } 00902 unique->keys -= totalDeleted; 00903 unique->dead = 0; 00904 #ifdef DD_STATS 00905 unique->nodesFreed += (double) totalDeleted; 00906 #endif 00907 00908 totalDeletedZ = 0; 00909 00910 for (i = 0; i < unique->sizeZ; i++) { 00911 if (unique->subtableZ[i].dead == 0) continue; 00912 nodelist = unique->subtableZ[i].nodelist; 00913 00914 deleted = 0; 00915 slots = unique->subtableZ[i].slots; 00916 for (j = 0; j < slots; j++) { 00917 lastP = &(nodelist[j]); 00918 node = *lastP; 00919 while (node != NULL) { 00920 next = node->next; 00921 if (node->ref == 0) { 00922 deleted++; 00923 #ifndef DD_UNSORTED_FREE_LIST 00924 #ifdef DD_RED_BLACK_FREE_LIST 00925 #ifdef __osf__ 00926 #pragma pointer_size save 00927 #pragma pointer_size short 00928 #endif 00929 cuddOrderedInsert(&tree,node); 00930 #ifdef __osf__ 00931 #pragma pointer_size restore 00932 #endif 00933 #endif 00934 #else 00935 cuddDeallocNode(unique,node); 00936 #endif 00937 } else { 00938 *lastP = node; 00939 lastP = &(node->next); 00940 } 00941 node = next; 00942 } 00943 *lastP = NULL; 00944 } 00945 if ((unsigned) deleted != unique->subtableZ[i].dead) { 00946 ddReportRefMess(unique, i, "cuddGarbageCollect"); 00947 } 00948 totalDeletedZ += deleted; 00949 unique->subtableZ[i].keys -= deleted; 00950 unique->subtableZ[i].dead = 0; 00951 } 00952 00953 /* No need to examine the constant table for ZDDs. 00954 ** If we did we should be careful not to count whatever dead 00955 ** nodes we found there among the dead ZDD nodes. */ 00956 if ((unsigned) totalDeletedZ != unique->deadZ) { 00957 ddReportRefMess(unique, -1, "cuddGarbageCollect"); 00958 } 00959 unique->keysZ -= totalDeletedZ; 00960 unique->deadZ = 0; 00961 #ifdef DD_STATS 00962 unique->nodesFreed += (double) totalDeletedZ; 00963 #endif 00964 00965 00966 #ifndef DD_UNSORTED_FREE_LIST 00967 #ifdef DD_RED_BLACK_FREE_LIST 00968 unique->nextFree = cuddOrderedThread(tree,unique->nextFree); 00969 #else 00970 memListTrav = unique->memoryList; 00971 sentry = NULL; 00972 while (memListTrav != NULL) { 00973 ptruint offset; 00974 nxtNode = (DdNodePtr *)memListTrav[0]; 00975 offset = (ptruint) memListTrav & (sizeof(DdNode) - 1); 00976 memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); 00977 downTrav = (DdNode *)memListTrav; 00978 k = 0; 00979 do { 00980 if (downTrav[k].ref == 0) { 00981 if (sentry == NULL) { 00982 unique->nextFree = sentry = &downTrav[k]; 00983 } else { 00984 /* First hook sentry->next to the dead node and then 00985 ** reassign sentry to the dead node. */ 00986 sentry = (sentry->next = &downTrav[k]); 00987 } 00988 } 00989 } while (++k < DD_MEM_CHUNK); 00990 memListTrav = nxtNode; 00991 } 00992 sentry->next = NULL; 00993 #endif 00994 #endif 00995 00996 unique->GCTime += util_cpu_time() - localTime; 00997 00998 hook = unique->postGCHook; 00999 while (hook != NULL) { 01000 int res = (hook->f)(unique,"DD",NULL); 01001 if (res == 0) return(0); 01002 hook = hook->next; 01003 } 01004 01005 #ifdef DD_VERBOSE 01006 (void) fprintf(unique->err," done\n"); 01007 #endif 01008 01009 return(totalDeleted+totalDeletedZ); 01010 01011 } /* end of cuddGarbageCollect */
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 341 of file cuddTable.c.
00346 { 00347 DdManager *unique = ALLOC(DdManager,1); 00348 int i, j; 00349 DdNodePtr *nodelist; 00350 DdNode *sentinel; 00351 unsigned int slots; 00352 int shift; 00353 00354 if (unique == NULL) { 00355 return(NULL); 00356 } 00357 sentinel = &(unique->sentinel); 00358 sentinel->ref = 0; 00359 sentinel->index = 0; 00360 cuddT(sentinel) = NULL; 00361 cuddE(sentinel) = NULL; 00362 sentinel->next = NULL; 00363 unique->epsilon = DD_EPSILON; 00364 unique->maxGrowth = DD_MAX_REORDER_GROWTH; 00365 unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH; 00366 unique->reordCycle = 0; /* do not use alternate threshold */ 00367 unique->size = numVars; 00368 unique->sizeZ = numVarsZ; 00369 unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars); 00370 unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ); 00371 00372 /* Adjust the requested number of slots to a power of 2. */ 00373 slots = 8; 00374 while (slots < numSlots) { 00375 slots <<= 1; 00376 } 00377 unique->initSlots = slots; 00378 shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots); 00379 00380 unique->slots = (numVars + numVarsZ + 1) * slots; 00381 unique->keys = 0; 00382 unique->maxLive = ~0; /* very large number */ 00383 unique->keysZ = 0; 00384 unique->dead = 0; 00385 unique->deadZ = 0; 00386 unique->gcFrac = DD_GC_FRAC_HI; 00387 unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); 00388 unique->looseUpTo = looseUpTo; 00389 unique->gcEnabled = 1; 00390 unique->allocated = 0; 00391 unique->reclaimed = 0; 00392 unique->subtables = ALLOC(DdSubtable,unique->maxSize); 00393 if (unique->subtables == NULL) { 00394 FREE(unique); 00395 return(NULL); 00396 } 00397 unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ); 00398 if (unique->subtableZ == NULL) { 00399 FREE(unique->subtables); 00400 FREE(unique); 00401 return(NULL); 00402 } 00403 unique->perm = ALLOC(int,unique->maxSize); 00404 if (unique->perm == NULL) { 00405 FREE(unique->subtables); 00406 FREE(unique->subtableZ); 00407 FREE(unique); 00408 return(NULL); 00409 } 00410 unique->invperm = ALLOC(int,unique->maxSize); 00411 if (unique->invperm == NULL) { 00412 FREE(unique->subtables); 00413 FREE(unique->subtableZ); 00414 FREE(unique->perm); 00415 FREE(unique); 00416 return(NULL); 00417 } 00418 unique->permZ = ALLOC(int,unique->maxSizeZ); 00419 if (unique->permZ == NULL) { 00420 FREE(unique->subtables); 00421 FREE(unique->subtableZ); 00422 FREE(unique->perm); 00423 FREE(unique->invperm); 00424 FREE(unique); 00425 return(NULL); 00426 } 00427 unique->invpermZ = ALLOC(int,unique->maxSizeZ); 00428 if (unique->invpermZ == NULL) { 00429 FREE(unique->subtables); 00430 FREE(unique->subtableZ); 00431 FREE(unique->perm); 00432 FREE(unique->invperm); 00433 FREE(unique->permZ); 00434 FREE(unique); 00435 return(NULL); 00436 } 00437 unique->map = NULL; 00438 unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); 00439 if (unique->stack == NULL) { 00440 FREE(unique->subtables); 00441 FREE(unique->subtableZ); 00442 FREE(unique->perm); 00443 FREE(unique->invperm); 00444 FREE(unique->permZ); 00445 FREE(unique->invpermZ); 00446 FREE(unique); 00447 return(NULL); 00448 } 00449 unique->stack[0] = NULL; /* to suppress harmless UMR */ 00450 00451 #ifndef DD_NO_DEATH_ROW 00452 unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2); 00453 unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth); 00454 if (unique->deathRow == NULL) { 00455 FREE(unique->subtables); 00456 FREE(unique->subtableZ); 00457 FREE(unique->perm); 00458 FREE(unique->invperm); 00459 FREE(unique->permZ); 00460 FREE(unique->invpermZ); 00461 FREE(unique->stack); 00462 FREE(unique); 00463 return(NULL); 00464 } 00465 for (i = 0; i < unique->deathRowDepth; i++) { 00466 unique->deathRow[i] = NULL; 00467 } 00468 unique->nextDead = 0; 00469 unique->deadMask = unique->deathRowDepth - 1; 00470 #endif 00471 00472 for (i = 0; (unsigned) i < numVars; i++) { 00473 unique->subtables[i].slots = slots; 00474 unique->subtables[i].shift = shift; 00475 unique->subtables[i].keys = 0; 00476 unique->subtables[i].dead = 0; 00477 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00478 unique->subtables[i].bindVar = 0; 00479 unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 00480 unique->subtables[i].pairIndex = 0; 00481 unique->subtables[i].varHandled = 0; 00482 unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; 00483 00484 nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots); 00485 if (nodelist == NULL) { 00486 for (j = 0; j < i; j++) { 00487 FREE(unique->subtables[j].nodelist); 00488 } 00489 FREE(unique->subtables); 00490 FREE(unique->subtableZ); 00491 FREE(unique->perm); 00492 FREE(unique->invperm); 00493 FREE(unique->permZ); 00494 FREE(unique->invpermZ); 00495 FREE(unique->stack); 00496 FREE(unique); 00497 return(NULL); 00498 } 00499 for (j = 0; (unsigned) j < slots; j++) { 00500 nodelist[j] = sentinel; 00501 } 00502 unique->perm[i] = i; 00503 unique->invperm[i] = i; 00504 } 00505 for (i = 0; (unsigned) i < numVarsZ; i++) { 00506 unique->subtableZ[i].slots = slots; 00507 unique->subtableZ[i].shift = shift; 00508 unique->subtableZ[i].keys = 0; 00509 unique->subtableZ[i].dead = 0; 00510 unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00511 nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots); 00512 if (nodelist == NULL) { 00513 for (j = 0; (unsigned) j < numVars; j++) { 00514 FREE(unique->subtables[j].nodelist); 00515 } 00516 FREE(unique->subtables); 00517 for (j = 0; j < i; j++) { 00518 FREE(unique->subtableZ[j].nodelist); 00519 } 00520 FREE(unique->subtableZ); 00521 FREE(unique->perm); 00522 FREE(unique->invperm); 00523 FREE(unique->permZ); 00524 FREE(unique->invpermZ); 00525 FREE(unique->stack); 00526 FREE(unique); 00527 return(NULL); 00528 } 00529 for (j = 0; (unsigned) j < slots; j++) { 00530 nodelist[j] = NULL; 00531 } 00532 unique->permZ[i] = i; 00533 unique->invpermZ[i] = i; 00534 } 00535 unique->constants.slots = slots; 00536 unique->constants.shift = shift; 00537 unique->constants.keys = 0; 00538 unique->constants.dead = 0; 00539 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 00540 nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots); 00541 if (nodelist == NULL) { 00542 for (j = 0; (unsigned) j < numVars; j++) { 00543 FREE(unique->subtables[j].nodelist); 00544 } 00545 FREE(unique->subtables); 00546 for (j = 0; (unsigned) j < numVarsZ; j++) { 00547 FREE(unique->subtableZ[j].nodelist); 00548 } 00549 FREE(unique->subtableZ); 00550 FREE(unique->perm); 00551 FREE(unique->invperm); 00552 FREE(unique->permZ); 00553 FREE(unique->invpermZ); 00554 FREE(unique->stack); 00555 FREE(unique); 00556 return(NULL); 00557 } 00558 for (j = 0; (unsigned) j < slots; j++) { 00559 nodelist[j] = NULL; 00560 } 00561 00562 unique->memoryList = NULL; 00563 unique->nextFree = NULL; 00564 00565 unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ) 00566 * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) * 00567 slots * sizeof(DdNodePtr) + 00568 (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr); 00569 #ifndef DD_NO_DEATH_ROW 00570 unique->memused += unique->deathRowDepth * sizeof(DdNodePtr); 00571 #endif 00572 00573 /* Initialize fields concerned with automatic dynamic reordering */ 00574 unique->reorderings = 0; 00575 unique->autoDyn = 0; /* initially disabled */ 00576 unique->autoDynZ = 0; /* initially disabled */ 00577 unique->realign = 0; /* initially disabled */ 00578 unique->realignZ = 0; /* initially disabled */ 00579 unique->reordered = 0; 00580 unique->autoMethod = CUDD_REORDER_SIFT; 00581 unique->autoMethodZ = CUDD_REORDER_SIFT; 00582 unique->nextDyn = DD_FIRST_REORDER; 00583 unique->countDead = ~0; 00584 unique->siftMaxVar = DD_SIFT_MAX_VAR; 00585 unique->siftMaxSwap = DD_SIFT_MAX_SWAPS; 00586 unique->tree = NULL; 00587 unique->treeZ = NULL; 00588 unique->groupcheck = CUDD_GROUP_CHECK7; 00589 unique->recomb = DD_DEFAULT_RECOMB; 00590 unique->symmviolation = 0; 00591 unique->arcviolation = 0; 00592 unique->populationSize = 0; 00593 unique->numberXovers = 0; 00594 unique->linear = NULL; 00595 unique->linearSize = 0; 00596 00597 /* Initialize ZDD universe. */ 00598 unique->univ = (DdNodePtr *)NULL; 00599 00600 /* Initialize auxiliary fields. */ 00601 unique->localCaches = NULL; 00602 unique->preGCHook = NULL; 00603 unique->postGCHook = NULL; 00604 unique->preReorderingHook = NULL; 00605 unique->postReorderingHook = NULL; 00606 unique->out = stdout; 00607 unique->err = stderr; 00608 unique->errorCode = CUDD_NO_ERROR; 00609 00610 /* Initialize statistical counters. */ 00611 unique->maxmemhard = ~ 0UL; 00612 unique->garbageCollections = 0; 00613 unique->GCTime = 0; 00614 unique->reordTime = 0; 00615 #ifdef DD_STATS 00616 unique->nodesDropped = 0; 00617 unique->nodesFreed = 0; 00618 #endif 00619 unique->peakLiveNodes = 0; 00620 #ifdef DD_UNIQUE_PROFILE 00621 unique->uniqueLookUps = 0; 00622 unique->uniqueLinks = 0; 00623 #endif 00624 #ifdef DD_COUNT 00625 unique->recursiveCalls = 0; 00626 unique->swapSteps = 0; 00627 #ifdef DD_STATS 00628 unique->nextSample = 250000; 00629 #endif 00630 #endif 00631 00632 return(unique); 00633 00634 } /* 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 1780 of file cuddTable.c.
01784 { 01785 DdSubtable *newsubtables; 01786 DdNodePtr *newnodelist; 01787 DdNodePtr *newvars; 01788 DdNode *sentinel = &(unique->sentinel); 01789 int oldsize,newsize; 01790 int i,j,index,reorderSave; 01791 unsigned int numSlots = unique->initSlots; 01792 int *newperm, *newinvperm, *newmap; 01793 DdNode *one, *zero; 01794 01795 #ifdef DD_DEBUG 01796 assert(n > 0 && level < unique->size); 01797 #endif 01798 01799 oldsize = unique->size; 01800 /* Easy case: there is still room in the current table. */ 01801 if (oldsize + n <= unique->maxSize) { 01802 /* Shift the tables at and below level. */ 01803 for (i = oldsize - 1; i >= level; i--) { 01804 unique->subtables[i+n].slots = unique->subtables[i].slots; 01805 unique->subtables[i+n].shift = unique->subtables[i].shift; 01806 unique->subtables[i+n].keys = unique->subtables[i].keys; 01807 unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys; 01808 unique->subtables[i+n].dead = unique->subtables[i].dead; 01809 unique->subtables[i+n].nodelist = unique->subtables[i].nodelist; 01810 unique->subtables[i+n].bindVar = unique->subtables[i].bindVar; 01811 unique->subtables[i+n].varType = unique->subtables[i].varType; 01812 unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex; 01813 unique->subtables[i+n].varHandled = unique->subtables[i].varHandled; 01814 unique->subtables[i+n].varToBeGrouped = 01815 unique->subtables[i].varToBeGrouped; 01816 01817 index = unique->invperm[i]; 01818 unique->invperm[i+n] = index; 01819 unique->perm[index] += n; 01820 } 01821 /* Create new subtables. */ 01822 for (i = 0; i < n; i++) { 01823 unique->subtables[level+i].slots = numSlots; 01824 unique->subtables[level+i].shift = sizeof(int) * 8 - 01825 cuddComputeFloorLog2(numSlots); 01826 unique->subtables[level+i].keys = 0; 01827 unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 01828 unique->subtables[level+i].dead = 0; 01829 unique->subtables[level+i].bindVar = 0; 01830 unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT; 01831 unique->subtables[level+i].pairIndex = 0; 01832 unique->subtables[level+i].varHandled = 0; 01833 unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE; 01834 01835 unique->perm[oldsize+i] = level + i; 01836 unique->invperm[level+i] = oldsize + i; 01837 newnodelist = unique->subtables[level+i].nodelist = 01838 ALLOC(DdNodePtr, numSlots); 01839 if (newnodelist == NULL) { 01840 unique->errorCode = CUDD_MEMORY_OUT; 01841 return(0); 01842 } 01843 for (j = 0; (unsigned) j < numSlots; j++) { 01844 newnodelist[j] = sentinel; 01845 } 01846 } 01847 if (unique->map != NULL) { 01848 for (i = 0; i < n; i++) { 01849 unique->map[oldsize+i] = oldsize + i; 01850 } 01851 } 01852 } else { 01853 /* The current table is too small: we need to allocate a new, 01854 ** larger one; move all old subtables, and initialize the new 01855 ** subtables. 01856 */ 01857 newsize = oldsize + n + DD_DEFAULT_RESIZE; 01858 #ifdef DD_VERBOSE 01859 (void) fprintf(unique->err, 01860 "Increasing the table size from %d to %d\n", 01861 unique->maxSize, newsize); 01862 #endif 01863 /* Allocate memory for new arrays (except nodelists). */ 01864 newsubtables = ALLOC(DdSubtable,newsize); 01865 if (newsubtables == NULL) { 01866 unique->errorCode = CUDD_MEMORY_OUT; 01867 return(0); 01868 } 01869 newvars = ALLOC(DdNodePtr,newsize); 01870 if (newvars == NULL) { 01871 unique->errorCode = CUDD_MEMORY_OUT; 01872 FREE(newsubtables); 01873 return(0); 01874 } 01875 newperm = ALLOC(int,newsize); 01876 if (newperm == NULL) { 01877 unique->errorCode = CUDD_MEMORY_OUT; 01878 FREE(newsubtables); 01879 FREE(newvars); 01880 return(0); 01881 } 01882 newinvperm = ALLOC(int,newsize); 01883 if (newinvperm == NULL) { 01884 unique->errorCode = CUDD_MEMORY_OUT; 01885 FREE(newsubtables); 01886 FREE(newvars); 01887 FREE(newperm); 01888 return(0); 01889 } 01890 if (unique->map != NULL) { 01891 newmap = ALLOC(int,newsize); 01892 if (newmap == NULL) { 01893 unique->errorCode = CUDD_MEMORY_OUT; 01894 FREE(newsubtables); 01895 FREE(newvars); 01896 FREE(newperm); 01897 FREE(newinvperm); 01898 return(0); 01899 } 01900 unique->memused += (newsize - unique->maxSize) * sizeof(int); 01901 } 01902 unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * 01903 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 01904 /* Copy levels before insertion points from old tables. */ 01905 for (i = 0; i < level; i++) { 01906 newsubtables[i].slots = unique->subtables[i].slots; 01907 newsubtables[i].shift = unique->subtables[i].shift; 01908 newsubtables[i].keys = unique->subtables[i].keys; 01909 newsubtables[i].maxKeys = unique->subtables[i].maxKeys; 01910 newsubtables[i].dead = unique->subtables[i].dead; 01911 newsubtables[i].nodelist = unique->subtables[i].nodelist; 01912 newsubtables[i].bindVar = unique->subtables[i].bindVar; 01913 newsubtables[i].varType = unique->subtables[i].varType; 01914 newsubtables[i].pairIndex = unique->subtables[i].pairIndex; 01915 newsubtables[i].varHandled = unique->subtables[i].varHandled; 01916 newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; 01917 01918 newvars[i] = unique->vars[i]; 01919 newperm[i] = unique->perm[i]; 01920 newinvperm[i] = unique->invperm[i]; 01921 } 01922 /* Finish initializing permutation for new table to old one. */ 01923 for (i = level; i < oldsize; i++) { 01924 newperm[i] = unique->perm[i]; 01925 } 01926 /* Initialize new levels. */ 01927 for (i = level; i < level + n; i++) { 01928 newsubtables[i].slots = numSlots; 01929 newsubtables[i].shift = sizeof(int) * 8 - 01930 cuddComputeFloorLog2(numSlots); 01931 newsubtables[i].keys = 0; 01932 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 01933 newsubtables[i].dead = 0; 01934 newsubtables[i].bindVar = 0; 01935 newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 01936 newsubtables[i].pairIndex = 0; 01937 newsubtables[i].varHandled = 0; 01938 newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; 01939 01940 newperm[oldsize + i - level] = i; 01941 newinvperm[i] = oldsize + i - level; 01942 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 01943 if (newnodelist == NULL) { 01944 /* We are going to leak some memory. We should clean up. */ 01945 unique->errorCode = CUDD_MEMORY_OUT; 01946 return(0); 01947 } 01948 for (j = 0; (unsigned) j < numSlots; j++) { 01949 newnodelist[j] = sentinel; 01950 } 01951 } 01952 /* Copy the old tables for levels past the insertion point. */ 01953 for (i = level; i < oldsize; i++) { 01954 newsubtables[i+n].slots = unique->subtables[i].slots; 01955 newsubtables[i+n].shift = unique->subtables[i].shift; 01956 newsubtables[i+n].keys = unique->subtables[i].keys; 01957 newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys; 01958 newsubtables[i+n].dead = unique->subtables[i].dead; 01959 newsubtables[i+n].nodelist = unique->subtables[i].nodelist; 01960 newsubtables[i+n].bindVar = unique->subtables[i].bindVar; 01961 newsubtables[i+n].varType = unique->subtables[i].varType; 01962 newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex; 01963 newsubtables[i+n].varHandled = unique->subtables[i].varHandled; 01964 newsubtables[i+n].varToBeGrouped = 01965 unique->subtables[i].varToBeGrouped; 01966 01967 newvars[i] = unique->vars[i]; 01968 index = unique->invperm[i]; 01969 newinvperm[i+n] = index; 01970 newperm[index] += n; 01971 } 01972 /* Update the map. */ 01973 if (unique->map != NULL) { 01974 for (i = 0; i < oldsize; i++) { 01975 newmap[i] = unique->map[i]; 01976 } 01977 for (i = oldsize; i < oldsize + n; i++) { 01978 newmap[i] = i; 01979 } 01980 FREE(unique->map); 01981 unique->map = newmap; 01982 } 01983 /* Install the new tables and free the old ones. */ 01984 FREE(unique->subtables); 01985 unique->subtables = newsubtables; 01986 unique->maxSize = newsize; 01987 FREE(unique->vars); 01988 unique->vars = newvars; 01989 FREE(unique->perm); 01990 unique->perm = newperm; 01991 FREE(unique->invperm); 01992 unique->invperm = newinvperm; 01993 /* Update the stack for iterative procedures. */ 01994 if (newsize > unique->maxSizeZ) { 01995 FREE(unique->stack); 01996 unique->stack = ALLOC(DdNodePtr,newsize + 1); 01997 if (unique->stack == NULL) { 01998 unique->errorCode = CUDD_MEMORY_OUT; 01999 return(0); 02000 } 02001 unique->stack[0] = NULL; /* to suppress harmless UMR */ 02002 unique->memused += 02003 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 02004 * sizeof(DdNode *); 02005 } 02006 } 02007 /* Update manager parameters to account for the new subtables. */ 02008 unique->slots += n * numSlots; 02009 ddFixLimits(unique); 02010 unique->size += n; 02011 02012 /* Now that the table is in a coherent state, create the new 02013 ** projection functions. We need to temporarily disable reordering, 02014 ** because we cannot reorder without projection functions in place. 02015 **/ 02016 one = unique->one; 02017 zero = Cudd_Not(one); 02018 02019 reorderSave = unique->autoDyn; 02020 unique->autoDyn = 0; 02021 for (i = oldsize; i < oldsize + n; i++) { 02022 unique->vars[i] = cuddUniqueInter(unique,i,one,zero); 02023 if (unique->vars[i] == NULL) { 02024 unique->autoDyn = reorderSave; 02025 /* Shift everything back so table remains coherent. */ 02026 for (j = oldsize; j < i; j++) { 02027 Cudd_IterDerefBdd(unique,unique->vars[j]); 02028 cuddDeallocNode(unique,unique->vars[j]); 02029 unique->vars[j] = NULL; 02030 } 02031 for (j = level; j < oldsize; j++) { 02032 unique->subtables[j].slots = unique->subtables[j+n].slots; 02033 unique->subtables[j].slots = unique->subtables[j+n].slots; 02034 unique->subtables[j].shift = unique->subtables[j+n].shift; 02035 unique->subtables[j].keys = unique->subtables[j+n].keys; 02036 unique->subtables[j].maxKeys = 02037 unique->subtables[j+n].maxKeys; 02038 unique->subtables[j].dead = unique->subtables[j+n].dead; 02039 FREE(unique->subtables[j].nodelist); 02040 unique->subtables[j].nodelist = 02041 unique->subtables[j+n].nodelist; 02042 unique->subtables[j+n].nodelist = NULL; 02043 unique->subtables[j].bindVar = 02044 unique->subtables[j+n].bindVar; 02045 unique->subtables[j].varType = 02046 unique->subtables[j+n].varType; 02047 unique->subtables[j].pairIndex = 02048 unique->subtables[j+n].pairIndex; 02049 unique->subtables[j].varHandled = 02050 unique->subtables[j+n].varHandled; 02051 unique->subtables[j].varToBeGrouped = 02052 unique->subtables[j+n].varToBeGrouped; 02053 index = unique->invperm[j+n]; 02054 unique->invperm[j] = index; 02055 unique->perm[index] -= n; 02056 } 02057 unique->size = oldsize; 02058 unique->slots -= n * numSlots; 02059 ddFixLimits(unique); 02060 (void) Cudd_DebugCheck(unique); 02061 return(0); 02062 } 02063 cuddRef(unique->vars[i]); 02064 } 02065 if (unique->tree != NULL) { 02066 unique->tree->size += n; 02067 unique->tree->index = unique->invperm[0]; 02068 ddPatchTree(unique,unique->tree); 02069 } 02070 unique->autoDyn = reorderSave; 02071 02072 return(1); 02073 02074 } /* end of cuddInsertSubtables */
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 1515 of file cuddTable.c.
01518 { 01519 unsigned int slots, oldslots; 01520 int shift, oldshift; 01521 int j, pos; 01522 DdNodePtr *nodelist, *oldnodelist; 01523 DdNode *node, *next; 01524 DdNode *sentinel = &(unique->sentinel); 01525 hack split; 01526 extern DD_OOMFP MMoutOfMemory; 01527 DD_OOMFP saveHandler; 01528 01529 if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) { 01530 unique->gcFrac = DD_GC_FRAC_LO; 01531 unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); 01532 #ifdef DD_VERBOSE 01533 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); 01534 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 01535 #endif 01536 } 01537 01538 if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) { 01539 unique->gcFrac = DD_GC_FRAC_MIN; 01540 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); 01541 #ifdef DD_VERBOSE 01542 (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN); 01543 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 01544 #endif 01545 cuddShrinkDeathRow(unique); 01546 if (cuddGarbageCollect(unique,1) > 0) return; 01547 } 01548 01549 if (i != CUDD_CONST_INDEX) { 01550 oldslots = unique->subtables[i].slots; 01551 oldshift = unique->subtables[i].shift; 01552 oldnodelist = unique->subtables[i].nodelist; 01553 01554 /* Compute the new size of the subtable. */ 01555 slots = oldslots << 1; 01556 shift = oldshift - 1; 01557 01558 saveHandler = MMoutOfMemory; 01559 MMoutOfMemory = Cudd_OutOfMem; 01560 nodelist = ALLOC(DdNodePtr, slots); 01561 MMoutOfMemory = saveHandler; 01562 if (nodelist == NULL) { 01563 (void) fprintf(unique->err, 01564 "Unable to resize subtable %d for lack of memory\n", 01565 i); 01566 /* Prevent frequent resizing attempts. */ 01567 (void) cuddGarbageCollect(unique,1); 01568 if (unique->stash != NULL) { 01569 FREE(unique->stash); 01570 unique->stash = NULL; 01571 /* Inhibit resizing of tables. */ 01572 cuddSlowTableGrowth(unique); 01573 } 01574 return; 01575 } 01576 unique->subtables[i].nodelist = nodelist; 01577 unique->subtables[i].slots = slots; 01578 unique->subtables[i].shift = shift; 01579 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01580 01581 /* Move the nodes from the old table to the new table. 01582 ** This code depends on the type of hash function. 01583 ** It assumes that the effect of doubling the size of the table 01584 ** is to retain one more bit of the 32-bit hash value. 01585 ** The additional bit is the LSB. */ 01586 for (j = 0; (unsigned) j < oldslots; j++) { 01587 DdNodePtr *evenP, *oddP; 01588 node = oldnodelist[j]; 01589 evenP = &(nodelist[j<<1]); 01590 oddP = &(nodelist[(j<<1)+1]); 01591 while (node != sentinel) { 01592 next = node->next; 01593 pos = ddHash(cuddT(node), cuddE(node), shift); 01594 if (pos & 1) { 01595 *oddP = node; 01596 oddP = &(node->next); 01597 } else { 01598 *evenP = node; 01599 evenP = &(node->next); 01600 } 01601 node = next; 01602 } 01603 *evenP = *oddP = sentinel; 01604 } 01605 FREE(oldnodelist); 01606 01607 #ifdef DD_VERBOSE 01608 (void) fprintf(unique->err, 01609 "rehashing layer %d: keys %d dead %d new size %d\n", 01610 i, unique->subtables[i].keys, 01611 unique->subtables[i].dead, slots); 01612 #endif 01613 } else { 01614 oldslots = unique->constants.slots; 01615 oldshift = unique->constants.shift; 01616 oldnodelist = unique->constants.nodelist; 01617 01618 /* The constant subtable is never subjected to reordering. 01619 ** Therefore, when it is resized, it is because it has just 01620 ** reached the maximum load. We can safely just double the size, 01621 ** with no need for the loop we use for the other tables. 01622 */ 01623 slots = oldslots << 1; 01624 shift = oldshift - 1; 01625 saveHandler = MMoutOfMemory; 01626 MMoutOfMemory = Cudd_OutOfMem; 01627 nodelist = ALLOC(DdNodePtr, slots); 01628 MMoutOfMemory = saveHandler; 01629 if (nodelist == NULL) { 01630 (void) fprintf(unique->err, 01631 "Unable to resize constant subtable for lack of memory\n"); 01632 (void) cuddGarbageCollect(unique,1); 01633 for (j = 0; j < unique->size; j++) { 01634 unique->subtables[j].maxKeys <<= 1; 01635 } 01636 unique->constants.maxKeys <<= 1; 01637 return; 01638 } 01639 unique->constants.slots = slots; 01640 unique->constants.shift = shift; 01641 unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01642 unique->constants.nodelist = nodelist; 01643 for (j = 0; (unsigned) j < slots; j++) { 01644 nodelist[j] = NULL; 01645 } 01646 for (j = 0; (unsigned) j < oldslots; j++) { 01647 node = oldnodelist[j]; 01648 while (node != NULL) { 01649 next = node->next; 01650 split.value = cuddV(node); 01651 pos = ddHash(split.bits[0], split.bits[1], shift); 01652 node->next = nodelist[pos]; 01653 nodelist[pos] = node; 01654 node = next; 01655 } 01656 } 01657 FREE(oldnodelist); 01658 01659 #ifdef DD_VERBOSE 01660 (void) fprintf(unique->err, 01661 "rehashing constants: keys %d dead %d new size %d\n", 01662 unique->constants.keys,unique->constants.dead,slots); 01663 #endif 01664 } 01665 01666 /* Update global data */ 01667 01668 unique->memused += (slots - oldslots) * sizeof(DdNodePtr); 01669 unique->slots += (slots - oldslots); 01670 ddFixLimits(unique); 01671 01672 } /* 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 2226 of file cuddTable.c.
02229 { 02230 DdSubtable *newsubtables; 02231 DdNodePtr *newnodelist; 02232 int oldsize,newsize; 02233 int i,j,reorderSave; 02234 unsigned int numSlots = unique->initSlots; 02235 int *newperm, *newinvperm; 02236 02237 oldsize = unique->sizeZ; 02238 /* Easy case: there is still room in the current table. */ 02239 if (index < unique->maxSizeZ) { 02240 for (i = oldsize; i <= index; i++) { 02241 unique->subtableZ[i].slots = numSlots; 02242 unique->subtableZ[i].shift = sizeof(int) * 8 - 02243 cuddComputeFloorLog2(numSlots); 02244 unique->subtableZ[i].keys = 0; 02245 unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02246 unique->subtableZ[i].dead = 0; 02247 unique->permZ[i] = i; 02248 unique->invpermZ[i] = i; 02249 newnodelist = unique->subtableZ[i].nodelist = 02250 ALLOC(DdNodePtr, numSlots); 02251 if (newnodelist == NULL) { 02252 unique->errorCode = CUDD_MEMORY_OUT; 02253 return(0); 02254 } 02255 for (j = 0; (unsigned) j < numSlots; j++) { 02256 newnodelist[j] = NULL; 02257 } 02258 } 02259 } else { 02260 /* The current table is too small: we need to allocate a new, 02261 ** larger one; move all old subtables, and initialize the new 02262 ** subtables up to index included. 02263 */ 02264 newsize = index + DD_DEFAULT_RESIZE; 02265 #ifdef DD_VERBOSE 02266 (void) fprintf(unique->err, 02267 "Increasing the ZDD table size from %d to %d\n", 02268 unique->maxSizeZ, newsize); 02269 #endif 02270 newsubtables = ALLOC(DdSubtable,newsize); 02271 if (newsubtables == NULL) { 02272 unique->errorCode = CUDD_MEMORY_OUT; 02273 return(0); 02274 } 02275 newperm = ALLOC(int,newsize); 02276 if (newperm == NULL) { 02277 unique->errorCode = CUDD_MEMORY_OUT; 02278 return(0); 02279 } 02280 newinvperm = ALLOC(int,newsize); 02281 if (newinvperm == NULL) { 02282 unique->errorCode = CUDD_MEMORY_OUT; 02283 return(0); 02284 } 02285 unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) * 02286 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 02287 if (newsize > unique->maxSize) { 02288 FREE(unique->stack); 02289 unique->stack = ALLOC(DdNodePtr,newsize + 1); 02290 if (unique->stack == NULL) { 02291 unique->errorCode = CUDD_MEMORY_OUT; 02292 return(0); 02293 } 02294 unique->stack[0] = NULL; /* to suppress harmless UMR */ 02295 unique->memused += 02296 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 02297 * sizeof(DdNode *); 02298 } 02299 for (i = 0; i < oldsize; i++) { 02300 newsubtables[i].slots = unique->subtableZ[i].slots; 02301 newsubtables[i].shift = unique->subtableZ[i].shift; 02302 newsubtables[i].keys = unique->subtableZ[i].keys; 02303 newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys; 02304 newsubtables[i].dead = unique->subtableZ[i].dead; 02305 newsubtables[i].nodelist = unique->subtableZ[i].nodelist; 02306 newperm[i] = unique->permZ[i]; 02307 newinvperm[i] = unique->invpermZ[i]; 02308 } 02309 for (i = oldsize; i <= index; i++) { 02310 newsubtables[i].slots = numSlots; 02311 newsubtables[i].shift = sizeof(int) * 8 - 02312 cuddComputeFloorLog2(numSlots); 02313 newsubtables[i].keys = 0; 02314 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02315 newsubtables[i].dead = 0; 02316 newperm[i] = i; 02317 newinvperm[i] = i; 02318 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 02319 if (newnodelist == NULL) { 02320 unique->errorCode = CUDD_MEMORY_OUT; 02321 return(0); 02322 } 02323 for (j = 0; (unsigned) j < numSlots; j++) { 02324 newnodelist[j] = NULL; 02325 } 02326 } 02327 FREE(unique->subtableZ); 02328 unique->subtableZ = newsubtables; 02329 unique->maxSizeZ = newsize; 02330 FREE(unique->permZ); 02331 unique->permZ = newperm; 02332 FREE(unique->invpermZ); 02333 unique->invpermZ = newinvperm; 02334 } 02335 unique->slots += (index + 1 - unique->sizeZ) * numSlots; 02336 ddFixLimits(unique); 02337 unique->sizeZ = index + 1; 02338 02339 /* Now that the table is in a coherent state, update the ZDD 02340 ** universe. We need to temporarily disable reordering, 02341 ** because we cannot reorder without universe in place. 02342 */ 02343 02344 reorderSave = unique->autoDynZ; 02345 unique->autoDynZ = 0; 02346 cuddZddFreeUniv(unique); 02347 if (!cuddZddInitUniv(unique)) { 02348 unique->autoDynZ = reorderSave; 02349 return(0); 02350 } 02351 unique->autoDynZ = reorderSave; 02352 02353 return(1); 02354 02355 } /* end of cuddResizeTableZdd */
void cuddShrinkSubtable | ( | DdManager * | unique, | |
int | i | |||
) |
Function********************************************************************
Synopsis [Shrinks a subtable.]
Description [Shrinks a subtable.]
SideEffects [None]
SeeAlso [cuddRehash]
Definition at line 1687 of file cuddTable.c.
01690 { 01691 int j; 01692 int shift, posn; 01693 DdNodePtr *nodelist, *oldnodelist; 01694 DdNode *node, *next; 01695 DdNode *sentinel = &(unique->sentinel); 01696 unsigned int slots, oldslots; 01697 extern DD_OOMFP MMoutOfMemory; 01698 DD_OOMFP saveHandler; 01699 01700 oldnodelist = unique->subtables[i].nodelist; 01701 oldslots = unique->subtables[i].slots; 01702 slots = oldslots >> 1; 01703 saveHandler = MMoutOfMemory; 01704 MMoutOfMemory = Cudd_OutOfMem; 01705 nodelist = ALLOC(DdNodePtr, slots); 01706 MMoutOfMemory = saveHandler; 01707 if (nodelist == NULL) { 01708 return; 01709 } 01710 unique->subtables[i].nodelist = nodelist; 01711 unique->subtables[i].slots = slots; 01712 unique->subtables[i].shift++; 01713 unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 01714 #ifdef DD_VERBOSE 01715 (void) fprintf(unique->err, 01716 "shrunk layer %d (%d keys) from %d to %d slots\n", 01717 i, unique->subtables[i].keys, oldslots, slots); 01718 #endif 01719 01720 for (j = 0; (unsigned) j < slots; j++) { 01721 nodelist[j] = sentinel; 01722 } 01723 shift = unique->subtables[i].shift; 01724 for (j = 0; (unsigned) j < oldslots; j++) { 01725 node = oldnodelist[j]; 01726 while (node != sentinel) { 01727 DdNode *looking, *T, *E; 01728 DdNodePtr *previousP; 01729 next = node->next; 01730 posn = ddHash(cuddT(node), cuddE(node), shift); 01731 previousP = &(nodelist[posn]); 01732 looking = *previousP; 01733 T = cuddT(node); 01734 E = cuddE(node); 01735 while (T < cuddT(looking)) { 01736 previousP = &(looking->next); 01737 looking = *previousP; 01738 #ifdef DD_UNIQUE_PROFILE 01739 unique->uniqueLinks++; 01740 #endif 01741 } 01742 while (T == cuddT(looking) && E < cuddE(looking)) { 01743 previousP = &(looking->next); 01744 looking = *previousP; 01745 #ifdef DD_UNIQUE_PROFILE 01746 unique->uniqueLinks++; 01747 #endif 01748 } 01749 node->next = *previousP; 01750 *previousP = node; 01751 node = next; 01752 } 01753 } 01754 FREE(oldnodelist); 01755 01756 unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *); 01757 unique->slots += slots - oldslots; 01758 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 01759 unique->cacheSlack = (int) 01760 ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) 01761 - 2 * (int) unique->cacheSlots; 01762 01763 } /* 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 2370 of file cuddTable.c.
02372 { 02373 int i; 02374 02375 unique->maxCacheHard = unique->cacheSlots - 1; 02376 unique->cacheSlack = - (int) (unique->cacheSlots + 1); 02377 for (i = 0; i < unique->size; i++) { 02378 unique->subtables[i].maxKeys <<= 2; 02379 } 02380 unique->gcFrac = DD_GC_FRAC_MIN; 02381 unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); 02382 cuddShrinkDeathRow(unique); 02383 (void) fprintf(unique->err,"Slowing down table growth: "); 02384 (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac); 02385 (void) fprintf(unique->err,"minDead = %u\n", unique->minDead); 02386 02387 } /* 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 1435 of file cuddTable.c.
01438 { 01439 int pos; 01440 DdNodePtr *nodelist; 01441 DdNode *looking; 01442 hack split; 01443 01444 #ifdef DD_UNIQUE_PROFILE 01445 unique->uniqueLookUps++; 01446 #endif 01447 01448 if (unique->constants.keys > unique->constants.maxKeys) { 01449 if (unique->gcEnabled && ((unique->dead > unique->minDead) || 01450 (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */ 01451 (void) cuddGarbageCollect(unique,1); 01452 } else { 01453 cuddRehash(unique,CUDD_CONST_INDEX); 01454 } 01455 } 01456 01457 cuddAdjust(value); /* for the case of crippled infinities */ 01458 01459 if (ddAbs(value) < unique->epsilon) { 01460 value = 0.0; 01461 } 01462 split.value = value; 01463 01464 pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift); 01465 nodelist = unique->constants.nodelist; 01466 looking = nodelist[pos]; 01467 01468 /* Here we compare values both for equality and for difference less 01469 * than epsilon. The first comparison is required when values are 01470 * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for 01471 * every X. 01472 */ 01473 while (looking != NULL) { 01474 if (looking->type.value == value || 01475 ddEqualVal(looking->type.value,value,unique->epsilon)) { 01476 if (looking->ref == 0) { 01477 cuddReclaim(unique,looking); 01478 } 01479 return(looking); 01480 } 01481 looking = looking->next; 01482 #ifdef DD_UNIQUE_PROFILE 01483 unique->uniqueLinks++; 01484 #endif 01485 } 01486 01487 unique->keys++; 01488 unique->constants.keys++; 01489 01490 looking = cuddAllocNode(unique); 01491 if (looking == NULL) return(NULL); 01492 looking->index = CUDD_CONST_INDEX; 01493 looking->type.value = value; 01494 looking->next = nodelist[pos]; 01495 nodelist[pos] = looking; 01496 01497 return(looking); 01498 01499 } /* 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 1115 of file cuddTable.c.
01120 { 01121 int pos; 01122 unsigned int level; 01123 int retval; 01124 DdNodePtr *nodelist; 01125 DdNode *looking; 01126 DdNodePtr *previousP; 01127 DdSubtable *subtable; 01128 int gcNumber; 01129 01130 #ifdef DD_UNIQUE_PROFILE 01131 unique->uniqueLookUps++; 01132 #endif 01133 01134 if (index >= unique->size) { 01135 if (!ddResizeTable(unique,index)) return(NULL); 01136 } 01137 01138 level = unique->perm[index]; 01139 subtable = &(unique->subtables[level]); 01140 01141 #ifdef DD_DEBUG 01142 assert(level < (unsigned) cuddI(unique,T->index)); 01143 assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); 01144 #endif 01145 01146 pos = ddHash(T, E, subtable->shift); 01147 nodelist = subtable->nodelist; 01148 previousP = &(nodelist[pos]); 01149 looking = *previousP; 01150 01151 while (T < cuddT(looking)) { 01152 previousP = &(looking->next); 01153 looking = *previousP; 01154 #ifdef DD_UNIQUE_PROFILE 01155 unique->uniqueLinks++; 01156 #endif 01157 } 01158 while (T == cuddT(looking) && E < cuddE(looking)) { 01159 previousP = &(looking->next); 01160 looking = *previousP; 01161 #ifdef DD_UNIQUE_PROFILE 01162 unique->uniqueLinks++; 01163 #endif 01164 } 01165 if (T == cuddT(looking) && E == cuddE(looking)) { 01166 if (looking->ref == 0) { 01167 cuddReclaim(unique,looking); 01168 } 01169 return(looking); 01170 } 01171 01172 /* countDead is 0 if deads should be counted and ~0 if they should not. */ 01173 if (unique->autoDyn && 01174 unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) { 01175 #ifdef DD_DEBUG 01176 retval = Cudd_DebugCheck(unique); 01177 if (retval != 0) return(NULL); 01178 retval = Cudd_CheckKeys(unique); 01179 if (retval != 0) return(NULL); 01180 #endif 01181 retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */ 01182 if (retval == 0) unique->reordered = 2; 01183 #ifdef DD_DEBUG 01184 retval = Cudd_DebugCheck(unique); 01185 if (retval != 0) unique->reordered = 2; 01186 retval = Cudd_CheckKeys(unique); 01187 if (retval != 0) unique->reordered = 2; 01188 #endif 01189 return(NULL); 01190 } 01191 01192 if (subtable->keys > subtable->maxKeys) { 01193 if (unique->gcEnabled && 01194 ((unique->dead > unique->minDead) || 01195 ((unique->dead > unique->minDead / 2) && 01196 (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */ 01197 (void) cuddGarbageCollect(unique,1); 01198 } else { 01199 cuddRehash(unique,(int)level); 01200 } 01201 /* Update pointer to insertion point. In the case of rehashing, 01202 ** the slot may have changed. In the case of garbage collection, 01203 ** the predecessor may have been dead. */ 01204 pos = ddHash(T, E, subtable->shift); 01205 nodelist = subtable->nodelist; 01206 previousP = &(nodelist[pos]); 01207 looking = *previousP; 01208 01209 while (T < cuddT(looking)) { 01210 previousP = &(looking->next); 01211 looking = *previousP; 01212 #ifdef DD_UNIQUE_PROFILE 01213 unique->uniqueLinks++; 01214 #endif 01215 } 01216 while (T == cuddT(looking) && E < cuddE(looking)) { 01217 previousP = &(looking->next); 01218 looking = *previousP; 01219 #ifdef DD_UNIQUE_PROFILE 01220 unique->uniqueLinks++; 01221 #endif 01222 } 01223 } 01224 01225 gcNumber = unique->garbageCollections; 01226 looking = cuddAllocNode(unique); 01227 if (looking == NULL) { 01228 return(NULL); 01229 } 01230 unique->keys++; 01231 subtable->keys++; 01232 01233 if (gcNumber != unique->garbageCollections) { 01234 DdNode *looking2; 01235 pos = ddHash(T, E, subtable->shift); 01236 nodelist = subtable->nodelist; 01237 previousP = &(nodelist[pos]); 01238 looking2 = *previousP; 01239 01240 while (T < cuddT(looking2)) { 01241 previousP = &(looking2->next); 01242 looking2 = *previousP; 01243 #ifdef DD_UNIQUE_PROFILE 01244 unique->uniqueLinks++; 01245 #endif 01246 } 01247 while (T == cuddT(looking2) && E < cuddE(looking2)) { 01248 previousP = &(looking2->next); 01249 looking2 = *previousP; 01250 #ifdef DD_UNIQUE_PROFILE 01251 unique->uniqueLinks++; 01252 #endif 01253 } 01254 } 01255 looking->index = index; 01256 cuddT(looking) = T; 01257 cuddE(looking) = E; 01258 looking->next = *previousP; 01259 *previousP = looking; 01260 cuddSatInc(T->ref); /* we know T is a regular pointer */ 01261 cuddRef(E); 01262 01263 #ifdef DD_DEBUG 01264 cuddCheckCollisionOrdering(unique,level,pos); 01265 #endif 01266 01267 return(looking); 01268 01269 } /* 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 1289 of file cuddTable.c.
01294 { 01295 DdNode *result; 01296 DdNode *v; 01297 01298 v = cuddUniqueInter(unique, index, DD_ONE(unique), 01299 Cudd_Not(DD_ONE(unique))); 01300 if (v == NULL) 01301 return(NULL); 01302 cuddRef(v); 01303 result = cuddBddIteRecur(unique, v, T, E); 01304 Cudd_RecursiveDeref(unique, v); 01305 return(result); 01306 }
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 1328 of file cuddTable.c.
01333 { 01334 int pos; 01335 unsigned int level; 01336 int retval; 01337 DdNodePtr *nodelist; 01338 DdNode *looking; 01339 DdSubtable *subtable; 01340 01341 #ifdef DD_UNIQUE_PROFILE 01342 unique->uniqueLookUps++; 01343 #endif 01344 01345 if (index >= unique->sizeZ) { 01346 if (!cuddResizeTableZdd(unique,index)) return(NULL); 01347 } 01348 01349 level = unique->permZ[index]; 01350 subtable = &(unique->subtableZ[level]); 01351 01352 #ifdef DD_DEBUG 01353 assert(level < (unsigned) cuddIZ(unique,T->index)); 01354 assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index)); 01355 #endif 01356 01357 if (subtable->keys > subtable->maxKeys) { 01358 if (unique->gcEnabled && ((unique->deadZ > unique->minDead) || 01359 (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */ 01360 (void) cuddGarbageCollect(unique,1); 01361 } else { 01362 ddRehashZdd(unique,(int)level); 01363 } 01364 } 01365 01366 pos = ddHash(T, E, subtable->shift); 01367 nodelist = subtable->nodelist; 01368 looking = nodelist[pos]; 01369 01370 while (looking != NULL) { 01371 if (cuddT(looking) == T && cuddE(looking) == E) { 01372 if (looking->ref == 0) { 01373 cuddReclaimZdd(unique,looking); 01374 } 01375 return(looking); 01376 } 01377 looking = looking->next; 01378 #ifdef DD_UNIQUE_PROFILE 01379 unique->uniqueLinks++; 01380 #endif 01381 } 01382 01383 /* countDead is 0 if deads should be counted and ~0 if they should not. */ 01384 if (unique->autoDynZ && 01385 unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) { 01386 #ifdef DD_DEBUG 01387 retval = Cudd_DebugCheck(unique); 01388 if (retval != 0) return(NULL); 01389 retval = Cudd_CheckKeys(unique); 01390 if (retval != 0) return(NULL); 01391 #endif 01392 retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */ 01393 if (retval == 0) unique->reordered = 2; 01394 #ifdef DD_DEBUG 01395 retval = Cudd_DebugCheck(unique); 01396 if (retval != 0) unique->reordered = 2; 01397 retval = Cudd_CheckKeys(unique); 01398 if (retval != 0) unique->reordered = 2; 01399 #endif 01400 return(NULL); 01401 } 01402 01403 unique->keysZ++; 01404 subtable->keys++; 01405 01406 looking = cuddAllocNode(unique); 01407 if (looking == NULL) return(NULL); 01408 looking->index = index; 01409 cuddT(looking) = T; 01410 cuddE(looking) = E; 01411 looking->next = nodelist[pos]; 01412 nodelist[pos] = looking; 01413 cuddRef(T); 01414 cuddRef(E); 01415 01416 return(looking); 01417 01418 } /* 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 1028 of file cuddTable.c.
01033 { 01034 DdNode *node; 01035 01036 if (T == DD_ZERO(zdd)) 01037 return(E); 01038 node = cuddUniqueInterZdd(zdd, id, T, E); 01039 return(node); 01040 01041 } /* 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 1061 of file cuddTable.c.
01066 { 01067 DdNode *f, *r, *t; 01068 DdNode *zdd_one = DD_ONE(dd); 01069 DdNode *zdd_zero = DD_ZERO(dd); 01070 01071 f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero); 01072 if (f == NULL) { 01073 return(NULL); 01074 } 01075 cuddRef(f); 01076 t = cuddZddProduct(dd, f, g); 01077 if (t == NULL) { 01078 Cudd_RecursiveDerefZdd(dd, f); 01079 return(NULL); 01080 } 01081 cuddRef(t); 01082 Cudd_RecursiveDerefZdd(dd, f); 01083 r = cuddZddUnion(dd, t, h); 01084 if (r == NULL) { 01085 Cudd_RecursiveDerefZdd(dd, t); 01086 return(NULL); 01087 } 01088 cuddRef(r); 01089 Cudd_RecursiveDerefZdd(dd, t); 01090 01091 cuddDeref(r); 01092 return(r); 01093 01094 } /* 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 2790 of file cuddTable.c.
02792 { 02793 unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); 02794 unique->cacheSlack = (int) ddMin(unique->maxCacheHard, 02795 DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - 02796 2 * (int) unique->cacheSlots; 02797 if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0) 02798 cuddCacheResize(unique); 02799 return; 02800 02801 } /* 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 3065 of file cuddTable.c.
03068 { 03069 MtrNode *auxnode = treenode; 03070 03071 while (auxnode != NULL) { 03072 auxnode->low = dd->perm[auxnode->index]; 03073 if (auxnode->child != NULL) { 03074 ddPatchTree(dd, auxnode->child); 03075 } 03076 auxnode = auxnode->younger; 03077 } 03078 03079 return; 03080 03081 } /* end of ddPatchTree */
static void ddRehashZdd | ( | DdManager * | unique, | |
int | i | |||
) | [static] |
AutomaticStart
Function********************************************************************
Synopsis [Rehashes a ZDD unique subtable.]
Description []
SideEffects [None]
SeeAlso [cuddRehash]
Definition at line 2407 of file cuddTable.c.
02410 { 02411 unsigned int slots, oldslots; 02412 int shift, oldshift; 02413 int j, pos; 02414 DdNodePtr *nodelist, *oldnodelist; 02415 DdNode *node, *next; 02416 extern DD_OOMFP MMoutOfMemory; 02417 DD_OOMFP saveHandler; 02418 02419 if (unique->slots > unique->looseUpTo) { 02420 unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); 02421 #ifdef DD_VERBOSE 02422 if (unique->gcFrac == DD_GC_FRAC_HI) { 02423 (void) fprintf(unique->err,"GC fraction = %.2f\t", 02424 DD_GC_FRAC_LO); 02425 (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); 02426 } 02427 #endif 02428 unique->gcFrac = DD_GC_FRAC_LO; 02429 } 02430 02431 assert(i != CUDD_MAXINDEX); 02432 oldslots = unique->subtableZ[i].slots; 02433 oldshift = unique->subtableZ[i].shift; 02434 oldnodelist = unique->subtableZ[i].nodelist; 02435 02436 /* Compute the new size of the subtable. Normally, we just 02437 ** double. However, after reordering, a table may be severely 02438 ** overloaded. Therefore, we iterate. */ 02439 slots = oldslots; 02440 shift = oldshift; 02441 do { 02442 slots <<= 1; 02443 shift--; 02444 } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys); 02445 02446 saveHandler = MMoutOfMemory; 02447 MMoutOfMemory = Cudd_OutOfMem; 02448 nodelist = ALLOC(DdNodePtr, slots); 02449 MMoutOfMemory = saveHandler; 02450 if (nodelist == NULL) { 02451 (void) fprintf(unique->err, 02452 "Unable to resize ZDD subtable %d for lack of memory.\n", 02453 i); 02454 (void) cuddGarbageCollect(unique,1); 02455 for (j = 0; j < unique->sizeZ; j++) { 02456 unique->subtableZ[j].maxKeys <<= 1; 02457 } 02458 return; 02459 } 02460 unique->subtableZ[i].nodelist = nodelist; 02461 unique->subtableZ[i].slots = slots; 02462 unique->subtableZ[i].shift = shift; 02463 unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; 02464 for (j = 0; (unsigned) j < slots; j++) { 02465 nodelist[j] = NULL; 02466 } 02467 for (j = 0; (unsigned) j < oldslots; j++) { 02468 node = oldnodelist[j]; 02469 while (node != NULL) { 02470 next = node->next; 02471 pos = ddHash(cuddT(node), cuddE(node), shift); 02472 node->next = nodelist[pos]; 02473 nodelist[pos] = node; 02474 node = next; 02475 } 02476 } 02477 FREE(oldnodelist); 02478 02479 #ifdef DD_VERBOSE 02480 (void) fprintf(unique->err, 02481 "rehashing layer %d: keys %d dead %d new size %d\n", 02482 i, unique->subtableZ[i].keys, 02483 unique->subtableZ[i].dead, slots); 02484 #endif 02485 02486 /* Update global data. */ 02487 unique->memused += (slots - oldslots) * sizeof(DdNode *); 02488 unique->slots += (slots - oldslots); 02489 ddFixLimits(unique); 02490 02491 } /* end of ddRehashZdd */
static void ddReportRefMess | ( | DdManager * | unique, | |
int | i, | |||
const char * | caller | |||
) | [static] |
Function********************************************************************
Synopsis [Reports problem in garbage collection.]
Description []
SideEffects [None]
SeeAlso [cuddGarbageCollect cuddGarbageCollectZdd]
Definition at line 3142 of file cuddTable.c.
03146 { 03147 if (i == CUDD_CONST_INDEX) { 03148 (void) fprintf(unique->err, 03149 "%s: problem in constants\n", caller); 03150 } else if (i != -1) { 03151 (void) fprintf(unique->err, 03152 "%s: problem in table %d\n", caller, i); 03153 } 03154 (void) fprintf(unique->err, " dead count != deleted\n"); 03155 (void) fprintf(unique->err, " This problem is often due to a missing \ 03156 call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \ 03157 See the CUDD Programmer's Guide for additional details."); 03158 abort(); 03159 03160 } /* 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 2508 of file cuddTable.c.
02511 { 02512 DdSubtable *newsubtables; 02513 DdNodePtr *newnodelist; 02514 DdNodePtr *newvars; 02515 DdNode *sentinel = &(unique->sentinel); 02516 int oldsize,newsize; 02517 int i,j,reorderSave; 02518 int numSlots = unique->initSlots; 02519 int *newperm, *newinvperm, *newmap; 02520 DdNode *one, *zero; 02521 02522 oldsize = unique->size; 02523 /* Easy case: there is still room in the current table. */ 02524 if (index < unique->maxSize) { 02525 for (i = oldsize; i <= index; i++) { 02526 unique->subtables[i].slots = numSlots; 02527 unique->subtables[i].shift = sizeof(int) * 8 - 02528 cuddComputeFloorLog2(numSlots); 02529 unique->subtables[i].keys = 0; 02530 unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02531 unique->subtables[i].dead = 0; 02532 unique->subtables[i].bindVar = 0; 02533 unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 02534 unique->subtables[i].pairIndex = 0; 02535 unique->subtables[i].varHandled = 0; 02536 unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; 02537 02538 unique->perm[i] = i; 02539 unique->invperm[i] = i; 02540 newnodelist = unique->subtables[i].nodelist = 02541 ALLOC(DdNodePtr, numSlots); 02542 if (newnodelist == NULL) { 02543 for (j = oldsize; j < i; j++) { 02544 FREE(unique->subtables[j].nodelist); 02545 } 02546 unique->errorCode = CUDD_MEMORY_OUT; 02547 return(0); 02548 } 02549 for (j = 0; j < numSlots; j++) { 02550 newnodelist[j] = sentinel; 02551 } 02552 } 02553 if (unique->map != NULL) { 02554 for (i = oldsize; i <= index; i++) { 02555 unique->map[i] = i; 02556 } 02557 } 02558 } else { 02559 /* The current table is too small: we need to allocate a new, 02560 ** larger one; move all old subtables, and initialize the new 02561 ** subtables up to index included. 02562 */ 02563 newsize = index + DD_DEFAULT_RESIZE; 02564 #ifdef DD_VERBOSE 02565 (void) fprintf(unique->err, 02566 "Increasing the table size from %d to %d\n", 02567 unique->maxSize, newsize); 02568 #endif 02569 newsubtables = ALLOC(DdSubtable,newsize); 02570 if (newsubtables == NULL) { 02571 unique->errorCode = CUDD_MEMORY_OUT; 02572 return(0); 02573 } 02574 newvars = ALLOC(DdNodePtr,newsize); 02575 if (newvars == NULL) { 02576 FREE(newsubtables); 02577 unique->errorCode = CUDD_MEMORY_OUT; 02578 return(0); 02579 } 02580 newperm = ALLOC(int,newsize); 02581 if (newperm == NULL) { 02582 FREE(newsubtables); 02583 FREE(newvars); 02584 unique->errorCode = CUDD_MEMORY_OUT; 02585 return(0); 02586 } 02587 newinvperm = ALLOC(int,newsize); 02588 if (newinvperm == NULL) { 02589 FREE(newsubtables); 02590 FREE(newvars); 02591 FREE(newperm); 02592 unique->errorCode = CUDD_MEMORY_OUT; 02593 return(0); 02594 } 02595 if (unique->map != NULL) { 02596 newmap = ALLOC(int,newsize); 02597 if (newmap == NULL) { 02598 FREE(newsubtables); 02599 FREE(newvars); 02600 FREE(newperm); 02601 FREE(newinvperm); 02602 unique->errorCode = CUDD_MEMORY_OUT; 02603 return(0); 02604 } 02605 unique->memused += (newsize - unique->maxSize) * sizeof(int); 02606 } 02607 unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * 02608 sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); 02609 if (newsize > unique->maxSizeZ) { 02610 FREE(unique->stack); 02611 unique->stack = ALLOC(DdNodePtr,newsize + 1); 02612 if (unique->stack == NULL) { 02613 FREE(newsubtables); 02614 FREE(newvars); 02615 FREE(newperm); 02616 FREE(newinvperm); 02617 if (unique->map != NULL) { 02618 FREE(newmap); 02619 } 02620 unique->errorCode = CUDD_MEMORY_OUT; 02621 return(0); 02622 } 02623 unique->stack[0] = NULL; /* to suppress harmless UMR */ 02624 unique->memused += 02625 (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) 02626 * sizeof(DdNode *); 02627 } 02628 for (i = 0; i < oldsize; i++) { 02629 newsubtables[i].slots = unique->subtables[i].slots; 02630 newsubtables[i].shift = unique->subtables[i].shift; 02631 newsubtables[i].keys = unique->subtables[i].keys; 02632 newsubtables[i].maxKeys = unique->subtables[i].maxKeys; 02633 newsubtables[i].dead = unique->subtables[i].dead; 02634 newsubtables[i].nodelist = unique->subtables[i].nodelist; 02635 newsubtables[i].bindVar = unique->subtables[i].bindVar; 02636 newsubtables[i].varType = unique->subtables[i].varType; 02637 newsubtables[i].pairIndex = unique->subtables[i].pairIndex; 02638 newsubtables[i].varHandled = unique->subtables[i].varHandled; 02639 newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; 02640 02641 newvars[i] = unique->vars[i]; 02642 newperm[i] = unique->perm[i]; 02643 newinvperm[i] = unique->invperm[i]; 02644 } 02645 for (i = oldsize; i <= index; i++) { 02646 newsubtables[i].slots = numSlots; 02647 newsubtables[i].shift = sizeof(int) * 8 - 02648 cuddComputeFloorLog2(numSlots); 02649 newsubtables[i].keys = 0; 02650 newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; 02651 newsubtables[i].dead = 0; 02652 newsubtables[i].bindVar = 0; 02653 newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; 02654 newsubtables[i].pairIndex = 0; 02655 newsubtables[i].varHandled = 0; 02656 newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; 02657 02658 newperm[i] = i; 02659 newinvperm[i] = i; 02660 newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); 02661 if (newnodelist == NULL) { 02662 unique->errorCode = CUDD_MEMORY_OUT; 02663 return(0); 02664 } 02665 for (j = 0; j < numSlots; j++) { 02666 newnodelist[j] = sentinel; 02667 } 02668 } 02669 if (unique->map != NULL) { 02670 for (i = 0; i < oldsize; i++) { 02671 newmap[i] = unique->map[i]; 02672 } 02673 for (i = oldsize; i <= index; i++) { 02674 newmap[i] = i; 02675 } 02676 FREE(unique->map); 02677 unique->map = newmap; 02678 } 02679 FREE(unique->subtables); 02680 unique->subtables = newsubtables; 02681 unique->maxSize = newsize; 02682 FREE(unique->vars); 02683 unique->vars = newvars; 02684 FREE(unique->perm); 02685 unique->perm = newperm; 02686 FREE(unique->invperm); 02687 unique->invperm = newinvperm; 02688 } 02689 02690 /* Now that the table is in a coherent state, create the new 02691 ** projection functions. We need to temporarily disable reordering, 02692 ** because we cannot reorder without projection functions in place. 02693 **/ 02694 one = unique->one; 02695 zero = Cudd_Not(one); 02696 02697 unique->size = index + 1; 02698 unique->slots += (index + 1 - oldsize) * numSlots; 02699 ddFixLimits(unique); 02700 02701 reorderSave = unique->autoDyn; 02702 unique->autoDyn = 0; 02703 for (i = oldsize; i <= index; i++) { 02704 unique->vars[i] = cuddUniqueInter(unique,i,one,zero); 02705 if (unique->vars[i] == NULL) { 02706 unique->autoDyn = reorderSave; 02707 for (j = oldsize; j < i; j++) { 02708 Cudd_IterDerefBdd(unique,unique->vars[j]); 02709 cuddDeallocNode(unique,unique->vars[j]); 02710 unique->vars[j] = NULL; 02711 } 02712 for (j = oldsize; j <= index; j++) { 02713 FREE(unique->subtables[j].nodelist); 02714 unique->subtables[j].nodelist = NULL; 02715 } 02716 unique->size = oldsize; 02717 unique->slots -= (index + 1 - oldsize) * numSlots; 02718 ddFixLimits(unique); 02719 return(0); 02720 } 02721 cuddRef(unique->vars[i]); 02722 } 02723 unique->autoDyn = reorderSave; 02724 02725 return(1); 02726 02727 } /* end of ddResizeTable */
char rcsid [] DD_UNUSED = "$Id: cuddTable.c,v 1.122 2009/02/19 16:24:28 fabio Exp $" [static] |
Definition at line 120 of file cuddTable.c.