#ifndef shash_h #define shash_h ///////////////////////////////////////////////// // Hash-List-File //J: saves and loads hash tables into files and allows fast // iteration over the saved hash table file template > class TKeyDatFl { private: TInt ElemCnt; TFIn FIn; TKey Key; TDat Dat; public: TKeyDatFl(const TStr& FNm) : FIn(FNm) { ElemCnt.Load(FIn); } int Len() const { return ElemCnt; } bool Next() { if (FIn.Eof()) { return false; } Key.Load(FIn); Dat.Load(FIn); return true; } const TKey& GetKey() const { return Key; } TKey& GetKey() { return Key; } const TDat& GetDat() const { return Dat; } TDat& GetDat() { return Dat; } static void Save(const TStr& OutFNm, const THash& Hash) { TFOut FOut(OutFNm); Load(FOut, Hash); } static void Save(TSOut& SOut, const THash& Hash) { SOut.Save(Hash.Len()); for (int k = Hash.FFirstKeyId(); Hash.FNextKeyId(k); ) { Hash.GetKey(k).Save(SOut); Hash[k].Save(SOut); } } static void LoadHash(const TStr& InFNm, THash& Hash, const int& LoadN=-1) { TFIn FIn(InFNm); Load(FIn, Hash, LoadN); } static void LoadHash(TSIn& SIn, THash& Hash, int LoadN=-1) { TInt ElemCnt(SIn); const int Start=clock(); if (ElemCnt < LoadN || LoadN == -1) { LoadN = ElemCnt; } printf("Loading %s: %d elements ... ", SIn.GetSNm().CStr(), LoadN); Hash.Gen(LoadN); for (int i = 0; i < LoadN; i++) { Hash.AddDat(TKey(SIn)).Load(SIn); } printf(" [%ds]\n", int((clock()-Start)/CLOCKS_PER_SEC)); } static void LoadKeyV(TSIn& SIn, TVec& KeyV, int LoadN=-1) { TInt ElemCnt(SIn); const int Start=clock(); if (ElemCnt < LoadN || LoadN == -1) { LoadN = ElemCnt; } printf("Loading %s: %d elements ... ", SIn.GetSNm().CStr(), LoadN); KeyV.Gen(LoadN, 0); for (int i = 0; i < LoadN; i++) { KeyV.Add(TKey(SIn)); TDat D(SIn); } printf(" [%ds]\n", int((clock()-Start)/CLOCKS_PER_SEC)); } static void LoadDatV(TSIn& SIn, TVec& DatV, int LoadN=-1) { TInt ElemCnt(SIn); const int Start=clock(); if (ElemCnt < LoadN || LoadN == -1) { LoadN = ElemCnt; } printf("Loading %s: %d elements ... ", SIn.GetSNm().CStr(), LoadN); DatV.Gen(LoadN, 0); for (int i = 0; i < LoadN; i++) { TKey(SIn); DatV.Add(TDat(SIn)); } printf(" [%ds]\n", int((clock()-Start)/CLOCKS_PER_SEC)); } }; ///////////////////////////////////////////////// // Sparse Table Group template // GroupSize=48; == 32*x+16 class TSparseGroup { private: unsigned char BitSet [(GroupSize-1)/8 + 1]; // fancy math is so we round up uint16 Buckets; // limits GroupSize to 64K TVal *Group; private: static int CharBit(const int& ValN) { return ValN >> 3; } static int ModBit(const int& ValN) { return 1 << (ValN&7); } bool BMTest(const int& ValN) const { return (BitSet[CharBit(ValN)] & ModBit(ValN)) != 0; } void BMSet(const int& ValN) { BitSet[CharBit(ValN)] |= ModBit(ValN); } void BMClear(const int& ValN) { BitSet[CharBit(ValN)] &= ~ModBit(ValN); } static int PosToOffset(const unsigned char *BitSet, int Pos); public: TSparseGroup() : Buckets(0), Group(NULL) { memset(BitSet, 0, sizeof(BitSet)); } TSparseGroup(TSIn& SIn) : Buckets(0), Group(NULL) { Load(SIn); } TSparseGroup(const TSparseGroup& SG); ~TSparseGroup() { if (Group != NULL) delete [] Group; } void Load(TSIn& SIn); void Save(TSOut& SOut) const; TSparseGroup& operator = (const TSparseGroup& SG); bool operator == (const TSparseGroup& SG) const; bool operator < (const TSparseGroup& SG) const; int Len() const { return Buckets; } int MxLen() const { return GroupSize; } int Reserved() const { return GroupSize; } bool Empty() const { return Buckets == 0; } void Clr(const bool& DoDel = true); int GetGroupSize() const { return GroupSize; } uint GetDiskSz() const { return sizeof(BitSet) + sizeof(uint16) + Buckets*sizeof(TVal); } bool IsEmpty(const int& ValN) const { return ! BMTest(ValN); } const TVal& Offset(const int& Pos) const { return Group[Pos]; } TVal& Offset(const int& Pos) { return Group[Pos]; } int OffsetToPos(int Offset) const; int PosToOffset(int Pos) const { return PosToOffset(BitSet, Pos); } const TVal& DefVal() const { static TVal DefValue = TVal(); return DefValue; } const TVal& Get(const int& ValN) const { if (BMTest(ValN)) return Group[PosToOffset(BitSet, ValN)]; else return DefVal(); } const TVal& operator [] (const int ValN) const { return Get(ValN); } TVal& Set(const int& ValN, const TVal& Val); TVal& Set(const int& ValN) { if (! BMTest(ValN)) Set(ValN, DefVal()); return Group[PosToOffset(BitSet, ValN)]; } void Del(const int& ValN); }; template int TSparseGroup::PosToOffset(const unsigned char *BitSet, int Pos) { static const int bits_in [256] = { // # of bits set in one char 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, }; // [Note: condition pos > 8 is an optimization; convince yourself we // give exactly the same result as if we had pos >= 8 here instead.] int Offset = 0; for ( ; Pos > 8; Pos -= 8 ) // bm[0..pos/8-1] Offset += bits_in[*BitSet++]; // chars we want *all* bits in return Offset + bits_in[*BitSet & ((1 << Pos)-1)]; // the char that includes pos } template TSparseGroup::TSparseGroup(const TSparseGroup& SG) : Buckets(SG.Buckets), Group(NULL) { memcpy(BitSet, SG.BitSet, sizeof(BitSet)); if (Buckets > 0) { Group = new TVal [Buckets]; for (int b = 0; b < Buckets; b++) { Group[b] = SG.Group[b]; } } } template void TSparseGroup::Load(TSIn& SIn) { SIn.LoadBf(BitSet, sizeof(BitSet)); SIn.Load(Buckets); if (Group != NULL) delete [] Group; Group = new TVal [Buckets]; for (int b = 0; b < Buckets; b++) { Group[b] = TVal(SIn); } } template void TSparseGroup::Save(TSOut& SOut) const { SOut.SaveBf(BitSet, sizeof(BitSet)); SOut.Save(Buckets); for (int b = 0; b < Buckets; b++) { Group[b].Save(SOut); } } template TSparseGroup& TSparseGroup::operator = (const TSparseGroup& SG) { if (this != &SG) { if (SG.Buckets == 0 && Group != NULL) { delete [] Group; Group = 0; } else { if (Buckets != SG.Buckets) { if (Group != NULL) delete [] Group; Group = new TVal [SG.Buckets]; } for (int b = 0; b < SG.Buckets; b++) { Group[b] = SG.Group[b]; } } Buckets = SG.Buckets; memcpy(BitSet, SG.BitSet, sizeof(BitSet)); } return *this; } template bool TSparseGroup::operator == (const TSparseGroup& SG) const { if (Buckets == SG.Buckets && memcmp(BitSet, SG.BitSet, sizeof(BitSet)) == 0) { for (int b = 0; b < Buckets; b++) { if (Group[b] != SG.Group[b]) return false; } return true; } return false; } template bool TSparseGroup::operator < (const TSparseGroup& SG) const { if (Buckets < SG.Buckets) return true; if (memcmp(BitSet, SG.BitSet, sizeof(BitSet)) == -1) return true; for (int b = 0; b < Buckets; b++) { if (Group[b] < SG.Group[b]) return true; } return false; } template int TSparseGroup::OffsetToPos(int Offset) const { Assert(Offset < Buckets); for (int i = 0; i < sizeof(BitSet); i++) { for (int b = 0; b < 8; b++) { if (TB1Def::GetBit(b, BitSet[i])) { if (Offset == 0) return i*8 + b; Offset--; } } } Fail; return -1; } template void TSparseGroup::Clr(const bool& DoDel) { if (DoDel && Group != NULL) { delete [] Group; Group = 0; } memset(BitSet, 0, sizeof(BitSet)); Buckets = 0; } template TVal& TSparseGroup::Set(const int& ValN, const TVal& Val) { const int Offset = PosToOffset(BitSet, ValN); if (! BMTest(ValN)) { const TVal *OldGroup = Group; Group = new TVal [Buckets+1]; for (int b = 0; b < Offset; b++) Group[b] = OldGroup[b]; for (int b = Offset+1; b <= Buckets; b++) Group[b] = OldGroup[b-1]; if (OldGroup != NULL) delete [] OldGroup; Buckets++; BMSet(ValN); } Group[Offset] = Val; return Group[Offset]; } template void TSparseGroup::Del(const int& ValN) { if (BMTest(ValN)) { const int Offset = PosToOffset(BitSet, ValN); if (--Buckets == 0) { delete [] Group; Group = 0; } else { const TVal *OldGroup = Group; Group = new TVal [Buckets]; for (int b = 0; b < Offset; b++) Group[b] = OldGroup[b]; for (int b = Offset+1; b <= Buckets; b++) Group[b-1] = OldGroup[b]; if (OldGroup != NULL) delete [] OldGroup; } BMClear(ValN); } } ///////////////////////////////////////////////// // Sparse Table Iterator template class TSparseTableI { private: typedef TSparseGroup TValGroup; typedef typename TVec::TIter TGroupVI; int CurOff; // Offset in the current group TGroupVI BegI, GroupI, EndI; public: TSparseTableI() : CurOff(0), GroupI(NULL), EndI(NULL) { } TSparseTableI(const TGroupVI& BegIter, const TGroupVI& CurIter, const TGroupVI& EndIter, const int& Offset = 0) : CurOff(Offset), BegI(BegIter), GroupI(CurIter), EndI(EndIter) { } TSparseTableI(const TSparseTableI& STI) : CurOff(STI.CurOff), BegI(STI.BegI), GroupI(STI.GroupI), EndI(STI.EndI) { } TSparseTableI& operator = (const TSparseTableI& STI) { CurOff=STI.CurOff; BegI=STI.BegI; GroupI=STI.GroupI; EndI=STI.EndI; return *this; } bool operator == (const TSparseTableI& STI) const { return GroupI == STI.GroupI && CurOff == STI.CurOff; } bool operator < (const TSparseTableI& STI) const { return GroupI < STI.GroupI || (GroupI == STI.GroupI && CurOff < STI.CurOff); } TSparseTableI& operator++ (int) { if (CurOff+1 == GroupI->Len()) { CurOff = 0; if (GroupI < EndI) { GroupI++; while (GroupI < EndI && GroupI->Empty()) { GroupI++; } } } else { CurOff++; } return *this; } TSparseTableI& operator-- (int) { if (CurOff == 0) { while (GroupI >= BegI && GroupI->Empty()) { GroupI--; } if (GroupI >= BegI) CurOff = GroupI->Len()-1; } else { CurOff--; } return *this; } int GetValN() const { return int(GroupI-BegI)*GroupSize + GroupI->OffsetToPos(CurOff); } bool IsEnd() const { return GroupI==EndI; } TVal& operator*() const { return GroupI->Offset(CurOff); } TVal& operator()() const { return GroupI->Offset(CurOff); } TVal* operator->() const { return &(operator*()); } }; ///////////////////////////////////////////////// // Sparse Table template // == 32*x+16 class TSparseTable { public: typedef TSparseGroup TSGroup; typedef TSparseTableI TIter; private: TInt MxVals, Vals; TVec GroupV; private: static int GetGroups(const int& Vals) { return Vals == 0 ? 0 : ((Vals-1) / GroupSize) + 1; } int PosInGroup(const int& ValN) const { return ValN % GroupSize; } int GroupNum(const int& ValN) const { return ValN / GroupSize; } const TSGroup& GetGrp1(const int& ValN) const { return GroupV[GroupNum(ValN)]; } TSGroup& GetGrp1(const int& ValN) { return GroupV[GroupNum(ValN)]; } public: TSparseTable(const int& MaxVals = 0) : MxVals(MaxVals), Vals(0), GroupV(GetGroups(MaxVals), GetGroups(MaxVals)) { } TSparseTable(const TSparseTable& ST) : MxVals(ST.MxVals), Vals(ST.Vals), GroupV(ST.GroupV) { } TSparseTable(TSIn& SIn) : MxVals(SIn), Vals(SIn), GroupV(SIn) { } void Load(TSIn& SIn) { MxVals.Load(SIn); Vals.Load(SIn); GroupV.Load(SIn); } void Save(TSOut& SOut) const { MxVals.Save(SOut); Vals.Save(SOut); GroupV.Save(SOut); } TSparseTable& operator = (const TSparseTable& ST); bool operator == (const TSparseTable& ST) const; bool operator < (const TSparseTable& ST) const; ::TSize GetMemUsed() const { return 2*sizeof(TInt)+Vals*sizeof(TVal)+GroupV.GetMemUsed(); } TIter BegI() const { if (Len() > 0) { int B = 0; while (B < Groups() && GroupV[B].Empty()) { B++; } return TIter(GroupV.BegI(), GroupV.BegI()+B, GroupV.EndI()); } return TIter(GroupV.BegI(), GroupV.EndI(), GroupV.EndI()); } TIter EndI() const { return TIter(GroupV.BegI(), GroupV.EndI(), GroupV.EndI()); } TIter GetI(const int& ValN) const { Assert(! IsEmpty(ValN)); typedef typename TVec::TIter TVIter; const TVIter GI = GroupV.GetI(GroupNum(ValN)); return TIter(GroupV.BegI(), GI, GroupV.EndI(), GI->PosToOffset(PosInGroup(ValN))); } int Len() const { return Vals; } int Reserved() const { return MxVals; } int Groups() const { return GroupV.Len(); } bool Empty() const { return Vals == 0; } uint GetDiskSz() const { return sizeof(TInt)*4 + ((GroupSize+16)/8)*Groups() + sizeof(TVal)*Vals; } void Clr(const bool& DoDel = true); void Reserve(const int NewVals) { Resize(NewVals); } void Resize(const int& NewVals); void Swap(TSparseTable& ST); bool IsEmpty(const int& ValN) const { return GroupV[GroupNum(ValN)].IsEmpty(PosInGroup(ValN)); } const TVal& Get(const int& ValN) const { return GroupV[GroupNum(ValN)].Get(PosInGroup(ValN)); } TVal& Set(const int& ValN, const TVal& Val); TVal& Set(const int& ValN); void Del(const int& ValN); TSGroup& GetGroup(const int& GroupN) { return GroupV[GroupN]; } const TSGroup& GetGroup(const int& GroupN) const { return GroupV[GroupN]; } }; template TSparseTable& TSparseTable::operator = (const TSparseTable& ST) { if (this != &ST) { MxVals = ST.MxVals; Vals = ST.Vals; GroupV = ST.GroupV; } return *this; } template bool TSparseTable::operator == (const TSparseTable& ST) const { return Vals == ST.Vals && MxVals == ST.MxVals && GroupV == ST.GroupV; } template bool TSparseTable::operator < (const TSparseTable& ST) const { return Vals < ST.Vals || (Vals == ST.Vals && GroupV < ST.GroupV); } template void TSparseTable::Clr(const bool& DoDel) { if (! DoDel) { for (int g = 0; g < GroupV.Len(); g++) GroupV[g].Clr(false); } else { MxVals = 0; GroupV.Clr(true); } Vals = 0; } template void TSparseTable::Resize(const int& NewVals) { // only allow to grow if (NewVals > MxVals) { const int Groups = GetGroups(NewVals); GroupV.Reserve(Groups, Groups); MxVals = NewVals; } } template void TSparseTable::Swap(TSparseTable& ST) { ::Swap(MxVals, ST.MxVals); ::Swap(Vals, ST.Vals); GroupV.Swap(ST.GroupV); } template TVal& TSparseTable::Set(const int& ValN, const TVal& Val) { Assert(ValN < MxVals); TSGroup& Group = GetGrp1(ValN); const int OldVals = Group.Len(); TVal& ValRef = Group.Set(PosInGroup(ValN), Val); Vals += Group.Len() - OldVals; return ValRef; } template TVal& TSparseTable::Set(const int& ValN) { Assert(ValN < MxVals); TSGroup& Group = GetGrp1(ValN); const int OldVals = Group.Len(); TVal& ValRef = Group.Set(PosInGroup(ValN)); Vals += Group.Len() - OldVals; return ValRef; } template void TSparseTable::Del(const int& ValN) { Assert(ValN < MxVals); TSGroup& Group = GetGrp1(ValN); const int OldVals = Group.Len(); Group.Del(PosInGroup(ValN)); Vals += Group.Len() - OldVals; } ///////////////////////////////////////////////// // Sparse Hash Key Dat #pragma pack(push, 1) // pack class size template class TSHashKeyDat { public: TKey Key; TDat Dat; public: TSHashKeyDat() : Key(), Dat() { } TSHashKeyDat(const TKey& _Key) : Key(_Key), Dat() { } TSHashKeyDat(const TKey& _Key, const TDat& _Dat) : Key(_Key), Dat(_Dat) { } TSHashKeyDat(const TSHashKeyDat& HashKeyDat) : Key(HashKeyDat.Key), Dat(HashKeyDat.Dat) { } explicit TSHashKeyDat(TSIn& SIn) : Key(SIn), Dat(SIn) { } void Save(TSOut& SOut) const { Key.Save(SOut); Dat.Save(SOut); } TSHashKeyDat& operator = (const TSHashKeyDat& HashKeyDat) { if (this != &HashKeyDat) { Key = HashKeyDat.Key; Dat = HashKeyDat.Dat; } return *this; } bool operator == (const TSHashKeyDat& HashKeyDat) const { return Key == HashKeyDat.Key; } bool operator < (const TSHashKeyDat& HashKeyDat) const { return Key < HashKeyDat.Key; } int Hash() const { return Key.GetPrimHashCd(); } }; #pragma pack(pop) ///////////////////////////////////////////////// // Sparse Hash Table template // GroupSize= 32*x+16, for some x class TSparseHash { public: typedef TSHashKeyDat THashKeyDat; typedef typename TSparseTable::TIter TIter; typedef typename TSparseTable::TSGroup TSGroup; public: static const float MxOccupancy; // = 0.7; //was 0.8 static const float MnOccupancy; // = 0.4 * MxOccupancy; static const int MinBuckets; // = 32 (must be power of 2) private: void ResetThresh(); int GetMinSize(const int& CurVals, const int& WantedVals) const; void CopyFrom(const TSparseHash& HT, const int& MnWanted); void MoveFrom(TSparseHash& HT, const int& MnWanted); void ResizeDelta(const int& ValsToAdd, const int& MnWanted = 0); void FindPos(const TKey& Key, int& Pos, int& PosToIns) const; private: TInt ShrinkThresh, ExpandThresh; TSparseTable Table; public: TSparseHash(const int& WantedVals = 0) : Table(GetMinSize(0, WantedVals)) { ResetThresh(); } TSparseHash(TSIn& SIn) : ShrinkThresh(SIn), ExpandThresh(SIn), Table(SIn) { } void Load(TSIn& SIn) { ShrinkThresh.Load(SIn); ExpandThresh.Load(SIn); Table.Load(SIn); } void Save(TSOut& SOut) const { ShrinkThresh.Save(SOut); ExpandThresh.Save(SOut); Table.Save(SOut); } TSparseHash& operator = (const TSparseHash& SHT); bool operator == (const TSparseHash& SHT) const; bool operator < (const TSparseHash& SHT) const; ::TSize GetMemUsed() const { return 2*sizeof(TInt)+Table.GetMemUsed(); } TIter BegI() const { return Table.BegI(); } TIter EndI() const { return Table.EndI(); } TIter GetI(const TKey& Key) const { Assert(IsKey(Key)); return Table.GetI(GetKeyId(Key)); } bool Empty() const { return Len() == 0; } int Len() const { return Table.Len(); } int Reserved() const { return Table.Reserved(); } uint GetDiskSz() const { return 2*sizeof(TInt) + Table.GetDiskSz(); } void Reserve(const int& MxVals) { if (MxVals > Len()) ResizeDelta(MxVals - Len(), 0); } void Clr(const bool& DoDel = true) { Table.Clr(DoDel); ResetThresh(); } void Swap(TSparseHash& HT); int AddKey(const TKey& Key); TDat& AddDat(const TKey& Key); TDat& AddDat(const TKey& Key, const TDat& Dat); const TKey& GetKey(const int& KeyId) const { return Table.Get(KeyId).Key; } int GetKeyId(const TKey& Key) const { int Pos, PosToIns; FindPos(Key, Pos, PosToIns); return Pos; } bool IsKey(const TKey& Key) const { return GetKeyId(Key) != -1; } bool IsKey(const TKey& Key, int& KeyId) const { KeyId = GetKeyId(Key); return KeyId != -1; } bool IsKeyId(const int& KeyId) const { return ! Table.IsEmpty(KeyId); } int GetRndKeyId(TRnd& Rnd = TInt::Rnd) const { Assert(Len()>0); int KeyId = Rnd.GetUniDevInt(Reserved()); while (! IsKeyId(KeyId)) { KeyId = Rnd.GetUniDevInt(Reserved()); } return KeyId; } const TDat& GetDat(const TKey& Key) const; TDat& GetDat(const TKey& Key); const TDat& GetDatKeyId(const int& KeyId) const { return Table.Get(KeyId).Dat; } TDat& GetDatKeyId(const int& KeyId) { return Table.Set(KeyId).Dat; } void GetKeyDat(const int& KeyId, TKey& Key, TDat& Dat) const; bool IsKeyGetDat(const TKey& Key, TDat& Dat) const; void GetKeyV(TVec& KeyV) const; void GetDatV(TVec& DatV) const; void GetKeyDatPrV(TVec >& KeyDatPrV) const; void GetDatKeyPrV(TVec >& DatKeyPrV) const; }; template const float TSparseHash::MxOccupancy = 0.8f; //0.8f; template const float TSparseHash::MnOccupancy = 0.4f * 0.8f; //0.8f template const int TSparseHash::MinBuckets = 32; template void TSparseHash::ResetThresh() { ExpandThresh = int(Table.Reserved() * MxOccupancy); ShrinkThresh = int(Table.Reserved() * MnOccupancy); } template int TSparseHash::GetMinSize(const int& CurVals, const int& WantedVals) const { int Size = MinBuckets; while (Size*MxOccupancy < WantedVals || CurVals >= Size * MxOccupancy) Size *= 2; return Size; } template void TSparseHash::CopyFrom(const TSparseHash& HT, const int& MnWanted) { Clr(false); const int NewSize = GetMinSize(HT.Reserved(), MnWanted); if (NewSize > Reserved()) { Table.Resize(NewSize); ResetThresh(); } const uint BuckM1 = Reserved() - 1; for (int g = 0; g < HT.Table.Groups(); g++) { const TSGroup& Group = HT.Table.GetGroup(g); for (int b = 0; b < Group.Len(); b++) { int Tries = 0; uint BuckNum; for (BuckNum = Group.Offset(b).Hash() & BuckM1; ! Table.IsEmpty(BuckNum); BuckNum = (BuckNum + Tries) & BuckM1) { Tries++; Assert(Tries < Reserved()); } Table.Set(BuckNum, Group.Offset(b)); } } } template void TSparseHash::MoveFrom(TSparseHash& HT, const int& MnWanted) { Clr(false); int NewSize; if (MnWanted == 0) NewSize = HT.Reserved(); else NewSize = GetMinSize(HT.Reserved(), MnWanted); if (NewSize > Reserved()) { Table.Resize(NewSize); ResetThresh(); } const uint BuckM1 = Reserved() - 1; for (int g = 0; g < HT.Table.Groups(); g++) { TSGroup& Group = HT.Table.GetGroup(g); for (int b = 0; b < Group.Len(); b++) { int Tries = 0; uint BuckNum; for (BuckNum = Group.Offset(b).Hash() & BuckM1; ! Table.IsEmpty(BuckNum); BuckNum = (BuckNum + Tries) & BuckM1) { Tries++; Assert(Tries < Reserved()); } Assert(Table.IsEmpty(BuckNum)); Table.Set(BuckNum, Group.Offset(b)); } Group.Clr(true); // delete } } template void TSparseHash::ResizeDelta(const int& ValsToAdd, const int& MnWanted) { if (Reserved() > MnWanted && Len()+ValsToAdd < ExpandThresh) { return; } const int NewSize = GetMinSize(Table.Len()+ValsToAdd, MnWanted); if (NewSize > Reserved()) { printf("***Resize SparseHash:%d->%d\n", Reserved(), NewSize); TSparseHash TmpHt(ValsToAdd+Len()); TmpHt.ResetThresh(); TmpHt.MoveFrom(*this, Len()); Swap(TmpHt); } } template void TSparseHash::FindPos(const TKey& Key, int& Pos, int& PosToIns) const { const uint BuckM1 = Reserved() - 1; uint BuckNum = Key.GetPrimHashCd() & BuckM1; int Tries = 0; while (true) { if (Table.IsEmpty(BuckNum)) { Pos = -1; PosToIns = BuckNum; return; } else if (Key == Table.Get(BuckNum).Key) { Pos = BuckNum; PosToIns = -1; return; } Tries++; BuckNum = (BuckNum + Tries) & BuckM1; Assert(Tries < Reserved()); } } template TSparseHash& TSparseHash::operator = (const TSparseHash& SHT) { if (this != &SHT) { ShrinkThresh = SHT.ShrinkThresh; ExpandThresh = SHT.ExpandThresh; Table = SHT.Table; } return *this; } template bool TSparseHash::operator == (const TSparseHash& SHT) const { return Table == SHT.Table; } template bool TSparseHash::operator < (const TSparseHash& SHT) const { return Table < SHT.Table; } template void TSparseHash::Swap(TSparseHash& HT) { ::Swap(ShrinkThresh, HT.ShrinkThresh); ::Swap(ExpandThresh, HT.ExpandThresh); Table.Swap(HT.Table); } template int TSparseHash::AddKey(const TKey& Key) { ResizeDelta(1); int Pos, PosToIns; FindPos(Key, Pos, PosToIns); if (Pos != -1) { return Pos; } // key exists else { Table.Set(PosToIns, THashKeyDat(Key)); return PosToIns; } } template TDat& TSparseHash::AddDat(const TKey& Key) { ResizeDelta(1); int Pos, PosToIns; FindPos(Key, Pos, PosToIns); if (PosToIns != -1) { return Table.Set(PosToIns, THashKeyDat(Key)).Dat; } else { return Table.Set(Pos).Dat; } } template TDat& TSparseHash::AddDat(const TKey& Key, const TDat& Dat) { ResizeDelta(1); int Pos, PosToIns; FindPos(Key, Pos, PosToIns); if (PosToIns != -1) { return Table.Set(PosToIns, THashKeyDat(Key, Dat)).Dat; } else { return Table.Set(Pos).Dat = Dat; } } template const TDat& TSparseHash::GetDat(const TKey& Key) const { int Pos, PosToIns; FindPos(Key, Pos, PosToIns); Assert(Pos != -1); return Table.Get(Pos).Dat; } template TDat& TSparseHash::GetDat(const TKey& Key) { int Pos, PosToIns; FindPos(Key, Pos, PosToIns); Assert(Pos != -1); return Table.Set(Pos).Dat; } template void TSparseHash::GetKeyDat(const int& KeyId, TKey& Key, TDat& Dat) const { Assert(IsKey(KeyId)); const THashKeyDat& KeyDat = Table.Get(KeyId); Key = KeyDat.Key; Dat = KeyDat.Dat; } template bool TSparseHash::IsKeyGetDat(const TKey& Key, TDat& Dat) const { int KeyId; if (IsKey(Key, KeyId)) { Dat=Table.Get(KeyId).Dat; return true; } else { return false; } } template void TSparseHash::GetKeyV(TVec& KeyV) const { KeyV.Gen(Len(), 0); for (TIter i = BegI(); i < EndI(); i++) { KeyV.Add(i->Key); } } template void TSparseHash::GetDatV(TVec& DatV) const { DatV.Gen(Len(), 0); for (TIter i = BegI(); i < EndI(); i++) { DatV.Add(i->Dat); } } template void TSparseHash::GetKeyDatPrV(TVec >& KeyDatPrV) const { KeyDatPrV.Gen(Len(), 0); for (TIter i = BegI(); i < EndI(); i++) { KeyDatPrV.Add(TPair(i->Key, i->Dat)); } } template void TSparseHash::GetDatKeyPrV(TVec >& DatKeyPrV) const { DatKeyPrV.Gen(Len(), 0); for (TIter i = BegI(); i < EndI(); i++) { DatKeyPrV.Add(TPair(i->Dat, i->Key)); } } ///////////////////////////////////////////////// // Sparse Set template // GroupSize= 32*x+16, for some x class TSparseSet { public: typedef typename TSparseTable::TIter TIter; typedef typename TSparseTable::TSGroup TSGroup; public: static const float MxOccupancy; // = 0.7; //was 0.8 static const float MnOccupancy; // = 0.4 * MxOccupancy; static const int MinBuckets; // = 32 (must be power of 2) private: void ResetThresh(); int GetMinSize(const int& CurVals, const int& WantedVals) const; void CopyFrom(const TSparseSet& SSet, const int& MnWanted); void MoveFrom(TSparseSet& SSet, const int& MnWanted); void ResizeDelta(const int& ValsToAdd, const int& MnWanted = 0); void FindPos(const TKey& Key, int& Pos, int& PosToIns) const; private: TInt ShrinkThresh, ExpandThresh; TSparseTable Table; public: TSparseSet(const int& WantedVals = 0) : Table(GetMinSize(0, WantedVals)) { ResetThresh(); } TSparseSet(TSIn& SIn) : ShrinkThresh(SIn), ExpandThresh(SIn), Table(SIn) { } void Load(TSIn& SIn) { ShrinkThresh.Load(SIn); ExpandThresh.Load(SIn); Table.Load(SIn); } void Save(TSOut& SOut) const { ShrinkThresh.Save(SOut); ExpandThresh.Save(SOut); Table.Save(SOut); } TSparseSet& operator = (const TSparseSet& SSet); bool operator == (const TSparseSet& SSet) const; bool operator < (const TSparseSet& SSet) const; ::TSize GetMemUsed() const { return 2*sizeof(TInt)+Table.GetMemUsed(); } TIter BegI() const { return Table.BegI(); } TIter EndI() const { return Table.EndI(); } TIter GetI(const int& KeyId) const { Assert(IsKeyId(KeyId)); return Table.GetI(KeyId); } bool Empty() const { return Len() == 0; } int Len() const { return Table.Len(); } int Reserved() const { return Table.Reserved(); } uint GetDiskSz() const { return 2*sizeof(TInt) + Table.GetDiskSz(); } void Reserve(const int& MxVals) { if (MxVals > Len()) ResizeDelta(MxVals - Len(), 0); } void Clr(const bool& DoDel = true) { Table.Clr(DoDel); ResetThresh(); } void Swap(TSparseSet& SSet); int AddKey(const TKey& Key); const TKey& GetKey(const int& KeyId) const { return Table.Get(KeyId); } int GetKeyId(const TKey& Key) const { int Pos, PosToIns; FindPos(Key, Pos, PosToIns); return Pos; } bool IsKey(const TKey& Key) const { return GetKeyId(Key) != -1; } bool IsKey(const TKey& Key, int& KeyId) const { KeyId = GetKeyId(Key); return KeyId != -1; } bool IsKeyId(const int& KeyId) const { return ! Table.IsEmpty(KeyId); } int GetRndKeyId(TRnd& Rnd = TInt::Rnd) const { Assert(Len()>0); int KeyId = Rnd.GetUniDevInt(Reserved()); while (! IsKeyId(KeyId)) { KeyId = Rnd.GetUniDevInt(Reserved()); } return KeyId; } void GetKeyV(TVec& KeyV) const; }; template const float TSparseSet::MxOccupancy = 0.8f; template const float TSparseSet::MnOccupancy = 0.4f * 0.8f; template const int TSparseSet::MinBuckets = 32; template void TSparseSet::ResetThresh() { ExpandThresh = int(Table.Reserved() * MxOccupancy); ShrinkThresh = int(Table.Reserved() * MnOccupancy); } template int TSparseSet::GetMinSize(const int& CurVals, const int& WantedVals) const { int Size = MinBuckets; while (Size*MxOccupancy <= WantedVals || CurVals > Size * MxOccupancy) Size *= 2; return Size; } template void TSparseSet::CopyFrom(const TSparseSet& SSet, const int& MnWanted) { Clr(false); const int NewSize = GetMinSize(SSet.Reserved(), MnWanted); if (NewSize > Reserved()) { Table.Resize(NewSize); ResetThresh(); } const uint BuckM1 = Reserved() - 1; for (int g = 0; g < SSet.Table.Groups(); g++) { const TSGroup& Group = SSet.Table.GetGroup(g); for (int b = 0; b < Group.Len(); b++) { int Tries = 0; uint BuckNum; for (BuckNum = Group.Offset(b).GetPrimHashCd() & BuckM1; ! Table.IsEmpty(BuckNum); BuckNum = (BuckNum + Tries) & BuckM1) { Tries++; Assert(Tries < Reserved()); } Table.Set(BuckNum, Group.Offset(b)); } } } template void TSparseSet::MoveFrom(TSparseSet& SSet, const int& MnWanted) { Clr(false); int NewSize; if (MnWanted == 0) NewSize = SSet.Reserved(); else NewSize = GetMinSize(SSet.Reserved(), MnWanted); if (NewSize > Reserved()) { Table.Resize(NewSize); ResetThresh(); } const uint BuckM1 = Reserved() - 1; for (int g = 0; g < SSet.Table.Groups(); g++) { TSGroup& Group = SSet.Table.GetGroup(g); for (int b = 0; b < Group.Len(); b++) { int Tries = 0; uint BuckNum; for (BuckNum = Group.Offset(b).GetPrimHashCd() & BuckM1; ! Table.IsEmpty(BuckNum); BuckNum = (BuckNum + Tries) & BuckM1) { Tries++; Assert(Tries < Reserved()); } Assert(Table.IsEmpty(BuckNum)); Table.Set(BuckNum, Group.Offset(b)); } Group.Clr(true); // delete } } template void TSparseSet::ResizeDelta(const int& ValsToAdd, const int& MnWanted) { if (Reserved() > MnWanted && Len()+ValsToAdd < ExpandThresh) { return; } const int NewSize = GetMinSize(Table.Len()+ValsToAdd, MnWanted); if (NewSize > Reserved()) { printf("***Resize SparseSet: %d->%d\n", Reserved(), NewSize); TSparseSet TmpSSet(Len()+ValsToAdd); TmpSSet.ResetThresh(); TmpSSet.MoveFrom(*this, Len()); Swap(TmpSSet); } } template void TSparseSet::FindPos(const TKey& Key, int& Pos, int& PosToIns) const { const uint BuckM1 = Reserved() - 1; uint BuckNum = Key.GetPrimHashCd() & BuckM1; int Tries = 0; while (true) { if (Table.IsEmpty(BuckNum)) { Pos = -1; PosToIns = BuckNum; return; } else if (Key == Table.Get(BuckNum)) { Pos = BuckNum; PosToIns = -1; return; } Tries++; BuckNum = (BuckNum + Tries) & BuckM1; Assert(Tries < Reserved()); } } template TSparseSet& TSparseSet::operator = (const TSparseSet& SSet) { if (this != &SSet) { ShrinkThresh = SSet.ShrinkThresh; ExpandThresh = SSet.ExpandThresh; Table = SSet.Table; } return *this; } template bool TSparseSet::operator == (const TSparseSet& SSet) const { return Table == SSet.Table; } template bool TSparseSet::operator < (const TSparseSet& SSet) const { return Table < SSet.Table; } template void TSparseSet::Swap(TSparseSet& SSet) { ::Swap(ShrinkThresh, SSet.ShrinkThresh); ::Swap(ExpandThresh, SSet.ExpandThresh); Table.Swap(SSet.Table); } template int TSparseSet::AddKey(const TKey& Key) { ResizeDelta(1); int Pos, PosToIns; FindPos(Key, Pos, PosToIns); if (Pos != -1) { return Pos; } // key exists else { Table.Set(PosToIns, Key); return PosToIns; } } template void TSparseSet::GetKeyV(TVec& KeyV) const { KeyV.Gen(Len(), 0); for (TIter I = BegI(); I < EndI(); I++) { KeyV.Add(I()); } } ///////////////////////////////////////////////// // Set-Hash-Key #pragma pack(push, 1) // pack class size template class THashSetKey{ public: TInt Next; TInt HashCd; TKey Key; public: THashSetKey(): Next(-1), HashCd(-1), Key() {} THashSetKey(const int& _Next, const int& _HashCd, const TKey& _Key): Next(_Next), HashCd(_HashCd), Key(_Key) {} explicit THashSetKey(TSIn& SIn): Next(SIn), HashCd(SIn), Key(SIn) {} void Save(TSOut& SOut) const { Next.Save(SOut); HashCd.Save(SOut); Key.Save(SOut); } void LoadXml(const PXmlTok& XmlTok, const TStr& Nm="") { XLoadHd(Nm); XLoad(Key); } void SaveXml(TSOut& SOut, const TStr& Nm) const { XSaveHd(Nm); XSave(Key); } THashSetKey& operator=(const THashSetKey& SetKey) { if (this!=&SetKey) { Next=SetKey.Next; HashCd=SetKey.HashCd; Key=SetKey.Key; } return *this; } }; #pragma pack(pop) ///////////////////////////////////////////////// // Set-Hash-Key-Iterator template class THashSetKeyI{ private: typedef THashSetKey TSetKey; TSetKey* KeyI; TSetKey* EndI; public: THashSetKeyI(): KeyI(NULL), EndI(NULL) { } THashSetKeyI(const THashSetKeyI& _SetKeyI): KeyI(_SetKeyI.KeyI), EndI(_SetKeyI.EndI) { } THashSetKeyI(const TSetKey* _KeyI, const TSetKey* _EndI): KeyI((TSetKey*)_KeyI), EndI((TSetKey*)_EndI) { } THashSetKeyI& operator=(const THashSetKeyI& SetKeyI) { KeyI=SetKeyI.KeyI; EndI=SetKeyI.EndI; return *this; } bool operator==(const THashSetKeyI& SetKeyI) const { return KeyI==SetKeyI.KeyI; } bool operator<(const THashSetKeyI& SetKeyI) const { return KeyIHashCd==-1) { KeyI++; } return *this; } THashSetKeyI& operator--(int) { do { KeyI--; } while (KeyI->HashCd==-1); return *this; } const TKey& operator*() const { return KeyI->Key; } const TKey& operator()() const { return KeyI->Key; } const TKey* operator->() const { return KeyI->Key; } const TKey& GetKey() const {Assert((KeyI!=NULL)&&(KeyI->HashCd!=-1)); return KeyI->Key; } }; ///////////////////////////////////////////////// // Set-Table template > class THashSet{ public: typedef THashSetKeyI TIter; private: typedef THashSetKey TSetKey; TIntV PortV; TVec KeyV; TBool AutoSizeP; TInt FFreeKeyId, FreeKeys; private: TSetKey& GetSetKey(const int& KeyId) { TSetKey& SetKey=KeyV[KeyId]; Assert(SetKey.HashCd!=-1); return SetKey; } const TSetKey& GetSetKey(const int& KeyId) const { const TSetKey& SetKey=KeyV[KeyId]; Assert(SetKey.HashCd!=-1); return SetKey; } uint GetNextPrime(const uint& Val) const; void Resize(); public: THashSet(): PortV(), KeyV(), AutoSizeP(true), FFreeKeyId(-1), FreeKeys(0) { } THashSet(const THashSet& Set): PortV(Set.PortV), KeyV(Set.KeyV), AutoSizeP(Set.AutoSizeP), FFreeKeyId(Set.FFreeKeyId), FreeKeys(Set.FreeKeys) { } THashSet(const int& ExpectVals, const bool& _AutoSizeP=false); explicit THashSet(const TVec& KeyV); explicit THashSet(TSIn& SIn): PortV(SIn), KeyV(SIn), AutoSizeP(SIn), FFreeKeyId(SIn), FreeKeys(SIn) { SIn.LoadCs(); } void Load(TSIn& SIn) { PortV.Load(SIn); KeyV.Load(SIn); AutoSizeP=TBool(SIn); FFreeKeyId=TInt(SIn); FreeKeys=TInt(SIn); SIn.LoadCs(); } void Save(TSOut& SOut) const { PortV.Save(SOut); KeyV.Save(SOut); AutoSizeP.Save(SOut); FFreeKeyId.Save(SOut); FreeKeys.Save(SOut); SOut.SaveCs(); } void LoadXml(const PXmlTok& XmlTok, const TStr& Nm="") { XLoadHd(Nm); TVec KeyV; XLoad(KeyV); XLoad(AutoSizeP); for (int KeyN=0; KeyN0) { if (IsKeyIdEqKeyN()) { return TIter(KeyV.BegI(), KeyV.EndI()); } int FKeyId=-1; FNextKeyId(FKeyId); return TIter(KeyV.BegI()+FKeyId, KeyV.EndI()); } return TIter(KeyV.EndI(), KeyV.EndI()); } TIter EndI() const {return TIter(KeyV.EndI(), KeyV.EndI()); } TIter GetI(const TKey& Key) const {return TIter(&KeyV[GetKeyId(Key)], KeyV.EndI()); } void Gen(const int& ExpectVals) { PortV.Gen(GetNextPrime(ExpectVals/2)); KeyV.Gen(ExpectVals, 0); FFreeKeyId=-1; FreeKeys=0; PortV.PutAll(TInt(-1)); } void Clr(const bool& DoDel=true, const int& NoDelLim=-1); bool Empty() const {return Len()==0; } int Len() const {return KeyV.Len()-FreeKeys; } int GetPorts() const {return PortV.Len(); } bool IsAutoSize() const {return AutoSizeP; } int GetMxKeyIds() const {return KeyV.Len(); } int GetReservedKeyIds() const { return KeyV.Reserved(); } bool IsKeyIdEqKeyN() const {return FreeKeys==0; } int AddKey(const TKey& Key); void AddKeyV(const TVec& KeyV); void DelKey(const TKey& Key); void DelIfKey(const TKey& Key) { int KeyId; if (IsKey(Key, KeyId)) {DelKeyId(KeyId); }} void DelKeyId(const int& KeyId) {DelKey(GetKey(KeyId)); } void DelKeyIdV(const TIntV& KeyIdV) { for (int KeyIdN=0; KeyIdN0); return Rnd.GetUniDevInt(Len()); } bool IsKey(const TKey& Key) const {return GetKeyId(Key)!=-1; } bool IsKey(const TKey& Key, int& KeyId) const { KeyId=GetKeyId(Key); return KeyId!=-1; } bool IsKeyId(const int& KeyId) const { return (0<=KeyId)&&(KeyId& KeyV) const; void Swap(THashSet& Set); void Defrag(); void Pack() {KeyV.Pack(); } }; template uint THashSet::GetNextPrime(const uint& Val) const { uint* f=(uint*)TIntH::HashPrimeT, *m, *l=(uint*)TIntH::HashPrimeT + (int)TIntH::HashPrimes; int h, len = (int)TIntH::HashPrimes; while (len > 0) { h = len >> 1; m = f + h; if (*m < Val) { f = m; f++; len = len - h - 1; } else len = h; } return f == l ? *(l - 1) : *f; } template void THashSet::Resize() { // resize & initialize port vector if (PortV.Len()==0) {PortV.Gen(17); } else if (AutoSizeP&&(KeyV.Len()>2*PortV.Len())) { PortV.Gen(GetNextPrime(PortV.Len()+1)); } else { return; } PortV.PutAll(TInt(-1)); // reSet keys for (int KeyId=0; KeyId THashSet::THashSet(const int& ExpectVals, const bool& _AutoSizeP): PortV(GetNextPrime(ExpectVals/2+1)), KeyV(ExpectVals, 0), AutoSizeP(_AutoSizeP), FFreeKeyId(-1), FreeKeys(0) { PortV.PutAll(TInt(-1)); } template THashSet::THashSet(const TVec& _KeyV) : PortV(GetNextPrime(_KeyV.Len()/2+1)), KeyV(_KeyV.Len(), 0), AutoSizeP(false), FFreeKeyId(-1), FreeKeys(0) { PortV.PutAll(TInt(-1)); for (int i = 0; i < _KeyV.Len(); i++) { AddKey(_KeyV[i]); } } template bool THashSet::operator==(const THashSet& Set) const { if (Len() != Set.Len()) { return false; } for (int k = FFirstKeyId(); FNextKeyId(k); k++) { if (! Set.IsKey(GetKey(k))) { return false; } } return true; } template void THashSet::Clr(const bool& DoDel, const int& NoDelLim) { if (DoDel) { PortV.Clr(); KeyV.Clr(); } else { PortV.PutAll(TInt(-1)); KeyV.Clr(DoDel, NoDelLim); } FFreeKeyId=TInt(-1); FreeKeys=TInt(0); } template int THashSet::AddKey(const TKey& Key) { if ((KeyV.Len()>2*PortV.Len())||PortV.Empty()) {Resize(); } int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); int HashCd=abs(THashFunc::GetSecHashCd(Key)); int PrevKeyId=-1; int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyV[KeyId].HashCd==HashCd) && (KeyV[KeyId].Key==Key))) { PrevKeyId=KeyId; KeyId=KeyV[KeyId].Next; } if (KeyId==-1) { if (FFreeKeyId==-1) { KeyId=KeyV.Add(TSetKey(-1, HashCd, Key)); } else { KeyId=FFreeKeyId; FFreeKeyId=KeyV[FFreeKeyId].Next; FreeKeys--; KeyV[KeyId].Next = -1; KeyV[KeyId].HashCd = HashCd; KeyV[KeyId].Key = Key; } if (PrevKeyId==-1) { PortV[PortN]=KeyId; } else { KeyV[PrevKeyId].Next=KeyId; } } return KeyId; } template void THashSet::AddKeyV(const TVec& KeyV) { for (int i = 0; i < KeyV.Len(); i++) { AddKey(KeyV[i]); } } template void THashSet::DelKey(const TKey& Key) { IAssert(!PortV.Empty()); int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); int HashCd=abs(THashFunc::GetSecHashCd(Key)); int PrevKeyId=-1; int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyV[KeyId].HashCd==HashCd) && (KeyV[KeyId].Key==Key))) { PrevKeyId=KeyId; KeyId=KeyV[KeyId].Next; } IAssertR(KeyId!=-1, Key.GetStr()); if (PrevKeyId==-1) {PortV[PortN]=KeyV[KeyId].Next; } else {KeyV[PrevKeyId].Next=KeyV[KeyId].Next; } KeyV[KeyId].Next=FFreeKeyId; FFreeKeyId=KeyId; FreeKeys++; KeyV[KeyId].HashCd=TInt(-1); KeyV[KeyId].Key=TKey(); } template void THashSet::MarkDelKey(const TKey& Key) { IAssert(!PortV.Empty()); int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); int HashCd=abs(THashFunc::GetSecHashCd(Key)); int PrevKeyId=-1; int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyV[KeyId].HashCd==HashCd) && (KeyV[KeyId].Key==Key))) { PrevKeyId=KeyId; KeyId=KeyV[KeyId].Next; } IAssertR(KeyId!=-1, Key.GetStr()); if (PrevKeyId==-1) {PortV[PortN]=KeyV[KeyId].Next; } else {KeyV[PrevKeyId].Next=KeyV[KeyId].Next; } KeyV[KeyId].Next=FFreeKeyId; FFreeKeyId=KeyId; FreeKeys++; KeyV[KeyId].HashCd=TInt(-1); } template int THashSet::GetKeyId(const TKey& Key) const { if (PortV.Empty()) {return -1; } int PortN=abs(THashFunc::GetPrimHashCd(Key)%PortV.Len()); int HashCd=abs(THashFunc::GetSecHashCd(Key)); int KeyId=PortV[PortN]; while ((KeyId!=-1) && !((KeyV[KeyId].HashCd==HashCd) && (KeyV[KeyId].Key==Key))) { KeyId=KeyV[KeyId].Next; } return KeyId; } template bool THashSet::FNextKeyId(int& KeyId) const { do {KeyId++; } while ((KeyId void THashSet::GetKeyV(TVec& KeyV) const { KeyV.Clr(); int KeyId=FFirstKeyId(); while (FNextKeyId(KeyId)) { KeyV.Add(GetKey(KeyId)); } } template void THashSet::Swap(THashSet& Set) { if (this!=&Set) { PortV.Swap(Set.PortV); KeyV.Swap(Set.KeyV); ::Swap(AutoSizeP, Set.AutoSizeP); ::Swap(FFreeKeyId, Set.FFreeKeyId); ::Swap(FreeKeys, Set.FreeKeys); } } template void THashSet::Defrag() { if (!IsKeyIdEqKeyN()) { THashSet Set(PortV.Len()); int KeyId=FFirstKeyId(); TKey Key; while (FNextKeyId(KeyId)) { GetKey(KeyId, Key); Set.AddKey(Key); } Pack(); operator=(Set); IAssert(IsKeyIdEqKeyN()); } } ///////////////////////////////////////////////// // Common Hash Set Types typedef THashSet TIntSet; typedef THashSet TFltSet; typedef THashSet TStrSet; typedef THashSet TIntPrSet; ///////////////////////////////////////////////// // Packed Vec template class TPackVec { public: typedef TVal* TIter; private: int Vals; TVal* ValT; void ResizeDelta(const int& ValsToAdd=1); public: TPackVec() : Vals(0), ValT(NULL) { } TPackVec(const TPackVec& Vec) : Vals(0), ValT(NULL) { Gen(Vec.Len()); memcpy(ValT, Vec.ValT, sizeof(TVal)*Vals); } explicit TPackVec(const int& _Vals) : Vals(_Vals) { if (Vals==0) { ValT=NULL; } else { ValT = (TVal *) realloc(ValT, sizeof(TVal)*Vals); } } ~TPackVec() { if (ValT != NULL) { free(ValT); } } explicit TPackVec(TSIn& SIn): Vals(0), ValT(NULL) { Load(SIn); } void Load(TSIn& SIn); void Save(TSOut& SOut) const; const TVal& operator [] (const int& ValN) const { return ValT[ValN]; } TVal& operator [] (const int& ValN) { return ValT[ValN]; } TPackVec& operator = (const TPackVec& Vec) { Gen(Vec.Len()); memcpy(ValT, Vec.ValT, sizeof(TVal)*Vals); return *this; } TVec& operator = (const TVec& Vec) { Gen(Vec.Len()); memcpy(ValT, Vec.ValT, sizeof(TVal)*Vals); return *this; } void Gen(const int& _Vals) { if (ValT != NULL) { free(ValT); } Vals = _Vals; if (Vals==0) { ValT=NULL; } else { ValT = (TVal *) realloc(ValT, sizeof(TVal)*Vals); } } void Clr() { if (ValT != NULL) { free(ValT); ValT=NULL; } Vals = 0; } bool Empty() const {return Vals==0; } int Len() const {return Vals; } const TVal& Last() const { return ValT[Len()-1]; } TVal& Last() { return ValT[Len()-1]; } TIter BegI() const {return ValT; } TIter EndI() const {return ValT+Vals; } TIter GetI(const int& ValN) const { return ValT+ValN; } void Add(const TVal& Val) { ResizeDelta(1); ValT[Vals-1]=Val; } void AddV(const TPackVec& ValV) { ResizeDelta(ValV.Len()); memcpy(ValT+Vals-ValV.Len(), ValV.BegI(), sizeof(TVal)*ValV.Len()); } void AddV(const TVec& ValV) { ResizeDelta(ValV.Len()); memcpy(ValT+Vals-ValV.Len(), ValV.BegI(), sizeof(TVal)*ValV.Len()); } void AddV(TSIn& FIn) { int NVals; FIn.Load(NVals); ResizeDelta(NVals); FIn.LoadBf(ValT+Vals-NVals, sizeof(TVal)*NVals); } void Sort(const bool& Asc=true) { if (Asc) { TVec::QSortCmp(BegI(), EndI(), TLss()); } else { TVec::QSortCmp(BegI(), EndI(), TGtr()); } } }; template void TPackVec::ResizeDelta(const int& ValsToAdd) { if (ValsToAdd == 0) return; Vals += ValsToAdd; ValT = (TVal *) realloc(ValT, sizeof(TVal)*Vals); EAssert(ValT != NULL); } template void TPackVec::Load(TSIn& SIn) { SIn.Load(Vals); if (Vals==0) { if (ValT != NULL) { free(ValT); } ValT = NULL; } else { ValT = (TVal *) realloc(ValT, sizeof(TVal)*Vals); } SIn.LoadBf(ValT, sizeof(TVal)*Vals); } template void TPackVec::Save(TSOut& SOut) const { SOut.Save(Vals); if (Vals != 0) { SOut.SaveBf(ValT, sizeof(TVal)*Vals); } } #endif