00001
00053 #include "util_hack.h"
00054 #include "cuddInt.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #ifndef lint
00074 static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $";
00075 #endif
00076
00077
00078
00079
00080
00081
00093 #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
00094 #define lqHash(key,shift) \
00095 (((unsigned)(unsigned long)(key) * DD_P1) >> (shift))
00096 #else
00097 #define lqHash(key,shift) \
00098 (((unsigned)(key) * DD_P1) >> (shift))
00099 #endif
00100
00101
00104
00105
00106
00107
00108 static DdQueueItem * hashLookup ARGS((DdLevelQueue *queue, void *key));
00109 static int hashInsert ARGS((DdLevelQueue *queue, DdQueueItem *item));
00110 static void hashDelete ARGS((DdLevelQueue *queue, DdQueueItem *item));
00111 static int hashResize ARGS((DdLevelQueue *queue));
00112
00116
00117
00118
00119
00120
00137 DdLevelQueue *
00138 cuddLevelQueueInit(
00139 int levels ,
00140 int itemSize ,
00141 int numBuckets )
00142 {
00143 DdLevelQueue *queue;
00144 int logSize;
00145
00146 queue = ALLOC(DdLevelQueue,1);
00147 if (queue == NULL)
00148 return(NULL);
00149 #ifdef __osf__
00150 #pragma pointer_size save
00151 #pragma pointer_size short
00152 #endif
00153
00154 queue->last = ALLOC(DdQueueItem *, levels);
00155 #ifdef __osf__
00156 #pragma pointer_size restore
00157 #endif
00158 if (queue->last == NULL) {
00159 FREE(queue);
00160 return(NULL);
00161 }
00162
00163 if (numBuckets < 2) numBuckets = 2;
00164 logSize = cuddComputeFloorLog2(numBuckets);
00165 queue->numBuckets = 1 << logSize;
00166 queue->shift = sizeof(int) * 8 - logSize;
00167 #ifdef __osf__
00168 #pragma pointer_size save
00169 #pragma pointer_size short
00170 #endif
00171 queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets);
00172 #ifdef __osf__
00173 #pragma pointer_size restore
00174 #endif
00175 if (queue->buckets == NULL) {
00176 FREE(queue->last);
00177 FREE(queue);
00178 return(NULL);
00179 }
00180 #ifdef __osf__
00181 #pragma pointer_size save
00182 #pragma pointer_size short
00183 #endif
00184 memset(queue->last, 0, levels * sizeof(DdQueueItem *));
00185 memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *));
00186 #ifdef __osf__
00187 #pragma pointer_size restore
00188 #endif
00189 queue->first = NULL;
00190 queue->freelist = NULL;
00191 queue->levels = levels;
00192 queue->itemsize = itemSize;
00193 queue->size = 0;
00194 queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY;
00195 return(queue);
00196
00197 }
00198
00199
00212 void
00213 cuddLevelQueueQuit(
00214 DdLevelQueue * queue)
00215 {
00216 DdQueueItem *item;
00217
00218 while (queue->freelist != NULL) {
00219 item = queue->freelist;
00220 queue->freelist = item->next;
00221 FREE(item);
00222 }
00223 while (queue->first != NULL) {
00224 item = (DdQueueItem *) queue->first;
00225 queue->first = item->next;
00226 FREE(item);
00227 }
00228 FREE(queue->buckets);
00229 FREE(queue->last);
00230 FREE(queue);
00231 return;
00232
00233 }
00234
00235
00250 void *
00251 cuddLevelQueueEnqueue(
00252 DdLevelQueue * queue ,
00253 void * key ,
00254 int level )
00255 {
00256 int plevel;
00257 DdQueueItem *item;
00258
00259 #ifdef DD_DEBUG
00260 assert(level < queue->levels);
00261 #endif
00262
00263 item = hashLookup(queue,key);
00264 if (item != NULL) return(item);
00265
00266
00267 if (queue->freelist == NULL) {
00268 item = (DdQueueItem *) ALLOC(char, queue->itemsize);
00269 if (item == NULL)
00270 return(NULL);
00271 } else {
00272 item = queue->freelist;
00273 queue->freelist = item->next;
00274 }
00275
00276 memset(item, 0, queue->itemsize);
00277 item->key = key;
00278
00279 queue->size++;
00280
00281 if (queue->last[level]) {
00282
00283 item->next = queue->last[level]->next;
00284 queue->last[level]->next = item;
00285 } else {
00286
00287
00288 plevel = level;
00289 while (plevel != 0 && queue->last[plevel] == NULL)
00290 plevel--;
00291 if (queue->last[plevel] == NULL) {
00292
00293 item->next = (DdQueueItem *) queue->first;
00294 queue->first = item;
00295 } else {
00296 item->next = queue->last[plevel]->next;
00297 queue->last[plevel]->next = item;
00298 }
00299 }
00300 queue->last[level] = item;
00301
00302
00303 if (hashInsert(queue,item) == 0) {
00304 return(NULL);
00305 }
00306 return(item);
00307
00308 }
00309
00310
00322 void
00323 cuddLevelQueueDequeue(
00324 DdLevelQueue * queue,
00325 int level)
00326 {
00327 DdQueueItem *item = (DdQueueItem *) queue->first;
00328
00329
00330 hashDelete(queue,item);
00331
00332
00333
00334 if (queue->last[level] == item)
00335 queue->last[level] = NULL;
00336
00337 queue->first = item->next;
00338
00339 item->next = queue->freelist;
00340 queue->freelist = item;
00341
00342 queue->size--;
00343 return;
00344
00345 }
00346
00347
00348
00349
00350
00351
00352
00366 static DdQueueItem *
00367 hashLookup(
00368 DdLevelQueue * queue,
00369 void * key)
00370 {
00371 int posn;
00372 DdQueueItem *item;
00373
00374 posn = lqHash(key,queue->shift);
00375 item = queue->buckets[posn];
00376
00377 while (item != NULL) {
00378 if (item->key == key) {
00379 return(item);
00380 }
00381 item = item->cnext;
00382 }
00383 return(NULL);
00384
00385 }
00386
00387
00401 static int
00402 hashInsert(
00403 DdLevelQueue * queue,
00404 DdQueueItem * item)
00405 {
00406 int result;
00407 int posn;
00408
00409 if (queue->size > queue->maxsize) {
00410 result = hashResize(queue);
00411 if (result == 0) return(0);
00412 }
00413
00414 posn = lqHash(item->key,queue->shift);
00415 item->cnext = queue->buckets[posn];
00416 queue->buckets[posn] = item;
00417
00418 return(1);
00419
00420 }
00421
00422
00435 static void
00436 hashDelete(
00437 DdLevelQueue * queue,
00438 DdQueueItem * item)
00439 {
00440 int posn;
00441 DdQueueItem *prevItem;
00442
00443 posn = lqHash(item->key,queue->shift);
00444 prevItem = queue->buckets[posn];
00445
00446 if (prevItem == NULL) return;
00447 if (prevItem == item) {
00448 queue->buckets[posn] = prevItem->cnext;
00449 return;
00450 }
00451
00452 while (prevItem->cnext != NULL) {
00453 if (prevItem->cnext == item) {
00454 prevItem->cnext = item->cnext;
00455 return;
00456 }
00457 prevItem = prevItem->cnext;
00458 }
00459 return;
00460
00461 }
00462
00463
00476 static int
00477 hashResize(
00478 DdLevelQueue * queue)
00479 {
00480 int j;
00481 int posn;
00482 DdQueueItem *item;
00483 DdQueueItem *next;
00484 int numBuckets;
00485 #ifdef __osf__
00486 #pragma pointer_size save
00487 #pragma pointer_size short
00488 #endif
00489 DdQueueItem **buckets;
00490 DdQueueItem **oldBuckets = queue->buckets;
00491 #ifdef __osf__
00492 #pragma pointer_size restore
00493 #endif
00494 int shift;
00495 int oldNumBuckets = queue->numBuckets;
00496 extern void (*MMoutOfMemory)(long);
00497 void (*saveHandler)(long);
00498
00499
00500 numBuckets = oldNumBuckets << 1;
00501 saveHandler = MMoutOfMemory;
00502 MMoutOfMemory = Cudd_OutOfMem;
00503 #ifdef __osf__
00504 #pragma pointer_size save
00505 #pragma pointer_size short
00506 #endif
00507 buckets = queue->buckets = ALLOC(DdQueueItem *, numBuckets);
00508 if (buckets == NULL) {
00509 queue->maxsize <<= 1;
00510 return(1);
00511 }
00512
00513 queue->numBuckets = numBuckets;
00514 shift = --(queue->shift);
00515 queue->maxsize <<= 1;
00516 memset(buckets, 0, numBuckets * sizeof(DdQueueItem *));
00517 #ifdef __osf__
00518 #pragma pointer_size restore
00519 #endif
00520 for (j = 0; j < oldNumBuckets; j++) {
00521 item = oldBuckets[j];
00522 while (item != NULL) {
00523 next = item->cnext;
00524 posn = lqHash(item->key, shift);
00525 item->cnext = buckets[posn];
00526 buckets[posn] = item;
00527 item = next;
00528 }
00529 }
00530 FREE(oldBuckets);
00531 return(1);
00532
00533 }