Annotation of researchv10no/cmd/cfront/ooptcfront/demo/VHashAssoc.c, revision 1.1.1.1

1.1       root        1: #include "check.h"
                      2: 
                      3: // This may look like C code, but it is really -*- C++ -*-
                      4: /* 
                      5: Copyright (C) 1988 Free Software Foundation
                      6:     written by Doug Lea ([email protected])
                      7: 
                      8: This file is part of GNU CC.
                      9: 
                     10: GNU CC is distributed in the hope that it will be useful,
                     11: but WITHOUT ANY WARRANTY.  No author or distributor
                     12: accepts responsibility to anyone for the consequences of using it
                     13: or for whether it serves any particular purpose or works at all,
                     14: unless he says so in writing.  Refer to the GNU CC General Public
                     15: License for full details.
                     16: 
                     17: Everyone is granted permission to copy, modify and redistribute
                     18: GNU CC, but only under the conditions described in the
                     19: GNU CC General Public License.   A copy of this license is
                     20: supposed to have been given to you along with GNU CC so you
                     21: can know your rights and responsibilities.  It should be in a
                     22: file named COPYING.  Among other things, the copyright notice
                     23: and this notice must be preserved on all copies.  
                     24: */
                     25: 
                     26: /* GNU hash tables converted to demonstrate PT */
                     27: 
                     28: template <class T, class U> class VHashAssocNode
                     29: {
                     30: public:
                     31:   T                     key;
                     32:   U                     cont;
                     33:   char                  status;
                     34: };
                     35: 
                     36: 
                     37: template <class T, class U> class VHashAssocTrav ;
                     38: 
                     39: 
                     40: template <class T, class U> class VHashAssoc
                     41: {
                     42:   friend class          VHashAssocTrav<T,U> ;
                     43: 
                     44:   VHashAssocNode<T,U> * tab;
                     45:   int                   size;
                     46:   int                   cnt;
                     47: 
                     48: public:
                     49:   static unsigned int (*key_hash_function)(T &);
                     50:   int  (* key_key_equality_function )(T&, T&);
                     51: 
                     52:   unsigned int          key_hash(T& a);
                     53:   int                   key_key_eq(T&a, T& b);    
                     54: 
                     55:                         VHashAssoc(int sz);
                     56:                         VHashAssoc(VHashAssoc& a);
                     57:                         ~VHashAssoc();
                     58: 
                     59:   VHashAssoc&     operator = (VHashAssoc& a);
                     60: 
                     61:   int                   count();
                     62:   int                   empty();
                     63:   int                   full();
                     64:   int                   capacity();
                     65: 
                     66:   void                  clear();
                     67:   void                  resize(int newsize);
                     68: 
                     69:   U&                  operator [] (T& k);
                     70:   int                   contains(T& key);
                     71:   int                   del(T& key);
                     72: 
                     73: 
                     74:   void                  apply(void f(U& v));
                     75:   void                  error(const char* msg);
                     76: };
                     77: 
                     78: template <class T, class U> class VHashAssocTrav
                     79: {
                     80:   VHashAssoc<T,U>*      h;
                     81:   int                   pos;
                     82: 
                     83: 
                     84: public:
                     85:                         VHashAssocTrav(VHashAssoc<T,U>& l);
                     86:                         ~VHashAssocTrav();
                     87:   int                   null();
                     88:   int                   valid();
                     89:                         operator void* ();
                     90:   int                   operator ! ();
                     91:   void                  advance();
                     92:   void                  reset();
                     93:   void                  reset(VHashAssoc<T,U>& l);
                     94:   T&                    key();
                     95:   U&                  get();
                     96: };
                     97: 
                     98: template <class T, class U>  unsigned int VHashAssoc<T,U>::key_hash(T& a)
                     99: {
                    100:   return (*VHashAssoc<T,U>::key_hash_function)(a);
                    101: }
                    102: 
                    103: template <class T, class U>   int VHashAssoc<T,U>::key_key_eq(T&a, T& b)
                    104: {
                    105:   return (*VHashAssoc<T,U>::key_key_equality_function)(a, b);
                    106: }
                    107: 
                    108: 
                    109: template <class T, class U>  VHashAssoc<T,U>::~VHashAssoc()
                    110: {
                    111:   delete [size] tab;
                    112: }
                    113: 
                    114: template <class T, class U>  VHashAssoc<T,U>::count()
                    115: {
                    116:   return cnt;
                    117: }
                    118: 
                    119: template <class T, class U>  VHashAssoc<T,U>::empty()
                    120: {
                    121:   return cnt == 0;
                    122: }
                    123: 
                    124: template <class T, class U>  VHashAssoc<T,U>::full()
                    125: {
                    126:   return cnt == size;
                    127: }
                    128: 
                    129: template <class T, class U>  VHashAssoc<T,U>::capacity()
                    130: {
                    131:   return size;
                    132: }
                    133: 
                    134: template <class T, class U>  VHashAssocTrav<T,U>::VHashAssocTrav(VHashAssoc<T,U>& a)
                    135: {
                    136:   h = &a;
                    137:   reset();
                    138: }
                    139: 
                    140: template <class T, class U>  void VHashAssocTrav<T,U>::reset(VHashAssoc<T,U>& a)
                    141: {
                    142:   h = &a;
                    143:   reset();
                    144: }
                    145: 
                    146: 
                    147: template <class T, class U>  VHashAssocTrav<T,U>::~VHashAssocTrav() {}
                    148: 
                    149: template <class T, class U>  VHashAssocTrav<T,U>::null()
                    150: {
                    151:   return pos < 0;
                    152: }
                    153: 
                    154: template <class T, class U>  VHashAssocTrav<T,U>::valid()
                    155: {
                    156:   return pos >= 0;
                    157: }
                    158: 
                    159: template <class T, class U>   VHashAssocTrav<T,U>::operator void* ()
                    160: {
                    161:   return (pos < 0)? 0 : this;
                    162: }
                    163: 
                    164: template <class T, class U>  VHashAssocTrav<T,U>::operator ! ()
                    165: {
                    166:   return (pos < 0);
                    167: }
                    168: 
                    169: 
                    170: template <class T, class U>  T & VHashAssocTrav<T,U>::key()
                    171: {
                    172:   if (pos < 0)
                    173:     h->error("operation on null traverser");
                    174:   return h->tab[pos].key;
                    175: }
                    176: 
                    177: template <class T, class U> U & VHashAssocTrav<T,U>::get()
                    178: {
                    179:   if (pos < 0)
                    180:     h->error("operation on null traverser");
                    181:   return h->tab[pos].cont;
                    182: }
                    183: 
                    184: enum  {EMPTYCELL, VALIDCELL, DELETEDCELL } ;
                    185: 
                    186: 
                    187: // error handling
                    188: 
                    189: 
                    190: 
                    191: template <class T, class U>void VHashAssoc<T,U>::error(const char* msg)
                    192: {
                    193:    // (*VHashAssoc_error_handler)(msg);
                    194: }
                    195: 
                    196: template <class T, class U>VHashAssoc<T,U>::VHashAssoc(int sz)
                    197: {
                    198:   tab = new VHashAssocNode<T,U>[size = sz];
                    199:   for (int i = 0; i < size; ++i) tab[i].status = EMPTYCELL;
                    200:   cnt = 0;
                    201: }
                    202: 
                    203: template <class T, class U>VHashAssoc<T,U>::VHashAssoc(VHashAssoc<T,U>& a)
                    204: {
                    205:   tab = new VHashAssocNode<T,U>[size = a.size];
                    206:   for (int i = 0; i < size; ++i) tab[i].status = EMPTYCELL;
                    207:   cnt = 0;
                    208:   for (VHashAssocTrav<T,U> p(a); p; p.advance())
                    209:     (*this)[p.key()] = p.get();
                    210: }
                    211: 
                    212: template <class T, class U> VHashAssoc<T,U>& VHashAssoc<T,U>::operator =
                    213: (VHashAssoc<T,U>& a)
                    214: {
                    215:   if (a.tab != tab)
                    216:   {
                    217:     clear();
                    218:     delete [size] tab;
                    219:     tab = new VHashAssocNode<T,U>[size = a.size];
                    220:     for (int i = 0; i < size; ++i) tab[i].status = EMPTYCELL;
                    221:     cnt = 0;
                    222:     for (VHashAssocTrav<T,U> p(a); p; p.advance())
                    223:       (*this)[p.key()] = p.get();
                    224:   }
                    225:   return *this;
                    226: }
                    227: 
                    228: /* 
                    229:  * hashing method: double hash based on high bits of hash fct,
                    230:  * followed by linear probe. Can't do too much better if Assoc
                    231:  * sizes not constrained to be prime.
                    232: */
                    233: 
                    234: 
                    235: static inline doublehashinc(unsigned int h, int s)
                    236: {
                    237:   return ((h / s) % s) >> 1;
                    238: }
                    239: 
                    240: 
                    241: template <class T, class U>U& VHashAssoc<T,U>::operator [](T & key)
                    242: {
                    243:   int bestspot = -1;
                    244:   unsigned int hashval = key_hash(key);
                    245:   int h = hashval % size;
                    246:   for (int i = 0; i <= size; ++i)
                    247:   {
                    248:     if (tab[h].status == EMPTYCELL)
                    249:     {
                    250:       if (bestspot < 0) bestspot = h;
                    251:       tab[bestspot].key = key;
                    252:       tab[bestspot].status = VALIDCELL;
                    253:       ++cnt;
                    254:       return tab[bestspot].cont;
                    255:     }
                    256:     else if (tab[h].status == DELETEDCELL)
                    257:     {
                    258:       if (bestspot < 0) bestspot = h;
                    259:     }
                    260:     else if (key_key_eq(tab[h].key, key))
                    261:       return tab[h].cont;
                    262:     if (i == 0)
                    263:       h = (h + doublehashinc(hashval, size)) % size;
                    264:     else if (++h >= size)
                    265:       h -= size;
                    266:   }
                    267:   error("cannot add to full Assoc table");
                    268:   return tab[0].cont ; // suppress warning message
                    269: }
                    270: 
                    271: 
                    272: template <class T, class U>int VHashAssoc<T,U>::contains(T & key)
                    273: {
                    274:   unsigned int hashval = key_hash(key);
                    275:   int h = hashval % size;
                    276:   for (int i = 0; i <= size; ++i)
                    277:   {
                    278:     if (tab[h].status == EMPTYCELL)
                    279:       return 0;
                    280:     else if (tab[h].status == VALIDCELL && key_key_eq(tab[h].key, key))
                    281:       return 1;
                    282:     if (i == 0)
                    283:       h = (h + doublehashinc(hashval, size)) % size;
                    284:     else if (++h >= size)
                    285:       h -= size;
                    286:   }
                    287:   return 0;
                    288: }
                    289: 
                    290: template <class T, class U>int VHashAssoc<T,U>::del(T & key)
                    291: {
                    292:   unsigned int hashval = key_hash(key);
                    293:   int h = hashval % size;
                    294:   for (int i = 0; i <= size; ++i)
                    295:   {
                    296:     if (tab[h].status == EMPTYCELL)
                    297:       return 0;
                    298:     else if (tab[h].status == VALIDCELL && key_key_eq(tab[h].key, key))
                    299:     {
                    300:       tab[h].status = DELETEDCELL;
                    301:       --cnt;
                    302:       return 1;
                    303:     }
                    304:     if (i == 0)
                    305:       h = (h + doublehashinc(hashval, size)) % size;
                    306:     else if (++h >= size)
                    307:       h -= size;
                    308:   }
                    309:   return 0;
                    310: }
                    311: 
                    312: /*
                    313: template <class T, class U>void VHashAssoc<T,U>::apply(UProcedure f)
                    314: {
                    315:   for (int i = 0; i < size; ++i)
                    316:     if (tab[i].status == VALIDCELL)
                    317:       (*f)(tab[i].cont);
                    318: }
                    319: */
                    320: 
                    321: template <class T, class U>void VHashAssoc<T,U>::clear()
                    322: {
                    323:   for (int i = 0; i < size; ++i)
                    324:     tab[i].status = EMPTYCELL;
                    325:   cnt = 0;
                    326: }
                    327: 
                    328: template <class T, class U>void VHashAssoc<T,U>::resize(int newsize)
                    329: {
                    330:   if (newsize < cnt)
                    331:     error("requested resize too small");
                    332:   VHashAssocNode<T,U>* oldtab = tab;
                    333:   int oldsize = size;
                    334:   tab = new VHashAssocNode<T,U>[size = newsize];
                    335:   for (int i = 0; i < size; ++i) 
                    336:     tab[i].status = EMPTYCELL;
                    337:   cnt = 0;
                    338:   for (i = 0; i < oldsize; ++i)
                    339:     if (oldtab[i].status == VALIDCELL)
                    340:       (*this)[oldtab[i].key] = oldtab[i].cont;
                    341:   delete [oldsize] oldtab;
                    342: }
                    343: 
                    344: template <class T, class U>void VHashAssocTrav<T,U>::reset()
                    345: {
                    346:   for (pos = 0; pos < h->size; ++pos)
                    347:     if (h->tab[pos].status == VALIDCELL)
                    348:       return;
                    349:   pos = -1;
                    350: }
                    351: 
                    352: template <class T, class U>void VHashAssocTrav<T,U>::advance()
                    353: {
                    354:   if (pos < 0)
                    355:     return;
                    356:   for (pos++; pos < h->size; ++pos)
                    357:     if (h->tab[pos].status == VALIDCELL)
                    358:       return;
                    359:   pos = -1;
                    360: }
                    361: 
                    362:   
                    363: const int size = 100 ;
                    364: 
                    365: 
                    366: unsigned int f(int & i) { return i ; }
                    367: 
                    368: unsigned int f1(char & i) { return (int)i ; }
                    369: 
                    370: int  g(int& k1, int& k2){
                    371:   return (k1 == k2) ;
                    372: }
                    373: 
                    374: int  g1(char & k1, char & k2){
                    375:   return (k1 == k2) ;
                    376: }
                    377: 
                    378: 
                    379: 
                    380: 
                    381: VHashAssoc<int, int> foo(2*size) ;
                    382: 
                    383:   
                    384: main () {
                    385: 
                    386: 
                    387:   start_test(__FILE__) ;
                    388: 
                    389:   foo.key_hash_function = f ;
                    390:   foo.key_key_equality_function= g ;
                    391:   // populate the hash
                    392:   for (int i = 0 ; ! foo.full() ; i++)
                    393:     foo[i] = i ;
                    394: 
                    395:   for (i = 0 ; i < size ; i++) {
                    396:     check(foo.contains(i)) ;
                    397:     check(foo[i] == i) ;
                    398:   }
                    399: 
                    400:   foo.resize(size * 4) ;
                    401:   
                    402: // repeat the tests, resizing should not have impacted it any
                    403:   for (i = 0 ; i < size ; i++) {
                    404:     check(foo.contains(i)) ;
                    405:     check(foo[i] == i) ;
                    406:     check (foo.del(i)) ;
                    407:     check(!foo.contains(i)) ;
                    408:   }
                    409:   {
                    410:   // try another one
                    411:   VHashAssoc<char, char *> foo(2*size) ;
                    412:   foo.key_hash_function = f1 ;
                    413:   foo.key_key_equality_function= g1 ;
                    414:   // populate the hash
                    415:   for (char i = 0 ; ! foo.full() ; i++) {
                    416:     char *p = new char ;
                    417:     *p = i ;
                    418:     foo[i] = p  ;
                    419:   }
                    420: 
                    421:   for (i = 0 ; i < size ; i++) {
                    422:     check(foo.contains(i)) ;
                    423:     check(*(foo[i]) == i) ;
                    424:   }
                    425: 
                    426:   foo.resize(size * 4) ;
                    427:   
                    428: // repeat the tests, resizing should not have impacted it any
                    429:   for (i = 0 ; i < size ; i++) {
                    430:     check(foo.contains(i)) ;
                    431:     check(*(foo[i]) == i) ;
                    432:     check (foo.del(i)) ;
                    433:     check(!foo.contains(i)) ;
                    434:   }
                    435: }
                    436: 
                    437:   end_test() ;
                    438: 
                    439: }
                    440:   

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.