#include namespace Upp { #ifdef _MSC_VER #pragma inline_depth(255) #pragma optimize("t", on) #endif unsigned Pow2Bound(unsigned i) { unsigned n = 1; while(n < i) { n <<= 1; if(n == 0) return 1 << 31; } return n; } unsigned PrimeBound(unsigned n) { static unsigned prime_tab[] = { 17, 29, 61, 127, 257, 509, 1021, 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617, 16777213, 33554467, 67108859, 134217757, 268435459, 536870909, 1073741827, 2147483647u, 4294967291u }; #ifdef DEPRECATED return *FindUpperBoundIter(prime_tab, prime_tab + __countof(prime_tab), n); #else return prime_tab[FindUpperBound(SubRange(prime_tab, prime_tab + __countof(prime_tab)), n)]; #endif } #ifdef FOLDHASH inline unsigned HashBound(unsigned i) { return Pow2Bound(i); } #else inline unsigned HashBound(unsigned i) { return PrimeBound(i); } #endif static int _EmptyHashBase = -1; inline void HashBase::Zero() { map = &_EmptyHashBase; mask = 0; unlinked = -1; } void HashBase::Free() { if(map != &_EmptyHashBase) delete [](byte *)map; Zero(); } void HashBase::ClearIndex() { link.Clear(); Free(); } HashBase::HashBase() { Zero(); } HashBase::HashBase(HashBase&& b) : hash(pick(b.hash)), link(pick(b.link)) { map = b.map; mask = b.mask; unlinked = b.unlinked; b.Zero(); } void HashBase::operator=(HashBase&& b) { hash = pick(b.hash); link = pick(b.link); Free(); map = b.map; mask = b.mask; unlinked = b.unlinked; b.Zero(); } HashBase::HashBase(const HashBase& b, int) : hash(b.hash, 0) { Zero(); Reindex(); } void HashBase::operator<<=(const HashBase& b) { ClearIndex(); hash = clone(b.hash); Reindex(); } HashBase::~HashBase() { Free(); } force_inline void HashBase::LinkBefore(int i, Link& l, int bi) { Link& bl = link[bi]; l.next = bi; l.prev = bl.prev; bl.prev = i; link[l.prev].next = i; } void HashBase::Trim(int count) { ASSERT(count <= hash.GetCount() && count >= 0); for(int i = count; i < link.GetCount(); i++) Unlink(i, link[i]); link.Trim(count); hash.SetCount(count); } void HashBase::Drop(int n) { Trim(hash.GetCount() - n); } void HashBase::FinishIndex() { int q = link.GetCount(); link.Reserve(hash.GetAlloc()); link.AddN(hash.GetCount() - q); for(int i = q; i < hash.GetCount(); i++) LinkTo(i, link[i], hash[i] & UNSIGNED_HIBIT ? unlinked : Mapi(i)); } void HashBase::Reindex(int n) { ClearIndex(); Free(); n = HashBound(n); mask = n - 1; map = (int *)new byte[n * sizeof(int)]; Fill(map, map + n, -1); FinishIndex(); } void HashBase::Reindex() { Reindex(hash.GetCount()); } void HashBase::SetUn(int i, unsigned _hash) { if(map) { Link& lnk = link[i]; Unlink(i, lnk); LinkTo(i, lnk, Maph(_hash & ~UNSIGNED_HIBIT)); } hash[i] = _hash & ~UNSIGNED_HIBIT; } Vector HashBase::GetUnlinked() const { Vector r; int q = unlinked; if(q >= 0) { do { r.Add(q); q = link[q].next; } while(q != unlinked); } return r; } int HashBase::Put(unsigned _hash) { if(unlinked < 0) return -1; Link& l = link[unlinked]; int i = unlinked; unlinked = link[unlinked].next; if(i == unlinked) unlinked = -1; else { link[l.next].prev = l.prev; link[l.prev].next = l.next; } LinkTo(i, l, Maph(_hash & ~UNSIGNED_HIBIT)); hash[i] = _hash & ~UNSIGNED_HIBIT; return i; } void HashBase::Set(int i, unsigned _hash) { if(map) { Link& lnk = link[i]; Unlink(i, lnk); int& mi = Maph(_hash & ~UNSIGNED_HIBIT); int ii = mi; if(ii < 0) mi = lnk.prev = lnk.next = i; else if(i < ii) { LinkBefore(i, lnk, ii); mi = i; } else { int l = ii; int h = link[ii].prev; if(h - i < i - l) { while(i < h) { h = link[h].prev; } LinkBefore(i, lnk, link[h].next); } else { l = link[l].next; while(i > l && l != ii) { l = link[l].next; } LinkBefore(i, lnk, l); } } } hash[i] = _hash & ~UNSIGNED_HIBIT; } void HashBase::Shrink() { hash.Shrink(); if((int)HashBound(hash.GetCount()) <= mask) { Reindex(hash.GetCount()); } else link.Shrink(); } void HashBase::Reserve(int n) { hash.Reserve(n); link.Reserve(n); if((int)HashBound(n) > mask) Reindex(n); } void HashBase::Remove(int i) { hash.Remove(i); ClearIndex(); Reindex(); } void HashBase::Remove(int i, int count) { hash.Remove(i, count); ClearIndex(); Reindex(); } void HashBase::Remove(const int *sorted_list, int count) { hash.Remove(sorted_list, count); ClearIndex(); Reindex(); } void HashBase::Insert(int i, unsigned _hash) { hash.Insert(i, _hash & ~UNSIGNED_HIBIT); ClearIndex(); Reindex(); } #ifdef UPP void HashBase::Serialize(Stream& s) { int version = 0; s / version; if(s.IsLoading()) ClearIndex(); hash.Serialize(s); Reindex(); } #endif void HashBase::Swap(HashBase& b) { UPP::Swap(hash, b.hash); UPP::Swap(link, b.link); UPP::Swap(map, b.map); UPP::Swap(mask, b.mask); UPP::Swap(unlinked, b.unlinked); } #ifdef CPU_X86 unsigned memhash(const void *ptr, size_t count) { unsigned hash = 1234567890U; const unsigned *ds = (unsigned *)ptr; const unsigned *de = ds + (count >> 2); while(ds < de) hash = ((hash << 5) - hash) ^ *ds++; const byte *s = (byte *)ds; const byte *e = s + (count & 3); while(s < e) hash = ((hash << 5) - hash) ^ *s++; return hash; } #else unsigned memhash(const void *ptr, size_t count) { unsigned hash = 1234567890U; const byte *s = (byte *)ptr; const byte *e = s + count; while(s < e) hash = ((hash << 5) - hash) ^ *s++; return hash; } #endif unsigned GetHashValue0(const double& d) { return memhash(&d, sizeof(double)); } }