Add additional functionality to Simplehash.
[repair.git] / Repair / RepairCompiler / MCC / Runtime / SimpleHash.cc
index bed5c1fc3ad9780c35dd042784ef874c016e9441..fef3507015bbd60a83c6190f8cafafd5d7bbdfca 100755 (executable)
@@ -79,6 +79,12 @@ WorkList::WorkList() {
   tailoffset=0;
 }
 
+void WorkList::reset() {
+  head=tail;
+  headoffset=0;
+  tailoffset=0;
+}
+
 int WorkList::hasMoreElements() {
   //  return (ptr != 0);
   return ((head!=tail)||(headoffset!=tailoffset));
@@ -124,10 +130,12 @@ void WorkList::pop() {
 
 void WorkList::add(int id,int type, int lvalue, int rvalue) {
   if (headoffset==WLISTSIZE) {
-    head->next=(struct ListNode *)malloc(sizeof(struct ListNode));
+    if (head->next==0) {
+      head->next=(struct ListNode *)malloc(sizeof(struct ListNode));
+      head->next=0;
+    }
     headoffset=0;
     head=head->next;
-    head->next=0;
   }
   head->data[headoffset++]=id;
   head->data[headoffset++]=type;
@@ -221,39 +229,64 @@ int SimpleHash::remove(int key, int data) {
     return 0;
 }
 
-
+void SimpleHash::addAll(SimpleHash * set) {
+  SimpleIterator it;
+  set->iterator(it);
+  while(it.hasNext()) {
+    int key=it.key();
+    int data=it.next();
+    add(key,data);
+  }
+}
 
 int SimpleHash::add(int key, int data) {
-    unsigned int hashkey = (unsigned int)key % size;
-    
-    struct SimpleNode **ptr = &bucket[hashkey];
-
-    /* check that this key/object pair isn't already here */
-    // TBD can be optimized for set v. relation */
-    while (*ptr) {
-        if ((*ptr)->key == key && (*ptr)->data == data) {
-            return 0;
-        }
-        ptr = &((*ptr)->next);
-    }
-    if (tailindex==ARRAYSIZE) {
-      listtail->nextarray=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
-      tailindex=0;
-      listtail=listtail->nextarray;
+  /* Rehash code */
+  if (numelements>=size) {
+    int newsize=2*size+1;
+    struct SimpleNode ** newbucket = (struct SimpleNode **) calloc(sizeof(struct SimpleNode *)*newsize,1);
+    for(int i=size-1;i>=0;i--) {
+      for(struct SimpleNode *ptr=bucket[i];ptr!=NULL;) {
+       struct SimpleNode * nextptr=ptr->next;
+       unsigned int newhashkey=(unsigned int)ptr->key % newsize;
+       ptr->next=newbucket[newhashkey];
+       newbucket[newhashkey]=ptr;
+       ptr=nextptr;
+      }
     }
-    
-    *ptr = &listtail->nodes[tailindex++];
-    (*ptr)->key=key;
-    (*ptr)->data=data;
-    (*ptr)->inuse=1;
+    size=newsize;
+    free(bucket);
+    bucket=newbucket;
+  }
 
-    numelements++;
-    
-    for (int i = 0; i < numparents; i++) {
-        parents[i]->add(key, data);
-    }
+  unsigned int hashkey = (unsigned int)key % size;
+  struct SimpleNode **ptr = &bucket[hashkey];
+  
+  /* check that this key/object pair isn't already here */
+  /* TBD can be optimized for set v. relation */
 
-    return 1;
+  while (*ptr) {
+    if ((*ptr)->key == key && (*ptr)->data == data) {
+      return 0;
+    }
+    ptr = &((*ptr)->next);
+  }
+  if (tailindex==ARRAYSIZE) {
+    listtail->nextarray=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
+    tailindex=0;
+    listtail=listtail->nextarray;
+  }
+  
+  *ptr = &listtail->nodes[tailindex++];
+  (*ptr)->key=key;
+  (*ptr)->data=data;
+  (*ptr)->inuse=1;
+  
+  numelements++;
+  
+  for (int i = 0; i < numparents; i++) {
+    parents[i]->add(key, data);
+  }
+  return 1;
 }
 
 bool SimpleHash::contains(int key) {
@@ -300,6 +333,20 @@ int SimpleHash::count(int key) {
     return count;
 }
 
+SimpleHash * SimpleHash::imageSet(int key) {
+  SimpleHash * newset=new SimpleHash(count(key));
+  unsigned int hashkey = (unsigned int)key % size;
+  
+  struct SimpleNode *ptr = bucket[hashkey];
+  while (ptr) {
+    if (ptr->key == key) {
+      newset->add(ptr->data,ptr->data);
+    }
+    ptr = ptr->next;
+  }
+  return newset;
+}
+
 int SimpleHash::get(int key, int&data) {
     unsigned int hashkey = (unsigned int)key % size;