inline int& HashBase::Maph(unsigned _hash) const { unsigned h = _hash & ~UNSIGNED_HIBIT; #ifdef FOLDHASH return map[mask & (h - SwapEndian32((dword)h))]; // return map[(mcount - 1) & (((h >> 23) - (h >> 15) - (h >> 7) - h))]; #else return map[h % mcount]; #endif } inline int& HashBase::Mapi(int i) const { return Maph(hash[i]); } inline void HashBase::LinkTo(int i, Link& l, int& m) { if(m >= 0) { Link& bl = link[m]; l.next = m; l.prev = bl.prev; bl.prev = i; link[l.prev].next = i; } else m = l.prev = l.next = i; } inline void HashBase::Add(unsigned _hash) { ASSERT(hash.GetCount() == link.GetCount()); int i = hash.GetCount(); hash.Add(_hash & ~UNSIGNED_HIBIT); if(hash.GetCount() <= mask) LinkTo(i, link.Add(), Maph(_hash)); else Reindex(); } inline void HashBase::Unlink(int i, Link& l, int& m) { if(i == m) { if(l.next == i) { m = -1; return; } m = l.next; } link[l.next].prev = l.prev; link[l.prev].next = l.next; } inline void HashBase::Unlink(int i, Link& l) { Unlink(i, l, hash[i] & UNSIGNED_HIBIT ? unlinked : Mapi(i)); } inline int HashBase::Find(unsigned _hash) const { return Maph(_hash); } inline int HashBase::FindNext(int i) const { int q = link[i].next; return q == Mapi(i) ? -1 : q; } inline int HashBase::FindLast(unsigned _hash) const { if(hash.GetCount() == 0) return - 1; int i = Find(_hash & ~UNSIGNED_HIBIT); return i >= 0 ? link[i].prev : -1; } inline int HashBase::FindPrev(int i) const { int q = link[i].prev; return q == link[Mapi(i)].prev ? -1 : q; } inline void HashBase::Unlink(int i) { ASSERT(!IsUnlinked(i)); hash[i] |= UNSIGNED_HIBIT; if(i < link.GetCount()) { Link& lnk = link[i]; Unlink(i, lnk, Mapi(i)); LinkTo(i, lnk, unlinked); } } template void Index::Hash() { hash.Clear(); for(int i = 0; i < key.GetCount(); i++) hash.Add(hashfn(key[i])); } template T& Index::Add(const T& x, unsigned _hash) { T& t = key.Add(x); hash.Add(_hash); return t; } template T& Index::Add(const T& x) { return Add(x, hashfn(x)); } template int Index::FindAdd(const T& _key, unsigned _hash) { int i = Find(_key, _hash); if(i >= 0) return i; i = key.GetCount(); Add(_key, _hash); return i; } template int Index::Put(const T& x, unsigned _hash) { int q = hash.Put(_hash); if(q < 0) { q = key.GetCount(); Add(x, _hash); } else key[q] = x; return q; } template int Index::Put(const T& x) { return Put(x, hashfn(x)); } template int Index::FindPut(const T& _key, unsigned _hash) { int i = Find(_key, _hash); if(i >= 0) return i; return Put(_key, _hash); } template int Index::FindPut(const T& key) { return FindPut(key, hashfn(key)); } template inline int Index::Find(const T& x, unsigned hash_) const { int i0 = hash.Find(hash_); if(i0 >= 0) { int i = i0; do { if(x == key[i]) return i; i = hash.GetNext(i); } while(i0 != i); } return -1; } template int Index::Find(const T& x) const { return Find(x, hashfn(x)); } template int Index::FindNext(int i) const { return Find0(key[i], hash.FindNext(i)); } template inline int Index::FindLast(const T& x, unsigned _hash) const { return FindB(x, hash.FindLast(_hash)); } template int Index::FindLast(const T& x) const { return FindLast(x, hashfn(x)); } template int Index::FindPrev(int i) const { return FindB(key[i], hash.FindPrev(i)); } template int Index::FindAdd(const T& key) { return FindAdd(key, hashfn(key)); } template T& Index::Set(int i, const T& x, unsigned _hash) { T& t = key[i]; t = x; hash.Set(i, _hash); return t; } template T& Index::Set(int i, const T& x) { return Set(i, x, hashfn(x)); } #ifdef UPP template void Index::Serialize(Stream& s) { if(s.IsLoading()) ClearIndex(); key.Serialize(s); hash.Serialize(s); } template void Index::Xmlize(XmlIO& xio, const char *itemtag) { XmlizeIndex >(xio, itemtag, *this); } template void Index::Jsonize(JsonIO& jio) { JsonizeIndex, T>(jio, *this); } template String Index::ToString() const { return AsStringArray(*this); } #endif template int Index::UnlinkKey(const T& k, unsigned h) { int n = 0; int q = hash.Find(h); while(q >= 0) { int w = q; q = hash.FindNext(q); if(k == key[w]) { hash.Unlink(w); n++; } } return n; } template int Index::UnlinkKey(const T& k) { return UnlinkKey(k, hashfn(k)); } template void Index::Sweep() { Vector b = hash.GetUnlinked(); Sort(b); Remove(b); } template T& Index::Insert(int i, const T& k, unsigned h) { key.Insert(i, k); hash.Insert(i, h); return key[i]; } template T& Index::Insert(int i, const T& k) { key.Insert(i, k); hash.Insert(i, hashfn(k)); return key[i]; } template void Index::Remove(int i) { key.Remove(i); hash.Remove(i); } template void Index::Remove(int i, int count) { key.Remove(i, count); hash.Remove(i, count); } template void Index::Remove(const int *sorted_list, int count) { key.Remove(sorted_list, count); hash.Remove(sorted_list, count); } template void Index::Remove(const Vector& sl) { Remove(sl, sl.GetCount()); } template int Index::RemoveKey(const T& k, unsigned h) { Vector rk; int q = Find(k, h); while(q >= 0) { rk.Add(q); q = FindNext(q); } Remove(rk); return rk.GetCount(); } template int Index::RemoveKey(const T& k) { return RemoveKey(k, hashfn(k)); } // ------------------ /* template T& ArrayIndex::Add(T *newt, unsigned _hash) { B::hash.Add(_hash); return B::key.Add(newt); } template T& ArrayIndex::Add(T *newt) { return Add(newt, B::hashfn(*newt)); } template T& ArrayIndex::Set(int i, T *newt, unsigned _hash) { T& t = B::key.Set(i, newt); B::hash.Set(i, _hash); return t; } template T& ArrayIndex::Set(int i, T *newt) { return Set(i, newt, B::hashfn(*newt)); } */ // -------------------- template int AMap::FindAdd(const K& k) { unsigned hash = key.hashfn(k); int i = Find(k, hash); if(i < 0) { i = GetCount(); key.Add(k, hash); value.Add(); } return i; } template int AMap::FindAdd(const K& k, const T& x) { unsigned hash = key.hashfn(k); int i = Find(k, hash); if(i < 0) { i = GetCount(); key.Add(k, hash); value.Add(x); } return i; } template int AMap::FindAdd(const K& k, T&& x) { unsigned hash = key.hashfn(k); int i = Find(k, hash); if(i < 0) { i = GetCount(); key.Add(k, hash); value.Add(pick(x)); } return i; } template int AMap::Put(const K& k, const T& x) { int i = key.Put(k); if(i < value.GetCount()) value[i] = x; else { ASSERT(i == value.GetCount()); value.Add(x); } return i; } template int AMap::PutDefault(const K& k) { int i = key.Put(k); if(i >= value.GetCount()) { ASSERT(i == value.GetCount()); value.Add(); } else { Destroy(&value[i], &value[i] + 1); Construct(&value[i], &value[i] + 1); } return i; } template int AMap::Put(const K& k, T&& x) { int i = key.Put(k); if(i < value.GetCount()) value[i] = pick(x); else { ASSERT(i == value.GetCount()); value.Add(pick(x)); } return i; } template T& AMap::Put(const K& k) { int i = key.Put(k); if(i < value.GetCount()) { Destroy(&value[i], &value[i] + 1); Construct(&value[i], &value[i] + 1); return value[i]; } else { ASSERT(i == value.GetCount()); return value.Add(); } } template int AMap::FindPut(const K& k) { unsigned hash = key.hashfn(k); int i = Find(k, hash); return i < 0 ? PutDefault(k) : i; } template int AMap::FindPut(const K& k, const T& init) { unsigned hash = key.hashfn(k); int i = Find(k, hash); if(i < 0) { i = key.Put(k, hash); if(i >= value.GetCount()) { ASSERT(i == value.GetCount()); i = value.GetCount(); value.Add(init); } else value[i] = init; } return i; } template int AMap::FindPut(const K& k, T&& init) { unsigned hash = key.hashfn(k); int i = Find(k, hash); if(i < 0) { i = key.Put(k, hash); value.At(i) = pick(init); } return i; } template T& AMap::GetAdd(const K& k) { unsigned hash = key.hashfn(k); int i = key.Find(k, hash); if(i >= 0) return value[i]; key.Add(k, hash); return value.Add(); } template T& AMap::GetAdd(const K& k, const T& x) { unsigned hash = key.hashfn(k); int i = Find(k, hash); if(i >= 0) return value[i]; key.Add(k, hash); value.Add(x); return value.Top(); } template T& AMap::GetAdd(const K& k, T&& x) { unsigned hash = key.hashfn(k); int i = Find(k, hash); if(i >= 0) return value[i]; key.Add(k, hash); value.Add(pick(x)); return value.Top(); } template T& AMap::GetPut(const K& k) { return value[FindPut(k)]; } template T& AMap::GetPut(const K& k, const T& x) { return value[FindPut(k, x)]; } template T& AMap::GetPut(const K& k, T&& x) { return value[FindPut(k, pick(x))]; } #ifdef UPP template void AMap::Serialize(Stream& s) { int version = 0; s / version % key % value; } template void AMap::Xmlize(XmlIO& xio) { XmlizeMap >(xio, "key", "value", *this); } template void AMap::Jsonize(JsonIO& jio) { JsonizeMap, K, T>(jio, *this, "key", "value"); } template String AMap::ToString() const { String r; r = "{"; for(int i = 0; i < GetCount(); i++) { if(i) r << ", "; if(IsUnlinked(i)) r << "UNLINKED "; r << GetKey(i) << ": " << (*this)[i]; } r << '}'; return r; } #endif template int AMap::RemoveKey(const K& k) { Vector rk; int q = Find(k); while(q >= 0) { rk.Add(q); q = FindNext(q); } Remove(rk); return rk.GetCount(); } template void AMap::Sweep() { Vector b = key.GetUnlinked(); Sort(b); key.Remove(b); value.Remove(b); } #ifdef UPP template void FixedAMap::Serialize(Stream& s) { s % key % value; } template void FixedAMap::Xmlize(XmlIO& xio) { XmlizeSortedMap >(xio, "key", "value", *this); } template void FixedAMap::Jsonize(JsonIO& jio) { JsonizeSortedMap, K, T>(jio, *this, "key", "value"); } template String FixedAMap::ToString() const { String r; r = "{"; for(int i = 0; i < GetCount(); i++) { if(i) r << ", "; r << GetKey(i) << ": " << (*this)[i]; } r << '}'; return r; } #endif