Add additional functionality to Simplehash.
[repair.git] / Repair / RepairCompiler / MCC / Runtime / SimpleHash.cc
index 63b23c3736b8d2b991725c88f355030a1e65bbfc..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;
     
@@ -341,7 +388,7 @@ SimpleHashException::SimpleHashException() {}
 // ************************************************************
 
 
-RepairHashNode::RepairHashNode(int setrelation, int rule, int lvalue, int rvalue, int data, int data2){
+RepairHashNode::RepairHashNode(int setrelation, int rule, int lvalue, int rvalue, int data, int data2, int ismodify){
     this->setrelation = setrelation;
     this->lvalue=lvalue;
     this->rvalue=rvalue;
@@ -350,6 +397,7 @@ RepairHashNode::RepairHashNode(int setrelation, int rule, int lvalue, int rvalue
     this->next = 0;
     this->lnext=0;
     this->rule=rule;
+    this->ismodify=ismodify;
 }
 
 // ************************************************************
@@ -366,8 +414,14 @@ RepairHash::RepairHash(int size) {
     this->numelements = 0;
 }
 
+#define REPAIRSIZE 100
 RepairHash::RepairHash() {
-  RepairHash(100);
+    this->size = REPAIRSIZE;
+    this->bucket = new RepairHashNode* [REPAIRSIZE];
+    for (int i=0;i<REPAIRSIZE;i++)
+      bucket[i]=0;
+    this->nodelist=0;
+    this->numelements = 0;
 }
 
 RepairHash::~RepairHash() {
@@ -387,7 +441,29 @@ int RepairHash::addset(int setv, int rule, int value, int data) {
 }
 
 int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int data) {
-  return addrelation(relation,rule,lvalue,rvalue,data, 0);
+    unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
+    
+    RepairHashNode **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)->setrelation == relation && 
+           (*ptr)->rule==rule &&
+           (*ptr)->lvalue==lvalue &&
+           (*ptr)->rvalue==rvalue &&
+           (*ptr)->data == data&&
+           (*ptr)->data2 == 0) {
+            return 0;
+        }
+        ptr = &((*ptr)->next);
+    }
+    
+    *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data,0,0);
+    (*ptr)->lnext=nodelist;
+    nodelist=*ptr;
+    numelements++;
+    return 1;
 }
 
 int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int data, int data2) {
@@ -409,7 +485,7 @@ int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int
         ptr = &((*ptr)->next);
     }
     
-    *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data,data2);
+    *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data,data2,1);
     (*ptr)->lnext=nodelist;
     nodelist=*ptr;
     numelements++;
@@ -443,6 +519,25 @@ int RepairHash::getset(int setv, int rule, int value) {
   return getrelation(setv||SETFLAG, rule, value,0);
 }
 
+int RepairHash::ismodify(int relation, int rule, int lvalue,int rvalue) {
+    unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
+    
+    RepairHashNode **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)->setrelation == relation && 
+           (*ptr)->rule==rule &&
+           (*ptr)->lvalue==lvalue &&
+           (*ptr)->rvalue==rvalue) {
+         return (*ptr)->ismodify;
+        }
+        ptr = &((*ptr)->next);
+    }
+    return 0;
+}
+
 int RepairHash::getrelation2(int relation, int rule, int lvalue,int rvalue) {
     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
     
@@ -461,6 +556,7 @@ int RepairHash::getrelation2(int relation, int rule, int lvalue,int rvalue) {
     }
     return 0;
 }
+
 int RepairHash::getrelation(int relation, int rule, int lvalue,int rvalue) {
     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;