home *** CD-ROM | disk | FTP | other *** search
-
-
- /* Copyright 1986 Norm Hutchinson and Eric Jul. May not be used for any *
- * purpose without written permission from the author. */
-
- /*
- * Sets are sets of integers.
- */
-
- #include "Kernel/h/assert.h"
- #include "Kernel/h/system.h"
- #include "Kernel/h/set.h"
-
- #define INITIALSIZE 8
-
- #define SETHASH(key, set) ((((key) << 1) ^ ((key) >> 6)) & set->maxIndex)
- static void CheckOutSetHashTable();
-
- #define MAXSETSTANDBY 20
- int nextFreeSet = 0;
- Set standbySets[MAXSETSTANDBY];
-
- Set Set_Create()
- {
- register Set m;
- register SETElemPtr elem, stopelem;
- register int myNil = NIL;
-
- if (nextFreeSet > 0) {
- /* Grab one from standby stack */
- m = standbySets[--nextFreeSet];
- return m;
- }
-
- m = (Set) malloc(sizeof(SetRecord));
- m->maxIndex = INITIALSIZE - 1;
- m->maxCount = m->maxIndex - (m->maxIndex >> 2); /* Max fill 87.5 % */
- m->count = 0;
- m->table = (SETElemPtr) malloc(INITIALSIZE * sizeof(SETElem));
- elem = &m->table[0];
- stopelem = &m->table[INITIALSIZE];
- do {
- elem->key = myNil;
- elem++;
- } while (elem != stopelem);
-
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- return(m);
- }
-
- Set Set_CreateSized(fCount)
- int fCount;
- {
- register int i;
- register Set m;
- register SETElemPtr entryPtr;
- register int myNil = NIL;
-
- assert(fCount > 0);
- m = (Set) malloc(sizeof(SetRecord));
- /* Make i the first power of two greater than fCount */
- for (i = 1; i <= fCount; i += i);
- i--;
- m->maxIndex = i;
- m->maxCount = m->maxIndex - (m->maxIndex >> 2); /* Max fill 87.5 % */
- m->count = 0;
- m->table = (SETElemPtr) malloc((unsigned)((i+1) * sizeof(SETElem)));
- entryPtr = &m->table[i+1];
- do {
- (--entryPtr)->key = myNil;
- } while (--i >= 0);
-
- # ifdef lint
- CheckOutSetHashTable(m);
- #endif
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- return(m);
- }
-
- void Set_Destroy(m)
- register Set m;
- {
- if (m == (Set) NULL) return;
- if ((nextFreeSet < MAXSETSTANDBY)
- && (m->maxIndex == INITIALSIZE - 1)
- ) {
- if (m->count != 0) {
- register int i;
- register SETElemPtr entryPtr;
- register int myNil = NIL;
-
- /* Reinitialize it */
- i = m->maxIndex;
- entryPtr = &m->table[i+1];
- do {
- /* Optimized for portable CC for VAX */
- (--entryPtr)->key = myNil;
- } while (--i >= 0);
- m->count = 0;
- }
-
- /* Nice set, recycle it */
- standbySets[nextFreeSet++] = m;
- #ifdef DEBUGMAP
- CheckOutSetHashTable(m);
- #endif DEBUGMAP
- return;
- }
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- free((char *)m->table);
- free((char *)m);
- }
-
- static void ExpandSetHashTable(m)
- register Set m;
- {
- register SETElem *nh, *oe, *ne;
- register int oldHashTableSize = m->maxIndex + 1, i;
- register int key;
- int index;
-
- m->maxIndex = oldHashTableSize * 2 - 1;
- m->maxCount = m->maxIndex - (m->maxIndex >> 2);
- nh = (SETElemPtr) malloc((unsigned)(oldHashTableSize * 2 * sizeof(SETElem)));
- for (i = 0; i <= m->maxIndex; i++) nh[i].key = NIL;
- for (i = 0; i < oldHashTableSize; i++) {
- oe = &m->table[i];
- key = oe->key;
- if (key == NIL) continue;
- index = SETHASH(key, m);
- while (1) {
- ne = &nh[index];
- if (ne->key == NIL) {
- ne->key = oe->key;
- break;
- } else {
- assert(ne->key !=key);
- index++;
- if (index > m->maxIndex) index = 0;
- }
- }
- }
- free((char *)m->table);
- m->table = nh;
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- }
-
- int Set_Lookup(m, key)
- register Set m;
- register int key;
- {
- register int index = SETHASH(key, m);
- register SETElemPtr e;
- register limit = m->maxIndex;
-
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- while (1) {
- e = &m->table[index];
- if (e->key == NIL) { /* we did not find it */
- return (NIL);
- } else if (e->key == key) {
- return (e->key);
- }
- if (++index > limit) index = 0;
- }
- }
-
- int Set_Member(m, key)
- register Set m;
- register int key;
- {
- register int index = SETHASH(key, m);
- register SETElemPtr e;
- register int myNil = NIL;
-
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- e = &m->table[index];
- while (1) {
- if (e->key == myNil) { /* we did not find it */
- return (0);
- } else if (e->key == key) {
- return (1);
- }
- e++;
- if (++index > m->maxIndex) {
- index = 0;
- e = &m->table[0];
- }
- }
- }
-
- void Set_Delete(m, key)
- register Set m;
- register int key;
- /* Remove the entry, if it is there */
- {
- register int index = SETHASH(key, m);
- register SETElemPtr e;
-
- while (1) {
- e = &m->table[index];
- if (e->key == NIL) { /* we did not find it */
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- return;
- }
- if (e->key == key) {
- /* Found it, now remove it */
- m->count--;
- e->key = NIL;
- while (1) {
- /* rehash until we reach nil again */
- if (++index > m->maxIndex) index = 0;
- e = & m->table[index];
- key = e->key;
- if (key == NIL) {
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- return;
- }
- /* rehashing is done by removing then reinserting */
- e->key = NIL;
- m->count--;
- Set_Insert(m, key);
- }
- }
- if (++index > m->maxIndex) index = 0;
- }
- }
-
- void Set_Insert(m, key)
- register Set m;
- register int key;
- {
- register int index;
- register SETElemPtr e;
- assert(key != NIL);
- if (m->count >= m->maxCount) ExpandSetHashTable(m);
- index = SETHASH(key, m);
- while (1) {
- e = &m->table[index];
- if (e->key == NIL) { /* put it here */
- e->key = key;
- m->count++;
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- return;
- } else if (e->key == key) {
- /* Already in set */
- #ifdef DEBUGSET
- CheckOutSetHashTable(m);
- #endif DEBUGSET
- return;
- }
- if (++index > m->maxIndex) index = 0;
- }
- }
-
- int Set_FindNext(m, startIndex, keyPtr)
- register Set m;
- int *startIndex;
- int *keyPtr;
- {
- register int i;
- register SETElemPtr e;
- for (i = *startIndex; i <= m->maxIndex; i++) {
- e = &m->table[i];
- if (e->key != NIL) {
- *keyPtr = e->key;
- *startIndex = i + 1;
- return(1);
- }
- }
- *keyPtr = NIL;
- *startIndex = -1;
- return(0);
- }
-
- void Set_Print(m)
- register Set m;
- {
- int key, index;
- printf(
- "\nDump of set @ 0x%05x, %d entr%s, current max %d\nIndex\tKey\n",
- m, m->count, m->count == 1 ? "y" : "ies", m->maxCount);
- for (index = 0; index <= m->maxIndex; index++) {
- key = m->table[index].key;
- printf("%3d\t0x%08.8x\n", index, key);
- }
- }
-
- static void CheckOutSetHashTable(m)
- register Set m;
- {
- register int i;
- register SETElemPtr realElement, e;
- register int index, firstIndex, count;
- count = 0;
-
- for (i = 0; i <= m->maxIndex; i++) {
- realElement = &m->table[i];
- if (realElement->key != NIL) {
- count++;
- index = SETHASH(realElement->key, m);
- firstIndex = index;
- while (1) {
- e = &m->table[index];
- if (e->key == NIL) { /* we did not find it */
- break;
- } else if (e->key == realElement->key) {
- break;
- } else {
- index++;
- if (index > m->maxIndex) index = 0;
- if (index == firstIndex) {
- index = -1;
- break;
- }
- }
- }
-
- if (index == -1 || e->key != realElement->key) {
- printf(
- "Set problem: Key 0x%x, rightIndex %d, realIndex %d\n",
- realElement->key, firstIndex, index);
- Set_Print(m);
- }
- }
- }
- if (count != m->count) {
- printf(
- "Set problem: Should have %d entries, but found %d.\n", m->count,
- count);
- Set_Print(m);
- }
- }
-
-