Checking in super-optimized SimpleHash code... Good for a little performance increase...
[repair.git] / Repair / RepairCompiler / MCC / SimpleHash.cc
1 #include "SimpleHash.h"
2 #include <stdarg.h>
3 #include <stdlib.h>
4
5 /* LINKED HASH NODE ****************************************************/
6
7 LinkedHashNode::LinkedHashNode(int key, int data, LinkedHashNode *next) {
8     this->key = key;
9     this->data = data;
10     this->next = next;
11     this->lnext=0;
12     this->lprev=0;
13 }
14
15 LinkedHashNode::LinkedHashNode() {
16     this->key = -1;
17     this->data = -1;
18     this->next = 0;
19     this->lnext=0;
20     this->lprev=0;
21 }
22
23 /* SIMPLE LIST ****************************************************/
24
25 SimpleList::SimpleList() {
26     ptr = 0;
27     head.next = 0;
28 }
29
30 void SimpleList::reset() {
31   // ptr = head.next;
32   ptr = &head;
33 }
34
35 int SimpleList::hasMoreElements() {
36   //  return (ptr != 0);
37   return (ptr->next != 0);
38 }
39
40 int SimpleList::nextElement() {
41   ptr = ptr->next;
42   return ptr->data;
43
44   //int data = ptr->data;
45   //ptr = ptr->next;
46   //return data;
47 }
48
49 void SimpleList::add(int data) {
50     LinkedHashNode *cur = &head;
51     while (cur->next) {
52         cur = cur->next;
53         if (cur->data == data) {
54             return; // no duplicates
55         }
56     }
57     cur->next = new LinkedHashNode(0, data, 0);
58     return;
59 }
60
61 int SimpleList::contains(int data) {
62     LinkedHashNode *cur = &head;
63     while (cur->next) {
64         cur = cur->next;
65         if (cur->data == data) {
66             return 1; // found!
67         }
68     }
69     return 0;    
70 }
71
72 /* WORK LIST ****************************************************/
73
74 WorkList::WorkList() {
75   head=(struct ListNode *) malloc(sizeof(struct ListNode));
76   tail=head;
77   headoffset=0;
78   tailoffset=0;
79 }
80
81 int WorkList::hasMoreElements() {
82   //  return (ptr != 0);
83   return ((head!=tail)||(headoffset!=tailoffset));
84 }
85
86 int WorkList::getid() {
87   return tail->data[tailoffset];
88 }
89
90 int WorkList::gettype() {
91   return tail->data[tailoffset+1];
92 }
93
94 int WorkList::getlvalue() {
95   return tail->data[tailoffset+2];
96 }
97
98 int WorkList::getrvalue() {
99   return tail->data[tailoffset+3];
100 }
101
102 WorkList::~WorkList() {
103   struct ListNode *ptr=tail;
104   while(ptr) {
105     struct ListNode *oldptr=ptr;
106     ptr=ptr->next;
107     free(oldptr);
108   }
109 }
110
111 void WorkList::pop() {
112   int newoffset=tailoffset+4;
113   struct ListNode *ptr=tail;
114   if (newoffset>=WLISTSIZE) {
115     newoffset-=WLISTSIZE;
116     struct ListNode *oldptr=ptr;
117     ptr=ptr->next;
118     free(oldptr);
119   }
120   tail=ptr;
121   tailoffset=newoffset;
122 }
123
124 void WorkList::add(int id,int type, int lvalue, int rvalue) {
125   if (headoffset==WLISTSIZE) {
126     head->next=(struct ListNode *)malloc(sizeof(struct ListNode));
127     headoffset=0;
128     head=head->next;
129   }
130   head->data[headoffset++]=id;
131   head->data[headoffset++]=type;
132   head->data[headoffset++]=lvalue;
133   head->data[headoffset++]=rvalue;
134 }
135
136 /* SIMPLE HASH ********************************************************/
137 SimpleIterator* SimpleHash::iterator() {
138   return new SimpleIterator(listhead,this);
139 }
140
141 SimpleHash::SimpleHash(int size) {
142     if (size <= 0) {
143         throw SimpleHashException();
144     }
145     this->size = size;
146     this->bucket = (struct SimpleNode **) calloc(sizeof(struct SimpleNode *)*size,1);
147     /* Set allocation blocks*/
148     this->listhead=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
149     this->listtail=this->listhead;
150     this->tailindex=0;
151     /*Set data counts*/
152     this->numparents = 0;
153     this->numchildren = 0;
154     this->numelements = 0;
155 }
156
157 SimpleHash::~SimpleHash() {
158   free(bucket);
159   struct ArraySimple *ptr=listhead;
160   while(ptr) {
161       struct ArraySimple *next=ptr->nextarray;
162       free(ptr);
163       ptr=next;
164   }
165 }
166
167 void SimpleHash::addParent(SimpleHash* parent) {
168     parents[numparents++] = parent;
169     parent->addChild(this);
170 }
171
172 void SimpleHash::addChild(SimpleHash *child) {
173   children[numchildren++]=child;
174 }
175
176 int SimpleHash::remove(int key, int data) {
177     unsigned int hashkey = (unsigned int)key % size;
178     
179     struct SimpleNode **ptr = &bucket[hashkey];
180
181     for (int i = 0; i < numchildren; i++) {
182       children[i]->remove(key, data);
183     }
184
185     while (*ptr) {
186         if ((*ptr)->key == key && (*ptr)->data == data) {
187           struct SimpleNode *toremove=*ptr;
188           *ptr=(*ptr)->next;
189
190           toremove->inuse=0; /* Marked as unused */
191
192           numelements--;
193           return 1;
194         }
195         ptr = &((*ptr)->next);
196     }
197
198     return 0;
199 }
200
201
202
203 int SimpleHash::add(int key, int data) {
204     unsigned int hashkey = (unsigned int)key % size;
205     
206     struct SimpleNode **ptr = &bucket[hashkey];
207
208     /* check that this key/object pair isn't already here */
209     // TBD can be optimized for set v. relation */
210     while (*ptr) {
211         if ((*ptr)->key == key && (*ptr)->data == data) {
212             return 0;
213         }
214         ptr = &((*ptr)->next);
215     }
216     if (tailindex==ARRAYSIZE) {
217       listtail->nextarray=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
218       tailindex=0;
219       listtail=listtail->nextarray;
220     }
221     
222     *ptr = &listtail->nodes[tailindex++];
223     (*ptr)->key=key;
224     (*ptr)->data=data;
225     (*ptr)->inuse=1;
226
227     numelements++;
228     
229     for (int i = 0; i < numparents; i++) {
230         parents[i]->add(key, data);
231     }
232
233     return 1;
234 }
235
236 bool SimpleHash::contains(int key) {
237     unsigned int hashkey = (unsigned int)key % size;
238     
239     struct SimpleNode *ptr = bucket[hashkey];
240     while (ptr) {
241         if (ptr->key == key) {
242             // we already have this object 
243             // stored in the hash so just return
244             return true;
245         }
246         ptr = ptr->next;
247     }
248     return false;
249 }
250
251 bool SimpleHash::contains(int key, int data) {
252     unsigned int hashkey = (unsigned int)key % size;
253     
254     struct SimpleNode *ptr = bucket[hashkey];
255     while (ptr) {
256         if (ptr->key == key && ptr->data == data) {
257             // we already have this object 
258             // stored in the hash so just return
259             return true;
260         }
261         ptr = ptr->next;
262     }
263     return false;
264 }
265
266 int SimpleHash::count(int key) {
267     unsigned int hashkey = (unsigned int)key % size;
268     int count = 0;
269
270     struct SimpleNode *ptr = bucket[hashkey];
271     while (ptr) {
272         if (ptr->key == key) {
273             count++;
274         }
275         ptr = ptr->next;
276     }
277     return count;
278 }
279
280 int SimpleHash::get(int key, int&data) {
281     unsigned int hashkey = (unsigned int)key % size;
282     
283     struct SimpleNode *ptr = bucket[hashkey];
284     while (ptr) {
285         if (ptr->key == key) {
286             data = ptr->data;
287             return 1; // success
288         }
289         ptr = ptr->next;
290     }
291         
292     return 0; // failure
293 }
294
295 int SimpleHash::countdata(int data) {
296     int count = 0;
297     struct ArraySimple *ptr = listhead;
298     while(ptr) {
299       if (ptr->nextarray) {
300         for(int i=0;i<ARRAYSIZE;i++)
301           if (ptr->nodes[i].data == data
302               &&ptr->nodes[i].inuse) {
303             count++;
304           }
305       } else {
306         for(int i=0;i<tailindex;i++)
307           if (ptr->nodes[i].data == data
308               &&ptr->nodes[i].inuse) {
309             count++;
310           }
311       }
312       ptr = ptr->nextarray;
313     }
314     return count;
315 }
316
317 SimpleHashException::SimpleHashException() {}
318 // ************************************************************
319
320
321 RepairHashNode::RepairHashNode(int setrelation, int rule, int lvalue, int rvalue, int data){
322     this->setrelation = setrelation;
323     this->lvalue=lvalue;
324     this->rvalue=rvalue;
325     this->data = data;
326     this->next = 0;
327     this->lnext=0;
328     this->rule=rule;
329 }
330
331 // ************************************************************
332
333 RepairHash::RepairHash(int size) {
334     if (size <= 0) {
335         throw SimpleHashException();
336     }
337     this->size = size;
338     this->bucket = new RepairHashNode* [size];
339     for (int i=0;i<size;i++)
340       bucket[i]=0;
341     this->nodelist=0;
342     this->numelements = 0;
343 }
344
345 RepairHash::RepairHash() {
346   RepairHash(100);
347 }
348
349 RepairHash::~RepairHash() {
350   delete [] this->bucket;
351   RepairHashNode *ptr=nodelist;
352   while(ptr) {
353       RepairHashNode *next=ptr->lnext;
354       delete ptr;
355       ptr=next;
356   }
357 }
358
359 #define SETFLAG (1<<31)
360
361 int RepairHash::addset(int setv, int rule, int value, int data) {
362   return addrelation(setv||SETFLAG, rule, value,0,data);
363 }
364
365 int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int data) {
366     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
367     
368     RepairHashNode **ptr = &bucket[hashkey];
369
370     /* check that this key/object pair isn't already here */
371     // TBD can be optimized for set v. relation */
372     while (*ptr) {
373         if ((*ptr)->setrelation == relation && 
374             (*ptr)->rule==rule &&
375             (*ptr)->lvalue==lvalue &&
376             (*ptr)->rvalue==rvalue &&
377             (*ptr)->data == data) {
378             return 0;
379         }
380         ptr = &((*ptr)->next);
381     }
382     
383     *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data);
384     (*ptr)->lnext=nodelist;
385     nodelist=*ptr;
386     numelements++;
387     return 1;
388 }
389
390 bool RepairHash::containsset(int setv, int rule, int value) {
391   return containsrelation(setv||SETFLAG, rule, value,0);
392 }
393
394 bool RepairHash::containsrelation(int relation, int rule, int lvalue, int rvalue) {
395     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
396     
397     RepairHashNode **ptr = &bucket[hashkey];
398
399     /* check that this key/object pair isn't already here */
400     // TBD can be optimized for set v. relation */
401     while (*ptr) {
402         if ((*ptr)->setrelation == relation && 
403             (*ptr)->rule==rule &&
404             (*ptr)->lvalue==lvalue &&
405             (*ptr)->rvalue==rvalue) {
406             return true;
407         }
408         ptr = &((*ptr)->next);
409     }
410     return false;
411 }
412
413 int RepairHash::getset(int setv, int rule, int value) {
414   return getrelation(setv||SETFLAG, rule, value,0);
415 }
416
417 int RepairHash::getrelation(int relation, int rule, int lvalue,int rvalue) {
418     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
419     
420     RepairHashNode **ptr = &bucket[hashkey];
421
422     /* check that this key/object pair isn't already here */
423     // TBD can be optimized for set v. relation */
424     while (*ptr) {
425         if ((*ptr)->setrelation == relation && 
426             (*ptr)->rule==rule &&
427             (*ptr)->lvalue==lvalue &&
428             (*ptr)->rvalue==rvalue) {
429           return (*ptr)->data;
430         }
431         ptr = &((*ptr)->next);
432     }
433     return 0;
434 }