00001
00075 #include "util.h"
00076 #include "cuddInt.h"
00077
00078
00079
00080
00081
00082 #define DD_MAX_HASHTABLE_DENSITY 2
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #ifndef lint
00099 static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.24 2009/03/08 02:49:02 fabio Exp $";
00100 #endif
00101
00102
00103
00104
00105
00117 #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
00118 #define ddLCHash2(f,g,shift) \
00119 ((((unsigned)(ptruint)(f) * DD_P1 + \
00120 (unsigned)(ptruint)(g)) * DD_P2) >> (shift))
00121 #else
00122 #define ddLCHash2(f,g,shift) \
00123 ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift))
00124 #endif
00125
00126
00138 #define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift)
00139
00140
00143
00144
00145
00146
00147 static void cuddLocalCacheResize (DdLocalCache *cache);
00148 DD_INLINE static unsigned int ddLCHash (DdNodePtr *key, unsigned int keysize, int shift);
00149 static void cuddLocalCacheAddToList (DdLocalCache *cache);
00150 static void cuddLocalCacheRemoveFromList (DdLocalCache *cache);
00151 static int cuddHashTableResize (DdHashTable *hash);
00152 DD_INLINE static DdHashItem * cuddHashTableAlloc (DdHashTable *hash);
00153
00157
00158
00159
00160
00161
00162
00163
00164
00165
00178 DdLocalCache *
00179 cuddLocalCacheInit(
00180 DdManager * manager ,
00181 unsigned int keySize ,
00182 unsigned int cacheSize ,
00183 unsigned int maxCacheSize )
00184 {
00185 DdLocalCache *cache;
00186 int logSize;
00187
00188 cache = ALLOC(DdLocalCache,1);
00189 if (cache == NULL) {
00190 manager->errorCode = CUDD_MEMORY_OUT;
00191 return(NULL);
00192 }
00193 cache->manager = manager;
00194 cache->keysize = keySize;
00195 cache->itemsize = (keySize + 1) * sizeof(DdNode *);
00196 #ifdef DD_CACHE_PROFILE
00197 cache->itemsize += sizeof(ptrint);
00198 #endif
00199 logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2));
00200 cacheSize = 1 << logSize;
00201 cache->item = (DdLocalCacheItem *)
00202 ALLOC(char, cacheSize * cache->itemsize);
00203 if (cache->item == NULL) {
00204 manager->errorCode = CUDD_MEMORY_OUT;
00205 FREE(cache);
00206 return(NULL);
00207 }
00208 cache->slots = cacheSize;
00209 cache->shift = sizeof(int) * 8 - logSize;
00210 cache->maxslots = ddMin(maxCacheSize,manager->slots);
00211 cache->minHit = manager->minHit;
00212
00213 cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1);
00214 cache->hits = 0;
00215 manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache);
00216
00217
00218 memset(cache->item, 0, cacheSize * cache->itemsize);
00219
00220
00221 cuddLocalCacheAddToList(cache);
00222
00223 return(cache);
00224
00225 }
00226
00227
00241 void
00242 cuddLocalCacheQuit(
00243 DdLocalCache * cache )
00244 {
00245 cache->manager->memused -=
00246 cache->slots * cache->itemsize + sizeof(DdLocalCache);
00247 cuddLocalCacheRemoveFromList(cache);
00248 FREE(cache->item);
00249 FREE(cache);
00250
00251 return;
00252
00253 }
00254
00255
00267 void
00268 cuddLocalCacheInsert(
00269 DdLocalCache * cache,
00270 DdNodePtr * key,
00271 DdNode * value)
00272 {
00273 unsigned int posn;
00274 DdLocalCacheItem *entry;
00275
00276 posn = ddLCHash(key,cache->keysize,cache->shift);
00277 entry = (DdLocalCacheItem *) ((char *) cache->item +
00278 posn * cache->itemsize);
00279 memcpy(entry->key,key,cache->keysize * sizeof(DdNode *));
00280 entry->value = value;
00281 #ifdef DD_CACHE_PROFILE
00282 entry->count++;
00283 #endif
00284
00285 }
00286
00287
00300 DdNode *
00301 cuddLocalCacheLookup(
00302 DdLocalCache * cache,
00303 DdNodePtr * key)
00304 {
00305 unsigned int posn;
00306 DdLocalCacheItem *entry;
00307 DdNode *value;
00308
00309 cache->lookUps++;
00310 posn = ddLCHash(key,cache->keysize,cache->shift);
00311 entry = (DdLocalCacheItem *) ((char *) cache->item +
00312 posn * cache->itemsize);
00313 if (entry->value != NULL &&
00314 memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) {
00315 cache->hits++;
00316 value = Cudd_Regular(entry->value);
00317 if (value->ref == 0) {
00318 cuddReclaim(cache->manager,value);
00319 }
00320 return(entry->value);
00321 }
00322
00323
00324
00325 if (cache->slots < cache->maxslots &&
00326 cache->hits > cache->lookUps * cache->minHit) {
00327 cuddLocalCacheResize(cache);
00328 }
00329
00330 return(NULL);
00331
00332 }
00333
00334
00347 void
00348 cuddLocalCacheClearDead(
00349 DdManager * manager)
00350 {
00351 DdLocalCache *cache = manager->localCaches;
00352 unsigned int keysize;
00353 unsigned int itemsize;
00354 unsigned int slots;
00355 DdLocalCacheItem *item;
00356 DdNodePtr *key;
00357 unsigned int i, j;
00358
00359 while (cache != NULL) {
00360 keysize = cache->keysize;
00361 itemsize = cache->itemsize;
00362 slots = cache->slots;
00363 item = cache->item;
00364 for (i = 0; i < slots; i++) {
00365 if (item->value != NULL) {
00366 if (Cudd_Regular(item->value)->ref == 0) {
00367 item->value = NULL;
00368 } else {
00369 key = item->key;
00370 for (j = 0; j < keysize; j++) {
00371 if (Cudd_Regular(key[j])->ref == 0) {
00372 item->value = NULL;
00373 break;
00374 }
00375 }
00376 }
00377 }
00378 item = (DdLocalCacheItem *) ((char *) item + itemsize);
00379 }
00380 cache = cache->next;
00381 }
00382 return;
00383
00384 }
00385
00386
00399 void
00400 cuddLocalCacheClearAll(
00401 DdManager * manager)
00402 {
00403 DdLocalCache *cache = manager->localCaches;
00404
00405 while (cache != NULL) {
00406 memset(cache->item, 0, cache->slots * cache->itemsize);
00407 cache = cache->next;
00408 }
00409 return;
00410
00411 }
00412
00413
00414 #ifdef DD_CACHE_PROFILE
00415
00416 #define DD_HYSTO_BINS 8
00417
00430 int
00431 cuddLocalCacheProfile(
00432 DdLocalCache * cache)
00433 {
00434 double count, mean, meansq, stddev, expected;
00435 long max, min;
00436 int imax, imin;
00437 int i, retval, slots;
00438 long *hystogram;
00439 int nbins = DD_HYSTO_BINS;
00440 int bin;
00441 long thiscount;
00442 double totalcount;
00443 int nzeroes;
00444 DdLocalCacheItem *entry;
00445 FILE *fp = cache->manager->out;
00446
00447 slots = cache->slots;
00448
00449 meansq = mean = expected = 0.0;
00450 max = min = (long) cache->item[0].count;
00451 imax = imin = nzeroes = 0;
00452 totalcount = 0.0;
00453
00454 hystogram = ALLOC(long, nbins);
00455 if (hystogram == NULL) {
00456 return(0);
00457 }
00458 for (i = 0; i < nbins; i++) {
00459 hystogram[i] = 0;
00460 }
00461
00462 for (i = 0; i < slots; i++) {
00463 entry = (DdLocalCacheItem *) ((char *) cache->item +
00464 i * cache->itemsize);
00465 thiscount = (long) entry->count;
00466 if (thiscount > max) {
00467 max = thiscount;
00468 imax = i;
00469 }
00470 if (thiscount < min) {
00471 min = thiscount;
00472 imin = i;
00473 }
00474 if (thiscount == 0) {
00475 nzeroes++;
00476 }
00477 count = (double) thiscount;
00478 mean += count;
00479 meansq += count * count;
00480 totalcount += count;
00481 expected += count * (double) i;
00482 bin = (i * nbins) / slots;
00483 hystogram[bin] += thiscount;
00484 }
00485 mean /= (double) slots;
00486 meansq /= (double) slots;
00487 stddev = sqrt(meansq - mean*mean);
00488
00489 retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean);
00490 if (retval == EOF) return(0);
00491 retval = fprintf(fp,"standard deviation = %g\n", stddev);
00492 if (retval == EOF) return(0);
00493 retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax);
00494 if (retval == EOF) return(0);
00495 retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin);
00496 if (retval == EOF) return(0);
00497 retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes);
00498 if (retval == EOF) return(0);
00499
00500 if (totalcount) {
00501 expected /= totalcount;
00502 retval = fprintf(fp,"Cache access hystogram for %d bins", nbins);
00503 if (retval == EOF) return(0);
00504 retval = fprintf(fp," (expected bin value = %g)\n# ", expected);
00505 if (retval == EOF) return(0);
00506 for (i = nbins - 1; i>=0; i--) {
00507 retval = fprintf(fp,"%ld ", hystogram[i]);
00508 if (retval == EOF) return(0);
00509 }
00510 retval = fprintf(fp,"\n");
00511 if (retval == EOF) return(0);
00512 }
00513
00514 FREE(hystogram);
00515 return(1);
00516
00517 }
00518 #endif
00519
00520
00533 DdHashTable *
00534 cuddHashTableInit(
00535 DdManager * manager,
00536 unsigned int keySize,
00537 unsigned int initSize)
00538 {
00539 DdHashTable *hash;
00540 int logSize;
00541
00542 #ifdef __osf__
00543 #pragma pointer_size save
00544 #pragma pointer_size short
00545 #endif
00546 hash = ALLOC(DdHashTable, 1);
00547 if (hash == NULL) {
00548 manager->errorCode = CUDD_MEMORY_OUT;
00549 return(NULL);
00550 }
00551 hash->keysize = keySize;
00552 hash->manager = manager;
00553 hash->memoryList = NULL;
00554 hash->nextFree = NULL;
00555 hash->itemsize = (keySize + 1) * sizeof(DdNode *) +
00556 sizeof(ptrint) + sizeof(DdHashItem *);
00557
00558 if (initSize < 2) initSize = 2;
00559 logSize = cuddComputeFloorLog2(initSize);
00560 hash->numBuckets = 1 << logSize;
00561 hash->shift = sizeof(int) * 8 - logSize;
00562 hash->bucket = ALLOC(DdHashItem *, hash->numBuckets);
00563 if (hash->bucket == NULL) {
00564 manager->errorCode = CUDD_MEMORY_OUT;
00565 FREE(hash);
00566 return(NULL);
00567 }
00568 memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *));
00569 hash->size = 0;
00570 hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY;
00571 #ifdef __osf__
00572 #pragma pointer_size restore
00573 #endif
00574 return(hash);
00575
00576 }
00577
00578
00590 void
00591 cuddHashTableQuit(
00592 DdHashTable * hash)
00593 {
00594 #ifdef __osf__
00595 #pragma pointer_size save
00596 #pragma pointer_size short
00597 #endif
00598 unsigned int i;
00599 DdManager *dd = hash->manager;
00600 DdHashItem *bucket;
00601 DdHashItem **memlist, **nextmem;
00602 unsigned int numBuckets = hash->numBuckets;
00603
00604 for (i = 0; i < numBuckets; i++) {
00605 bucket = hash->bucket[i];
00606 while (bucket != NULL) {
00607 Cudd_RecursiveDeref(dd, bucket->value);
00608 bucket = bucket->next;
00609 }
00610 }
00611
00612 memlist = hash->memoryList;
00613 while (memlist != NULL) {
00614 nextmem = (DdHashItem **) memlist[0];
00615 FREE(memlist);
00616 memlist = nextmem;
00617 }
00618
00619 FREE(hash->bucket);
00620 FREE(hash);
00621 #ifdef __osf__
00622 #pragma pointer_size restore
00623 #endif
00624
00625 return;
00626
00627 }
00628
00629
00643 int
00644 cuddHashTableInsert(
00645 DdHashTable * hash,
00646 DdNodePtr * key,
00647 DdNode * value,
00648 ptrint count)
00649 {
00650 int result;
00651 unsigned int posn;
00652 DdHashItem *item;
00653 unsigned int i;
00654
00655 #ifdef DD_DEBUG
00656 assert(hash->keysize > 3);
00657 #endif
00658
00659 if (hash->size > hash->maxsize) {
00660 result = cuddHashTableResize(hash);
00661 if (result == 0) return(0);
00662 }
00663 item = cuddHashTableAlloc(hash);
00664 if (item == NULL) return(0);
00665 hash->size++;
00666 item->value = value;
00667 cuddRef(value);
00668 item->count = count;
00669 for (i = 0; i < hash->keysize; i++) {
00670 item->key[i] = key[i];
00671 }
00672 posn = ddLCHash(key,hash->keysize,hash->shift);
00673 item->next = hash->bucket[posn];
00674 hash->bucket[posn] = item;
00675
00676 return(1);
00677
00678 }
00679
00680
00698 DdNode *
00699 cuddHashTableLookup(
00700 DdHashTable * hash,
00701 DdNodePtr * key)
00702 {
00703 unsigned int posn;
00704 DdHashItem *item, *prev;
00705 unsigned int i, keysize;
00706
00707 #ifdef DD_DEBUG
00708 assert(hash->keysize > 3);
00709 #endif
00710
00711 posn = ddLCHash(key,hash->keysize,hash->shift);
00712 item = hash->bucket[posn];
00713 prev = NULL;
00714
00715 keysize = hash->keysize;
00716 while (item != NULL) {
00717 DdNodePtr *key2 = item->key;
00718 int equal = 1;
00719 for (i = 0; i < keysize; i++) {
00720 if (key[i] != key2[i]) {
00721 equal = 0;
00722 break;
00723 }
00724 }
00725 if (equal) {
00726 DdNode *value = item->value;
00727 cuddSatDec(item->count);
00728 if (item->count == 0) {
00729 cuddDeref(value);
00730 if (prev == NULL) {
00731 hash->bucket[posn] = item->next;
00732 } else {
00733 prev->next = item->next;
00734 }
00735 item->next = hash->nextFree;
00736 hash->nextFree = item;
00737 hash->size--;
00738 }
00739 return(value);
00740 }
00741 prev = item;
00742 item = item->next;
00743 }
00744 return(NULL);
00745
00746 }
00747
00748
00762 int
00763 cuddHashTableInsert1(
00764 DdHashTable * hash,
00765 DdNode * f,
00766 DdNode * value,
00767 ptrint count)
00768 {
00769 int result;
00770 unsigned int posn;
00771 DdHashItem *item;
00772
00773 #ifdef DD_DEBUG
00774 assert(hash->keysize == 1);
00775 #endif
00776
00777 if (hash->size > hash->maxsize) {
00778 result = cuddHashTableResize(hash);
00779 if (result == 0) return(0);
00780 }
00781 item = cuddHashTableAlloc(hash);
00782 if (item == NULL) return(0);
00783 hash->size++;
00784 item->value = value;
00785 cuddRef(value);
00786 item->count = count;
00787 item->key[0] = f;
00788 posn = ddLCHash2(f,f,hash->shift);
00789 item->next = hash->bucket[posn];
00790 hash->bucket[posn] = item;
00791
00792 return(1);
00793
00794 }
00795
00796
00814 DdNode *
00815 cuddHashTableLookup1(
00816 DdHashTable * hash,
00817 DdNode * f)
00818 {
00819 unsigned int posn;
00820 DdHashItem *item, *prev;
00821
00822 #ifdef DD_DEBUG
00823 assert(hash->keysize == 1);
00824 #endif
00825
00826 posn = ddLCHash2(f,f,hash->shift);
00827 item = hash->bucket[posn];
00828 prev = NULL;
00829
00830 while (item != NULL) {
00831 DdNodePtr *key = item->key;
00832 if (f == key[0]) {
00833 DdNode *value = item->value;
00834 cuddSatDec(item->count);
00835 if (item->count == 0) {
00836 cuddDeref(value);
00837 if (prev == NULL) {
00838 hash->bucket[posn] = item->next;
00839 } else {
00840 prev->next = item->next;
00841 }
00842 item->next = hash->nextFree;
00843 hash->nextFree = item;
00844 hash->size--;
00845 }
00846 return(value);
00847 }
00848 prev = item;
00849 item = item->next;
00850 }
00851 return(NULL);
00852
00853 }
00854
00855
00869 int
00870 cuddHashTableInsert2(
00871 DdHashTable * hash,
00872 DdNode * f,
00873 DdNode * g,
00874 DdNode * value,
00875 ptrint count)
00876 {
00877 int result;
00878 unsigned int posn;
00879 DdHashItem *item;
00880
00881 #ifdef DD_DEBUG
00882 assert(hash->keysize == 2);
00883 #endif
00884
00885 if (hash->size > hash->maxsize) {
00886 result = cuddHashTableResize(hash);
00887 if (result == 0) return(0);
00888 }
00889 item = cuddHashTableAlloc(hash);
00890 if (item == NULL) return(0);
00891 hash->size++;
00892 item->value = value;
00893 cuddRef(value);
00894 item->count = count;
00895 item->key[0] = f;
00896 item->key[1] = g;
00897 posn = ddLCHash2(f,g,hash->shift);
00898 item->next = hash->bucket[posn];
00899 hash->bucket[posn] = item;
00900
00901 return(1);
00902
00903 }
00904
00905
00923 DdNode *
00924 cuddHashTableLookup2(
00925 DdHashTable * hash,
00926 DdNode * f,
00927 DdNode * g)
00928 {
00929 unsigned int posn;
00930 DdHashItem *item, *prev;
00931
00932 #ifdef DD_DEBUG
00933 assert(hash->keysize == 2);
00934 #endif
00935
00936 posn = ddLCHash2(f,g,hash->shift);
00937 item = hash->bucket[posn];
00938 prev = NULL;
00939
00940 while (item != NULL) {
00941 DdNodePtr *key = item->key;
00942 if ((f == key[0]) && (g == key[1])) {
00943 DdNode *value = item->value;
00944 cuddSatDec(item->count);
00945 if (item->count == 0) {
00946 cuddDeref(value);
00947 if (prev == NULL) {
00948 hash->bucket[posn] = item->next;
00949 } else {
00950 prev->next = item->next;
00951 }
00952 item->next = hash->nextFree;
00953 hash->nextFree = item;
00954 hash->size--;
00955 }
00956 return(value);
00957 }
00958 prev = item;
00959 item = item->next;
00960 }
00961 return(NULL);
00962
00963 }
00964
00965
00979 int
00980 cuddHashTableInsert3(
00981 DdHashTable * hash,
00982 DdNode * f,
00983 DdNode * g,
00984 DdNode * h,
00985 DdNode * value,
00986 ptrint count)
00987 {
00988 int result;
00989 unsigned int posn;
00990 DdHashItem *item;
00991
00992 #ifdef DD_DEBUG
00993 assert(hash->keysize == 3);
00994 #endif
00995
00996 if (hash->size > hash->maxsize) {
00997 result = cuddHashTableResize(hash);
00998 if (result == 0) return(0);
00999 }
01000 item = cuddHashTableAlloc(hash);
01001 if (item == NULL) return(0);
01002 hash->size++;
01003 item->value = value;
01004 cuddRef(value);
01005 item->count = count;
01006 item->key[0] = f;
01007 item->key[1] = g;
01008 item->key[2] = h;
01009 posn = ddLCHash3(f,g,h,hash->shift);
01010 item->next = hash->bucket[posn];
01011 hash->bucket[posn] = item;
01012
01013 return(1);
01014
01015 }
01016
01017
01035 DdNode *
01036 cuddHashTableLookup3(
01037 DdHashTable * hash,
01038 DdNode * f,
01039 DdNode * g,
01040 DdNode * h)
01041 {
01042 unsigned int posn;
01043 DdHashItem *item, *prev;
01044
01045 #ifdef DD_DEBUG
01046 assert(hash->keysize == 3);
01047 #endif
01048
01049 posn = ddLCHash3(f,g,h,hash->shift);
01050 item = hash->bucket[posn];
01051 prev = NULL;
01052
01053 while (item != NULL) {
01054 DdNodePtr *key = item->key;
01055 if ((f == key[0]) && (g == key[1]) && (h == key[2])) {
01056 DdNode *value = item->value;
01057 cuddSatDec(item->count);
01058 if (item->count == 0) {
01059 cuddDeref(value);
01060 if (prev == NULL) {
01061 hash->bucket[posn] = item->next;
01062 } else {
01063 prev->next = item->next;
01064 }
01065 item->next = hash->nextFree;
01066 hash->nextFree = item;
01067 hash->size--;
01068 }
01069 return(value);
01070 }
01071 prev = item;
01072 item = item->next;
01073 }
01074 return(NULL);
01075
01076 }
01077
01078
01079
01080
01081
01082
01083
01095 static void
01096 cuddLocalCacheResize(
01097 DdLocalCache * cache)
01098 {
01099 DdLocalCacheItem *item, *olditem, *entry, *old;
01100 int i, shift;
01101 unsigned int posn;
01102 unsigned int slots, oldslots;
01103 extern DD_OOMFP MMoutOfMemory;
01104 DD_OOMFP saveHandler;
01105
01106 olditem = cache->item;
01107 oldslots = cache->slots;
01108 slots = cache->slots = oldslots << 1;
01109
01110 #ifdef DD_VERBOSE
01111 (void) fprintf(cache->manager->err,
01112 "Resizing local cache from %d to %d entries\n",
01113 oldslots, slots);
01114 (void) fprintf(cache->manager->err,
01115 "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n",
01116 cache->hits, cache->lookUps, cache->hits / cache->lookUps);
01117 #endif
01118
01119 saveHandler = MMoutOfMemory;
01120 MMoutOfMemory = Cudd_OutOfMem;
01121 cache->item = item =
01122 (DdLocalCacheItem *) ALLOC(char, slots * cache->itemsize);
01123 MMoutOfMemory = saveHandler;
01124
01125 if (item == NULL) {
01126 #ifdef DD_VERBOSE
01127 (void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n");
01128 #endif
01129 cache->slots = oldslots;
01130 cache->item = olditem;
01131
01132 cache->maxslots = oldslots - 1;
01133 return;
01134 }
01135 shift = --(cache->shift);
01136 cache->manager->memused += (slots - oldslots) * cache->itemsize;
01137
01138
01139 memset(item, 0, slots * cache->itemsize);
01140
01141
01142 for (i = 0; (unsigned) i < oldslots; i++) {
01143 old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize);
01144 if (old->value != NULL) {
01145 posn = ddLCHash(old->key,cache->keysize,shift);
01146 entry = (DdLocalCacheItem *) ((char *) item +
01147 posn * cache->itemsize);
01148 memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *));
01149 entry->value = old->value;
01150 }
01151 }
01152
01153 FREE(olditem);
01154
01155
01156
01157
01158 cache->lookUps = (double) (int) (slots * cache->minHit + 1);
01159 cache->hits = 0;
01160
01161 }
01162
01163
01176 DD_INLINE
01177 static unsigned int
01178 ddLCHash(
01179 DdNodePtr * key,
01180 unsigned int keysize,
01181 int shift)
01182 {
01183 unsigned int val = (unsigned int) (ptrint) key[0] * DD_P2;
01184 unsigned int i;
01185
01186 for (i = 1; i < keysize; i++) {
01187 val = val * DD_P1 + (int) (ptrint) key[i];
01188 }
01189
01190 return(val >> shift);
01191
01192 }
01193
01194
01206 static void
01207 cuddLocalCacheAddToList(
01208 DdLocalCache * cache)
01209 {
01210 DdManager *manager = cache->manager;
01211
01212 cache->next = manager->localCaches;
01213 manager->localCaches = cache;
01214 return;
01215
01216 }
01217
01218
01230 static void
01231 cuddLocalCacheRemoveFromList(
01232 DdLocalCache * cache)
01233 {
01234 DdManager *manager = cache->manager;
01235 #ifdef __osf__
01236 #pragma pointer_size save
01237 #pragma pointer_size short
01238 #endif
01239 DdLocalCache **prevCache, *nextCache;
01240 #ifdef __osf__
01241 #pragma pointer_size restore
01242 #endif
01243
01244 prevCache = &(manager->localCaches);
01245 nextCache = manager->localCaches;
01246
01247 while (nextCache != NULL) {
01248 if (nextCache == cache) {
01249 *prevCache = nextCache->next;
01250 return;
01251 }
01252 prevCache = &(nextCache->next);
01253 nextCache = nextCache->next;
01254 }
01255 return;
01256
01257 }
01258
01259
01272 static int
01273 cuddHashTableResize(
01274 DdHashTable * hash)
01275 {
01276 int j;
01277 unsigned int posn;
01278 DdHashItem *item;
01279 DdHashItem *next;
01280 #ifdef __osf__
01281 #pragma pointer_size save
01282 #pragma pointer_size short
01283 #endif
01284 DdNode **key;
01285 int numBuckets;
01286 DdHashItem **buckets;
01287 DdHashItem **oldBuckets = hash->bucket;
01288 #ifdef __osf__
01289 #pragma pointer_size restore
01290 #endif
01291 int shift;
01292 int oldNumBuckets = hash->numBuckets;
01293 extern DD_OOMFP MMoutOfMemory;
01294 DD_OOMFP saveHandler;
01295
01296
01297 numBuckets = oldNumBuckets << 1;
01298 saveHandler = MMoutOfMemory;
01299 MMoutOfMemory = Cudd_OutOfMem;
01300 #ifdef __osf__
01301 #pragma pointer_size save
01302 #pragma pointer_size short
01303 #endif
01304 buckets = ALLOC(DdHashItem *, numBuckets);
01305 MMoutOfMemory = saveHandler;
01306 if (buckets == NULL) {
01307 hash->maxsize <<= 1;
01308 return(1);
01309 }
01310
01311 hash->bucket = buckets;
01312 hash->numBuckets = numBuckets;
01313 shift = --(hash->shift);
01314 hash->maxsize <<= 1;
01315 memset(buckets, 0, numBuckets * sizeof(DdHashItem *));
01316 #ifdef __osf__
01317 #pragma pointer_size restore
01318 #endif
01319 if (hash->keysize == 1) {
01320 for (j = 0; j < oldNumBuckets; j++) {
01321 item = oldBuckets[j];
01322 while (item != NULL) {
01323 next = item->next;
01324 key = item->key;
01325 posn = ddLCHash2(key[0], key[0], shift);
01326 item->next = buckets[posn];
01327 buckets[posn] = item;
01328 item = next;
01329 }
01330 }
01331 } else if (hash->keysize == 2) {
01332 for (j = 0; j < oldNumBuckets; j++) {
01333 item = oldBuckets[j];
01334 while (item != NULL) {
01335 next = item->next;
01336 key = item->key;
01337 posn = ddLCHash2(key[0], key[1], shift);
01338 item->next = buckets[posn];
01339 buckets[posn] = item;
01340 item = next;
01341 }
01342 }
01343 } else if (hash->keysize == 3) {
01344 for (j = 0; j < oldNumBuckets; j++) {
01345 item = oldBuckets[j];
01346 while (item != NULL) {
01347 next = item->next;
01348 key = item->key;
01349 posn = ddLCHash3(key[0], key[1], key[2], shift);
01350 item->next = buckets[posn];
01351 buckets[posn] = item;
01352 item = next;
01353 }
01354 }
01355 } else {
01356 for (j = 0; j < oldNumBuckets; j++) {
01357 item = oldBuckets[j];
01358 while (item != NULL) {
01359 next = item->next;
01360 posn = ddLCHash(item->key, hash->keysize, shift);
01361 item->next = buckets[posn];
01362 buckets[posn] = item;
01363 item = next;
01364 }
01365 }
01366 }
01367 FREE(oldBuckets);
01368 return(1);
01369
01370 }
01371
01372
01387 DD_INLINE
01388 static DdHashItem *
01389 cuddHashTableAlloc(
01390 DdHashTable * hash)
01391 {
01392 int i;
01393 unsigned int itemsize = hash->itemsize;
01394 extern DD_OOMFP MMoutOfMemory;
01395 DD_OOMFP saveHandler;
01396 #ifdef __osf__
01397 #pragma pointer_size save
01398 #pragma pointer_size short
01399 #endif
01400 DdHashItem **mem, *thisOne, *next, *item;
01401
01402 if (hash->nextFree == NULL) {
01403 saveHandler = MMoutOfMemory;
01404 MMoutOfMemory = Cudd_OutOfMem;
01405 mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
01406 MMoutOfMemory = saveHandler;
01407 #ifdef __osf__
01408 #pragma pointer_size restore
01409 #endif
01410 if (mem == NULL) {
01411 if (hash->manager->stash != NULL) {
01412 FREE(hash->manager->stash);
01413 hash->manager->stash = NULL;
01414
01415 hash->manager->maxCacheHard = hash->manager->cacheSlots - 1;
01416 hash->manager->cacheSlack = - (int) (hash->manager->cacheSlots + 1);
01417 for (i = 0; i < hash->manager->size; i++) {
01418 hash->manager->subtables[i].maxKeys <<= 2;
01419 }
01420 hash->manager->gcFrac = 0.2;
01421 hash->manager->minDead =
01422 (unsigned) (0.2 * (double) hash->manager->slots);
01423 #ifdef __osf__
01424 #pragma pointer_size save
01425 #pragma pointer_size short
01426 #endif
01427 mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize);
01428 #ifdef __osf__
01429 #pragma pointer_size restore
01430 #endif
01431 }
01432 if (mem == NULL) {
01433 (*MMoutOfMemory)((long)((DD_MEM_CHUNK + 1) * itemsize));
01434 hash->manager->errorCode = CUDD_MEMORY_OUT;
01435 return(NULL);
01436 }
01437 }
01438
01439 mem[0] = (DdHashItem *) hash->memoryList;
01440 hash->memoryList = mem;
01441
01442 thisOne = (DdHashItem *) ((char *) mem + itemsize);
01443 hash->nextFree = thisOne;
01444 for (i = 1; i < DD_MEM_CHUNK; i++) {
01445 next = (DdHashItem *) ((char *) thisOne + itemsize);
01446 thisOne->next = next;
01447 thisOne = next;
01448 }
01449
01450 thisOne->next = NULL;
01451
01452 }
01453 item = hash->nextFree;
01454 hash->nextFree = item->next;
01455 return(item);
01456
01457 }