#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 }; return *FindUpperBoundIter(prime_tab, prime_tab + __countof(prime_tab), n); } #ifdef FOLDHASH inline unsigned HashBound(unsigned i) { return Pow2Bound(i); } #else inline unsigned HashBound(unsigned i) { return PrimeBound(i); } #endif void HashBase::Free() { if(map) delete [](byte *)map; map = NULL; mcount = 0; } void HashBase::ClearIndex() { link.Clear(); unlinked = -1; Free(); } HashBase::HashBase() { unlinked = -1; map = NULL; mcount = 0; } HashBase::HashBase(pick_ HashBase& b) : hash(b.hash), link(b.link) { map = b.map; mcount = b.mcount; unlinked = b.unlinked; const_cast(b).map = NULL; } void HashBase::operator=(pick_ HashBase& b) { hash = b.hash; link = b.link; Free(); map = b.map; mcount = b.mcount; unlinked = b.unlinked; const_cast(b).map = NULL; } HashBase::HashBase(const HashBase& b, int) : hash(b.hash, 0) { unlinked = -1; mcount = 0; map = NULL; Reindex(); } void HashBase::operator<<=(const HashBase& b) { ClearIndex(); hash <<= 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(); mcount = n = HashBound(n); map = (int *)new byte[n * sizeof(int)]; Fill(map, map + n, -1); FinishIndex(); } void HashBase::Reindex() { Reindex(hash.GetCount()); } void HashBase::Add(unsigned _hash) { hash.Add(_hash & ~UNSIGNED_HIBIT); DoIndex(); } 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()) < mcount) { ClearIndex(); DoIndex(); } else link.Shrink(); } void HashBase::Reserve(int n) { hash.Reserve(n); link.Reserve(n); if((int)HashBound(n) > mcount) 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(mcount, b.mcount); 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)); } void Bits::Clear() { if(bp && alloc >= 0) delete[] bp; alloc = 0; bp = NULL; } void Bits::Set(int i, bool b) { ASSERT(i >= 0 && alloc >= 0); int q = i >> 5; if(q >= alloc) { int nalloc = 2 * q + 1; dword *nbp = new dword[nalloc]; if(bp) { Copy(nbp, bp, bp + alloc); delete[] bp; } Fill(nbp + alloc, nbp + nalloc, (dword)0); bp = nbp; alloc = nalloc; } i &= 31; ASSERT(q < alloc); bp[q] = (bp[q] & ~(1 << i)) | (b << i); } void Bits::Set(int i, bool b, int count) { //! Optimize !!! while(count--) Set(i++, b); } END_UPP_NAMESPACE