00001
00080 #include "util.h"
00081 #include "cuddInt.h"
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 #ifndef lint
00101 static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.13 2009/03/08 02:49:02 fabio Exp $";
00102 #endif
00103
00104
00105
00106
00107
00108
00120 #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
00121 #define lqHash(key,shift) \
00122 (((unsigned)(ptruint)(key) * DD_P1) >> (shift))
00123 #else
00124 #define lqHash(key,shift) \
00125 (((unsigned)(key) * DD_P1) >> (shift))
00126 #endif
00127
00128
00131
00132
00133
00134
00135 static DdQueueItem * hashLookup (DdLevelQueue *queue, void *key);
00136 static int hashInsert (DdLevelQueue *queue, DdQueueItem *item);
00137 static void hashDelete (DdLevelQueue *queue, DdQueueItem *item);
00138 static int hashResize (DdLevelQueue *queue);
00139
00143
00144
00145
00146
00147
00164 DdLevelQueue *
00165 cuddLevelQueueInit(
00166 int levels ,
00167 int itemSize ,
00168 int numBuckets )
00169 {
00170 DdLevelQueue *queue;
00171 int logSize;
00172
00173 queue = ALLOC(DdLevelQueue,1);
00174 if (queue == NULL)
00175 return(NULL);
00176 #ifdef __osf__
00177 #pragma pointer_size save
00178 #pragma pointer_size short
00179 #endif
00180
00181 queue->last = ALLOC(DdQueueItem *, levels);
00182 #ifdef __osf__
00183 #pragma pointer_size restore
00184 #endif
00185 if (queue->last == NULL) {
00186 FREE(queue);
00187 return(NULL);
00188 }
00189
00190 if (numBuckets < 2) numBuckets = 2;
00191 logSize = cuddComputeFloorLog2(numBuckets);
00192 queue->numBuckets = 1 << logSize;
00193 queue->shift = sizeof(int) * 8 - logSize;
00194 #ifdef __osf__
00195 #pragma pointer_size save
00196 #pragma pointer_size short
00197 #endif
00198 queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets);
00199 #ifdef __osf__
00200 #pragma pointer_size restore
00201 #endif
00202 if (queue->buckets == NULL) {
00203 FREE(queue->last);
00204 FREE(queue);
00205 return(NULL);
00206 }
00207 #ifdef __osf__
00208 #pragma pointer_size save
00209 #pragma pointer_size short
00210 #endif
00211 memset(queue->last, 0, levels * sizeof(DdQueueItem *));
00212 memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *));
00213 #ifdef __osf__
00214 #pragma pointer_size restore
00215 #endif
00216 queue->first = NULL;
00217 queue->freelist = NULL;
00218 queue->levels = levels;
00219 queue->itemsize = itemSize;
00220 queue->size = 0;
00221 queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY;
00222 return(queue);
00223
00224 }
00225
00226
00239 void
00240 cuddLevelQueueQuit(
00241 DdLevelQueue * queue)
00242 {
00243 DdQueueItem *item;
00244
00245 while (queue->freelist != NULL) {
00246 item = queue->freelist;
00247 queue->freelist = item->next;
00248 FREE(item);
00249 }
00250 while (queue->first != NULL) {
00251 item = (DdQueueItem *) queue->first;
00252 queue->first = item->next;
00253 FREE(item);
00254 }
00255 FREE(queue->buckets);
00256 FREE(queue->last);
00257 FREE(queue);
00258 return;
00259
00260 }
00261
00262
00277 void *
00278 cuddLevelQueueEnqueue(
00279 DdLevelQueue * queue ,
00280 void * key ,
00281 int level )
00282 {
00283 int plevel;
00284 DdQueueItem *item;
00285
00286 #ifdef DD_DEBUG
00287 assert(level < queue->levels);
00288 #endif
00289
00290 item = hashLookup(queue,key);
00291 if (item != NULL) return(item);
00292
00293
00294 if (queue->freelist == NULL) {
00295 item = (DdQueueItem *) ALLOC(char, queue->itemsize);
00296 if (item == NULL)
00297 return(NULL);
00298 } else {
00299 item = queue->freelist;
00300 queue->freelist = item->next;
00301 }
00302
00303 memset(item, 0, queue->itemsize);
00304 item->key = key;
00305
00306 queue->size++;
00307
00308 if (queue->last[level]) {
00309
00310 item->next = queue->last[level]->next;
00311 queue->last[level]->next = item;
00312 } else {
00313
00314
00315 plevel = level;
00316 while (plevel != 0 && queue->last[plevel] == NULL)
00317 plevel--;
00318 if (queue->last[plevel] == NULL) {
00319
00320 item->next = (DdQueueItem *) queue->first;
00321 queue->first = item;
00322 } else {
00323 item->next = queue->last[plevel]->next;
00324 queue->last[plevel]->next = item;
00325 }
00326 }
00327 queue->last[level] = item;
00328
00329
00330 if (hashInsert(queue,item) == 0) {
00331 return(NULL);
00332 }
00333 return(item);
00334
00335 }
00336
00337
00349 void
00350 cuddLevelQueueDequeue(
00351 DdLevelQueue * queue,
00352 int level)
00353 {
00354 DdQueueItem *item = (DdQueueItem *) queue->first;
00355
00356
00357 hashDelete(queue,item);
00358
00359
00360
00361 if (queue->last[level] == item)
00362 queue->last[level] = NULL;
00363
00364 queue->first = item->next;
00365
00366 item->next = queue->freelist;
00367 queue->freelist = item;
00368
00369 queue->size--;
00370 return;
00371
00372 }
00373
00374
00375
00376
00377
00378
00379
00393 static DdQueueItem *
00394 hashLookup(
00395 DdLevelQueue * queue,
00396 void * key)
00397 {
00398 int posn;
00399 DdQueueItem *item;
00400
00401 posn = lqHash(key,queue->shift);
00402 item = queue->buckets[posn];
00403
00404 while (item != NULL) {
00405 if (item->key == key) {
00406 return(item);
00407 }
00408 item = item->cnext;
00409 }
00410 return(NULL);
00411
00412 }
00413
00414
00428 static int
00429 hashInsert(
00430 DdLevelQueue * queue,
00431 DdQueueItem * item)
00432 {
00433 int result;
00434 int posn;
00435
00436 if (queue->size > queue->maxsize) {
00437 result = hashResize(queue);
00438 if (result == 0) return(0);
00439 }
00440
00441 posn = lqHash(item->key,queue->shift);
00442 item->cnext = queue->buckets[posn];
00443 queue->buckets[posn] = item;
00444
00445 return(1);
00446
00447 }
00448
00449
00462 static void
00463 hashDelete(
00464 DdLevelQueue * queue,
00465 DdQueueItem * item)
00466 {
00467 int posn;
00468 DdQueueItem *prevItem;
00469
00470 posn = lqHash(item->key,queue->shift);
00471 prevItem = queue->buckets[posn];
00472
00473 if (prevItem == NULL) return;
00474 if (prevItem == item) {
00475 queue->buckets[posn] = prevItem->cnext;
00476 return;
00477 }
00478
00479 while (prevItem->cnext != NULL) {
00480 if (prevItem->cnext == item) {
00481 prevItem->cnext = item->cnext;
00482 return;
00483 }
00484 prevItem = prevItem->cnext;
00485 }
00486 return;
00487
00488 }
00489
00490
00503 static int
00504 hashResize(
00505 DdLevelQueue * queue)
00506 {
00507 int j;
00508 int posn;
00509 DdQueueItem *item;
00510 DdQueueItem *next;
00511 int numBuckets;
00512 #ifdef __osf__
00513 #pragma pointer_size save
00514 #pragma pointer_size short
00515 #endif
00516 DdQueueItem **buckets;
00517 DdQueueItem **oldBuckets = queue->buckets;
00518 #ifdef __osf__
00519 #pragma pointer_size restore
00520 #endif
00521 int shift;
00522 int oldNumBuckets = queue->numBuckets;
00523 extern DD_OOMFP MMoutOfMemory;
00524 DD_OOMFP saveHandler;
00525
00526
00527 numBuckets = oldNumBuckets << 1;
00528 saveHandler = MMoutOfMemory;
00529 MMoutOfMemory = Cudd_OutOfMem;
00530 #ifdef __osf__
00531 #pragma pointer_size save
00532 #pragma pointer_size short
00533 #endif
00534 buckets = queue->buckets = ALLOC(DdQueueItem *, numBuckets);
00535 MMoutOfMemory = saveHandler;
00536 if (buckets == NULL) {
00537 queue->maxsize <<= 1;
00538 return(1);
00539 }
00540
00541 queue->numBuckets = numBuckets;
00542 shift = --(queue->shift);
00543 queue->maxsize <<= 1;
00544 memset(buckets, 0, numBuckets * sizeof(DdQueueItem *));
00545 #ifdef __osf__
00546 #pragma pointer_size restore
00547 #endif
00548 for (j = 0; j < oldNumBuckets; j++) {
00549 item = oldBuckets[j];
00550 while (item != NULL) {
00551 next = item->cnext;
00552 posn = lqHash(item->key, shift);
00553 item->cnext = buckets[posn];
00554 buckets[posn] = item;
00555 item = next;
00556 }
00557 }
00558 FREE(oldBuckets);
00559 return(1);
00560
00561 }