Add additional functionality to Simplehash.
[repair.git] / Repair / RepairCompiler / MCC / Runtime / SimpleHash.cc
index d420a1c3934481809934c67d073c10c117be9010..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;
@@ -137,13 +145,15 @@ void WorkList::add(int id,int type, int lvalue, int rvalue) {
 
 /* SIMPLE HASH ********************************************************/
 SimpleIterator* SimpleHash::iterator() {
-  return new SimpleIterator(listhead,this);
+  return new SimpleIterator(listhead,listtail,tailindex/*,this*/);
 }
 
 void SimpleHash::iterator(SimpleIterator & it) {
-  it.table=this;
+  //  it.table=this;
   it.cur=listhead;
   it.index=0;
+  it.tailindex=tailindex;
+  it.tail=listtail;
 }
 
 SimpleHash::SimpleHash(int size) {
@@ -172,6 +182,19 @@ SimpleHash::~SimpleHash() {
   }
 }
 
+int SimpleHash::firstkey() {
+  struct ArraySimple *ptr=listhead;
+  int index=0;
+  while((index==ARRAYSIZE)||!ptr->nodes[index].inuse) {
+    if (index==ARRAYSIZE) {
+      index=0;
+      ptr=ptr->nextarray;
+    } else
+      index++;
+  }
+  return ptr->nodes[index].key;
+}
+
 void SimpleHash::addParent(SimpleHash* parent) {
     parents[numparents++] = parent;
     parent->addChild(this);
@@ -206,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) {
@@ -285,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;
     
@@ -326,14 +388,16 @@ SimpleHashException::SimpleHashException() {}
 // ************************************************************
 
 
-RepairHashNode::RepairHashNode(int setrelation, int rule, int lvalue, int rvalue, int data){
+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;
     this->data = data;
+    this->data2 = data2;
     this->next = 0;
     this->lnext=0;
     this->rule=rule;
+    this->ismodify=ismodify;
 }
 
 // ************************************************************
@@ -350,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() {
@@ -382,13 +452,40 @@ int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int
            (*ptr)->rule==rule &&
            (*ptr)->lvalue==lvalue &&
            (*ptr)->rvalue==rvalue &&
-           (*ptr)->data == data) {
+           (*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) {
+    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 == data2) {
             return 0;
         }
         ptr = &((*ptr)->next);
     }
     
-    *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data);
+    *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data,data2,1);
     (*ptr)->lnext=nodelist;
     nodelist=*ptr;
     numelements++;
@@ -422,6 +519,44 @@ 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;
+    
+    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)->data2;
+        }
+        ptr = &((*ptr)->next);
+    }
+    return 0;
+}
+
 int RepairHash::getrelation(int relation, int rule, int lvalue,int rvalue) {
     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;