#include "util.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#define | lqHash(key, shift) (((unsigned)(key) * DD_P1) >> (shift)) |
Functions | |
static DdQueueItem * | hashLookup (DdLevelQueue *queue, void *key) |
static int | hashInsert (DdLevelQueue *queue, DdQueueItem *item) |
static void | hashDelete (DdLevelQueue *queue, DdQueueItem *item) |
static int | hashResize (DdLevelQueue *queue) |
DdLevelQueue * | cuddLevelQueueInit (int levels, int itemSize, int numBuckets) |
void | cuddLevelQueueQuit (DdLevelQueue *queue) |
void * | cuddLevelQueueEnqueue (DdLevelQueue *queue, void *key, int level) |
void | cuddLevelQueueDequeue (DdLevelQueue *queue, int level) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddLevelQ.c,v 1.13 2009/03/08 02:49:02 fabio Exp $" |
#define lqHash | ( | key, | |||
shift | ) | (((unsigned)(key) * DD_P1) >> (shift)) |
Macro***********************************************************************
Synopsis [Hash function for the table of a level queue.]
Description [Hash function for the table of a level queue.]
SideEffects [None]
SeeAlso [hashInsert hashLookup hashDelete]
Definition at line 124 of file cuddLevelQ.c.
void cuddLevelQueueDequeue | ( | DdLevelQueue * | queue, | |
int | level | |||
) |
Function********************************************************************
Synopsis [Remove an item from the front of a level queue.]
Description [Remove an item from the front of a level queue.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue]
Definition at line 350 of file cuddLevelQ.c.
00353 { 00354 DdQueueItem *item = (DdQueueItem *) queue->first; 00355 00356 /* Delete from the hash table. */ 00357 hashDelete(queue,item); 00358 00359 /* Since we delete from the front, if this is the last item for 00360 ** its level, there are no other items for the same level. */ 00361 if (queue->last[level] == item) 00362 queue->last[level] = NULL; 00363 00364 queue->first = item->next; 00365 /* Put item on the free list. */ 00366 item->next = queue->freelist; 00367 queue->freelist = item; 00368 /* Update stats. */ 00369 queue->size--; 00370 return; 00371 00372 } /* end of cuddLevelQueueDequeue */
void* cuddLevelQueueEnqueue | ( | DdLevelQueue * | queue, | |
void * | key, | |||
int | level | |||
) |
Function********************************************************************
Synopsis [Inserts a new key in a level queue.]
Description [Inserts a new key in a level queue. A new entry is created in the queue only if the node is not already enqueued. Returns a pointer to the queue item if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue]
Definition at line 278 of file cuddLevelQ.c.
00282 { 00283 int plevel; 00284 DdQueueItem *item; 00285 00286 #ifdef DD_DEBUG 00287 assert(level < queue->levels); 00288 #endif 00289 /* Check whether entry for this node exists. */ 00290 item = hashLookup(queue,key); 00291 if (item != NULL) return(item); 00292 00293 /* Get a free item from either the free list or the memory manager. */ 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 /* Initialize. */ 00303 memset(item, 0, queue->itemsize); 00304 item->key = key; 00305 /* Update stats. */ 00306 queue->size++; 00307 00308 if (queue->last[level]) { 00309 /* There are already items for this level in the queue. */ 00310 item->next = queue->last[level]->next; 00311 queue->last[level]->next = item; 00312 } else { 00313 /* There are no items at the current level. Look for the first 00314 ** non-empty level preceeding this one. */ 00315 plevel = level; 00316 while (plevel != 0 && queue->last[plevel] == NULL) 00317 plevel--; 00318 if (queue->last[plevel] == NULL) { 00319 /* No element precedes this one in the queue. */ 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 /* Insert entry for the key in the hash table. */ 00330 if (hashInsert(queue,item) == 0) { 00331 return(NULL); 00332 } 00333 return(item); 00334 00335 } /* end of cuddLevelQueueEnqueue */
DdLevelQueue* cuddLevelQueueInit | ( | int | levels, | |
int | itemSize, | |||
int | numBuckets | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Initializes a level queue.]
Description [Initializes a level queue. A level queue is a queue where inserts are based on the levels of the nodes. Within each level the policy is FIFO. Level queues are useful in traversing a BDD top-down. Queue items are kept in a free list when dequeued for efficiency. Returns a pointer to the new queue if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue]
Definition at line 165 of file cuddLevelQ.c.
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 /* Keep pointers to the insertion points for all levels. */ 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 /* Use a hash table to test for uniqueness. */ 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 } /* end of cuddLevelQueueInit */
void cuddLevelQueueQuit | ( | DdLevelQueue * | queue | ) |
Function********************************************************************
Synopsis [Shuts down a level queue.]
Description [Shuts down a level queue and releases all the associated memory.]
SideEffects [None]
SeeAlso [cuddLevelQueueInit]
Definition at line 240 of file cuddLevelQ.c.
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 } /* end of cuddLevelQueueQuit */
static void hashDelete | ( | DdLevelQueue * | queue, | |
DdQueueItem * | item | |||
) | [static] |
Function********************************************************************
Synopsis [Removes an item from the hash table of a level queue.]
Description [Removes an item from the hash table of a level queue. Nothing is done if the item is not in the table.]
SideEffects [None]
SeeAlso [cuddLevelQueueDequeue hashInsert]
Definition at line 463 of file cuddLevelQ.c.
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 } /* end of hashDelete */
static int hashInsert | ( | DdLevelQueue * | queue, | |
DdQueueItem * | item | |||
) | [static] |
Function********************************************************************
Synopsis [Inserts an item in the hash table of a level queue.]
Description [Inserts an item in the hash table of a level queue. Returns 1 if successful; 0 otherwise. No check is performed to see if an item with the same key is already in the hash table.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue]
Definition at line 429 of file cuddLevelQ.c.
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 } /* end of hashInsert */
static DdQueueItem * hashLookup | ( | DdLevelQueue * | queue, | |
void * | key | |||
) | [static] |
AutomaticStart
Function********************************************************************
Synopsis [Looks up a key in the hash table of a level queue.]
Description [Looks up a key in the hash table of a level queue. Returns a pointer to the item with the given key if the key is found; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue hashInsert]
Definition at line 394 of file cuddLevelQ.c.
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 } /* end of hashLookup */
static int hashResize | ( | DdLevelQueue * | queue | ) | [static] |
Function********************************************************************
Synopsis [Resizes the hash table of a level queue.]
Description [Resizes the hash table of a level queue. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [hashInsert]
Definition at line 504 of file cuddLevelQ.c.
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 /* Compute the new size of the subtable. */ 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 } /* end of hashResize */
char rcsid [] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.13 2009/03/08 02:49:02 fabio Exp $" [static] |
CFile***********************************************************************
FileName [cuddLevelQ.c]
PackageName [cudd]
Synopsis [Procedure to manage level queues.]
Description [The functions in this file allow an application to easily manipulate a queue where nodes are prioritized by level. The emphasis is on efficiency. Therefore, the queue items can have variable size. If the application does not need to attach information to the nodes, it can declare the queue items to be of type DdQueueItem. Otherwise, it can declare them to be of a structure type such that the first three fields are data pointers. The third pointer points to the node. The first two pointers are used by the level queue functions. The remaining fields are initialized to 0 when a new item is created, and are then left to the exclusive use of the application. On the DEC Alphas the three pointers must be 32-bit pointers when CUDD is compiled with 32-bit pointers. The level queue functions make sure that each node appears at most once in the queue. They do so by keeping a hash table where the node is used as key. Queue items are recycled via a free list for efficiency.
Internal procedures provided by this module:
Static procedures included in this module:
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2004, 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.]
Definition at line 101 of file cuddLevelQ.c.