You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1557 lines
						
					
					
						
							40 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1557 lines
						
					
					
						
							40 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddLCache.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Functions for local caches.] | |
|  | |
|   Description [Internal procedures included in this module: | |
| 		<ul> | |
| 		<li> cuddLocalCacheInit() | |
| 		<li> cuddLocalCacheQuit() | |
| 		<li> cuddLocalCacheInsert() | |
| 		<li> cuddLocalCacheLookup() | |
| 		<li> cuddLocalCacheClearDead() | |
| 		<li> cuddLocalCacheClearAll() | |
| 		<li> cuddLocalCacheProfile() | |
| 		<li> cuddHashTableInit() | |
| 		<li> cuddHashTableQuit() | |
| 		<li> cuddHashTableGenericQuit() | |
| 		<li> cuddHashTableInsert() | |
| 		<li> cuddHashTableLookup() | |
| 		<li> cuddHashTableGenericInsert() | |
| 		<li> cuddHashTableGenericLookup() | |
| 		<li> cuddHashTableInsert2() | |
| 		<li> cuddHashTableLookup2() | |
| 		<li> cuddHashTableInsert3() | |
| 		<li> cuddHashTableLookup3() | |
| 		</ul> | |
| 	    Static procedures included in this module: | |
| 		<ul> | |
| 		<li> cuddLocalCacheResize() | |
| 		<li> ddLCHash() | |
| 		<li> cuddLocalCacheAddToList() | |
| 		<li> cuddLocalCacheRemoveFromList() | |
| 		<li> cuddHashTableResize() | |
| 		<li> cuddHashTableAlloc() | |
| 		</ul> ] | |
|  | |
|   SeeAlso     [] | |
|  | |
|   Author      [Fabio Somenzi] | |
|  | |
|   Copyright   [Copyright (c) 1995-2012, Regents of the University of Colorado | |
|  | |
|   All rights reserved. | |
|  | |
|   Redistribution and use in source and binary forms, with or without | |
|   modification, are permitted provided that the following conditions | |
|   are met: | |
|  | |
|   Redistributions of source code must retain the above copyright | |
|   notice, this list of conditions and the following disclaimer. | |
|  | |
|   Redistributions in binary form must reproduce the above copyright | |
|   notice, this list of conditions and the following disclaimer in the | |
|   documentation and/or other materials provided with the distribution. | |
|  | |
|   Neither the name of the University of Colorado nor the names of its | |
|   contributors may be used to endorse or promote products derived from | |
|   this software without specific prior written permission. | |
|  | |
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
|   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
|   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
|   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
|   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
|   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
|   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
|   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
|   POSSIBILITY OF SUCH DAMAGE.] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "util.h" | |
| #include "cuddInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Constant declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #define DD_MAX_HASHTABLE_DENSITY 2	/* tells when to resize a table */ | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.27 2012/02/05 01:07:19 fabio Exp $"; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Macro*********************************************************************** | |
|  | |
|   Synopsis    [Computes hash function for keys of one operand.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [ddLCHash3 ddLCHash] | |
|  | |
| ******************************************************************************/ | |
| #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 | |
| #define ddLCHash1(f,shift) \ | |
| (((unsigned)(ptruint)(f) * DD_P1) >> (shift)) | |
| #else | |
| #define ddLCHash1(f,shift) \ | |
| (((unsigned)(f) * DD_P1) >> (shift)) | |
| #endif | |
|  | |
| 
 | |
| /**Macro*********************************************************************** | |
|  | |
|   Synopsis    [Computes hash function for keys of two operands.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [ddLCHash3 ddLCHash] | |
|  | |
| ******************************************************************************/ | |
| #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 | |
| #define ddLCHash2(f,g,shift) \ | |
| ((((unsigned)(ptruint)(f) * DD_P1 + \ | |
|    (unsigned)(ptruint)(g)) * DD_P2) >> (shift)) | |
| #else | |
| #define ddLCHash2(f,g,shift) \ | |
| ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift)) | |
| #endif | |
|  | |
| 
 | |
| /**Macro*********************************************************************** | |
|  | |
|   Synopsis    [Computes hash function for keys of three operands.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [ddLCHash2 ddLCHash] | |
|  | |
| ******************************************************************************/ | |
| #define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift) | |
|  | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| static void cuddLocalCacheResize (DdLocalCache *cache); | |
| DD_INLINE static unsigned int ddLCHash (DdNodePtr *key, unsigned int keysize, int shift); | |
| static void cuddLocalCacheAddToList (DdLocalCache *cache); | |
| static void cuddLocalCacheRemoveFromList (DdLocalCache *cache); | |
| static int cuddHashTableResize (DdHashTable *hash); | |
| DD_INLINE static DdHashItem * cuddHashTableAlloc (DdHashTable *hash); | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Initializes a local computed table.] | |
|  | |
|   Description [Initializes a computed table.  Returns a pointer the | |
|   the new local cache in case of success; NULL otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddInitCache] | |
|  | |
| ******************************************************************************/ | |
| DdLocalCache * | |
| cuddLocalCacheInit( | |
|   DdManager * manager /* manager */, | |
|   unsigned int  keySize /* size of the key (number of operands) */, | |
|   unsigned int  cacheSize /* Initial size of the cache */, | |
|   unsigned int  maxCacheSize /* Size of the cache beyond which no resizing occurs */) | |
| { | |
|     DdLocalCache *cache; | |
|     int logSize; | |
| 
 | |
|     cache = ALLOC(DdLocalCache,1); | |
|     if (cache == NULL) { | |
| 	manager->errorCode = CUDD_MEMORY_OUT; | |
| 	return(NULL); | |
|     } | |
|     cache->manager = manager; | |
|     cache->keysize = keySize; | |
|     cache->itemsize = (keySize + 1) * sizeof(DdNode *); | |
| #ifdef DD_CACHE_PROFILE | |
|     cache->itemsize += sizeof(ptrint); | |
| #endif | |
|     logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2)); | |
|     cacheSize = 1 << logSize; | |
|     cache->item = (DdLocalCacheItem *) | |
| 	ALLOC(char, cacheSize * cache->itemsize); | |
|     if (cache->item == NULL) { | |
| 	manager->errorCode = CUDD_MEMORY_OUT; | |
| 	FREE(cache); | |
| 	return(NULL); | |
|     } | |
|     cache->slots = cacheSize; | |
|     cache->shift = sizeof(int) * 8 - logSize; | |
|     cache->maxslots = ddMin(maxCacheSize,manager->slots); | |
|     cache->minHit = manager->minHit; | |
|     /* Initialize to avoid division by 0 and immediate resizing. */ | |
|     cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1); | |
|     cache->hits = 0; | |
|     manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache); | |
| 
 | |
|     /* Initialize the cache. */ | |
|     memset(cache->item, 0, cacheSize * cache->itemsize); | |
| 
 | |
|     /* Add to manager's list of local caches for GC. */ | |
|     cuddLocalCacheAddToList(cache); | |
| 
 | |
|     return(cache); | |
| 
 | |
| } /* end of cuddLocalCacheInit */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Shuts down a local computed table.] | |
|  | |
|   Description [Initializes the computed table. It is called by | |
|   Cudd_Init. Returns a pointer the the new local cache in case of | |
|   success; NULL otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddLocalCacheInit] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddLocalCacheQuit( | |
|   DdLocalCache * cache /* cache to be shut down */) | |
| { | |
|     cache->manager->memused -= | |
| 	cache->slots * cache->itemsize + sizeof(DdLocalCache); | |
|     cuddLocalCacheRemoveFromList(cache); | |
|     FREE(cache->item); | |
|     FREE(cache); | |
| 
 | |
|     return; | |
| 
 | |
| } /* end of cuddLocalCacheQuit */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Inserts a result in a local cache.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddLocalCacheInsert( | |
|   DdLocalCache * cache, | |
|   DdNodePtr * key, | |
|   DdNode * value) | |
| { | |
|     unsigned int posn; | |
|     DdLocalCacheItem *entry; | |
| 
 | |
|     posn = ddLCHash(key,cache->keysize,cache->shift); | |
|     entry = (DdLocalCacheItem *) ((char *) cache->item + | |
| 				  posn * cache->itemsize); | |
|     memcpy(entry->key,key,cache->keysize * sizeof(DdNode *)); | |
|     entry->value = value; | |
| #ifdef DD_CACHE_PROFILE | |
|     entry->count++; | |
| #endif | |
|  | |
| } /* end of cuddLocalCacheInsert */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Looks up in a local cache.] | |
|  | |
|   Description [Looks up in a local cache. Returns the result if found; | |
|   it returns NULL if no result is found.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| DdNode * | |
| cuddLocalCacheLookup( | |
|   DdLocalCache * cache, | |
|   DdNodePtr * key) | |
| { | |
|     unsigned int posn; | |
|     DdLocalCacheItem *entry; | |
|     DdNode *value; | |
| 
 | |
|     cache->lookUps++; | |
|     posn = ddLCHash(key,cache->keysize,cache->shift); | |
|     entry = (DdLocalCacheItem *) ((char *) cache->item + | |
| 				  posn * cache->itemsize); | |
|     if (entry->value != NULL && | |
| 	memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) { | |
| 	cache->hits++; | |
| 	value = Cudd_Regular(entry->value); | |
| 	if (value->ref == 0) { | |
| 	    cuddReclaim(cache->manager,value); | |
| 	} | |
| 	return(entry->value); | |
|     } | |
| 
 | |
|     /* Cache miss: decide whether to resize */ | |
| 
 | |
|     if (cache->slots < cache->maxslots && | |
| 	cache->hits > cache->lookUps * cache->minHit) { | |
| 	cuddLocalCacheResize(cache); | |
|     } | |
| 
 | |
|     return(NULL); | |
| 
 | |
| } /* end of cuddLocalCacheLookup */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Clears the dead entries of the local caches of a manager.] | |
|  | |
|   Description [Clears the dead entries of the local caches of a manager. | |
|   Used during garbage collection.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddLocalCacheClearDead( | |
|   DdManager * manager) | |
| { | |
|     DdLocalCache *cache = manager->localCaches; | |
|     unsigned int keysize; | |
|     unsigned int itemsize; | |
|     unsigned int slots; | |
|     DdLocalCacheItem *item; | |
|     DdNodePtr *key; | |
|     unsigned int i, j; | |
| 
 | |
|     while (cache != NULL) { | |
| 	keysize = cache->keysize; | |
| 	itemsize = cache->itemsize; | |
| 	slots = cache->slots; | |
| 	item = cache->item; | |
| 	for (i = 0; i < slots; i++) { | |
| 	    if (item->value != NULL) { | |
| 		if (Cudd_Regular(item->value)->ref == 0) { | |
| 		    item->value = NULL; | |
| 		} else { | |
| 		    key = item->key; | |
| 		    for (j = 0; j < keysize; j++) { | |
| 			if (Cudd_Regular(key[j])->ref == 0) { | |
| 			    item->value = NULL; | |
| 			    break; | |
| 			} | |
| 		    } | |
| 		} | |
| 	    } | |
| 	    item = (DdLocalCacheItem *) ((char *) item + itemsize); | |
| 	} | |
| 	cache = cache->next; | |
|     } | |
|     return; | |
| 
 | |
| } /* end of cuddLocalCacheClearDead */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Clears the local caches of a manager.] | |
|  | |
|   Description [Clears the local caches of a manager. | |
|   Used before reordering.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddLocalCacheClearAll( | |
|   DdManager * manager) | |
| { | |
|     DdLocalCache *cache = manager->localCaches; | |
| 
 | |
|     while (cache != NULL) { | |
| 	memset(cache->item, 0, cache->slots * cache->itemsize); | |
| 	cache = cache->next; | |
|     } | |
|     return; | |
| 
 | |
| } /* end of cuddLocalCacheClearAll */ | |
| 
 | |
| 
 | |
| #ifdef DD_CACHE_PROFILE | |
|  | |
| #define DD_HYSTO_BINS 8 | |
|  | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes and prints a profile of a local cache usage.] | |
|  | |
|   Description [Computes and prints a profile of a local cache usage. | |
|   Returns 1 if successful; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddLocalCacheProfile( | |
|   DdLocalCache * cache) | |
| { | |
|     double count, mean, meansq, stddev, expected; | |
|     long max, min; | |
|     int imax, imin; | |
|     int i, retval, slots; | |
|     long *hystogram; | |
|     int nbins = DD_HYSTO_BINS; | |
|     int bin; | |
|     long thiscount; | |
|     double totalcount; | |
|     int nzeroes; | |
|     DdLocalCacheItem *entry; | |
|     FILE *fp = cache->manager->out; | |
| 
 | |
|     slots = cache->slots; | |
| 
 | |
|     meansq = mean = expected = 0.0; | |
|     max = min = (long) cache->item[0].count; | |
|     imax = imin = nzeroes = 0; | |
|     totalcount = 0.0; | |
| 
 | |
|     hystogram = ALLOC(long, nbins); | |
|     if (hystogram == NULL) { | |
| 	return(0); | |
|     } | |
|     for (i = 0; i < nbins; i++) { | |
| 	hystogram[i] = 0; | |
|     } | |
| 
 | |
|     for (i = 0; i < slots; i++) { | |
| 	entry = (DdLocalCacheItem *) ((char *) cache->item + | |
| 				      i * cache->itemsize); | |
| 	thiscount = (long) entry->count; | |
| 	if (thiscount > max) { | |
| 	    max = thiscount; | |
| 	    imax = i; | |
| 	} | |
| 	if (thiscount < min) { | |
| 	    min = thiscount; | |
| 	    imin = i; | |
| 	} | |
| 	if (thiscount == 0) { | |
| 	    nzeroes++; | |
| 	} | |
| 	count = (double) thiscount; | |
| 	mean += count; | |
| 	meansq += count * count; | |
| 	totalcount += count; | |
| 	expected += count * (double) i; | |
| 	bin = (i * nbins) / slots; | |
| 	hystogram[bin] += thiscount; | |
|     } | |
|     mean /= (double) slots; | |
|     meansq /= (double) slots; | |
|     stddev = sqrt(meansq - mean*mean); | |
| 
 | |
|     retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean); | |
|     if (retval == EOF) return(0); | |
|     retval = fprintf(fp,"standard deviation = %g\n", stddev); | |
|     if (retval == EOF) return(0); | |
|     retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); | |
|     if (retval == EOF) return(0); | |
|     retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); | |
|     if (retval == EOF) return(0); | |
|     retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes); | |
|     if (retval == EOF) return(0); | |
| 
 | |
|     if (totalcount) { | |
| 	expected /= totalcount; | |
| 	retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); | |
| 	if (retval == EOF) return(0); | |
| 	retval = fprintf(fp," (expected bin value = %g)\n# ", expected); | |
| 	if (retval == EOF) return(0); | |
| 	for (i = nbins - 1; i>=0; i--) { | |
| 	    retval = fprintf(fp,"%ld ", hystogram[i]); | |
| 	    if (retval == EOF) return(0); | |
| 	} | |
| 	retval = fprintf(fp,"\n"); | |
| 	if (retval == EOF) return(0); | |
|     } | |
| 
 | |
|     FREE(hystogram); | |
|     return(1); | |
| 
 | |
| } /* end of cuddLocalCacheProfile */ | |
| #endif | |
|  | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Initializes a hash table.] | |
|  | |
|   Description [Initializes a hash table. Returns a pointer to the new | |
|   table if successful; NULL otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableQuit] | |
|  | |
| ******************************************************************************/ | |
| DdHashTable * | |
| cuddHashTableInit( | |
|   DdManager * manager, | |
|   unsigned int  keySize, | |
|   unsigned int  initSize) | |
| { | |
|     DdHashTable *hash; | |
|     int logSize; | |
| 
 | |
|     hash = ALLOC(DdHashTable, 1); | |
|     if (hash == NULL) { | |
| 	manager->errorCode = CUDD_MEMORY_OUT; | |
| 	return(NULL); | |
|     } | |
|     hash->keysize = keySize; | |
|     hash->manager = manager; | |
|     hash->memoryList = NULL; | |
|     hash->nextFree = NULL; | |
|     hash->itemsize = (keySize + 1) * sizeof(DdNode *) + | |
| 	sizeof(ptrint) + sizeof(DdHashItem *); | |
|     /* We have to guarantee that the shift be < 32. */ | |
|     if (initSize < 2) initSize = 2; | |
|     logSize = cuddComputeFloorLog2(initSize); | |
|     hash->numBuckets = 1 << logSize; | |
|     hash->shift = sizeof(int) * 8 - logSize; | |
|     hash->bucket = ALLOC(DdHashItem *, hash->numBuckets); | |
|     if (hash->bucket == NULL) { | |
| 	manager->errorCode = CUDD_MEMORY_OUT; | |
| 	FREE(hash); | |
| 	return(NULL); | |
|     } | |
|     memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *)); | |
|     hash->size = 0; | |
|     hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY; | |
|     return(hash); | |
| 
 | |
| } /* end of cuddHashTableInit */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Shuts down a hash table.] | |
|  | |
|   Description [Shuts down a hash table, dereferencing all the values.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableInit] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddHashTableQuit( | |
|   DdHashTable * hash) | |
| { | |
|     unsigned int i; | |
|     DdManager *dd = hash->manager; | |
|     DdHashItem *bucket; | |
|     DdHashItem **memlist, **nextmem; | |
|     unsigned int numBuckets = hash->numBuckets; | |
| 
 | |
|     for (i = 0; i < numBuckets; i++) { | |
| 	bucket = hash->bucket[i]; | |
| 	while (bucket != NULL) { | |
| 	    Cudd_RecursiveDeref(dd, bucket->value); | |
| 	    bucket = bucket->next; | |
| 	} | |
|     } | |
| 
 | |
|     memlist = hash->memoryList; | |
|     while (memlist != NULL) { | |
| 	nextmem = (DdHashItem **) memlist[0]; | |
| 	FREE(memlist); | |
| 	memlist = nextmem; | |
|     } | |
| 
 | |
|     FREE(hash->bucket); | |
|     FREE(hash); | |
| 
 | |
|     return; | |
| 
 | |
| } /* end of cuddHashTableQuit */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Shuts down a hash table.] | |
|  | |
|   Description [Shuts down a hash table, when the values are not DdNode | |
|   pointers.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableInit] | |
|  | |
| ******************************************************************************/ | |
| void | |
| cuddHashTableGenericQuit( | |
|   DdHashTable * hash) | |
| { | |
| #ifdef __osf__ | |
| #pragma pointer_size save | |
| #pragma pointer_size short | |
| #endif | |
|     DdHashItem **memlist, **nextmem; | |
| 
 | |
|     memlist = hash->memoryList; | |
|     while (memlist != NULL) { | |
| 	nextmem = (DdHashItem **) memlist[0]; | |
| 	FREE(memlist); | |
| 	memlist = nextmem; | |
|     } | |
| 
 | |
|     FREE(hash->bucket); | |
|     FREE(hash); | |
| #ifdef __osf__ | |
| #pragma pointer_size restore | |
| #endif | |
|  | |
|     return; | |
| 
 | |
| } /* end of cuddHashTableGenericQuit */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Inserts an item in a hash table.] | |
|  | |
|   Description [Inserts an item in a hash table when the key has more than | |
|   three pointers.  Returns 1 if successful; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3 | |
|   cuddHashTableLookup] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddHashTableInsert( | |
|   DdHashTable * hash, | |
|   DdNodePtr * key, | |
|   DdNode * value, | |
|   ptrint count) | |
| { | |
|     int result; | |
|     unsigned int posn; | |
|     DdHashItem *item; | |
|     unsigned int i; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize > 3); | |
| #endif | |
|  | |
|     if (hash->size > hash->maxsize) { | |
| 	result = cuddHashTableResize(hash); | |
| 	if (result == 0) return(0); | |
|     } | |
|     item = cuddHashTableAlloc(hash); | |
|     if (item == NULL) return(0); | |
|     hash->size++; | |
|     item->value = value; | |
|     cuddRef(value); | |
|     item->count = count; | |
|     for (i = 0; i < hash->keysize; i++) { | |
| 	item->key[i] = key[i]; | |
|     } | |
|     posn = ddLCHash(key,hash->keysize,hash->shift); | |
|     item->next = hash->bucket[posn]; | |
|     hash->bucket[posn] = item; | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of cuddHashTableInsert */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Looks up a key in a hash table.] | |
|  | |
|   Description [Looks up a key consisting of more than three pointers | |
|   in a hash table.  Returns the value associated to the key if there | |
|   is an entry for the given key in the table; NULL otherwise. If the | |
|   entry is present, its reference counter is decremented if not | |
|   saturated. If the counter reaches 0, the value of the entry is | |
|   dereferenced, and the entry is returned to the free list.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3 | |
|   cuddHashTableInsert] | |
|  | |
| ******************************************************************************/ | |
| DdNode * | |
| cuddHashTableLookup( | |
|   DdHashTable * hash, | |
|   DdNodePtr * key) | |
| { | |
|     unsigned int posn; | |
|     DdHashItem *item, *prev; | |
|     unsigned int i, keysize; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize > 3); | |
| #endif | |
|  | |
|     posn = ddLCHash(key,hash->keysize,hash->shift); | |
|     item = hash->bucket[posn]; | |
|     prev = NULL; | |
| 
 | |
|     keysize = hash->keysize; | |
|     while (item != NULL) { | |
| 	DdNodePtr *key2 = item->key; | |
| 	int equal = 1; | |
| 	for (i = 0; i < keysize; i++) { | |
| 	    if (key[i] != key2[i]) { | |
| 		equal = 0; | |
| 		break; | |
| 	    } | |
| 	} | |
| 	if (equal) { | |
| 	    DdNode *value = item->value; | |
| 	    cuddSatDec(item->count); | |
| 	    if (item->count == 0) { | |
| 		cuddDeref(value); | |
| 		if (prev == NULL) { | |
| 		    hash->bucket[posn] = item->next; | |
| 		} else { | |
| 		    prev->next = item->next; | |
| 		} | |
| 		item->next = hash->nextFree; | |
| 		hash->nextFree = item; | |
| 		hash->size--; | |
| 	    } | |
| 	    return(value); | |
| 	} | |
| 	prev = item; | |
| 	item = item->next; | |
|     } | |
|     return(NULL); | |
| 
 | |
| } /* end of cuddHashTableLookup */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Inserts an item in a hash table.] | |
|  | |
|   Description [Inserts an item in a hash table when the key is one pointer. | |
|   Returns 1 if successful; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3 | |
|   cuddHashTableLookup1] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddHashTableInsert1( | |
|   DdHashTable * hash, | |
|   DdNode * f, | |
|   DdNode * value, | |
|   ptrint count) | |
| { | |
|     int result; | |
|     unsigned int posn; | |
|     DdHashItem *item; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 1); | |
| #endif | |
|  | |
|     if (hash->size > hash->maxsize) { | |
| 	result = cuddHashTableResize(hash); | |
| 	if (result == 0) return(0); | |
|     } | |
|     item = cuddHashTableAlloc(hash); | |
|     if (item == NULL) return(0); | |
|     hash->size++; | |
|     item->value = value; | |
|     cuddRef(value); | |
|     item->count = count; | |
|     item->key[0] = f; | |
|     posn = ddLCHash1(f,hash->shift); | |
|     item->next = hash->bucket[posn]; | |
|     hash->bucket[posn] = item; | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of cuddHashTableInsert1 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Looks up a key consisting of one pointer in a hash table.] | |
|  | |
|   Description [Looks up a key consisting of one pointer in a hash table. | |
|   Returns the value associated to the key if there is an entry for the given | |
|   key in the table; NULL otherwise. If the entry is present, its reference | |
|   counter is decremented if not saturated. If the counter reaches 0, the | |
|   value of the entry is dereferenced, and the entry is returned to the free | |
|   list.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3 | |
|   cuddHashTableInsert1] | |
|  | |
| ******************************************************************************/ | |
| DdNode * | |
| cuddHashTableLookup1( | |
|   DdHashTable * hash, | |
|   DdNode * f) | |
| { | |
|     unsigned int posn; | |
|     DdHashItem *item, *prev; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 1); | |
| #endif | |
|  | |
|     posn = ddLCHash1(f,hash->shift); | |
|     item = hash->bucket[posn]; | |
|     prev = NULL; | |
| 
 | |
|     while (item != NULL) { | |
| 	DdNodePtr *key = item->key; | |
| 	if (f == key[0]) { | |
| 	    DdNode *value = item->value; | |
| 	    cuddSatDec(item->count); | |
| 	    if (item->count == 0) { | |
| 		cuddDeref(value); | |
| 		if (prev == NULL) { | |
| 		    hash->bucket[posn] = item->next; | |
| 		} else { | |
| 		    prev->next = item->next; | |
| 		} | |
| 		item->next = hash->nextFree; | |
| 		hash->nextFree = item; | |
| 		hash->size--; | |
| 	    } | |
| 	    return(value); | |
| 	} | |
| 	prev = item; | |
| 	item = item->next; | |
|     } | |
|     return(NULL); | |
| 
 | |
| } /* end of cuddHashTableLookup1 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Inserts an item in a hash table.] | |
|  | |
|   Description [Inserts an item in a hash table when the key is one | |
|   pointer and the value is not a DdNode pointer.  Returns 1 if | |
|   successful; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableInsert1 cuddHashTableGenericLookup] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddHashTableGenericInsert( | |
|   DdHashTable * hash, | |
|   DdNode * f, | |
|   void * value) | |
| { | |
|     int result; | |
|     unsigned int posn; | |
|     DdHashItem *item; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 1); | |
| #endif | |
|  | |
|     if (hash->size > hash->maxsize) { | |
| 	result = cuddHashTableResize(hash); | |
| 	if (result == 0) return(0); | |
|     } | |
|     item = cuddHashTableAlloc(hash); | |
|     if (item == NULL) return(0); | |
|     hash->size++; | |
|     item->value = (DdNode *) value; | |
|     item->count = 0; | |
|     item->key[0] = f; | |
|     posn = ddLCHash1(f,hash->shift); | |
|     item->next = hash->bucket[posn]; | |
|     hash->bucket[posn] = item; | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of cuddHashTableGenericInsert */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Looks up a key consisting of one pointer in a hash table.] | |
|  | |
|   Description [Looks up a key consisting of one pointer in a hash | |
|   table when the value is not a DdNode pointer.  Returns the value | |
|   associated to the key if there is an entry for the given key in the | |
|   table; NULL otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableLookup1 cuddHashTableGenericInsert] | |
|  | |
| ******************************************************************************/ | |
| void * | |
| cuddHashTableGenericLookup( | |
|   DdHashTable * hash, | |
|   DdNode * f) | |
| { | |
|     unsigned int posn; | |
|     DdHashItem *item; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 1); | |
| #endif | |
|  | |
|     posn = ddLCHash1(f,hash->shift); | |
|     item = hash->bucket[posn]; | |
| 
 | |
|     while (item != NULL) { | |
| 	if (f == item->key[0]) { | |
|             return ((void *) item->value); | |
| 	} | |
| 	item = item->next; | |
|     } | |
|     return(NULL); | |
| 
 | |
| } /* end of cuddHashTableGenericLookup */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Inserts an item in a hash table.] | |
|  | |
|   Description [Inserts an item in a hash table when the key is | |
|   composed of two pointers. Returns 1 if successful; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3 | |
|   cuddHashTableLookup2] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddHashTableInsert2( | |
|   DdHashTable * hash, | |
|   DdNode * f, | |
|   DdNode * g, | |
|   DdNode * value, | |
|   ptrint count) | |
| { | |
|     int result; | |
|     unsigned int posn; | |
|     DdHashItem *item; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 2); | |
| #endif | |
|  | |
|     if (hash->size > hash->maxsize) { | |
| 	result = cuddHashTableResize(hash); | |
| 	if (result == 0) return(0); | |
|     } | |
|     item = cuddHashTableAlloc(hash); | |
|     if (item == NULL) return(0); | |
|     hash->size++; | |
|     item->value = value; | |
|     cuddRef(value); | |
|     item->count = count; | |
|     item->key[0] = f; | |
|     item->key[1] = g; | |
|     posn = ddLCHash2(f,g,hash->shift); | |
|     item->next = hash->bucket[posn]; | |
|     hash->bucket[posn] = item; | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of cuddHashTableInsert2 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Looks up a key consisting of two pointers in a hash table.] | |
|  | |
|   Description [Looks up a key consisting of two pointer in a hash table. | |
|   Returns the value associated to the key if there is an entry for the given | |
|   key in the table; NULL otherwise. If the entry is present, its reference | |
|   counter is decremented if not saturated. If the counter reaches 0, the | |
|   value of the entry is dereferenced, and the entry is returned to the free | |
|   list.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3 | |
|   cuddHashTableInsert2] | |
|  | |
| ******************************************************************************/ | |
| DdNode * | |
| cuddHashTableLookup2( | |
|   DdHashTable * hash, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     unsigned int posn; | |
|     DdHashItem *item, *prev; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 2); | |
| #endif | |
|  | |
|     posn = ddLCHash2(f,g,hash->shift); | |
|     item = hash->bucket[posn]; | |
|     prev = NULL; | |
| 
 | |
|     while (item != NULL) { | |
| 	DdNodePtr *key = item->key; | |
| 	if ((f == key[0]) && (g == key[1])) { | |
| 	    DdNode *value = item->value; | |
| 	    cuddSatDec(item->count); | |
| 	    if (item->count == 0) { | |
| 		cuddDeref(value); | |
| 		if (prev == NULL) { | |
| 		    hash->bucket[posn] = item->next; | |
| 		} else { | |
| 		    prev->next = item->next; | |
| 		} | |
| 		item->next = hash->nextFree; | |
| 		hash->nextFree = item; | |
| 		hash->size--; | |
| 	    } | |
| 	    return(value); | |
| 	} | |
| 	prev = item; | |
| 	item = item->next; | |
|     } | |
|     return(NULL); | |
| 
 | |
| } /* end of cuddHashTableLookup2 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Inserts an item in a hash table.] | |
|  | |
|   Description [Inserts an item in a hash table when the key is | |
|   composed of three pointers. Returns 1 if successful; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2 | |
|   cuddHashTableLookup3] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddHashTableInsert3( | |
|   DdHashTable * hash, | |
|   DdNode * f, | |
|   DdNode * g, | |
|   DdNode * h, | |
|   DdNode * value, | |
|   ptrint count) | |
| { | |
|     int result; | |
|     unsigned int posn; | |
|     DdHashItem *item; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 3); | |
| #endif | |
|  | |
|     if (hash->size > hash->maxsize) { | |
| 	result = cuddHashTableResize(hash); | |
| 	if (result == 0) return(0); | |
|     } | |
|     item = cuddHashTableAlloc(hash); | |
|     if (item == NULL) return(0); | |
|     hash->size++; | |
|     item->value = value; | |
|     cuddRef(value); | |
|     item->count = count; | |
|     item->key[0] = f; | |
|     item->key[1] = g; | |
|     item->key[2] = h; | |
|     posn = ddLCHash3(f,g,h,hash->shift); | |
|     item->next = hash->bucket[posn]; | |
|     hash->bucket[posn] = item; | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of cuddHashTableInsert3 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Looks up a key consisting of three pointers in a hash table.] | |
|  | |
|   Description [Looks up a key consisting of three pointers in a hash table. | |
|   Returns the value associated to the key if there is an entry for the given | |
|   key in the table; NULL otherwise. If the entry is present, its reference | |
|   counter is decremented if not saturated. If the counter reaches 0, the | |
|   value of the entry is dereferenced, and the entry is returned to the free | |
|   list.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2 | |
|   cuddHashTableInsert3] | |
|  | |
| ******************************************************************************/ | |
| DdNode * | |
| cuddHashTableLookup3( | |
|   DdHashTable * hash, | |
|   DdNode * f, | |
|   DdNode * g, | |
|   DdNode * h) | |
| { | |
|     unsigned int posn; | |
|     DdHashItem *item, *prev; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(hash->keysize == 3); | |
| #endif | |
|  | |
|     posn = ddLCHash3(f,g,h,hash->shift); | |
|     item = hash->bucket[posn]; | |
|     prev = NULL; | |
| 
 | |
|     while (item != NULL) { | |
| 	DdNodePtr *key = item->key; | |
| 	if ((f == key[0]) && (g == key[1]) && (h == key[2])) { | |
| 	    DdNode *value = item->value; | |
| 	    cuddSatDec(item->count); | |
| 	    if (item->count == 0) { | |
| 		cuddDeref(value); | |
| 		if (prev == NULL) { | |
| 		    hash->bucket[posn] = item->next; | |
| 		} else { | |
| 		    prev->next = item->next; | |
| 		} | |
| 		item->next = hash->nextFree; | |
| 		hash->nextFree = item; | |
| 		hash->size--; | |
| 	    } | |
| 	    return(value); | |
| 	} | |
| 	prev = item; | |
| 	item = item->next; | |
|     } | |
|     return(NULL); | |
| 
 | |
| } /* end of cuddHashTableLookup3 */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Resizes a local cache.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| cuddLocalCacheResize( | |
|   DdLocalCache * cache) | |
| { | |
|     DdLocalCacheItem *item, *olditem, *entry, *old; | |
|     int i, shift; | |
|     unsigned int posn; | |
|     unsigned int slots, oldslots; | |
|     extern DD_OOMFP MMoutOfMemory; | |
|     DD_OOMFP saveHandler; | |
| 
 | |
|     olditem = cache->item; | |
|     oldslots = cache->slots; | |
|     slots = cache->slots = oldslots << 1; | |
| 
 | |
| #ifdef DD_VERBOSE | |
|     (void) fprintf(cache->manager->err, | |
| 		   "Resizing local cache from %d to %d entries\n", | |
| 		   oldslots, slots); | |
|     (void) fprintf(cache->manager->err, | |
| 		   "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n", | |
| 		   cache->hits, cache->lookUps, cache->hits / cache->lookUps); | |
| #endif | |
|  | |
|     saveHandler = MMoutOfMemory; | |
|     MMoutOfMemory = Cudd_OutOfMem; | |
|     cache->item = item = | |
| 	(DdLocalCacheItem *) ALLOC(char, slots * cache->itemsize); | |
|     MMoutOfMemory = saveHandler; | |
|     /* If we fail to allocate the new table we just give up. */ | |
|     if (item == NULL) { | |
| #ifdef DD_VERBOSE | |
| 	(void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n"); | |
| #endif | |
| 	cache->slots = oldslots; | |
| 	cache->item = olditem; | |
| 	/* Do not try to resize again. */ | |
| 	cache->maxslots = oldslots - 1; | |
| 	return; | |
|     } | |
|     shift = --(cache->shift); | |
|     cache->manager->memused += (slots - oldslots) * cache->itemsize; | |
| 
 | |
|     /* Clear new cache. */ | |
|     memset(item, 0, slots * cache->itemsize); | |
| 
 | |
|     /* Copy from old cache to new one. */ | |
|     for (i = 0; (unsigned) i < oldslots; i++) { | |
| 	old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize); | |
| 	if (old->value != NULL) { | |
| 	    posn = ddLCHash(old->key,cache->keysize,shift); | |
| 	    entry = (DdLocalCacheItem *) ((char *) item + | |
| 					  posn * cache->itemsize); | |
| 	    memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *)); | |
| 	    entry->value = old->value; | |
| 	} | |
|     } | |
| 
 | |
|     FREE(olditem); | |
| 
 | |
|     /* Reinitialize measurements so as to avoid division by 0 and | |
|     ** immediate resizing. | |
|     */ | |
|     cache->lookUps = (double) (int) (slots * cache->minHit + 1); | |
|     cache->hits = 0; | |
| 
 | |
| } /* end of cuddLocalCacheResize */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes the hash value for a local cache.] | |
|  | |
|   Description [Computes the hash value for a local cache. Returns the | |
|   bucket index.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| DD_INLINE | |
| static unsigned int | |
| ddLCHash( | |
|   DdNodePtr * key, | |
|   unsigned int keysize, | |
|   int shift) | |
| { | |
|     unsigned int val = (unsigned int) (ptrint) key[0] * DD_P2; | |
|     unsigned int i; | |
| 
 | |
|     for (i = 1; i < keysize; i++) { | |
| 	val = val * DD_P1 + (int) (ptrint) key[i]; | |
|     } | |
| 
 | |
|     return(val >> shift); | |
| 
 | |
| } /* end of ddLCHash */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Inserts a local cache in the manager list.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| cuddLocalCacheAddToList( | |
|   DdLocalCache * cache) | |
| { | |
|     DdManager *manager = cache->manager; | |
| 
 | |
|     cache->next = manager->localCaches; | |
|     manager->localCaches = cache; | |
|     return; | |
| 
 | |
| } /* end of cuddLocalCacheAddToList */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Removes a local cache from the manager list.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| cuddLocalCacheRemoveFromList( | |
|   DdLocalCache * cache) | |
| { | |
|     DdManager *manager = cache->manager; | |
|     DdLocalCache **prevCache, *nextCache; | |
| 
 | |
|     prevCache = &(manager->localCaches); | |
|     nextCache = manager->localCaches; | |
| 
 | |
|     while (nextCache != NULL) { | |
| 	if (nextCache == cache) { | |
| 	    *prevCache = nextCache->next; | |
| 	    return; | |
| 	} | |
| 	prevCache = &(nextCache->next); | |
| 	nextCache = nextCache->next; | |
|     } | |
|     return;			/* should never get here */ | |
| 
 | |
| } /* end of cuddLocalCacheRemoveFromList */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Resizes a hash table.] | |
|  | |
|   Description [Resizes a hash table. Returns 1 if successful; 0 | |
|   otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddHashTableInsert] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| cuddHashTableResize( | |
|   DdHashTable * hash) | |
| { | |
|     int j; | |
|     unsigned int posn; | |
|     DdHashItem *item; | |
|     DdHashItem *next; | |
|     DdNode **key; | |
|     int numBuckets; | |
|     DdHashItem **buckets; | |
|     DdHashItem **oldBuckets = hash->bucket; | |
|     int shift; | |
|     int oldNumBuckets = hash->numBuckets; | |
|     extern DD_OOMFP MMoutOfMemory; | |
|     DD_OOMFP saveHandler; | |
| 
 | |
|     /* Compute the new size of the table. */ | |
|     numBuckets = oldNumBuckets << 1; | |
|     saveHandler = MMoutOfMemory; | |
|     MMoutOfMemory = Cudd_OutOfMem; | |
|     buckets = ALLOC(DdHashItem *, numBuckets); | |
|     MMoutOfMemory = saveHandler; | |
|     if (buckets == NULL) { | |
| 	hash->maxsize <<= 1; | |
| 	return(1); | |
|     } | |
| 
 | |
|     hash->bucket = buckets; | |
|     hash->numBuckets = numBuckets; | |
|     shift = --(hash->shift); | |
|     hash->maxsize <<= 1; | |
|     memset(buckets, 0, numBuckets * sizeof(DdHashItem *)); | |
|     if (hash->keysize == 1) { | |
| 	for (j = 0; j < oldNumBuckets; j++) { | |
| 	    item = oldBuckets[j]; | |
| 	    while (item != NULL) { | |
| 		next = item->next; | |
| 		key = item->key; | |
| 		posn = ddLCHash2(key[0], key[0], shift); | |
| 		item->next = buckets[posn]; | |
| 		buckets[posn] = item; | |
| 		item = next; | |
| 	    } | |
| 	} | |
|     } else if (hash->keysize == 2) { | |
| 	for (j = 0; j < oldNumBuckets; j++) { | |
| 	    item = oldBuckets[j]; | |
| 	    while (item != NULL) { | |
| 		next = item->next; | |
| 		key = item->key; | |
| 		posn = ddLCHash2(key[0], key[1], shift); | |
| 		item->next = buckets[posn]; | |
| 		buckets[posn] = item; | |
| 		item = next; | |
| 	    } | |
| 	} | |
|     } else if (hash->keysize == 3) { | |
| 	for (j = 0; j < oldNumBuckets; j++) { | |
| 	    item = oldBuckets[j]; | |
| 	    while (item != NULL) { | |
| 		next = item->next; | |
| 		key = item->key; | |
| 		posn = ddLCHash3(key[0], key[1], key[2], shift); | |
| 		item->next = buckets[posn]; | |
| 		buckets[posn] = item; | |
| 		item = next; | |
| 	    } | |
| 	} | |
|     } else { | |
| 	for (j = 0; j < oldNumBuckets; j++) { | |
| 	    item = oldBuckets[j]; | |
| 	    while (item != NULL) { | |
| 		next = item->next; | |
| 		posn = ddLCHash(item->key, hash->keysize, shift); | |
| 		item->next = buckets[posn]; | |
| 		buckets[posn] = item; | |
| 		item = next; | |
| 	    } | |
| 	} | |
|     } | |
|     FREE(oldBuckets); | |
|     return(1); | |
| 
 | |
| } /* end of cuddHashTableResize */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Fast storage allocation for items in a hash table.] | |
|  | |
|   Description [Fast storage allocation for items in a hash table. The | |
|   first 4 bytes of a chunk contain a pointer to the next block; the | |
|   rest contains DD_MEM_CHUNK spaces for hash items.  Returns a pointer to | |
|   a new item if successful; NULL is memory is full.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [cuddAllocNode cuddDynamicAllocNode] | |
|  | |
| ******************************************************************************/ | |
| DD_INLINE | |
| static DdHashItem * | |
| cuddHashTableAlloc( | |
|   DdHashTable * hash) | |
| { | |
|     int i; | |
|     unsigned int itemsize = hash->itemsize; | |
|     extern DD_OOMFP MMoutOfMemory; | |
|     DD_OOMFP saveHandler; | |
|     DdHashItem **mem, *thisOne, *next, *item; | |
| 
 | |
|     if (hash->nextFree == NULL) { | |
| 	saveHandler = MMoutOfMemory; | |
| 	MMoutOfMemory = Cudd_OutOfMem; | |
| 	mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); | |
| 	MMoutOfMemory = saveHandler; | |
| 	if (mem == NULL) { | |
| 	    if (hash->manager->stash != NULL) { | |
| 		FREE(hash->manager->stash); | |
| 		hash->manager->stash = NULL; | |
| 		/* Inhibit resizing of tables. */ | |
| 		hash->manager->maxCacheHard = hash->manager->cacheSlots - 1; | |
| 		hash->manager->cacheSlack = - (int) (hash->manager->cacheSlots + 1); | |
| 		for (i = 0; i < hash->manager->size; i++) { | |
| 		    hash->manager->subtables[i].maxKeys <<= 2; | |
| 		} | |
| 		hash->manager->gcFrac = 0.2; | |
| 		hash->manager->minDead = | |
| 		    (unsigned) (0.2 * (double) hash->manager->slots); | |
| 		mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); | |
| 	    } | |
| 	    if (mem == NULL) { | |
| 		(*MMoutOfMemory)((long)((DD_MEM_CHUNK + 1) * itemsize)); | |
| 		hash->manager->errorCode = CUDD_MEMORY_OUT; | |
| 		return(NULL); | |
| 	    } | |
| 	} | |
| 
 | |
| 	mem[0] = (DdHashItem *) hash->memoryList; | |
| 	hash->memoryList = mem; | |
| 
 | |
| 	thisOne = (DdHashItem *) ((char *) mem + itemsize); | |
| 	hash->nextFree = thisOne; | |
| 	for (i = 1; i < DD_MEM_CHUNK; i++) { | |
| 	    next = (DdHashItem *) ((char *) thisOne + itemsize); | |
| 	    thisOne->next = next; | |
| 	    thisOne = next; | |
| 	} | |
| 
 | |
| 	thisOne->next = NULL; | |
| 
 | |
|     } | |
|     item = hash->nextFree; | |
|     hash->nextFree = item->next; | |
|     return(item); | |
| 
 | |
| } /* end of cuddHashTableAlloc */
 |