struct Hashfn1 { Ranhash hasher; Int n; Hashfn1(Int nn) : n(nn) {} Ullong fn(const void *key) { Uint *k; Ullong *kk; switch (n) { case 4: k = (Uint *)key; return hasher.int64(*k); case 8: kk = (Ullong *)key; return hasher.int64(*kk); default: throw("Hashfn1 is for 4 or 8 byte keys only."); } } }; struct Hashfn2 { static Ullong hashfn_tab[256]; Ullong h; Int n; Hashfn2(Int nn) : n(nn) { if (n == 1) n = 0; h = 0x544B2FBACAAF1684LL; for (Int j=0; j<256; j++) { for (Int i=0; i<31; i++) { h = (h >> 7) ^ h; h = (h << 11) ^ h; h = (h >> 10) ^ h; } hashfn_tab[j] = h; } } Ullong fn(const void *key) { Int j; char *k = (char *)key; h=0xBB40E64DA205B064LL; j=0; while (n ? j++ < n : *k) { h = (h * 7664345821815920749LL) ^ hashfn_tab[(unsigned char)(*k)]; k++; } return h; } }; Ullong Hashfn2::hashfn_tab[256]; template struct Hashtable { Int nhash, nmax, nn, ng; VecInt htable, next, garbg; VecUllong thehash; hfnT hash; Hashtable(Int nh, Int nm); Int iget(const keyT &key); Int iset(const keyT &key); Int ierase(const keyT &key); Int ireserve(); Int irelinquish(Int k); }; template Hashtable::Hashtable(Int nh, Int nm): hash(sizeof(keyT)), nhash(nh), nmax(nm), nn(0), ng(0), htable(nh), next(nm), garbg(nm), thehash(nm) { for (Int j=0; j Int Hashtable::iget(const keyT &key) { Int j,k; Ullong pp = hash.fn(&key); j = (Int)(pp % nhash); for (k = htable[j]; k != -1; k = next[k]) { if (thehash[k] == pp) { return k; } } return -1; } template Int Hashtable::iset(const keyT &key) { Int j,k,kprev; Ullong pp = hash.fn(&key); j = (Int)(pp % nhash); if (htable[j] == -1) { k = ng ? garbg[--ng] : nn++ ; htable[j] = k; } else { for (k = htable[j]; k != -1; k = next[k]) { if (thehash[k] == pp) { return k; } kprev = k; } k = ng ? garbg[--ng] : nn++ ; next[kprev] = k; } if (k >= nmax) throw("storing too many values"); thehash[k] = pp; next[k] = -1; return k; } template Int Hashtable::ierase(const keyT &key) { Int j,k,kprev; Ullong pp = hash.fn(&key); j = (Int)(pp % nhash); if (htable[j] == -1) return -1; kprev = -1; for (k = htable[j]; k != -1; k = next[k]) { if (thehash[k] == pp) { if (kprev == -1) htable[j] = next[k]; else next[kprev] = next[k]; garbg[ng++] = k; return k; } kprev = k; } return -1; } template Int Hashtable::ireserve() { Int k = ng ? garbg[--ng] : nn++ ; if (k >= nmax) throw("reserving too many values"); next[k] = -2; return k; } template Int Hashtable::irelinquish(Int k) { if (next[k] != -2) {return -1;} garbg[ng++] = k; return k; } template struct Hash : Hashtable { using Hashtable::iget; using Hashtable::iset; using Hashtable::ierase; vector els; Hash(Int nh, Int nm) : Hashtable(nh, nm), els(nm) {} void set(const keyT &key, const elT &el) {els[iset(key)] = el;} Int get(const keyT &key, elT &el) { Int ll = iget(key); if (ll < 0) return 0; el = els[ll]; return 1; } elT& operator[] (const keyT &key) { Int ll = iget(key); if (ll < 0) { ll = iset(key); els[ll] = elT(); } return els[ll]; } Int count(const keyT &key) { Int ll = iget(key); return (ll < 0 ? 0 : 1); } Int erase(const keyT &key) { return (ierase(key) < 0 ? 0 : 1); } }; template struct Mhash : Hashtable { using Hashtable::iget; using Hashtable::iset; using Hashtable::ierase; using Hashtable::ireserve; using Hashtable::irelinquish; vector els; VecInt nextsis; Int nextget; Mhash(Int nh, Int nm); Int store(const keyT &key, const elT &el); Int erase(const keyT &key, const elT &el); Int count(const keyT &key); Int getinit(const keyT &key); Int getnext(elT &el); }; template Mhash::Mhash(Int nh, Int nm) : Hashtable(nh, nm), nextget(-1), els(nm), nextsis(nm) { for (Int j=0; j Int Mhash::store(const keyT &key, const elT &el) { Int j,k; j = iset(key); if (nextsis[j] == -2) { els[j] = el; nextsis[j] = -1; return j; } else { while (nextsis[j] != -1) {j = nextsis[j];} k = ireserve(); els[k] = el; nextsis[j] = k; nextsis[k] = -1; return k; } } template Int Mhash::erase(const keyT &key, const elT &el) { Int j = -1,kp = -1,kpp = -1; Int k = iget(key); while (k >= 0) { if (j < 0 && el == els[k]) j = k; kpp = kp; kp = k; k=nextsis[k]; } if (j < 0) return 0; if (kpp < 0) { ierase(key); nextsis[j] = -2; } else { if (j != kp) els[j] = els[kp]; nextsis[kpp] = -1; irelinquish(kp); nextsis[kp] = -2; } return 1; } template Int Mhash::count(const keyT &key) { Int next, n = 1; if ((next = iget(key)) < 0) return 0; while ((next = nextsis[next]) >= 0) {n++;} return n; } template Int Mhash::getinit(const keyT &key) { nextget = iget(key); return ((nextget < 0)? 0 : 1); } template Int Mhash::getnext(elT &el) { if (nextget < 0) {return 0;} el = els[nextget]; nextget = nextsis[nextget]; return 1; }