SVF
Classes | Typedefs | Functions | Variables
cuddTable.c File Reference
#include "CUDD/util.h"
#include "CUDD/cuddInt.h"

Go to the source code of this file.

Classes

union  hack
 

Typedefs

typedef union hack hack
 

Functions

static void ddRehashZdd (DdManager *unique, int i)
 
static int ddResizeTable (DdManager *unique, int index, int amount)
 
static int cuddFindParent (DdManager *table, DdNode *node)
 
static DD_INLINE void ddFixLimits (DdManager *unique)
 
static void ddPatchTree (DdManager *dd, MtrNode *treenode)
 
static void ddReportRefMess (DdManager *unique, int i, const char *caller)
 
unsigned int Cudd_Prime (unsigned int p)
 
int Cudd_Reserve (DdManager *manager, int amount)
 
DdNodecuddAllocNode (DdManager *unique)
 
DdManagercuddInitTable (unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo)
 
void cuddFreeTable (DdManager *unique)
 
int cuddGarbageCollect (DdManager *unique, int clearCache)
 
DdNodecuddZddGetNode (DdManager *zdd, int id, DdNode *T, DdNode *E)
 
DdNodecuddZddGetNodeIVO (DdManager *dd, int index, DdNode *g, DdNode *h)
 
DdNodecuddUniqueInter (DdManager *unique, int index, DdNode *T, DdNode *E)
 
DdNodecuddUniqueInterIVO (DdManager *unique, int index, DdNode *T, DdNode *E)
 
DdNodecuddUniqueInterZdd (DdManager *unique, int index, DdNode *T, DdNode *E)
 
DdNodecuddUniqueConst (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.126 2012/02/05 01:07:19 fabio Exp $"
 

Typedef Documentation

◆ hack

typedef union hack hack

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 [Copyright (c) 1995-2012, Regents of the University of Colorado

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]

Function Documentation

◆ Cudd_Prime()

unsigned int Cudd_Prime ( unsigned int  p)

AutomaticEnd Function********************************************************************

Synopsis [Returns the next prime >= p.]

Description []

SideEffects [None]

Definition at line 185 of file cuddTable.c.

187 {
188  int i,pn;
189 
190  p--;
191  do {
192  p++;
193  if (p&1) {
194  pn = 1;
195  i = 3;
196  while ((unsigned) (i * i) <= p) {
197  if (p % i == 0) {
198  pn = 0;
199  break;
200  }
201  i += 2;
202  }
203  } else {
204  pn = 0;
205  }
206  } while (!pn);
207  return(p);
208 
209 } /* end of Cudd_Prime */

◆ Cudd_Reserve()

int Cudd_Reserve ( DdManager manager,
int  amount 
)

Function********************************************************************

Synopsis [Expand manager without creating variables.]

Description [Expand a manager by a specified number of subtables without actually creating new variables. This function can be used to reduce the frequency of resizing when an estimate of the number of variables is available. One would call this function instead of passing the number of variables to Cudd_Init if variables should not be created right away of if the estimate on their number became available only after the manager has been created. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [Cudd_Init]

Definition at line 230 of file cuddTable.c.

233 {
234  int currentSize = manager->size;
235  if (amount < 0)
236  return(0);
237  if (currentSize + amount < currentSize) /* overflow */
238  return(0);
239  if (amount <= manager->maxSize - manager->size)
240  return(1);
241  return ddResizeTable(manager, -1, amount);
242 
243 } /* end of Cudd_Reserve */
static int ddResizeTable(DdManager *unique, int index, int amount)
Definition: cuddTable.c:2555
int size
Definition: cuddInt.h:345

◆ cuddAllocNode()

DdNode* cuddAllocNode ( DdManager unique)

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 266 of file cuddTable.c.

268 {
269  int i;
270  DdNodePtr *mem;
271  DdNode *list, *node;
272  extern DD_OOMFP MMoutOfMemory;
273  DD_OOMFP saveHandler;
274 
275  if (unique->nextFree == NULL) { /* free list is empty */
276  /* Check for exceeded limits. */
277  if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) >
278  unique->maxLive) {
279  unique->errorCode = CUDD_TOO_MANY_NODES;
280  return(NULL);
281  }
282  if (util_cpu_time() - unique->startTime > unique->timeLimit) {
284  return(NULL);
285  }
286  if (unique->stash == NULL || unique->memused > unique->maxmemhard) {
287  (void) cuddGarbageCollect(unique,1);
288  mem = NULL;
289  }
290  if (unique->nextFree == NULL) {
291  if (unique->memused > unique->maxmemhard) {
293  return(NULL);
294  }
295  /* Try to allocate a new block. */
296  saveHandler = MMoutOfMemory;
297  MMoutOfMemory = Cudd_OutOfMem;
298  mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
299  MMoutOfMemory = saveHandler;
300  if (mem == NULL) {
301  /* No more memory: Try collecting garbage. If this succeeds,
302  ** we end up with mem still NULL, but unique->nextFree !=
303  ** NULL. */
304  if (cuddGarbageCollect(unique,1) == 0) {
305  /* Last resort: Free the memory stashed away, if there
306  ** any. If this succeeeds, mem != NULL and
307  ** unique->nextFree still NULL. */
308  if (unique->stash != NULL) {
309  FREE(unique->stash);
310  unique->stash = NULL;
311  /* Inhibit resizing of tables. */
312  cuddSlowTableGrowth(unique);
313  /* Now try again. */
314  mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
315  }
316  if (mem == NULL) {
317  /* Out of luck. Call the default handler to do
318  ** whatever it specifies for a failed malloc.
319  ** If this handler returns, then set error code,
320  ** print warning, and return. */
321  (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
322  unique->errorCode = CUDD_MEMORY_OUT;
323 #ifdef DD_VERBOSE
324  (void) fprintf(unique->err,
325  "cuddAllocNode: out of memory");
326  (void) fprintf(unique->err, "Memory in use = %lu\n",
327  unique->memused);
328 #endif
329  return(NULL);
330  }
331  }
332  }
333  if (mem != NULL) { /* successful allocation; slice memory */
334  ptruint offset;
335  unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
336  mem[0] = (DdNodePtr) unique->memoryList;
337  unique->memoryList = mem;
338 
339  /* Here we rely on the fact that a DdNode is as large
340  ** as 4 pointers. */
341  offset = (ptruint) mem & (sizeof(DdNode) - 1);
342  mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
343  assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0);
344  list = (DdNode *) mem;
345 
346  i = 1;
347  do {
348  list[i - 1].ref = 0;
349  list[i - 1].next = &list[i];
350  } while (++i < DD_MEM_CHUNK);
351 
352  list[DD_MEM_CHUNK-1].ref = 0;
353  list[DD_MEM_CHUNK-1].next = NULL;
354 
355  unique->nextFree = &list[0];
356  }
357  }
358  }
359  unique->allocated++;
360  node = unique->nextFree;
361  unique->nextFree = node->next;
362  return(node);
363 
364 } /* end of cuddAllocNode */
DdHalfWord ref
Definition: cudd.h:272
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
double allocated
Definition: cuddInt.h:365
Definition: cudd.h:270
unsigned int deadZ
Definition: cuddInt.h:356
#define FREE(obj)
Definition: util.h:80
unsigned long startTime
Definition: cuddInt.h:426
#define assert(ex)
Definition: util.h:141
FILE * err
Definition: cuddInt.h:424
DdNode * DdNodePtr
Definition: cuddInt.h:253
void(* DD_OOMFP)(long)
Definition: cudd.h:311
struct DdNode DdNode
Definition: cudd.h:262
unsigned int dead
Definition: cuddInt.h:355
unsigned int maxLive
Definition: cuddInt.h:357
char * stash
Definition: cuddInt.h:382
unsigned int keys
Definition: cuddInt.h:353
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
#define ALLOC(type, num)
Definition: util.h:76
DdNode * next
Definition: cudd.h:273
long util_cpu_time(void)
Definition: cpu_time.c:34
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
DdNode ** memoryList
Definition: cuddInt.h:380
void cuddSlowTableGrowth(DdManager *unique)
Definition: cuddTable.c:2414
unsigned long memused
Definition: cuddInt.h:429
unsigned int ptruint
Definition: cuddInt.h:250
DdNode * nextFree
Definition: cuddInt.h:381
unsigned long maxmemhard
Definition: cuddInt.h:431
#define DD_MEM_CHUNK
Definition: cuddInt.h:105
unsigned int keysZ
Definition: cuddInt.h:354
unsigned long timeLimit
Definition: cuddInt.h:427
Cudd_ErrorType errorCode
Definition: cuddInt.h:425

◆ cuddDestroySubtables()

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 2137 of file cuddTable.c.

2140 {
2141  DdSubtable *subtables;
2142  DdNodePtr *nodelist;
2143  DdNodePtr *vars;
2144  int firstIndex, lastIndex;
2145  int index, level, newlevel;
2146  int lowestLevel;
2147  int shift;
2148  int found;
2149 
2150  /* Sanity check and set up. */
2151  if (n <= 0) return(0);
2152  if (n > unique->size) n = unique->size;
2153 
2154  subtables = unique->subtables;
2155  vars = unique->vars;
2156  firstIndex = unique->size - n;
2157  lastIndex = unique->size;
2158 
2159  /* Check for nodes labeled by the variables being destroyed
2160  ** that may still be in use. It is allowed to destroy a variable
2161  ** only if there are no such nodes. Also, find the lowest level
2162  ** among the variables being destroyed. This will make further
2163  ** processing more efficient.
2164  */
2165  lowestLevel = unique->size;
2166  for (index = firstIndex; index < lastIndex; index++) {
2167  level = unique->perm[index];
2168  if (level < lowestLevel) lowestLevel = level;
2169  nodelist = subtables[level].nodelist;
2170  if (subtables[level].keys - subtables[level].dead != 1) return(0);
2171  /* The projection function should be isolated. If the ref count
2172  ** is 1, everything is OK. If the ref count is saturated, then
2173  ** we need to make sure that there are no nodes pointing to it.
2174  ** As for the external references, we assume the application is
2175  ** responsible for them.
2176  */
2177  if (vars[index]->ref != 1) {
2178  if (vars[index]->ref != DD_MAXREF) return(0);
2179  found = cuddFindParent(unique,vars[index]);
2180  if (found) {
2181  return(0);
2182  } else {
2183  vars[index]->ref = 1;
2184  }
2185  }
2186  Cudd_RecursiveDeref(unique,vars[index]);
2187  }
2188 
2189  /* Collect garbage, because we cannot afford having dead nodes pointing
2190  ** to the dead nodes in the subtables being destroyed.
2191  */
2192  (void) cuddGarbageCollect(unique,1);
2193 
2194  /* Here we know we can destroy our subtables. */
2195  for (index = firstIndex; index < lastIndex; index++) {
2196  level = unique->perm[index];
2197  nodelist = subtables[level].nodelist;
2198 #ifdef DD_DEBUG
2199  assert(subtables[level].keys == 0);
2200 #endif
2201  FREE(nodelist);
2202  unique->memused -= sizeof(DdNodePtr) * subtables[level].slots;
2203  unique->slots -= subtables[level].slots;
2204  unique->dead -= subtables[level].dead;
2205  }
2206 
2207  /* Here all subtables to be destroyed have their keys field == 0 and
2208  ** their hash tables have been freed.
2209  ** We now scan the subtables from level lowestLevel + 1 to level size - 1,
2210  ** shifting the subtables as required. We keep a running count of
2211  ** how many subtables have been moved, so that we know by how many
2212  ** positions each subtable should be shifted.
2213  */
2214  shift = 1;
2215  for (level = lowestLevel + 1; level < unique->size; level++) {
2216  if (subtables[level].keys == 0) {
2217  shift++;
2218  continue;
2219  }
2220  newlevel = level - shift;
2221  subtables[newlevel].slots = subtables[level].slots;
2222  subtables[newlevel].shift = subtables[level].shift;
2223  subtables[newlevel].keys = subtables[level].keys;
2224  subtables[newlevel].maxKeys = subtables[level].maxKeys;
2225  subtables[newlevel].dead = subtables[level].dead;
2226  subtables[newlevel].nodelist = subtables[level].nodelist;
2227  index = unique->invperm[level];
2228  unique->perm[index] = newlevel;
2229  unique->invperm[newlevel] = index;
2230  subtables[newlevel].bindVar = subtables[level].bindVar;
2231  subtables[newlevel].varType = subtables[level].varType;
2232  subtables[newlevel].pairIndex = subtables[level].pairIndex;
2233  subtables[newlevel].varHandled = subtables[level].varHandled;
2234  subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped;
2235  }
2236  /* Destroy the map. If a surviving variable is
2237  ** mapped to a dying variable, and the map were used again,
2238  ** an out-of-bounds access to unique->vars would result. */
2239  if (unique->map != NULL) {
2240  cuddCacheFlush(unique);
2241  FREE(unique->map);
2242  unique->map = NULL;
2243  }
2244 
2245  unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
2246  unique->size -= n;
2247 
2248  return(1);
2249 
2250 } /* end of cuddDestroySubtables */
DdHalfWord ref
Definition: cudd.h:272
#define DD_MAXREF
Definition: cuddInt.h:101
unsigned int keys
Definition: cuddInt.h:314
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:150
int * map
Definition: cuddInt.h:374
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
#define assert(ex)
Definition: util.h:141
int size
Definition: cuddInt.h:345
double gcFrac
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:352
int bindVar
Definition: cuddInt.h:318
DdSubtable * subtables
Definition: cuddInt.h:349
DdNode * DdNodePtr
Definition: cuddInt.h:253
Cudd_VariableType varType
Definition: cuddInt.h:320
unsigned int dead
Definition: cuddInt.h:355
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
unsigned int dead
Definition: cuddInt.h:316
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:323
static int cuddFindParent(DdManager *table, DdNode *node)
Definition: cuddTable.c:2796
unsigned int maxKeys
Definition: cuddInt.h:315
DdNode ** nodelist
Definition: cuddInt.h:311
int varHandled
Definition: cuddInt.h:322
unsigned long memused
Definition: cuddInt.h:429
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1004
unsigned int slots
Definition: cuddInt.h:313
DdNode ** vars
Definition: cuddInt.h:373
int pairIndex
Definition: cuddInt.h:321
int * invperm
Definition: cuddInt.h:371
int shift
Definition: cuddInt.h:312
int * perm
Definition: cuddInt.h:369
unsigned int minDead
Definition: cuddInt.h:358

◆ cuddFindParent()

static int cuddFindParent ( DdManager table,
DdNode node 
)
static

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 2796 of file cuddTable.c.

2799 {
2800  int i,j;
2801  int slots;
2802  DdNodePtr *nodelist;
2803  DdNode *f;
2804 
2805  for (i = cuddI(table,node->index) - 1; i >= 0; i--) {
2806  nodelist = table->subtables[i].nodelist;
2807  slots = table->subtables[i].slots;
2808 
2809  for (j = 0; j < slots; j++) {
2810  f = nodelist[j];
2811  while (cuddT(f) > node) {
2812  f = f->next;
2813  }
2814  while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) {
2815  f = f->next;
2816  }
2817  if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) {
2818  return(1);
2819  }
2820  }
2821  }
2822 
2823  return(0);
2824 
2825 } /* end of cuddFindParent */
Definition: cudd.h:270
#define Cudd_Regular(node)
Definition: cudd.h:384
DdSubtable * subtables
Definition: cuddInt.h:349
DdNode * next
Definition: cudd.h:273
DdNode ** nodelist
Definition: cuddInt.h:311
#define cuddT(node)
Definition: cuddInt.h:609
#define cuddI(dd, index)
Definition: cuddInt.h:659
DdHalfWord index
Definition: cudd.h:271
unsigned int slots
Definition: cuddInt.h:313
#define cuddE(node)
Definition: cuddInt.h:625

◆ cuddFreeTable()

void cuddFreeTable ( DdManager unique)

Function********************************************************************

Synopsis [Frees the resources associated to a unique table.]

Description []

SideEffects [None]

SeeAlso [cuddInitTable]

Definition at line 692 of file cuddTable.c.

694 {
695  DdNodePtr *next;
696  DdNodePtr *memlist = unique->memoryList;
697  int i;
698 
699  if (unique->univ != NULL) cuddZddFreeUniv(unique);
700  while (memlist != NULL) {
701  next = (DdNodePtr *) memlist[0]; /* link to next block */
702  FREE(memlist);
703  memlist = next;
704  }
705  unique->nextFree = NULL;
706  unique->memoryList = NULL;
707 
708  for (i = 0; i < unique->size; i++) {
709  FREE(unique->subtables[i].nodelist);
710  }
711  for (i = 0; i < unique->sizeZ; i++) {
712  FREE(unique->subtableZ[i].nodelist);
713  }
714  FREE(unique->constants.nodelist);
715  FREE(unique->subtables);
716  FREE(unique->subtableZ);
717  FREE(unique->acache);
718  FREE(unique->perm);
719  FREE(unique->permZ);
720  FREE(unique->invperm);
721  FREE(unique->invpermZ);
722  FREE(unique->vars);
723  if (unique->map != NULL) FREE(unique->map);
724  FREE(unique->stack);
725 #ifndef DD_NO_DEATH_ROW
726  FREE(unique->deathRow);
727 #endif
728  if (unique->tree != NULL) Mtr_FreeTree(unique->tree);
729  if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ);
730  if (unique->linear != NULL) FREE(unique->linear);
731  while (unique->preGCHook != NULL)
732  Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK);
733  while (unique->postGCHook != NULL)
735  while (unique->preReorderingHook != NULL)
736  Cudd_RemoveHook(unique,unique->preReorderingHook->f,
738  while (unique->postReorderingHook != NULL)
739  Cudd_RemoveHook(unique,unique->postReorderingHook->f,
741  FREE(unique);
742 
743 } /* end of cuddFreeTable */
void cuddZddFreeUniv(DdManager *zdd)
Definition: cuddInit.c:294
int * map
Definition: cuddInt.h:374
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
DdHook * preReorderingHook
Definition: cuddInt.h:421
int * invpermZ
Definition: cuddInt.h:372
int size
Definition: cuddInt.h:345
void Mtr_FreeTree(MtrNode *node)
Definition: mtrBasic.c:187
DdSubtable * subtables
Definition: cuddInt.h:349
int * permZ
Definition: cuddInt.h:370
MtrNode * tree
Definition: cuddInt.h:408
DD_HFP f
Definition: cuddInt.h:241
DdNode ** deathRow
Definition: cuddInt.h:384
DdNode ** stack
Definition: cuddInt.h:364
DdHook * postReorderingHook
Definition: cuddInt.h:422
long * linear
Definition: cuddInt.h:378
DdNode ** nodelist
Definition: cuddInt.h:311
int Cudd_RemoveHook(DdManager *dd, DD_HFP f, Cudd_HookType where)
Definition: cuddAPI.c:3631
DdNode ** memoryList
Definition: cuddInt.h:380
DdNode * nextFree
Definition: cuddInt.h:381
int sizeZ
Definition: cuddInt.h:346
DdNode ** vars
Definition: cuddInt.h:373
DdHook * postGCHook
Definition: cuddInt.h:420
MtrNode * treeZ
Definition: cuddInt.h:409
int * invperm
Definition: cuddInt.h:371
DdSubtable constants
Definition: cuddInt.h:351
DdCache * acache
Definition: cuddInt.h:335
DdHook * preGCHook
Definition: cuddInt.h:419
int * perm
Definition: cuddInt.h:369
DdSubtable * subtableZ
Definition: cuddInt.h:350
DdNode ** univ
Definition: cuddInt.h:375

◆ cuddGarbageCollect()

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 762 of file cuddTable.c.

765 {
766  DdHook *hook;
767  DdCache *cache = unique->cache;
768  DdNode *sentinel = &(unique->sentinel);
769  DdNodePtr *nodelist;
770  int i, j, deleted, totalDeleted, totalDeletedZ;
771  DdCache *c;
772  DdNode *node,*next;
773  DdNodePtr *lastP;
774  int slots;
775  unsigned long localTime;
776 #ifndef DD_UNSORTED_FREE_LIST
777 #ifdef DD_RED_BLACK_FREE_LIST
778  DdNodePtr tree;
779 #else
780  DdNodePtr *memListTrav, *nxtNode;
781  DdNode *downTrav, *sentry;
782  int k;
783 #endif
784 #endif
785 
786 #ifndef DD_NO_DEATH_ROW
787  cuddClearDeathRow(unique);
788 #endif
789 
790  hook = unique->preGCHook;
791  while (hook != NULL) {
792  int res = (hook->f)(unique,"DD",NULL);
793  if (res == 0) return(0);
794  hook = hook->next;
795  }
796 
797  if (unique->dead + unique->deadZ == 0) {
798  hook = unique->postGCHook;
799  while (hook != NULL) {
800  int res = (hook->f)(unique,"DD",NULL);
801  if (res == 0) return(0);
802  hook = hook->next;
803  }
804  return(0);
805  }
806 
807  /* If many nodes are being reclaimed, we want to resize the tables
808  ** more aggressively, to reduce the frequency of garbage collection.
809  */
810  if (clearCache && unique->gcFrac == DD_GC_FRAC_LO &&
811  unique->slots <= unique->looseUpTo && unique->stash != NULL) {
812  unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
813 #ifdef DD_VERBOSE
814  (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI);
815  (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
816 #endif
817  unique->gcFrac = DD_GC_FRAC_HI;
818  return(0);
819  }
820 
821  localTime = util_cpu_time();
822 
823  unique->garbageCollections++;
824 #ifdef DD_VERBOSE
825  (void) fprintf(unique->err,
826  "garbage collecting (%d dead BDD nodes out of %d, min %d)...",
827  unique->dead, unique->keys, unique->minDead);
828  (void) fprintf(unique->err,
829  " (%d dead ZDD nodes out of %d)...",
830  unique->deadZ, unique->keysZ);
831 #endif
832 
833  /* Remove references to garbage collected nodes from the cache. */
834  if (clearCache) {
835  slots = unique->cacheSlots;
836  for (i = 0; i < slots; i++) {
837  c = &cache[i];
838  if (c->data != NULL) {
839  if (cuddClean(c->f)->ref == 0 ||
840  cuddClean(c->g)->ref == 0 ||
841  (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) ||
842  (c->data != DD_NON_CONSTANT &&
843  Cudd_Regular(c->data)->ref == 0)) {
844  c->data = NULL;
845  unique->cachedeletions++;
846  }
847  }
848  }
849  cuddLocalCacheClearDead(unique);
850  }
851 
852  /* Now return dead nodes to free list. Count them for sanity check. */
853  totalDeleted = 0;
854 #ifndef DD_UNSORTED_FREE_LIST
855 #ifdef DD_RED_BLACK_FREE_LIST
856  tree = NULL;
857 #endif
858 #endif
859 
860  for (i = 0; i < unique->size; i++) {
861  if (unique->subtables[i].dead == 0) continue;
862  nodelist = unique->subtables[i].nodelist;
863 
864  deleted = 0;
865  slots = unique->subtables[i].slots;
866  for (j = 0; j < slots; j++) {
867  lastP = &(nodelist[j]);
868  node = *lastP;
869  while (node != sentinel) {
870  next = node->next;
871  if (node->ref == 0) {
872  deleted++;
873 #ifndef DD_UNSORTED_FREE_LIST
874 #ifdef DD_RED_BLACK_FREE_LIST
875  cuddOrderedInsert(&tree,node);
876 #endif
877 #else
878  cuddDeallocNode(unique,node);
879 #endif
880  } else {
881  *lastP = node;
882  lastP = &(node->next);
883  }
884  node = next;
885  }
886  *lastP = sentinel;
887  }
888  if ((unsigned) deleted != unique->subtables[i].dead) {
889  ddReportRefMess(unique, i, "cuddGarbageCollect");
890  }
891  totalDeleted += deleted;
892  unique->subtables[i].keys -= deleted;
893  unique->subtables[i].dead = 0;
894  }
895  if (unique->constants.dead != 0) {
896  nodelist = unique->constants.nodelist;
897  deleted = 0;
898  slots = unique->constants.slots;
899  for (j = 0; j < slots; j++) {
900  lastP = &(nodelist[j]);
901  node = *lastP;
902  while (node != NULL) {
903  next = node->next;
904  if (node->ref == 0) {
905  deleted++;
906 #ifndef DD_UNSORTED_FREE_LIST
907 #ifdef DD_RED_BLACK_FREE_LIST
908  cuddOrderedInsert(&tree,node);
909 #endif
910 #else
911  cuddDeallocNode(unique,node);
912 #endif
913  } else {
914  *lastP = node;
915  lastP = &(node->next);
916  }
917  node = next;
918  }
919  *lastP = NULL;
920  }
921  if ((unsigned) deleted != unique->constants.dead) {
922  ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect");
923  }
924  totalDeleted += deleted;
925  unique->constants.keys -= deleted;
926  unique->constants.dead = 0;
927  }
928  if ((unsigned) totalDeleted != unique->dead) {
929  ddReportRefMess(unique, -1, "cuddGarbageCollect");
930  }
931  unique->keys -= totalDeleted;
932  unique->dead = 0;
933 #ifdef DD_STATS
934  unique->nodesFreed += (double) totalDeleted;
935 #endif
936 
937  totalDeletedZ = 0;
938 
939  for (i = 0; i < unique->sizeZ; i++) {
940  if (unique->subtableZ[i].dead == 0) continue;
941  nodelist = unique->subtableZ[i].nodelist;
942 
943  deleted = 0;
944  slots = unique->subtableZ[i].slots;
945  for (j = 0; j < slots; j++) {
946  lastP = &(nodelist[j]);
947  node = *lastP;
948  while (node != NULL) {
949  next = node->next;
950  if (node->ref == 0) {
951  deleted++;
952 #ifndef DD_UNSORTED_FREE_LIST
953 #ifdef DD_RED_BLACK_FREE_LIST
954  cuddOrderedInsert(&tree,node);
955 #endif
956 #else
957  cuddDeallocNode(unique,node);
958 #endif
959  } else {
960  *lastP = node;
961  lastP = &(node->next);
962  }
963  node = next;
964  }
965  *lastP = NULL;
966  }
967  if ((unsigned) deleted != unique->subtableZ[i].dead) {
968  ddReportRefMess(unique, i, "cuddGarbageCollect");
969  }
970  totalDeletedZ += deleted;
971  unique->subtableZ[i].keys -= deleted;
972  unique->subtableZ[i].dead = 0;
973  }
974 
975  /* No need to examine the constant table for ZDDs.
976  ** If we did we should be careful not to count whatever dead
977  ** nodes we found there among the dead ZDD nodes. */
978  if ((unsigned) totalDeletedZ != unique->deadZ) {
979  ddReportRefMess(unique, -1, "cuddGarbageCollect");
980  }
981  unique->keysZ -= totalDeletedZ;
982  unique->deadZ = 0;
983 #ifdef DD_STATS
984  unique->nodesFreed += (double) totalDeletedZ;
985 #endif
986 
987 
988 #ifndef DD_UNSORTED_FREE_LIST
989 #ifdef DD_RED_BLACK_FREE_LIST
990  unique->nextFree = cuddOrderedThread(tree,unique->nextFree);
991 #else
992  memListTrav = unique->memoryList;
993  sentry = NULL;
994  while (memListTrav != NULL) {
995  ptruint offset;
996  nxtNode = (DdNodePtr *)memListTrav[0];
997  offset = (ptruint) memListTrav & (sizeof(DdNode) - 1);
998  memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
999  downTrav = (DdNode *)memListTrav;
1000  k = 0;
1001  do {
1002  if (downTrav[k].ref == 0) {
1003  if (sentry == NULL) {
1004  unique->nextFree = sentry = &downTrav[k];
1005  } else {
1006  /* First hook sentry->next to the dead node and then
1007  ** reassign sentry to the dead node. */
1008  sentry = (sentry->next = &downTrav[k]);
1009  }
1010  }
1011  } while (++k < DD_MEM_CHUNK);
1012  memListTrav = nxtNode;
1013  }
1014  sentry->next = NULL;
1015 #endif
1016 #endif
1017 
1018  unique->GCTime += util_cpu_time() - localTime;
1019 
1020  hook = unique->postGCHook;
1021  while (hook != NULL) {
1022  int res = (hook->f)(unique,"DD",NULL);
1023  if (res == 0) return(0);
1024  hook = hook->next;
1025  }
1026 
1027 #ifdef DD_VERBOSE
1028  (void) fprintf(unique->err," done\n");
1029 #endif
1030 
1031  return(totalDeleted+totalDeletedZ);
1032 
1033 } /* end of cuddGarbageCollect */
static void ddReportRefMess(DdManager *unique, int i, const char *caller)
Definition: cuddTable.c:3195
DdHalfWord ref
Definition: cudd.h:272
unsigned int keys
Definition: cuddInt.h:314
DdNode * f
Definition: cuddInt.h:302
Definition: cudd.h:270
unsigned int deadZ
Definition: cuddInt.h:356
DdNode * data
Definition: cuddInt.h:304
int size
Definition: cuddInt.h:345
double gcFrac
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:352
ptruint h
Definition: cuddInt.h:303
#define Cudd_Regular(node)
Definition: cudd.h:384
FILE * err
Definition: cuddInt.h:424
DdNode * g
Definition: cuddInt.h:302
int garbageCollections
Definition: cuddInt.h:432
DdSubtable * subtables
Definition: cuddInt.h:349
DdNode * DdNodePtr
Definition: cuddInt.h:253
DD_HFP f
Definition: cuddInt.h:241
struct DdNode DdNode
Definition: cudd.h:262
#define DD_GC_FRAC_HI
Definition: cuddInt.h:135
unsigned int dead
Definition: cuddInt.h:355
unsigned int cacheSlots
Definition: cuddInt.h:337
DdNode sentinel
Definition: cuddInt.h:328
char * stash
Definition: cuddInt.h:382
unsigned int keys
Definition: cuddInt.h:353
unsigned int dead
Definition: cuddInt.h:316
DdCache * cache
Definition: cuddInt.h:336
DdNode * next
Definition: cudd.h:273
#define DD_GC_FRAC_LO
Definition: cuddInt.h:134
#define CUDD_CONST_INDEX
Definition: cudd.h:113
DdNode ** nodelist
Definition: cuddInt.h:311
long util_cpu_time(void)
Definition: cpu_time.c:34
void cuddLocalCacheClearDead(DdManager *manager)
Definition: cuddLCache.c:371
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
unsigned long GCTime
Definition: cuddInt.h:433
DdNode ** memoryList
Definition: cuddInt.h:380
unsigned int ptruint
Definition: cuddInt.h:250
DdNode * nextFree
Definition: cuddInt.h:381
struct DdHook * next
Definition: cuddInt.h:242
void cuddClearDeathRow(DdManager *table)
Definition: cuddRef.c:722
int sizeZ
Definition: cuddInt.h:346
unsigned int looseUpTo
Definition: cuddInt.h:361
unsigned int slots
Definition: cuddInt.h:313
DdHook * postGCHook
Definition: cuddInt.h:420
#define cuddClean(p)
Definition: cuddInt.h:757
DdSubtable constants
Definition: cuddInt.h:351
double cachedeletions
Definition: cuddInt.h:440
#define DD_MEM_CHUNK
Definition: cuddInt.h:105
unsigned int keysZ
Definition: cuddInt.h:354
DdHook * preGCHook
Definition: cuddInt.h:419
unsigned int minDead
Definition: cuddInt.h:358
DdSubtable * subtableZ
Definition: cuddInt.h:350
#define DD_NON_CONSTANT
Definition: cuddInt.h:124

◆ cuddInitTable()

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 380 of file cuddTable.c.

385 {
386  DdManager *unique = ALLOC(DdManager,1);
387  int i, j;
388  DdNodePtr *nodelist;
389  DdNode *sentinel;
390  unsigned int slots;
391  int shift;
392 
393  if (unique == NULL) {
394  return(NULL);
395  }
396  sentinel = &(unique->sentinel);
397  sentinel->ref = 0;
398  sentinel->index = 0;
399  cuddT(sentinel) = NULL;
400  cuddE(sentinel) = NULL;
401  sentinel->next = NULL;
402  unique->epsilon = DD_EPSILON;
403  unique->size = numVars;
404  unique->sizeZ = numVarsZ;
405  unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars);
406  unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ);
407 
408  /* Adjust the requested number of slots to a power of 2. */
409  slots = 8;
410  while (slots < numSlots) {
411  slots <<= 1;
412  }
413  unique->initSlots = slots;
414  shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots);
415 
416  unique->slots = (numVars + numVarsZ + 1) * slots;
417  unique->keys = 0;
418  unique->maxLive = ~0; /* very large number */
419  unique->keysZ = 0;
420  unique->dead = 0;
421  unique->deadZ = 0;
422  unique->gcFrac = DD_GC_FRAC_HI;
423  unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots);
424  unique->looseUpTo = looseUpTo;
425  unique->gcEnabled = 1;
426  unique->allocated = 0;
427  unique->reclaimed = 0;
428  unique->subtables = ALLOC(DdSubtable,unique->maxSize);
429  if (unique->subtables == NULL) {
430  FREE(unique);
431  return(NULL);
432  }
433  unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ);
434  if (unique->subtableZ == NULL) {
435  FREE(unique->subtables);
436  FREE(unique);
437  return(NULL);
438  }
439  unique->perm = ALLOC(int,unique->maxSize);
440  if (unique->perm == NULL) {
441  FREE(unique->subtables);
442  FREE(unique->subtableZ);
443  FREE(unique);
444  return(NULL);
445  }
446  unique->invperm = ALLOC(int,unique->maxSize);
447  if (unique->invperm == NULL) {
448  FREE(unique->subtables);
449  FREE(unique->subtableZ);
450  FREE(unique->perm);
451  FREE(unique);
452  return(NULL);
453  }
454  unique->permZ = ALLOC(int,unique->maxSizeZ);
455  if (unique->permZ == NULL) {
456  FREE(unique->subtables);
457  FREE(unique->subtableZ);
458  FREE(unique->perm);
459  FREE(unique->invperm);
460  FREE(unique);
461  return(NULL);
462  }
463  unique->invpermZ = ALLOC(int,unique->maxSizeZ);
464  if (unique->invpermZ == NULL) {
465  FREE(unique->subtables);
466  FREE(unique->subtableZ);
467  FREE(unique->perm);
468  FREE(unique->invperm);
469  FREE(unique->permZ);
470  FREE(unique);
471  return(NULL);
472  }
473  unique->map = NULL;
474  unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1);
475  if (unique->stack == NULL) {
476  FREE(unique->subtables);
477  FREE(unique->subtableZ);
478  FREE(unique->perm);
479  FREE(unique->invperm);
480  FREE(unique->permZ);
481  FREE(unique->invpermZ);
482  FREE(unique);
483  return(NULL);
484  }
485  unique->stack[0] = NULL; /* to suppress harmless UMR */
486 
487 #ifndef DD_NO_DEATH_ROW
488  unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2);
489  unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth);
490  if (unique->deathRow == NULL) {
491  FREE(unique->subtables);
492  FREE(unique->subtableZ);
493  FREE(unique->perm);
494  FREE(unique->invperm);
495  FREE(unique->permZ);
496  FREE(unique->invpermZ);
497  FREE(unique->stack);
498  FREE(unique);
499  return(NULL);
500  }
501  for (i = 0; i < unique->deathRowDepth; i++) {
502  unique->deathRow[i] = NULL;
503  }
504  unique->nextDead = 0;
505  unique->deadMask = unique->deathRowDepth - 1;
506 #endif
507 
508  for (i = 0; (unsigned) i < numVars; i++) {
509  unique->subtables[i].slots = slots;
510  unique->subtables[i].shift = shift;
511  unique->subtables[i].keys = 0;
512  unique->subtables[i].dead = 0;
513  unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
514  unique->subtables[i].bindVar = 0;
516  unique->subtables[i].pairIndex = 0;
517  unique->subtables[i].varHandled = 0;
519 
520  nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots);
521  if (nodelist == NULL) {
522  for (j = 0; j < i; j++) {
523  FREE(unique->subtables[j].nodelist);
524  }
525  FREE(unique->subtables);
526  FREE(unique->subtableZ);
527  FREE(unique->perm);
528  FREE(unique->invperm);
529  FREE(unique->permZ);
530  FREE(unique->invpermZ);
531  FREE(unique->stack);
532  FREE(unique);
533  return(NULL);
534  }
535  for (j = 0; (unsigned) j < slots; j++) {
536  nodelist[j] = sentinel;
537  }
538  unique->perm[i] = i;
539  unique->invperm[i] = i;
540  }
541  for (i = 0; (unsigned) i < numVarsZ; i++) {
542  unique->subtableZ[i].slots = slots;
543  unique->subtableZ[i].shift = shift;
544  unique->subtableZ[i].keys = 0;
545  unique->subtableZ[i].dead = 0;
546  unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
547  nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots);
548  if (nodelist == NULL) {
549  for (j = 0; (unsigned) j < numVars; j++) {
550  FREE(unique->subtables[j].nodelist);
551  }
552  FREE(unique->subtables);
553  for (j = 0; j < i; j++) {
554  FREE(unique->subtableZ[j].nodelist);
555  }
556  FREE(unique->subtableZ);
557  FREE(unique->perm);
558  FREE(unique->invperm);
559  FREE(unique->permZ);
560  FREE(unique->invpermZ);
561  FREE(unique->stack);
562  FREE(unique);
563  return(NULL);
564  }
565  for (j = 0; (unsigned) j < slots; j++) {
566  nodelist[j] = NULL;
567  }
568  unique->permZ[i] = i;
569  unique->invpermZ[i] = i;
570  }
571  unique->constants.slots = slots;
572  unique->constants.shift = shift;
573  unique->constants.keys = 0;
574  unique->constants.dead = 0;
575  unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
576  nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots);
577  if (nodelist == NULL) {
578  for (j = 0; (unsigned) j < numVars; j++) {
579  FREE(unique->subtables[j].nodelist);
580  }
581  FREE(unique->subtables);
582  for (j = 0; (unsigned) j < numVarsZ; j++) {
583  FREE(unique->subtableZ[j].nodelist);
584  }
585  FREE(unique->subtableZ);
586  FREE(unique->perm);
587  FREE(unique->invperm);
588  FREE(unique->permZ);
589  FREE(unique->invpermZ);
590  FREE(unique->stack);
591  FREE(unique);
592  return(NULL);
593  }
594  for (j = 0; (unsigned) j < slots; j++) {
595  nodelist[j] = NULL;
596  }
597 
598  unique->memoryList = NULL;
599  unique->nextFree = NULL;
600 
601  unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ)
602  * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) *
603  slots * sizeof(DdNodePtr) +
604  (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr);
605 #ifndef DD_NO_DEATH_ROW
606  unique->memused += unique->deathRowDepth * sizeof(DdNodePtr);
607 #endif
608 
609  /* Initialize fields concerned with automatic dynamic reordering. */
610  unique->reordered = 0;
611  unique->reorderings = 0;
612  unique->maxReorderings = ~0;
613  unique->siftMaxVar = DD_SIFT_MAX_VAR;
614  unique->siftMaxSwap = DD_SIFT_MAX_SWAPS;
616  unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH;
617  unique->reordCycle = 0; /* do not use alternate threshold */
618  unique->autoDyn = 0; /* initially disabled */
619  unique->autoDynZ = 0; /* initially disabled */
620  unique->autoMethod = CUDD_REORDER_SIFT;
621  unique->autoMethodZ = CUDD_REORDER_SIFT;
622  unique->realign = 0; /* initially disabled */
623  unique->realignZ = 0; /* initially disabled */
624  unique->nextDyn = DD_FIRST_REORDER;
625  unique->countDead = ~0;
626  unique->tree = NULL;
627  unique->treeZ = NULL;
628  unique->groupcheck = CUDD_GROUP_CHECK7;
629  unique->recomb = DD_DEFAULT_RECOMB;
630  unique->symmviolation = 0;
631  unique->arcviolation = 0;
632  unique->populationSize = 0;
633  unique->numberXovers = 0;
634  unique->randomizeOrder = 0;
635  unique->linear = NULL;
636  unique->linearSize = 0;
637 
638  /* Initialize ZDD universe. */
639  unique->univ = (DdNodePtr *)NULL;
640 
641  /* Initialize auxiliary fields. */
642  unique->localCaches = NULL;
643  unique->preGCHook = NULL;
644  unique->postGCHook = NULL;
645  unique->preReorderingHook = NULL;
646  unique->postReorderingHook = NULL;
647  unique->out = stdout;
648  unique->err = stderr;
649  unique->errorCode = CUDD_NO_ERROR;
650  unique->startTime = util_cpu_time();
651  unique->timeLimit = ~0UL;
652 
653  /* Initialize statistical counters. */
654  unique->maxmemhard = ~ 0UL;
655  unique->garbageCollections = 0;
656  unique->GCTime = 0;
657  unique->reordTime = 0;
658 #ifdef DD_STATS
659  unique->nodesDropped = 0;
660  unique->nodesFreed = 0;
661 #endif
662  unique->peakLiveNodes = 0;
663 #ifdef DD_UNIQUE_PROFILE
664  unique->uniqueLookUps = 0;
665  unique->uniqueLinks = 0;
666 #endif
667 #ifdef DD_COUNT
668  unique->recursiveCalls = 0;
669  unique->swapSteps = 0;
670 #ifdef DD_STATS
671  unique->nextSample = 250000;
672 #endif
673 #endif
674 
675  return(unique);
676 
677 } /* end of cuddInitTable */
DdHalfWord ref
Definition: cudd.h:272
Cudd_AggregationType groupcheck
Definition: cuddInt.h:410
unsigned int keys
Definition: cuddInt.h:314
unsigned long reordTime
Definition: cuddInt.h:434
Cudd_ReorderingType autoMethod
Definition: cuddInt.h:402
#define DD_SIFT_MAX_VAR
Definition: cuddInt.h:148
unsigned int peakLiveNodes
Definition: cuddInt.h:445
int maxSizeZ
Definition: cuddInt.h:348
double allocated
Definition: cuddInt.h:365
int * map
Definition: cuddInt.h:374
Definition: cudd.h:270
unsigned int deadZ
Definition: cuddInt.h:356
#define FREE(obj)
Definition: util.h:80
int siftMaxSwap
Definition: cuddInt.h:396
DdHook * preReorderingHook
Definition: cuddInt.h:421
unsigned deadMask
Definition: cuddInt.h:387
unsigned long startTime
Definition: cuddInt.h:426
int * invpermZ
Definition: cuddInt.h:372
int reordCycle
Definition: cuddInt.h:399
int size
Definition: cuddInt.h:345
double gcFrac
Definition: cuddInt.h:359
struct DdManager DdManager
Definition: cudd.h:280
unsigned int slots
Definition: cuddInt.h:352
double maxGrowthAlt
Definition: cuddInt.h:398
int realign
Definition: cuddInt.h:404
double maxGrowth
Definition: cuddInt.h:397
FILE * err
Definition: cuddInt.h:424
int garbageCollections
Definition: cuddInt.h:432
int populationSize
Definition: cuddInt.h:414
#define DD_FIRST_REORDER
Definition: cuddInt.h:152
Cudd_ReorderingType autoMethodZ
Definition: cuddInt.h:403
int bindVar
Definition: cuddInt.h:318
DdSubtable * subtables
Definition: cuddInt.h:349
int * permZ
Definition: cuddInt.h:370
DdNode * DdNodePtr
Definition: cuddInt.h:253
#define DD_EPSILON
Definition: cuddInt.h:110
MtrNode * tree
Definition: cuddInt.h:408
struct DdSubtable DdSubtable
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
#define DD_DEFAULT_RECOMB
Definition: cuddInt.h:150
DdNode ** deathRow
Definition: cuddInt.h:384
DdNode ** stack
Definition: cuddInt.h:364
unsigned int countDead
Definition: cuddInt.h:407
unsigned int initSlots
Definition: cuddInt.h:363
unsigned int randomizeOrder
Definition: cuddInt.h:416
Cudd_VariableType varType
Definition: cuddInt.h:320
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
#define DD_GC_FRAC_HI
Definition: cuddInt.h:135
unsigned int dead
Definition: cuddInt.h:355
unsigned int maxLive
Definition: cuddInt.h:357
int recomb
Definition: cuddInt.h:411
DdNode sentinel
Definition: cuddInt.h:328
DdHook * postReorderingHook
Definition: cuddInt.h:422
unsigned int keys
Definition: cuddInt.h:353
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
FILE * out
Definition: cuddInt.h:423
#define DD_SIFT_MAX_SWAPS
Definition: cuddInt.h:149
int realignZ
Definition: cuddInt.h:405
DdNode * next
Definition: cudd.h:273
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:323
int maxSize
Definition: cuddInt.h:347
unsigned int maxKeys
Definition: cuddInt.h:315
long * linear
Definition: cuddInt.h:378
int gcEnabled
Definition: cuddInt.h:360
#define ddMax(x, y)
Definition: cuddInt.h:785
int symmviolation
Definition: cuddInt.h:412
int numberXovers
Definition: cuddInt.h:415
DdNode ** nodelist
Definition: cuddInt.h:311
int linearSize
Definition: cuddInt.h:376
DdLocalCache * localCaches
Definition: cuddInt.h:417
long util_cpu_time(void)
Definition: cpu_time.c:34
#define cuddT(node)
Definition: cuddInt.h:609
int nextDead
Definition: cuddInt.h:386
int varHandled
Definition: cuddInt.h:322
unsigned long GCTime
Definition: cuddInt.h:433
DdNode ** memoryList
Definition: cuddInt.h:380
unsigned int maxReorderings
Definition: cuddInt.h:394
unsigned long memused
Definition: cuddInt.h:429
int siftMaxVar
Definition: cuddInt.h:395
int deathRowDepth
Definition: cuddInt.h:385
DdNode * nextFree
Definition: cuddInt.h:381
#define DD_DEFAULT_RESIZE
Definition: cuddInt.h:103
int sizeZ
Definition: cuddInt.h:346
DdHalfWord index
Definition: cudd.h:271
unsigned int looseUpTo
Definition: cuddInt.h:361
unsigned int slots
Definition: cuddInt.h:313
unsigned int reorderings
Definition: cuddInt.h:393
unsigned long maxmemhard
Definition: cuddInt.h:431
DdHook * postGCHook
Definition: cuddInt.h:420
int pairIndex
Definition: cuddInt.h:321
#define DD_MAX_REORDER_GROWTH
Definition: cuddInt.h:151
CUDD_VALUE_TYPE epsilon
Definition: cuddInt.h:390
MtrNode * treeZ
Definition: cuddInt.h:409
int autoDynZ
Definition: cuddInt.h:401
#define cuddE(node)
Definition: cuddInt.h:625
int arcviolation
Definition: cuddInt.h:413
int * invperm
Definition: cuddInt.h:371
DdSubtable constants
Definition: cuddInt.h:351
int cuddComputeFloorLog2(unsigned int value)
Definition: cuddCache.c:1036
int autoDyn
Definition: cuddInt.h:400
int shift
Definition: cuddInt.h:312
unsigned int keysZ
Definition: cuddInt.h:354
DdHook * preGCHook
Definition: cuddInt.h:419
int * perm
Definition: cuddInt.h:369
unsigned long timeLimit
Definition: cuddInt.h:427
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
unsigned int minDead
Definition: cuddInt.h:358
double reclaimed
Definition: cuddInt.h:367
DdSubtable * subtableZ
Definition: cuddInt.h:350
DdNode ** univ
Definition: cuddInt.h:375

◆ cuddInsertSubtables()

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 1824 of file cuddTable.c.

1828 {
1829  DdSubtable *newsubtables;
1830  DdNodePtr *newnodelist;
1831  DdNodePtr *newvars;
1832  DdNode *sentinel = &(unique->sentinel);
1833  int oldsize,newsize;
1834  int i,j,index,reorderSave;
1835  unsigned int numSlots = unique->initSlots;
1836  int *newperm, *newinvperm, *newmap;
1837  DdNode *one, *zero;
1838 
1839 #ifdef DD_DEBUG
1840  assert(n > 0 && level < unique->size);
1841 #endif
1842 
1843  oldsize = unique->size;
1844  /* Easy case: there is still room in the current table. */
1845  if (oldsize + n <= unique->maxSize) {
1846  /* Shift the tables at and below level. */
1847  for (i = oldsize - 1; i >= level; i--) {
1848  unique->subtables[i+n].slots = unique->subtables[i].slots;
1849  unique->subtables[i+n].shift = unique->subtables[i].shift;
1850  unique->subtables[i+n].keys = unique->subtables[i].keys;
1851  unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys;
1852  unique->subtables[i+n].dead = unique->subtables[i].dead;
1853  unique->subtables[i+n].nodelist = unique->subtables[i].nodelist;
1854  unique->subtables[i+n].bindVar = unique->subtables[i].bindVar;
1855  unique->subtables[i+n].varType = unique->subtables[i].varType;
1856  unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex;
1857  unique->subtables[i+n].varHandled = unique->subtables[i].varHandled;
1858  unique->subtables[i+n].varToBeGrouped =
1859  unique->subtables[i].varToBeGrouped;
1860 
1861  index = unique->invperm[i];
1862  unique->invperm[i+n] = index;
1863  unique->perm[index] += n;
1864  }
1865  /* Create new subtables. */
1866  for (i = 0; i < n; i++) {
1867  unique->subtables[level+i].slots = numSlots;
1868  unique->subtables[level+i].shift = sizeof(int) * 8 -
1869  cuddComputeFloorLog2(numSlots);
1870  unique->subtables[level+i].keys = 0;
1871  unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
1872  unique->subtables[level+i].dead = 0;
1873  unique->subtables[level+i].bindVar = 0;
1874  unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT;
1875  unique->subtables[level+i].pairIndex = 0;
1876  unique->subtables[level+i].varHandled = 0;
1877  unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE;
1878 
1879  unique->perm[oldsize+i] = level + i;
1880  unique->invperm[level+i] = oldsize + i;
1881  newnodelist = unique->subtables[level+i].nodelist =
1882  ALLOC(DdNodePtr, numSlots);
1883  if (newnodelist == NULL) {
1884  unique->errorCode = CUDD_MEMORY_OUT;
1885  return(0);
1886  }
1887  for (j = 0; (unsigned) j < numSlots; j++) {
1888  newnodelist[j] = sentinel;
1889  }
1890  }
1891  if (unique->map != NULL) {
1892  for (i = 0; i < n; i++) {
1893  unique->map[oldsize+i] = oldsize + i;
1894  }
1895  }
1896  } else {
1897  /* The current table is too small: we need to allocate a new,
1898  ** larger one; move all old subtables, and initialize the new
1899  ** subtables.
1900  */
1901  newsize = oldsize + n + DD_DEFAULT_RESIZE;
1902 #ifdef DD_VERBOSE
1903  (void) fprintf(unique->err,
1904  "Increasing the table size from %d to %d\n",
1905  unique->maxSize, newsize);
1906 #endif
1907  /* Allocate memory for new arrays (except nodelists). */
1908  newsubtables = ALLOC(DdSubtable,newsize);
1909  if (newsubtables == NULL) {
1910  unique->errorCode = CUDD_MEMORY_OUT;
1911  return(0);
1912  }
1913  newvars = ALLOC(DdNodePtr,newsize);
1914  if (newvars == NULL) {
1915  unique->errorCode = CUDD_MEMORY_OUT;
1916  FREE(newsubtables);
1917  return(0);
1918  }
1919  newperm = ALLOC(int,newsize);
1920  if (newperm == NULL) {
1921  unique->errorCode = CUDD_MEMORY_OUT;
1922  FREE(newsubtables);
1923  FREE(newvars);
1924  return(0);
1925  }
1926  newinvperm = ALLOC(int,newsize);
1927  if (newinvperm == NULL) {
1928  unique->errorCode = CUDD_MEMORY_OUT;
1929  FREE(newsubtables);
1930  FREE(newvars);
1931  FREE(newperm);
1932  return(0);
1933  }
1934  if (unique->map != NULL) {
1935  newmap = ALLOC(int,newsize);
1936  if (newmap == NULL) {
1937  unique->errorCode = CUDD_MEMORY_OUT;
1938  FREE(newsubtables);
1939  FREE(newvars);
1940  FREE(newperm);
1941  FREE(newinvperm);
1942  return(0);
1943  }
1944  unique->memused += (newsize - unique->maxSize) * sizeof(int);
1945  }
1946  unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
1947  sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
1948  /* Copy levels before insertion points from old tables. */
1949  for (i = 0; i < level; i++) {
1950  newsubtables[i].slots = unique->subtables[i].slots;
1951  newsubtables[i].shift = unique->subtables[i].shift;
1952  newsubtables[i].keys = unique->subtables[i].keys;
1953  newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
1954  newsubtables[i].dead = unique->subtables[i].dead;
1955  newsubtables[i].nodelist = unique->subtables[i].nodelist;
1956  newsubtables[i].bindVar = unique->subtables[i].bindVar;
1957  newsubtables[i].varType = unique->subtables[i].varType;
1958  newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
1959  newsubtables[i].varHandled = unique->subtables[i].varHandled;
1960  newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
1961 
1962  newvars[i] = unique->vars[i];
1963  newperm[i] = unique->perm[i];
1964  newinvperm[i] = unique->invperm[i];
1965  }
1966  /* Finish initializing permutation for new table to old one. */
1967  for (i = level; i < oldsize; i++) {
1968  newperm[i] = unique->perm[i];
1969  }
1970  /* Initialize new levels. */
1971  for (i = level; i < level + n; i++) {
1972  newsubtables[i].slots = numSlots;
1973  newsubtables[i].shift = sizeof(int) * 8 -
1974  cuddComputeFloorLog2(numSlots);
1975  newsubtables[i].keys = 0;
1976  newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
1977  newsubtables[i].dead = 0;
1978  newsubtables[i].bindVar = 0;
1979  newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
1980  newsubtables[i].pairIndex = 0;
1981  newsubtables[i].varHandled = 0;
1982  newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
1983 
1984  newperm[oldsize + i - level] = i;
1985  newinvperm[i] = oldsize + i - level;
1986  newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
1987  if (newnodelist == NULL) {
1988  /* We are going to leak some memory. We should clean up. */
1989  unique->errorCode = CUDD_MEMORY_OUT;
1990  return(0);
1991  }
1992  for (j = 0; (unsigned) j < numSlots; j++) {
1993  newnodelist[j] = sentinel;
1994  }
1995  }
1996  /* Copy the old tables for levels past the insertion point. */
1997  for (i = level; i < oldsize; i++) {
1998  newsubtables[i+n].slots = unique->subtables[i].slots;
1999  newsubtables[i+n].shift = unique->subtables[i].shift;
2000  newsubtables[i+n].keys = unique->subtables[i].keys;
2001  newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys;
2002  newsubtables[i+n].dead = unique->subtables[i].dead;
2003  newsubtables[i+n].nodelist = unique->subtables[i].nodelist;
2004  newsubtables[i+n].bindVar = unique->subtables[i].bindVar;
2005  newsubtables[i+n].varType = unique->subtables[i].varType;
2006  newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex;
2007  newsubtables[i+n].varHandled = unique->subtables[i].varHandled;
2008  newsubtables[i+n].varToBeGrouped =
2009  unique->subtables[i].varToBeGrouped;
2010 
2011  newvars[i] = unique->vars[i];
2012  index = unique->invperm[i];
2013  newinvperm[i+n] = index;
2014  newperm[index] += n;
2015  }
2016  /* Update the map. */
2017  if (unique->map != NULL) {
2018  for (i = 0; i < oldsize; i++) {
2019  newmap[i] = unique->map[i];
2020  }
2021  for (i = oldsize; i < oldsize + n; i++) {
2022  newmap[i] = i;
2023  }
2024  FREE(unique->map);
2025  unique->map = newmap;
2026  }
2027  /* Install the new tables and free the old ones. */
2028  FREE(unique->subtables);
2029  unique->subtables = newsubtables;
2030  unique->maxSize = newsize;
2031  FREE(unique->vars);
2032  unique->vars = newvars;
2033  FREE(unique->perm);
2034  unique->perm = newperm;
2035  FREE(unique->invperm);
2036  unique->invperm = newinvperm;
2037  /* Update the stack for iterative procedures. */
2038  if (newsize > unique->maxSizeZ) {
2039  FREE(unique->stack);
2040  unique->stack = ALLOC(DdNodePtr,newsize + 1);
2041  if (unique->stack == NULL) {
2042  unique->errorCode = CUDD_MEMORY_OUT;
2043  return(0);
2044  }
2045  unique->stack[0] = NULL; /* to suppress harmless UMR */
2046  unique->memused +=
2047  (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
2048  * sizeof(DdNode *);
2049  }
2050  }
2051  /* Update manager parameters to account for the new subtables. */
2052  unique->slots += n * numSlots;
2053  ddFixLimits(unique);
2054  unique->size += n;
2055 
2056  /* Now that the table is in a coherent state, create the new
2057  ** projection functions. We need to temporarily disable reordering,
2058  ** because we cannot reorder without projection functions in place.
2059  **/
2060  one = unique->one;
2061  zero = Cudd_Not(one);
2062 
2063  reorderSave = unique->autoDyn;
2064  unique->autoDyn = 0;
2065  for (i = oldsize; i < oldsize + n; i++) {
2066  unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
2067  if (unique->vars[i] == NULL) {
2068  unique->autoDyn = reorderSave;
2069  /* Shift everything back so table remains coherent. */
2070  for (j = oldsize; j < i; j++) {
2071  Cudd_IterDerefBdd(unique,unique->vars[j]);
2072  cuddDeallocNode(unique,unique->vars[j]);
2073  unique->vars[j] = NULL;
2074  }
2075  for (j = level; j < oldsize; j++) {
2076  unique->subtables[j].slots = unique->subtables[j+n].slots;
2077  unique->subtables[j].slots = unique->subtables[j+n].slots;
2078  unique->subtables[j].shift = unique->subtables[j+n].shift;
2079  unique->subtables[j].keys = unique->subtables[j+n].keys;
2080  unique->subtables[j].maxKeys =
2081  unique->subtables[j+n].maxKeys;
2082  unique->subtables[j].dead = unique->subtables[j+n].dead;
2083  FREE(unique->subtables[j].nodelist);
2084  unique->subtables[j].nodelist =
2085  unique->subtables[j+n].nodelist;
2086  unique->subtables[j+n].nodelist = NULL;
2087  unique->subtables[j].bindVar =
2088  unique->subtables[j+n].bindVar;
2089  unique->subtables[j].varType =
2090  unique->subtables[j+n].varType;
2091  unique->subtables[j].pairIndex =
2092  unique->subtables[j+n].pairIndex;
2093  unique->subtables[j].varHandled =
2094  unique->subtables[j+n].varHandled;
2095  unique->subtables[j].varToBeGrouped =
2096  unique->subtables[j+n].varToBeGrouped;
2097  index = unique->invperm[j+n];
2098  unique->invperm[j] = index;
2099  unique->perm[index] -= n;
2100  }
2101  unique->size = oldsize;
2102  unique->slots -= n * numSlots;
2103  ddFixLimits(unique);
2104  (void) Cudd_DebugCheck(unique);
2105  return(0);
2106  }
2107  cuddRef(unique->vars[i]);
2108  }
2109  if (unique->tree != NULL) {
2110  unique->tree->size += n;
2111  unique->tree->index = unique->invperm[0];
2112  ddPatchTree(unique,unique->tree);
2113  }
2114  unique->autoDyn = reorderSave;
2115 
2116  return(1);
2117 
2118 } /* end of cuddInsertSubtables */
void Cudd_IterDerefBdd(DdManager *table, DdNode *n)
Definition: cuddRef.c:213
#define cuddRef(n)
Definition: cuddInt.h:557
unsigned int keys
Definition: cuddInt.h:314
int maxSizeZ
Definition: cuddInt.h:348
int * map
Definition: cuddInt.h:374
Definition: cudd.h:270
static void ddPatchTree(DdManager *dd, MtrNode *treenode)
Definition: cuddTable.c:3118
#define Cudd_Not(node)
Definition: cudd.h:354
MtrHalfWord size
Definition: mtr.h:129
#define FREE(obj)
Definition: util.h:80
#define assert(ex)
Definition: util.h:141
int size
Definition: cuddInt.h:345
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
int bindVar
Definition: cuddInt.h:318
DdSubtable * subtables
Definition: cuddInt.h:349
MtrNode * tree
Definition: cuddInt.h:408
struct DdSubtable DdSubtable
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
DdNode ** stack
Definition: cuddInt.h:364
unsigned int initSlots
Definition: cuddInt.h:363
Cudd_VariableType varType
Definition: cuddInt.h:320
static DdNode * one
Definition: cuddSat.c:105
DdNode sentinel
Definition: cuddInt.h:328
MtrHalfWord index
Definition: mtr.h:130
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:323
int maxSize
Definition: cuddInt.h:347
unsigned int maxKeys
Definition: cuddInt.h:315
#define ddMax(x, y)
Definition: cuddInt.h:785
DdNode ** nodelist
Definition: cuddInt.h:311
int Cudd_DebugCheck(DdManager *table)
Definition: cuddCheck.c:138
int varHandled
Definition: cuddInt.h:322
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
unsigned long memused
Definition: cuddInt.h:429
#define DD_DEFAULT_RESIZE
Definition: cuddInt.h:103
unsigned int slots
Definition: cuddInt.h:313
DdNode ** vars
Definition: cuddInt.h:373
int pairIndex
Definition: cuddInt.h:321
static DdNode * zero
Definition: cuddSat.c:105
DdNode * one
Definition: cuddInt.h:329
static DD_INLINE void ddFixLimits(DdManager *unique)
Definition: cuddTable.c:2843
int * invperm
Definition: cuddInt.h:371
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1137
int cuddComputeFloorLog2(unsigned int value)
Definition: cuddCache.c:1036
int autoDyn
Definition: cuddInt.h:400
int shift
Definition: cuddInt.h:312
int * perm
Definition: cuddInt.h:369
Cudd_ErrorType errorCode
Definition: cuddInt.h:425

◆ cuddRehash()

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 1559 of file cuddTable.c.

1562 {
1563  unsigned int slots, oldslots;
1564  int shift, oldshift;
1565  int j, pos;
1566  DdNodePtr *nodelist, *oldnodelist;
1567  DdNode *node, *next;
1568  DdNode *sentinel = &(unique->sentinel);
1569  hack split;
1570  extern DD_OOMFP MMoutOfMemory;
1571  DD_OOMFP saveHandler;
1572 
1573  if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) {
1574  unique->gcFrac = DD_GC_FRAC_LO;
1575  unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
1576 #ifdef DD_VERBOSE
1577  (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO);
1578  (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
1579 #endif
1580  }
1581 
1582  if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) {
1583  unique->gcFrac = DD_GC_FRAC_MIN;
1584  unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
1585 #ifdef DD_VERBOSE
1586  (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN);
1587  (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
1588 #endif
1589  cuddShrinkDeathRow(unique);
1590  if (cuddGarbageCollect(unique,1) > 0) return;
1591  }
1592 
1593  if (i != CUDD_CONST_INDEX) {
1594  oldslots = unique->subtables[i].slots;
1595  oldshift = unique->subtables[i].shift;
1596  oldnodelist = unique->subtables[i].nodelist;
1597 
1598  /* Compute the new size of the subtable. */
1599  slots = oldslots << 1;
1600  shift = oldshift - 1;
1601 
1602  saveHandler = MMoutOfMemory;
1603  MMoutOfMemory = Cudd_OutOfMem;
1604  nodelist = ALLOC(DdNodePtr, slots);
1605  MMoutOfMemory = saveHandler;
1606  if (nodelist == NULL) {
1607  (void) fprintf(unique->err,
1608  "Unable to resize subtable %d for lack of memory\n",
1609  i);
1610  /* Prevent frequent resizing attempts. */
1611  (void) cuddGarbageCollect(unique,1);
1612  if (unique->stash != NULL) {
1613  FREE(unique->stash);
1614  unique->stash = NULL;
1615  /* Inhibit resizing of tables. */
1616  cuddSlowTableGrowth(unique);
1617  }
1618  return;
1619  }
1620  unique->subtables[i].nodelist = nodelist;
1621  unique->subtables[i].slots = slots;
1622  unique->subtables[i].shift = shift;
1623  unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
1624 
1625  /* Move the nodes from the old table to the new table.
1626  ** This code depends on the type of hash function.
1627  ** It assumes that the effect of doubling the size of the table
1628  ** is to retain one more bit of the 32-bit hash value.
1629  ** The additional bit is the LSB. */
1630  for (j = 0; (unsigned) j < oldslots; j++) {
1631  DdNodePtr *evenP, *oddP;
1632  node = oldnodelist[j];
1633  evenP = &(nodelist[j<<1]);
1634  oddP = &(nodelist[(j<<1)+1]);
1635  while (node != sentinel) {
1636  next = node->next;
1637  pos = ddHash(cuddT(node), cuddE(node), shift);
1638  if (pos & 1) {
1639  *oddP = node;
1640  oddP = &(node->next);
1641  } else {
1642  *evenP = node;
1643  evenP = &(node->next);
1644  }
1645  node = next;
1646  }
1647  *evenP = *oddP = sentinel;
1648  }
1649  FREE(oldnodelist);
1650 
1651 #ifdef DD_VERBOSE
1652  (void) fprintf(unique->err,
1653  "rehashing layer %d: keys %d dead %d new size %d\n",
1654  i, unique->subtables[i].keys,
1655  unique->subtables[i].dead, slots);
1656 #endif
1657  } else {
1658  oldslots = unique->constants.slots;
1659  oldshift = unique->constants.shift;
1660  oldnodelist = unique->constants.nodelist;
1661 
1662  /* The constant subtable is never subjected to reordering.
1663  ** Therefore, when it is resized, it is because it has just
1664  ** reached the maximum load. We can safely just double the size,
1665  ** with no need for the loop we use for the other tables.
1666  */
1667  slots = oldslots << 1;
1668  shift = oldshift - 1;
1669  saveHandler = MMoutOfMemory;
1670  MMoutOfMemory = Cudd_OutOfMem;
1671  nodelist = ALLOC(DdNodePtr, slots);
1672  MMoutOfMemory = saveHandler;
1673  if (nodelist == NULL) {
1674  (void) fprintf(unique->err,
1675  "Unable to resize constant subtable for lack of memory\n");
1676  (void) cuddGarbageCollect(unique,1);
1677  for (j = 0; j < unique->size; j++) {
1678  unique->subtables[j].maxKeys <<= 1;
1679  }
1680  unique->constants.maxKeys <<= 1;
1681  return;
1682  }
1683  unique->constants.slots = slots;
1684  unique->constants.shift = shift;
1685  unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
1686  unique->constants.nodelist = nodelist;
1687  for (j = 0; (unsigned) j < slots; j++) {
1688  nodelist[j] = NULL;
1689  }
1690  for (j = 0; (unsigned) j < oldslots; j++) {
1691  node = oldnodelist[j];
1692  while (node != NULL) {
1693  next = node->next;
1694  split.value = cuddV(node);
1695  pos = ddHash(split.bits[0], split.bits[1], shift);
1696  node->next = nodelist[pos];
1697  nodelist[pos] = node;
1698  node = next;
1699  }
1700  }
1701  FREE(oldnodelist);
1702 
1703 #ifdef DD_VERBOSE
1704  (void) fprintf(unique->err,
1705  "rehashing constants: keys %d dead %d new size %d\n",
1706  unique->constants.keys,unique->constants.dead,slots);
1707 #endif
1708  }
1709 
1710  /* Update global data */
1711 
1712  unique->memused += (slots - oldslots) * sizeof(DdNodePtr);
1713  unique->slots += (slots - oldslots);
1714  ddFixLimits(unique);
1715 
1716 } /* end of cuddRehash */
unsigned int keys
Definition: cuddInt.h:314
#define ddHash(f, g, s)
Definition: cuddInt.h:696
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
unsigned int bits[2]
Definition: cuddTable.c:109
int size
Definition: cuddInt.h:345
double gcFrac
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
DdSubtable * subtables
Definition: cuddInt.h:349
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
void(* DD_OOMFP)(long)
Definition: cudd.h:311
#define cuddV(node)
Definition: cuddInt.h:641
#define DD_GC_FRAC_HI
Definition: cuddInt.h:135
DdNode sentinel
Definition: cuddInt.h:328
char * stash
Definition: cuddInt.h:382
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
DdNode * next
Definition: cudd.h:273
#define DD_GC_FRAC_LO
Definition: cuddInt.h:134
unsigned int maxKeys
Definition: cuddInt.h:315
#define CUDD_CONST_INDEX
Definition: cudd.h:113
DdNode ** nodelist
Definition: cuddInt.h:311
#define cuddT(node)
Definition: cuddInt.h:609
CUDD_VALUE_TYPE value
Definition: cuddTable.c:108
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
#define DD_GC_FRAC_MIN
Definition: cuddInt.h:136
void cuddSlowTableGrowth(DdManager *unique)
Definition: cuddTable.c:2414
unsigned long memused
Definition: cuddInt.h:429
unsigned int looseUpTo
Definition: cuddInt.h:361
unsigned int slots
Definition: cuddInt.h:313
#define cuddE(node)
Definition: cuddInt.h:625
static DD_INLINE void ddFixLimits(DdManager *unique)
Definition: cuddTable.c:2843
DdSubtable constants
Definition: cuddInt.h:351
unsigned long maxmem
Definition: cuddInt.h:430
int shift
Definition: cuddInt.h:312
void cuddShrinkDeathRow(DdManager *table)
Definition: cuddRef.c:684
unsigned int minDead
Definition: cuddInt.h:358

◆ cuddResizeTableZdd()

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 2270 of file cuddTable.c.

2273 {
2274  DdSubtable *newsubtables;
2275  DdNodePtr *newnodelist;
2276  int oldsize,newsize;
2277  int i,j,reorderSave;
2278  unsigned int numSlots = unique->initSlots;
2279  int *newperm, *newinvperm;
2280 
2281  oldsize = unique->sizeZ;
2282  /* Easy case: there is still room in the current table. */
2283  if (index < unique->maxSizeZ) {
2284  for (i = oldsize; i <= index; i++) {
2285  unique->subtableZ[i].slots = numSlots;
2286  unique->subtableZ[i].shift = sizeof(int) * 8 -
2287  cuddComputeFloorLog2(numSlots);
2288  unique->subtableZ[i].keys = 0;
2289  unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
2290  unique->subtableZ[i].dead = 0;
2291  unique->permZ[i] = i;
2292  unique->invpermZ[i] = i;
2293  newnodelist = unique->subtableZ[i].nodelist =
2294  ALLOC(DdNodePtr, numSlots);
2295  if (newnodelist == NULL) {
2296  unique->errorCode = CUDD_MEMORY_OUT;
2297  return(0);
2298  }
2299  for (j = 0; (unsigned) j < numSlots; j++) {
2300  newnodelist[j] = NULL;
2301  }
2302  }
2303  } else {
2304  /* The current table is too small: we need to allocate a new,
2305  ** larger one; move all old subtables, and initialize the new
2306  ** subtables up to index included.
2307  */
2308  newsize = index + DD_DEFAULT_RESIZE;
2309 #ifdef DD_VERBOSE
2310  (void) fprintf(unique->err,
2311  "Increasing the ZDD table size from %d to %d\n",
2312  unique->maxSizeZ, newsize);
2313 #endif
2314  newsubtables = ALLOC(DdSubtable,newsize);
2315  if (newsubtables == NULL) {
2316  unique->errorCode = CUDD_MEMORY_OUT;
2317  return(0);
2318  }
2319  newperm = ALLOC(int,newsize);
2320  if (newperm == NULL) {
2321  unique->errorCode = CUDD_MEMORY_OUT;
2322  return(0);
2323  }
2324  newinvperm = ALLOC(int,newsize);
2325  if (newinvperm == NULL) {
2326  unique->errorCode = CUDD_MEMORY_OUT;
2327  return(0);
2328  }
2329  unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) *
2330  sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
2331  if (newsize > unique->maxSize) {
2332  FREE(unique->stack);
2333  unique->stack = ALLOC(DdNodePtr,newsize + 1);
2334  if (unique->stack == NULL) {
2335  unique->errorCode = CUDD_MEMORY_OUT;
2336  return(0);
2337  }
2338  unique->stack[0] = NULL; /* to suppress harmless UMR */
2339  unique->memused +=
2340  (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
2341  * sizeof(DdNode *);
2342  }
2343  for (i = 0; i < oldsize; i++) {
2344  newsubtables[i].slots = unique->subtableZ[i].slots;
2345  newsubtables[i].shift = unique->subtableZ[i].shift;
2346  newsubtables[i].keys = unique->subtableZ[i].keys;
2347  newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys;
2348  newsubtables[i].dead = unique->subtableZ[i].dead;
2349  newsubtables[i].nodelist = unique->subtableZ[i].nodelist;
2350  newperm[i] = unique->permZ[i];
2351  newinvperm[i] = unique->invpermZ[i];
2352  }
2353  for (i = oldsize; i <= index; i++) {
2354  newsubtables[i].slots = numSlots;
2355  newsubtables[i].shift = sizeof(int) * 8 -
2356  cuddComputeFloorLog2(numSlots);
2357  newsubtables[i].keys = 0;
2358  newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
2359  newsubtables[i].dead = 0;
2360  newperm[i] = i;
2361  newinvperm[i] = i;
2362  newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
2363  if (newnodelist == NULL) {
2364  unique->errorCode = CUDD_MEMORY_OUT;
2365  return(0);
2366  }
2367  for (j = 0; (unsigned) j < numSlots; j++) {
2368  newnodelist[j] = NULL;
2369  }
2370  }
2371  FREE(unique->subtableZ);
2372  unique->subtableZ = newsubtables;
2373  unique->maxSizeZ = newsize;
2374  FREE(unique->permZ);
2375  unique->permZ = newperm;
2376  FREE(unique->invpermZ);
2377  unique->invpermZ = newinvperm;
2378  }
2379  unique->slots += (index + 1 - unique->sizeZ) * numSlots;
2380  ddFixLimits(unique);
2381  unique->sizeZ = index + 1;
2382 
2383  /* Now that the table is in a coherent state, update the ZDD
2384  ** universe. We need to temporarily disable reordering,
2385  ** because we cannot reorder without universe in place.
2386  */
2387 
2388  reorderSave = unique->autoDynZ;
2389  unique->autoDynZ = 0;
2390  cuddZddFreeUniv(unique);
2391  if (!cuddZddInitUniv(unique)) {
2392  unique->autoDynZ = reorderSave;
2393  return(0);
2394  }
2395  unique->autoDynZ = reorderSave;
2396 
2397  return(1);
2398 
2399 } /* end of cuddResizeTableZdd */
unsigned int keys
Definition: cuddInt.h:314
void cuddZddFreeUniv(DdManager *zdd)
Definition: cuddInit.c:294
int maxSizeZ
Definition: cuddInt.h:348
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
int * invpermZ
Definition: cuddInt.h:372
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
int * permZ
Definition: cuddInt.h:370
struct DdSubtable DdSubtable
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
DdNode ** stack
Definition: cuddInt.h:364
unsigned int initSlots
Definition: cuddInt.h:363
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
int maxSize
Definition: cuddInt.h:347
unsigned int maxKeys
Definition: cuddInt.h:315
#define ddMax(x, y)
Definition: cuddInt.h:785
DdNode ** nodelist
Definition: cuddInt.h:311
int cuddZddInitUniv(DdManager *zdd)
Definition: cuddInit.c:245
unsigned long memused
Definition: cuddInt.h:429
#define DD_DEFAULT_RESIZE
Definition: cuddInt.h:103
int sizeZ
Definition: cuddInt.h:346
unsigned int slots
Definition: cuddInt.h:313
int autoDynZ
Definition: cuddInt.h:401
static DD_INLINE void ddFixLimits(DdManager *unique)
Definition: cuddTable.c:2843
int cuddComputeFloorLog2(unsigned int value)
Definition: cuddCache.c:1036
int shift
Definition: cuddInt.h:312
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddShrinkSubtable()

void cuddShrinkSubtable ( DdManager unique,
int  i 
)

Function********************************************************************

Synopsis [Shrinks a subtable.]

Description [Shrinks a subtable.]

SideEffects [None]

SeeAlso [cuddRehash]

Definition at line 1731 of file cuddTable.c.

1734 {
1735  int j;
1736  int shift, posn;
1737  DdNodePtr *nodelist, *oldnodelist;
1738  DdNode *node, *next;
1739  DdNode *sentinel = &(unique->sentinel);
1740  unsigned int slots, oldslots;
1741  extern DD_OOMFP MMoutOfMemory;
1742  DD_OOMFP saveHandler;
1743 
1744  oldnodelist = unique->subtables[i].nodelist;
1745  oldslots = unique->subtables[i].slots;
1746  slots = oldslots >> 1;
1747  saveHandler = MMoutOfMemory;
1748  MMoutOfMemory = Cudd_OutOfMem;
1749  nodelist = ALLOC(DdNodePtr, slots);
1750  MMoutOfMemory = saveHandler;
1751  if (nodelist == NULL) {
1752  return;
1753  }
1754  unique->subtables[i].nodelist = nodelist;
1755  unique->subtables[i].slots = slots;
1756  unique->subtables[i].shift++;
1757  unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
1758 #ifdef DD_VERBOSE
1759  (void) fprintf(unique->err,
1760  "shrunk layer %d (%d keys) from %d to %d slots\n",
1761  i, unique->subtables[i].keys, oldslots, slots);
1762 #endif
1763 
1764  for (j = 0; (unsigned) j < slots; j++) {
1765  nodelist[j] = sentinel;
1766  }
1767  shift = unique->subtables[i].shift;
1768  for (j = 0; (unsigned) j < oldslots; j++) {
1769  node = oldnodelist[j];
1770  while (node != sentinel) {
1771  DdNode *looking, *T, *E;
1772  DdNodePtr *previousP;
1773  next = node->next;
1774  posn = ddHash(cuddT(node), cuddE(node), shift);
1775  previousP = &(nodelist[posn]);
1776  looking = *previousP;
1777  T = cuddT(node);
1778  E = cuddE(node);
1779  while (T < cuddT(looking)) {
1780  previousP = &(looking->next);
1781  looking = *previousP;
1782 #ifdef DD_UNIQUE_PROFILE
1783  unique->uniqueLinks++;
1784 #endif
1785  }
1786  while (T == cuddT(looking) && E < cuddE(looking)) {
1787  previousP = &(looking->next);
1788  looking = *previousP;
1789 #ifdef DD_UNIQUE_PROFILE
1790  unique->uniqueLinks++;
1791 #endif
1792  }
1793  node->next = *previousP;
1794  *previousP = node;
1795  node = next;
1796  }
1797  }
1798  FREE(oldnodelist);
1799 
1800  unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *);
1801  unique->slots += slots - oldslots;
1802  unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
1803  unique->cacheSlack = (int)
1805  - 2 * (int) unique->cacheSlots;
1806 
1807 } /* end of cuddShrinkSubtable */
unsigned int keys
Definition: cuddInt.h:314
#define ddHash(f, g, s)
Definition: cuddInt.h:696
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
double gcFrac
Definition: cuddInt.h:359
unsigned int maxCacheHard
Definition: cuddInt.h:343
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
DdSubtable * subtables
Definition: cuddInt.h:349
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
void(* DD_OOMFP)(long)
Definition: cudd.h:311
unsigned int cacheSlots
Definition: cuddInt.h:337
DdNode sentinel
Definition: cuddInt.h:328
#define ALLOC(type, num)
Definition: util.h:76
DdNode * next
Definition: cudd.h:273
unsigned int maxKeys
Definition: cuddInt.h:315
DdNode ** nodelist
Definition: cuddInt.h:311
#define ddMin(x, y)
Definition: cuddInt.h:771
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:145
int cacheSlack
Definition: cuddInt.h:342
#define cuddT(node)
Definition: cuddInt.h:609
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
unsigned long memused
Definition: cuddInt.h:429
unsigned int slots
Definition: cuddInt.h:313
#define cuddE(node)
Definition: cuddInt.h:625
int shift
Definition: cuddInt.h:312
unsigned int minDead
Definition: cuddInt.h:358

◆ cuddSlowTableGrowth()

void cuddSlowTableGrowth ( DdManager unique)

Function********************************************************************

Synopsis [Adjusts parameters of a table to slow down its growth.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 2414 of file cuddTable.c.

2416 {
2417  int i;
2418 
2419  unique->maxCacheHard = unique->cacheSlots - 1;
2420  unique->cacheSlack = - (int) (unique->cacheSlots + 1);
2421  for (i = 0; i < unique->size; i++) {
2422  unique->subtables[i].maxKeys <<= 2;
2423  }
2424  unique->gcFrac = DD_GC_FRAC_MIN;
2425  unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots);
2426  cuddShrinkDeathRow(unique);
2427  (void) fprintf(unique->err,"Slowing down table growth: ");
2428  (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac);
2429  (void) fprintf(unique->err,"minDead = %u\n", unique->minDead);
2430 
2431 } /* end of cuddSlowTableGrowth */
int size
Definition: cuddInt.h:345
double gcFrac
Definition: cuddInt.h:359
unsigned int maxCacheHard
Definition: cuddInt.h:343
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
DdSubtable * subtables
Definition: cuddInt.h:349
unsigned int cacheSlots
Definition: cuddInt.h:337
unsigned int maxKeys
Definition: cuddInt.h:315
int cacheSlack
Definition: cuddInt.h:342
#define DD_GC_FRAC_MIN
Definition: cuddInt.h:136
void cuddShrinkDeathRow(DdManager *table)
Definition: cuddRef.c:684
unsigned int minDead
Definition: cuddInt.h:358

◆ cuddUniqueConst()

DdNode* cuddUniqueConst ( DdManager unique,
CUDD_VALUE_TYPE  value 
)

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 1479 of file cuddTable.c.

1482 {
1483  int pos;
1484  DdNodePtr *nodelist;
1485  DdNode *looking;
1486  hack split;
1487 
1488 #ifdef DD_UNIQUE_PROFILE
1489  unique->uniqueLookUps++;
1490 #endif
1491 
1492  if (unique->constants.keys > unique->constants.maxKeys) {
1493  if (unique->gcEnabled && ((unique->dead > unique->minDead) ||
1494  (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */
1495  (void) cuddGarbageCollect(unique,1);
1496  } else {
1497  cuddRehash(unique,CUDD_CONST_INDEX);
1498  }
1499  }
1500 
1501  cuddAdjust(value); /* for the case of crippled infinities */
1502 
1503  if (ddAbs(value) < unique->epsilon) {
1504  value = 0.0;
1505  }
1506  split.value = value;
1507 
1508  pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift);
1509  nodelist = unique->constants.nodelist;
1510  looking = nodelist[pos];
1511 
1512  /* Here we compare values both for equality and for difference less
1513  * than epsilon. The first comparison is required when values are
1514  * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for
1515  * every X.
1516  */
1517  while (looking != NULL) {
1518  if (looking->type.value == value ||
1519  ddEqualVal(looking->type.value,value,unique->epsilon)) {
1520  if (looking->ref == 0) {
1521  cuddReclaim(unique,looking);
1522  }
1523  return(looking);
1524  }
1525  looking = looking->next;
1526 #ifdef DD_UNIQUE_PROFILE
1527  unique->uniqueLinks++;
1528 #endif
1529  }
1530 
1531  unique->keys++;
1532  unique->constants.keys++;
1533 
1534  looking = cuddAllocNode(unique);
1535  if (looking == NULL) return(NULL);
1536  looking->index = CUDD_CONST_INDEX;
1537  looking->type.value = value;
1538  looking->next = nodelist[pos];
1539  nodelist[pos] = looking;
1540 
1541  return(looking);
1542 
1543 } /* end of cuddUniqueConst */
DdHalfWord ref
Definition: cudd.h:272
unsigned int keys
Definition: cuddInt.h:314
#define ddHash(f, g, s)
Definition: cuddInt.h:696
union DdNode::@0 type
Definition: cudd.h:270
unsigned int bits[2]
Definition: cuddTable.c:109
void cuddReclaim(DdManager *table, DdNode *n)
Definition: cuddRef.c:580
unsigned int dead
Definition: cuddInt.h:355
CUDD_VALUE_TYPE value
Definition: cudd.h:275
unsigned int keys
Definition: cuddInt.h:353
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
unsigned int dead
Definition: cuddInt.h:316
DdNode * next
Definition: cudd.h:273
#define ddAbs(x)
Definition: cuddInt.h:799
void cuddRehash(DdManager *unique, int i)
Definition: cuddTable.c:1559
unsigned int maxKeys
Definition: cuddInt.h:315
int gcEnabled
Definition: cuddInt.h:360
#define CUDD_CONST_INDEX
Definition: cudd.h:113
DdNode ** nodelist
Definition: cuddInt.h:311
CUDD_VALUE_TYPE value
Definition: cuddTable.c:108
#define ddEqualVal(x, y, e)
Definition: cuddInt.h:814
DdHalfWord index
Definition: cudd.h:271
CUDD_VALUE_TYPE epsilon
Definition: cuddInt.h:390
DdSubtable constants
Definition: cuddInt.h:351
#define cuddAdjust(x)
Definition: cuddInt.h:932
int shift
Definition: cuddInt.h:312
DdNode * cuddAllocNode(DdManager *unique)
Definition: cuddTable.c:266
unsigned int minDead
Definition: cuddInt.h:358

◆ cuddUniqueInter()

DdNode* cuddUniqueInter ( DdManager unique,
int  index,
DdNode T,
DdNode E 
)

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 1137 of file cuddTable.c.

1142 {
1143  int pos;
1144  unsigned int level;
1145  int retval;
1146  DdNodePtr *nodelist;
1147  DdNode *looking;
1148  DdNodePtr *previousP;
1149  DdSubtable *subtable;
1150  int gcNumber;
1151 
1152 #ifdef DD_UNIQUE_PROFILE
1153  unique->uniqueLookUps++;
1154 #endif
1155 
1156  if ((0x1ffffUL & (unsigned long) unique->cacheMisses) == 0) {
1157  if (util_cpu_time() - unique->startTime > unique->timeLimit) {
1158  unique->errorCode = CUDD_TIMEOUT_EXPIRED;
1159  return(NULL);
1160  }
1161  }
1162  if (index >= unique->size) {
1163  int amount = ddMax(DD_DEFAULT_RESIZE,unique->size/20);
1164  if (!ddResizeTable(unique,index,amount)) return(NULL);
1165  }
1166 
1167  level = unique->perm[index];
1168  subtable = &(unique->subtables[level]);
1169 
1170 #ifdef DD_DEBUG
1171  assert(level < (unsigned) cuddI(unique,T->index));
1172  assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
1173 #endif
1174 
1175  pos = ddHash(T, E, subtable->shift);
1176  nodelist = subtable->nodelist;
1177  previousP = &(nodelist[pos]);
1178  looking = *previousP;
1179 
1180  while (T < cuddT(looking)) {
1181  previousP = &(looking->next);
1182  looking = *previousP;
1183 #ifdef DD_UNIQUE_PROFILE
1184  unique->uniqueLinks++;
1185 #endif
1186  }
1187  while (T == cuddT(looking) && E < cuddE(looking)) {
1188  previousP = &(looking->next);
1189  looking = *previousP;
1190 #ifdef DD_UNIQUE_PROFILE
1191  unique->uniqueLinks++;
1192 #endif
1193  }
1194  if (T == cuddT(looking) && E == cuddE(looking)) {
1195  if (looking->ref == 0) {
1196  cuddReclaim(unique,looking);
1197  }
1198  return(looking);
1199  }
1200 
1201  /* countDead is 0 if deads should be counted and ~0 if they should not. */
1202  if (unique->autoDyn &&
1203  unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn &&
1204  unique->maxReorderings > 0) {
1205  unsigned long cpuTime;
1206 #ifdef DD_DEBUG
1207  retval = Cudd_DebugCheck(unique);
1208  if (retval != 0) return(NULL);
1209  retval = Cudd_CheckKeys(unique);
1210  if (retval != 0) return(NULL);
1211 #endif
1212  retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */
1213  unique->maxReorderings--;
1214  if (retval == 0) {
1215  unique->reordered = 2;
1216  } else if ((cpuTime = util_cpu_time()) - unique->startTime > unique->timeLimit) {
1217  unique->errorCode = CUDD_TIMEOUT_EXPIRED;
1218  unique->reordered = 0;
1219  } else if (unique->timeLimit - (cpuTime - unique->startTime)
1220  < unique->reordTime) {
1221  unique->autoDyn = 0;
1222  }
1223 #ifdef DD_DEBUG
1224  retval = Cudd_DebugCheck(unique);
1225  if (retval != 0) unique->reordered = 2;
1226  retval = Cudd_CheckKeys(unique);
1227  if (retval != 0) unique->reordered = 2;
1228 #endif
1229  return(NULL);
1230  }
1231 
1232  if (subtable->keys > subtable->maxKeys) {
1233  if (unique->gcEnabled &&
1234  ((unique->dead > unique->minDead) ||
1235  ((unique->dead > unique->minDead / 2) &&
1236  (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */
1237  if (util_cpu_time() - unique->startTime > unique->timeLimit) {
1238  unique->errorCode = CUDD_TIMEOUT_EXPIRED;
1239  return(NULL);
1240  }
1241  (void) cuddGarbageCollect(unique,1);
1242  } else {
1243  cuddRehash(unique,(int)level);
1244  }
1245  /* Update pointer to insertion point. In the case of rehashing,
1246  ** the slot may have changed. In the case of garbage collection,
1247  ** the predecessor may have been dead. */
1248  pos = ddHash(T, E, subtable->shift);
1249  nodelist = subtable->nodelist;
1250  previousP = &(nodelist[pos]);
1251  looking = *previousP;
1252 
1253  while (T < cuddT(looking)) {
1254  previousP = &(looking->next);
1255  looking = *previousP;
1256 #ifdef DD_UNIQUE_PROFILE
1257  unique->uniqueLinks++;
1258 #endif
1259  }
1260  while (T == cuddT(looking) && E < cuddE(looking)) {
1261  previousP = &(looking->next);
1262  looking = *previousP;
1263 #ifdef DD_UNIQUE_PROFILE
1264  unique->uniqueLinks++;
1265 #endif
1266  }
1267  }
1268 
1269  gcNumber = unique->garbageCollections;
1270  looking = cuddAllocNode(unique);
1271  if (looking == NULL) {
1272  return(NULL);
1273  }
1274  unique->keys++;
1275  subtable->keys++;
1276 
1277  if (gcNumber != unique->garbageCollections) {
1278  DdNode *looking2;
1279  pos = ddHash(T, E, subtable->shift);
1280  nodelist = subtable->nodelist;
1281  previousP = &(nodelist[pos]);
1282  looking2 = *previousP;
1283 
1284  while (T < cuddT(looking2)) {
1285  previousP = &(looking2->next);
1286  looking2 = *previousP;
1287 #ifdef DD_UNIQUE_PROFILE
1288  unique->uniqueLinks++;
1289 #endif
1290  }
1291  while (T == cuddT(looking2) && E < cuddE(looking2)) {
1292  previousP = &(looking2->next);
1293  looking2 = *previousP;
1294 #ifdef DD_UNIQUE_PROFILE
1295  unique->uniqueLinks++;
1296 #endif
1297  }
1298  }
1299  looking->index = index;
1300  cuddT(looking) = T;
1301  cuddE(looking) = E;
1302  looking->next = *previousP;
1303  *previousP = looking;
1304  cuddSatInc(T->ref); /* we know T is a regular pointer */
1305  cuddRef(E);
1306 
1307 #ifdef DD_DEBUG
1308  cuddCheckCollisionOrdering(unique,level,pos);
1309 #endif
1310 
1311  return(looking);
1312 
1313 } /* end of cuddUniqueInter */
DdHalfWord ref
Definition: cudd.h:272
#define cuddRef(n)
Definition: cuddInt.h:557
unsigned int keys
Definition: cuddInt.h:314
static int ddResizeTable(DdManager *unique, int index, int amount)
Definition: cuddTable.c:2555
#define ddHash(f, g, s)
Definition: cuddInt.h:696
unsigned long reordTime
Definition: cuddInt.h:434
Cudd_ReorderingType autoMethod
Definition: cuddInt.h:402
Definition: cudd.h:270
unsigned long startTime
Definition: cuddInt.h:426
#define assert(ex)
Definition: util.h:141
int size
Definition: cuddInt.h:345
#define Cudd_Regular(node)
Definition: cudd.h:384
void cuddReclaim(DdManager *table, DdNode *n)
Definition: cuddRef.c:580
int garbageCollections
Definition: cuddInt.h:432
DdSubtable * subtables
Definition: cuddInt.h:349
unsigned int countDead
Definition: cuddInt.h:407
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
unsigned int dead
Definition: cuddInt.h:355
unsigned int keys
Definition: cuddInt.h:353
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
unsigned int dead
Definition: cuddInt.h:316
DdNode * next
Definition: cudd.h:273
void cuddRehash(DdManager *unique, int i)
Definition: cuddTable.c:1559
unsigned int maxKeys
Definition: cuddInt.h:315
int gcEnabled
Definition: cuddInt.h:360
#define ddMax(x, y)
Definition: cuddInt.h:785
DdNode ** nodelist
Definition: cuddInt.h:311
int Cudd_DebugCheck(DdManager *table)
Definition: cuddCheck.c:138
long util_cpu_time(void)
Definition: cpu_time.c:34
#define cuddT(node)
Definition: cuddInt.h:609
unsigned int maxReorderings
Definition: cuddInt.h:394
#define cuddI(dd, index)
Definition: cuddInt.h:659
#define DD_DEFAULT_RESIZE
Definition: cuddInt.h:103
DdHalfWord index
Definition: cudd.h:271
double cacheMisses
Definition: cuddInt.h:339
int Cudd_CheckKeys(DdManager *table)
Definition: cuddCheck.c:460
#define cuddE(node)
Definition: cuddInt.h:625
int Cudd_ReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddReorder.c:172
int autoDyn
Definition: cuddInt.h:400
int shift
Definition: cuddInt.h:312
int * perm
Definition: cuddInt.h:369
unsigned long timeLimit
Definition: cuddInt.h:427
DdNode * cuddAllocNode(DdManager *unique)
Definition: cuddTable.c:266
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
unsigned int minDead
Definition: cuddInt.h:358
#define cuddSatInc(x)
Definition: cuddInt.h:831

◆ cuddUniqueInterIVO()

DdNode* cuddUniqueInterIVO ( DdManager unique,
int  index,
DdNode T,
DdNode E 
)

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 1333 of file cuddTable.c.

1338 {
1339  DdNode *result;
1340  DdNode *v;
1341 
1342  v = cuddUniqueInter(unique, index, DD_ONE(unique),
1343  Cudd_Not(DD_ONE(unique)));
1344  if (v == NULL)
1345  return(NULL);
1346  /* Since v is a projection function, we can skip the call to cuddRef. */
1347  result = cuddBddIteRecur(unique, v, T, E);
1348  return(result);
1349 
1350 } /* end of cuddUniqueInterIVO */
Definition: cudd.h:270
#define Cudd_Not(node)
Definition: cudd.h:354
DdNode * cuddBddIteRecur(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddBddIte.c:742
static int result
Definition: cuddGenetic.c:121
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1137
#define DD_ONE(dd)
Definition: cuddInt.h:864

◆ cuddUniqueInterZdd()

DdNode* cuddUniqueInterZdd ( DdManager unique,
int  index,
DdNode T,
DdNode E 
)

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 1372 of file cuddTable.c.

1377 {
1378  int pos;
1379  unsigned int level;
1380  int retval;
1381  DdNodePtr *nodelist;
1382  DdNode *looking;
1383  DdSubtable *subtable;
1384 
1385 #ifdef DD_UNIQUE_PROFILE
1386  unique->uniqueLookUps++;
1387 #endif
1388 
1389  if (index >= unique->sizeZ) {
1390  if (!cuddResizeTableZdd(unique,index)) return(NULL);
1391  }
1392 
1393  level = unique->permZ[index];
1394  subtable = &(unique->subtableZ[level]);
1395 
1396 #ifdef DD_DEBUG
1397  assert(level < (unsigned) cuddIZ(unique,T->index));
1398  assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index));
1399 #endif
1400 
1401  if (subtable->keys > subtable->maxKeys) {
1402  if (unique->gcEnabled && ((unique->deadZ > unique->minDead) ||
1403  (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */
1404  (void) cuddGarbageCollect(unique,1);
1405  } else {
1406  ddRehashZdd(unique,(int)level);
1407  }
1408  }
1409 
1410  pos = ddHash(T, E, subtable->shift);
1411  nodelist = subtable->nodelist;
1412  looking = nodelist[pos];
1413 
1414  while (looking != NULL) {
1415  if (cuddT(looking) == T && cuddE(looking) == E) {
1416  if (looking->ref == 0) {
1417  cuddReclaimZdd(unique,looking);
1418  }
1419  return(looking);
1420  }
1421  looking = looking->next;
1422 #ifdef DD_UNIQUE_PROFILE
1423  unique->uniqueLinks++;
1424 #endif
1425  }
1426 
1427  /* countDead is 0 if deads should be counted and ~0 if they should not. */
1428  if (unique->autoDynZ &&
1429  unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) {
1430 #ifdef DD_DEBUG
1431  retval = Cudd_DebugCheck(unique);
1432  if (retval != 0) return(NULL);
1433  retval = Cudd_CheckKeys(unique);
1434  if (retval != 0) return(NULL);
1435 #endif
1436  retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */
1437  if (retval == 0) unique->reordered = 2;
1438 #ifdef DD_DEBUG
1439  retval = Cudd_DebugCheck(unique);
1440  if (retval != 0) unique->reordered = 2;
1441  retval = Cudd_CheckKeys(unique);
1442  if (retval != 0) unique->reordered = 2;
1443 #endif
1444  return(NULL);
1445  }
1446 
1447  unique->keysZ++;
1448  subtable->keys++;
1449 
1450  looking = cuddAllocNode(unique);
1451  if (looking == NULL) return(NULL);
1452  looking->index = index;
1453  cuddT(looking) = T;
1454  cuddE(looking) = E;
1455  looking->next = nodelist[pos];
1456  nodelist[pos] = looking;
1457  cuddRef(T);
1458  cuddRef(E);
1459 
1460  return(looking);
1461 
1462 } /* end of cuddUniqueInterZdd */
DdHalfWord ref
Definition: cudd.h:272
#define cuddRef(n)
Definition: cuddInt.h:557
unsigned int keys
Definition: cuddInt.h:314
#define ddHash(f, g, s)
Definition: cuddInt.h:696
#define cuddIZ(dd, index)
Definition: cuddInt.h:677
Definition: cudd.h:270
unsigned int deadZ
Definition: cuddInt.h:356
#define assert(ex)
Definition: util.h:141
#define Cudd_Regular(node)
Definition: cudd.h:384
Cudd_ReorderingType autoMethodZ
Definition: cuddInt.h:403
int * permZ
Definition: cuddInt.h:370
unsigned int countDead
Definition: cuddInt.h:407
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
int cuddResizeTableZdd(DdManager *unique, int index)
Definition: cuddTable.c:2270
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
unsigned int dead
Definition: cuddInt.h:316
DdNode * next
Definition: cudd.h:273
unsigned int maxKeys
Definition: cuddInt.h:315
int gcEnabled
Definition: cuddInt.h:360
DdNode ** nodelist
Definition: cuddInt.h:311
int Cudd_DebugCheck(DdManager *table)
Definition: cuddCheck.c:138
#define cuddT(node)
Definition: cuddInt.h:609
static void ddRehashZdd(DdManager *unique, int i)
Definition: cuddTable.c:2451
void cuddReclaimZdd(DdManager *table, DdNode *n)
Definition: cuddRef.c:634
int Cudd_zddReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddZddReord.c:167
int sizeZ
Definition: cuddInt.h:346
DdHalfWord index
Definition: cudd.h:271
int Cudd_CheckKeys(DdManager *table)
Definition: cuddCheck.c:460
int autoDynZ
Definition: cuddInt.h:401
#define cuddE(node)
Definition: cuddInt.h:625
int shift
Definition: cuddInt.h:312
unsigned int keysZ
Definition: cuddInt.h:354
DdNode * cuddAllocNode(DdManager *unique)
Definition: cuddTable.c:266
unsigned int minDead
Definition: cuddInt.h:358
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddGetNode()

DdNode* cuddZddGetNode ( DdManager zdd,
int  id,
DdNode T,
DdNode E 
)

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 1050 of file cuddTable.c.

1055 {
1056  DdNode *node;
1057 
1058  if (T == DD_ZERO(zdd))
1059  return(E);
1060  node = cuddUniqueInterZdd(zdd, id, T, E);
1061  return(node);
1062 
1063 } /* end of cuddZddGetNode */
Definition: cudd.h:270
DdNode * cuddUniqueInterZdd(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1372
#define DD_ZERO(dd)
Definition: cuddInt.h:880

◆ cuddZddGetNodeIVO()

DdNode* cuddZddGetNodeIVO ( DdManager dd,
int  index,
DdNode g,
DdNode h 
)

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 1083 of file cuddTable.c.

1088 {
1089  DdNode *f, *r, *t;
1090  DdNode *zdd_one = DD_ONE(dd);
1091  DdNode *zdd_zero = DD_ZERO(dd);
1092 
1093  f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero);
1094  if (f == NULL) {
1095  return(NULL);
1096  }
1097  cuddRef(f);
1098  t = cuddZddProduct(dd, f, g);
1099  if (t == NULL) {
1100  Cudd_RecursiveDerefZdd(dd, f);
1101  return(NULL);
1102  }
1103  cuddRef(t);
1104  Cudd_RecursiveDerefZdd(dd, f);
1105  r = cuddZddUnion(dd, t, h);
1106  if (r == NULL) {
1107  Cudd_RecursiveDerefZdd(dd, t);
1108  return(NULL);
1109  }
1110  cuddRef(r);
1111  Cudd_RecursiveDerefZdd(dd, t);
1112 
1113  cuddDeref(r);
1114  return(r);
1115 
1116 } /* end of cuddZddGetNodeIVO */
#define cuddRef(n)
Definition: cuddInt.h:557
void Cudd_RecursiveDerefZdd(DdManager *table, DdNode *n)
Definition: cuddRef.c:381
#define cuddDeref(n)
Definition: cuddInt.h:577
Definition: cudd.h:270
DdNode * cuddZddProduct(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddZddFuncs.c:376
DdNode * cuddZddUnion(DdManager *zdd, DdNode *P, DdNode *Q)
Definition: cuddZddSetop.c:549
DdNode * cuddUniqueInterZdd(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1372
#define DD_ONE(dd)
Definition: cuddInt.h:864
#define DD_ZERO(dd)
Definition: cuddInt.h:880

◆ ddFixLimits()

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 2843 of file cuddTable.c.

2845 {
2846  unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots);
2847  unique->cacheSlack = (int) ddMin(unique->maxCacheHard,
2848  DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) -
2849  2 * (int) unique->cacheSlots;
2850  if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0)
2851  cuddCacheResize(unique);
2852  return;
2853 
2854 } /* end of ddFixLimits */
double gcFrac
Definition: cuddInt.h:359
unsigned int maxCacheHard
Definition: cuddInt.h:343
unsigned int slots
Definition: cuddInt.h:352
void cuddCacheResize(DdManager *table)
Definition: cuddCache.c:889
unsigned int cacheSlots
Definition: cuddInt.h:337
#define ddMin(x, y)
Definition: cuddInt.h:771
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:145
int cacheSlack
Definition: cuddInt.h:342
unsigned int minDead
Definition: cuddInt.h:358
if(DEFINED IN_SOURCE_BUILD) set(LLVM_LINK_COMPONENTS BitWriter Core IPO IrReader InstCombine Instrumentation Target Linker Analysis ScalarOpts Support Svf Cudd) add_llvm_tool(dvf dda.cpp) else() add_executable(dvf dda.cpp) target_link_libraries(dvf Svf Cudd $
Definition: CMakeLists.txt:2

◆ ddPatchTree()

static void ddPatchTree ( DdManager dd,
MtrNode treenode 
)
static

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 3118 of file cuddTable.c.

3121 {
3122  MtrNode *auxnode = treenode;
3123 
3124  while (auxnode != NULL) {
3125  auxnode->low = dd->perm[auxnode->index];
3126  if (auxnode->child != NULL) {
3127  ddPatchTree(dd, auxnode->child);
3128  }
3129  auxnode = auxnode->younger;
3130  }
3131 
3132  return;
3133 
3134 } /* end of ddPatchTree */
static void ddPatchTree(DdManager *dd, MtrNode *treenode)
Definition: cuddTable.c:3118
struct MtrNode * younger
Definition: mtr.h:134
MtrHalfWord index
Definition: mtr.h:130
MtrHalfWord low
Definition: mtr.h:128
Definition: mtr.h:126
struct MtrNode * child
Definition: mtr.h:132
int * perm
Definition: cuddInt.h:369

◆ ddRehashZdd()

static void ddRehashZdd ( DdManager unique,
int  i 
)
static

AutomaticStart

Function********************************************************************

Synopsis [Rehashes a ZDD unique subtable.]

Description []

SideEffects [None]

SeeAlso [cuddRehash]

Definition at line 2451 of file cuddTable.c.

2454 {
2455  unsigned int slots, oldslots;
2456  int shift, oldshift;
2457  int j, pos;
2458  DdNodePtr *nodelist, *oldnodelist;
2459  DdNode *node, *next;
2460  extern DD_OOMFP MMoutOfMemory;
2461  DD_OOMFP saveHandler;
2462 
2463  if (unique->slots > unique->looseUpTo) {
2464  unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots);
2465 #ifdef DD_VERBOSE
2466  if (unique->gcFrac == DD_GC_FRAC_HI) {
2467  (void) fprintf(unique->err,"GC fraction = %.2f\t",
2468  DD_GC_FRAC_LO);
2469  (void) fprintf(unique->err,"minDead = %d\n", unique->minDead);
2470  }
2471 #endif
2472  unique->gcFrac = DD_GC_FRAC_LO;
2473  }
2474 
2475  assert(i != CUDD_MAXINDEX);
2476  oldslots = unique->subtableZ[i].slots;
2477  oldshift = unique->subtableZ[i].shift;
2478  oldnodelist = unique->subtableZ[i].nodelist;
2479 
2480  /* Compute the new size of the subtable. Normally, we just
2481  ** double. However, after reordering, a table may be severely
2482  ** overloaded. Therefore, we iterate. */
2483  slots = oldslots;
2484  shift = oldshift;
2485  do {
2486  slots <<= 1;
2487  shift--;
2488  } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys);
2489 
2490  saveHandler = MMoutOfMemory;
2491  MMoutOfMemory = Cudd_OutOfMem;
2492  nodelist = ALLOC(DdNodePtr, slots);
2493  MMoutOfMemory = saveHandler;
2494  if (nodelist == NULL) {
2495  (void) fprintf(unique->err,
2496  "Unable to resize ZDD subtable %d for lack of memory.\n",
2497  i);
2498  (void) cuddGarbageCollect(unique,1);
2499  for (j = 0; j < unique->sizeZ; j++) {
2500  unique->subtableZ[j].maxKeys <<= 1;
2501  }
2502  return;
2503  }
2504  unique->subtableZ[i].nodelist = nodelist;
2505  unique->subtableZ[i].slots = slots;
2506  unique->subtableZ[i].shift = shift;
2507  unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
2508  for (j = 0; (unsigned) j < slots; j++) {
2509  nodelist[j] = NULL;
2510  }
2511  for (j = 0; (unsigned) j < oldslots; j++) {
2512  node = oldnodelist[j];
2513  while (node != NULL) {
2514  next = node->next;
2515  pos = ddHash(cuddT(node), cuddE(node), shift);
2516  node->next = nodelist[pos];
2517  nodelist[pos] = node;
2518  node = next;
2519  }
2520  }
2521  FREE(oldnodelist);
2522 
2523 #ifdef DD_VERBOSE
2524  (void) fprintf(unique->err,
2525  "rehashing layer %d: keys %d dead %d new size %d\n",
2526  i, unique->subtableZ[i].keys,
2527  unique->subtableZ[i].dead, slots);
2528 #endif
2529 
2530  /* Update global data. */
2531  unique->memused += (slots - oldslots) * sizeof(DdNode *);
2532  unique->slots += (slots - oldslots);
2533  ddFixLimits(unique);
2534 
2535 } /* end of ddRehashZdd */
unsigned int keys
Definition: cuddInt.h:314
#define ddHash(f, g, s)
Definition: cuddInt.h:696
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
#define assert(ex)
Definition: util.h:141
double gcFrac
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
void(* DD_OOMFP)(long)
Definition: cudd.h:311
#define DD_GC_FRAC_HI
Definition: cuddInt.h:135
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
DdNode * next
Definition: cudd.h:273
#define DD_GC_FRAC_LO
Definition: cuddInt.h:134
unsigned int maxKeys
Definition: cuddInt.h:315
DdNode ** nodelist
Definition: cuddInt.h:311
#define cuddT(node)
Definition: cuddInt.h:609
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
unsigned long memused
Definition: cuddInt.h:429
int sizeZ
Definition: cuddInt.h:346
unsigned int looseUpTo
Definition: cuddInt.h:361
unsigned int slots
Definition: cuddInt.h:313
#define CUDD_MAXINDEX
Definition: cudd.h:108
#define cuddE(node)
Definition: cuddInt.h:625
static DD_INLINE void ddFixLimits(DdManager *unique)
Definition: cuddTable.c:2843
int shift
Definition: cuddInt.h:312
unsigned int minDead
Definition: cuddInt.h:358
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ ddReportRefMess()

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 3195 of file cuddTable.c.

3199 {
3200  if (i == CUDD_CONST_INDEX) {
3201  (void) fprintf(unique->err,
3202  "%s: problem in constants\n", caller);
3203  } else if (i != -1) {
3204  (void) fprintf(unique->err,
3205  "%s: problem in table %d\n", caller, i);
3206  }
3207  (void) fprintf(unique->err, " dead count != deleted\n");
3208  (void) fprintf(unique->err, " This problem is often due to a missing \
3209 call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \
3210 See the CUDD Programmer's Guide for additional details.");
3211  abort();
3212 
3213 } /* end of ddReportRefMess */
FILE * err
Definition: cuddInt.h:424
#define CUDD_CONST_INDEX
Definition: cudd.h:113
VOID_OR_INT abort()

◆ ddResizeTable()

static int ddResizeTable ( DdManager unique,
int  index,
int  amount 
)
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. The parameter amount determines how much spare space is allocated to prevent too frequent resizing. If index is negative, the table is resized, but no new variables are created. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [Cudd_Reserve cuddResizeTableZdd]

Definition at line 2555 of file cuddTable.c.

2559 {
2560  DdSubtable *newsubtables;
2561  DdNodePtr *newnodelist;
2562  DdNodePtr *newvars;
2563  DdNode *sentinel = &(unique->sentinel);
2564  int oldsize,newsize;
2565  int i,j,reorderSave;
2566  int numSlots = unique->initSlots;
2567  int *newperm, *newinvperm, *newmap;
2568  DdNode *one, *zero;
2569 
2570  oldsize = unique->size;
2571  /* Easy case: there is still room in the current table. */
2572  if (index >= 0 && index < unique->maxSize) {
2573  for (i = oldsize; i <= index; i++) {
2574  unique->subtables[i].slots = numSlots;
2575  unique->subtables[i].shift = sizeof(int) * 8 -
2576  cuddComputeFloorLog2(numSlots);
2577  unique->subtables[i].keys = 0;
2578  unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
2579  unique->subtables[i].dead = 0;
2580  unique->subtables[i].bindVar = 0;
2582  unique->subtables[i].pairIndex = 0;
2583  unique->subtables[i].varHandled = 0;
2585 
2586  unique->perm[i] = i;
2587  unique->invperm[i] = i;
2588  newnodelist = unique->subtables[i].nodelist =
2589  ALLOC(DdNodePtr, numSlots);
2590  if (newnodelist == NULL) {
2591  for (j = oldsize; j < i; j++) {
2592  FREE(unique->subtables[j].nodelist);
2593  }
2594  unique->errorCode = CUDD_MEMORY_OUT;
2595  return(0);
2596  }
2597  for (j = 0; j < numSlots; j++) {
2598  newnodelist[j] = sentinel;
2599  }
2600  }
2601  if (unique->map != NULL) {
2602  for (i = oldsize; i <= index; i++) {
2603  unique->map[i] = i;
2604  }
2605  }
2606  } else {
2607  /* The current table is too small: we need to allocate a new,
2608  ** larger one; move all old subtables, and initialize the new
2609  ** subtables up to index included.
2610  */
2611  newsize = (index < 0) ? amount : index + amount;
2612 #ifdef DD_VERBOSE
2613  (void) fprintf(unique->err,
2614  "Increasing the table size from %d to %d\n",
2615  unique->maxSize, newsize);
2616 #endif
2617  newsubtables = ALLOC(DdSubtable,newsize);
2618  if (newsubtables == NULL) {
2619  unique->errorCode = CUDD_MEMORY_OUT;
2620  return(0);
2621  }
2622  newvars = ALLOC(DdNodePtr,newsize);
2623  if (newvars == NULL) {
2624  FREE(newsubtables);
2625  unique->errorCode = CUDD_MEMORY_OUT;
2626  return(0);
2627  }
2628  newperm = ALLOC(int,newsize);
2629  if (newperm == NULL) {
2630  FREE(newsubtables);
2631  FREE(newvars);
2632  unique->errorCode = CUDD_MEMORY_OUT;
2633  return(0);
2634  }
2635  newinvperm = ALLOC(int,newsize);
2636  if (newinvperm == NULL) {
2637  FREE(newsubtables);
2638  FREE(newvars);
2639  FREE(newperm);
2640  unique->errorCode = CUDD_MEMORY_OUT;
2641  return(0);
2642  }
2643  if (unique->map != NULL) {
2644  newmap = ALLOC(int,newsize);
2645  if (newmap == NULL) {
2646  FREE(newsubtables);
2647  FREE(newvars);
2648  FREE(newperm);
2649  FREE(newinvperm);
2650  unique->errorCode = CUDD_MEMORY_OUT;
2651  return(0);
2652  }
2653  unique->memused += (newsize - unique->maxSize) * sizeof(int);
2654  }
2655  unique->memused += (newsize - unique->maxSize) * ((numSlots+1) *
2656  sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable));
2657  if (newsize > unique->maxSizeZ) {
2658  FREE(unique->stack);
2659  unique->stack = ALLOC(DdNodePtr,newsize + 1);
2660  if (unique->stack == NULL) {
2661  FREE(newsubtables);
2662  FREE(newvars);
2663  FREE(newperm);
2664  FREE(newinvperm);
2665  if (unique->map != NULL) {
2666  FREE(newmap);
2667  }
2668  unique->errorCode = CUDD_MEMORY_OUT;
2669  return(0);
2670  }
2671  unique->stack[0] = NULL; /* to suppress harmless UMR */
2672  unique->memused +=
2673  (newsize - ddMax(unique->maxSize,unique->maxSizeZ))
2674  * sizeof(DdNode *);
2675  }
2676  for (i = 0; i < oldsize; i++) {
2677  newsubtables[i].slots = unique->subtables[i].slots;
2678  newsubtables[i].shift = unique->subtables[i].shift;
2679  newsubtables[i].keys = unique->subtables[i].keys;
2680  newsubtables[i].maxKeys = unique->subtables[i].maxKeys;
2681  newsubtables[i].dead = unique->subtables[i].dead;
2682  newsubtables[i].nodelist = unique->subtables[i].nodelist;
2683  newsubtables[i].bindVar = unique->subtables[i].bindVar;
2684  newsubtables[i].varType = unique->subtables[i].varType;
2685  newsubtables[i].pairIndex = unique->subtables[i].pairIndex;
2686  newsubtables[i].varHandled = unique->subtables[i].varHandled;
2687  newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped;
2688 
2689  newvars[i] = unique->vars[i];
2690  newperm[i] = unique->perm[i];
2691  newinvperm[i] = unique->invperm[i];
2692  }
2693  for (i = oldsize; i <= index; i++) {
2694  newsubtables[i].slots = numSlots;
2695  newsubtables[i].shift = sizeof(int) * 8 -
2696  cuddComputeFloorLog2(numSlots);
2697  newsubtables[i].keys = 0;
2698  newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY;
2699  newsubtables[i].dead = 0;
2700  newsubtables[i].bindVar = 0;
2701  newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT;
2702  newsubtables[i].pairIndex = 0;
2703  newsubtables[i].varHandled = 0;
2704  newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE;
2705 
2706  newperm[i] = i;
2707  newinvperm[i] = i;
2708  newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots);
2709  if (newnodelist == NULL) {
2710  unique->errorCode = CUDD_MEMORY_OUT;
2711  return(0);
2712  }
2713  for (j = 0; j < numSlots; j++) {
2714  newnodelist[j] = sentinel;
2715  }
2716  }
2717  if (unique->map != NULL) {
2718  for (i = 0; i < oldsize; i++) {
2719  newmap[i] = unique->map[i];
2720  }
2721  for (i = oldsize; i <= index; i++) {
2722  newmap[i] = i;
2723  }
2724  FREE(unique->map);
2725  unique->map = newmap;
2726  }
2727  FREE(unique->subtables);
2728  unique->subtables = newsubtables;
2729  unique->maxSize = newsize;
2730  FREE(unique->vars);
2731  unique->vars = newvars;
2732  FREE(unique->perm);
2733  unique->perm = newperm;
2734  FREE(unique->invperm);
2735  unique->invperm = newinvperm;
2736  }
2737 
2738  /* Now that the table is in a coherent state, create the new
2739  ** projection functions. We need to temporarily disable reordering,
2740  ** because we cannot reorder without projection functions in place.
2741  **/
2742  if (index >= 0) {
2743  one = unique->one;
2744  zero = Cudd_Not(one);
2745 
2746  unique->size = index + 1;
2747  if (unique->tree != NULL) {
2748  unique->tree->size = ddMax(unique->tree->size, unique->size);
2749  }
2750  unique->slots += (index + 1 - oldsize) * numSlots;
2751  ddFixLimits(unique);
2752 
2753  reorderSave = unique->autoDyn;
2754  unique->autoDyn = 0;
2755  for (i = oldsize; i <= index; i++) {
2756  unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
2757  if (unique->vars[i] == NULL) {
2758  unique->autoDyn = reorderSave;
2759  for (j = oldsize; j < i; j++) {
2760  Cudd_IterDerefBdd(unique,unique->vars[j]);
2761  cuddDeallocNode(unique,unique->vars[j]);
2762  unique->vars[j] = NULL;
2763  }
2764  for (j = oldsize; j <= index; j++) {
2765  FREE(unique->subtables[j].nodelist);
2766  unique->subtables[j].nodelist = NULL;
2767  }
2768  unique->size = oldsize;
2769  unique->slots -= (index + 1 - oldsize) * numSlots;
2770  ddFixLimits(unique);
2771  return(0);
2772  }
2773  cuddRef(unique->vars[i]);
2774  }
2775  unique->autoDyn = reorderSave;
2776  }
2777 
2778  return(1);
2779 
2780 } /* end of ddResizeTable */
void Cudd_IterDerefBdd(DdManager *table, DdNode *n)
Definition: cuddRef.c:213
#define cuddRef(n)
Definition: cuddInt.h:557
unsigned int keys
Definition: cuddInt.h:314
int maxSizeZ
Definition: cuddInt.h:348
int * map
Definition: cuddInt.h:374
Definition: cudd.h:270
#define Cudd_Not(node)
Definition: cudd.h:354
MtrHalfWord size
Definition: mtr.h:129
#define FREE(obj)
Definition: util.h:80
int size
Definition: cuddInt.h:345
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
int bindVar
Definition: cuddInt.h:318
DdSubtable * subtables
Definition: cuddInt.h:349
MtrNode * tree
Definition: cuddInt.h:408
struct DdSubtable DdSubtable
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
DdNode ** stack
Definition: cuddInt.h:364
unsigned int initSlots
Definition: cuddInt.h:363
Cudd_VariableType varType
Definition: cuddInt.h:320
static DdNode * one
Definition: cuddSat.c:105
DdNode sentinel
Definition: cuddInt.h:328
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:323
int maxSize
Definition: cuddInt.h:347
unsigned int maxKeys
Definition: cuddInt.h:315
#define ddMax(x, y)
Definition: cuddInt.h:785
DdNode ** nodelist
Definition: cuddInt.h:311
int varHandled
Definition: cuddInt.h:322
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
unsigned long memused
Definition: cuddInt.h:429
unsigned int slots
Definition: cuddInt.h:313
DdNode ** vars
Definition: cuddInt.h:373
int pairIndex
Definition: cuddInt.h:321
static DdNode * zero
Definition: cuddSat.c:105
DdNode * one
Definition: cuddInt.h:329
static DD_INLINE void ddFixLimits(DdManager *unique)
Definition: cuddTable.c:2843
int * invperm
Definition: cuddInt.h:371
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1137
int cuddComputeFloorLog2(unsigned int value)
Definition: cuddCache.c:1036
int autoDyn
Definition: cuddInt.h:400
int shift
Definition: cuddInt.h:312
int * perm
Definition: cuddInt.h:369
Cudd_ErrorType errorCode
Definition: cuddInt.h:425

Variable Documentation

◆ DD_UNUSED

char rcsid [] DD_UNUSED = "$Id: cuddTable.c,v 1.126 2012/02/05 01:07:19 fabio Exp $"
static

Definition at line 121 of file cuddTable.c.